2003-08-13 05:53:07 +04:00
/*
Unix SMB / CIFS implementation .
transaction2 handling
Copyright ( C ) Andrew Tridgell 2003
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
/*
This file handles the parsing of transact2 requests
*/
# include "includes.h"
2004-12-16 15:31:34 +03:00
# include "dlinklist.h"
2004-11-02 10:18:24 +03:00
# include "smb_server/smb_server.h"
2005-07-28 04:27:28 +04:00
# include "librpc/gen_ndr/ndr_misc.h"
2005-12-28 01:51:30 +03:00
# include "ntvfs/ntvfs.h"
2005-12-28 18:38:36 +03:00
# include "libcli/raw/libcliraw.h"
2004-11-02 10:18:24 +03:00
2006-03-18 14:10:21 +03:00
# define TRANS2_CHECK_ASYNC_STATUS_SIMPLE do { \
if ( ! NT_STATUS_IS_OK ( req - > ntvfs - > async_states - > status ) ) { \
trans2_setup_reply ( trans , 0 , 0 , 0 ) ; \
return req - > ntvfs - > async_states - > status ; \
} \
} while ( 0 )
# define TRANS2_CHECK_ASYNC_STATUS(ptr, type) do { \
TRANS2_CHECK_ASYNC_STATUS_SIMPLE ; \
ptr = talloc_get_type ( op - > op_info , type ) ; \
} while ( 0 )
2006-03-17 12:42:04 +03:00
/*
hold the state of a nttrans op while in progress . Needed to allow for async backend
functions .
*/
struct trans_op {
struct smbsrv_request * req ;
struct smb_trans2 * trans ;
uint8_t command ;
NTSTATUS ( * send_fn ) ( struct trans_op * ) ;
void * op_info ;
} ;
2003-08-13 05:53:07 +04:00
# define CHECK_MIN_BLOB_SIZE(blob, size) do { \
if ( ( blob ) - > length < ( size ) ) { \
return NT_STATUS_INFO_LENGTH_MISMATCH ; \
} } while ( 0 )
/* grow the data allocation size of a trans2 reply - this guarantees
that requests to grow the data size later will not change the
pointer */
2006-03-17 12:42:04 +03:00
static BOOL trans2_grow_data_allocation ( struct smb_trans2 * trans ,
2004-12-20 06:12:09 +03:00
uint32_t new_size )
2003-08-13 05:53:07 +04:00
{
if ( new_size < = trans - > out . data . length ) {
2004-12-20 06:12:09 +03:00
return True ;
2003-08-13 05:53:07 +04:00
}
2006-03-17 12:42:04 +03:00
trans - > out . data . data = talloc_realloc ( trans , trans - > out . data . data ,
2005-01-07 07:39:16 +03:00
uint8_t , new_size ) ;
2004-12-20 06:12:09 +03:00
return ( trans - > out . data . data ! = NULL ) ;
2003-08-13 05:53:07 +04:00
}
/* grow the data size of a trans2 reply */
2006-03-17 12:42:04 +03:00
static BOOL trans2_grow_data ( struct smb_trans2 * trans ,
2004-12-20 06:12:09 +03:00
uint32_t new_size )
2003-08-13 05:53:07 +04:00
{
2006-03-17 12:42:04 +03:00
if ( ! trans2_grow_data_allocation ( trans , new_size ) ) {
2004-12-20 06:12:09 +03:00
return False ;
}
2003-08-13 05:53:07 +04:00
trans - > out . data . length = new_size ;
2004-12-20 06:12:09 +03:00
return True ;
2003-08-13 05:53:07 +04:00
}
/* grow the data, zero filling any new bytes */
2006-03-17 12:42:04 +03:00
static BOOL trans2_grow_data_fill ( struct smb_trans2 * trans ,
2004-12-20 06:12:09 +03:00
uint32_t new_size )
2003-08-13 05:53:07 +04:00
{
2004-12-20 06:12:09 +03:00
uint32_t old_size = trans - > out . data . length ;
2006-03-17 12:42:04 +03:00
if ( ! trans2_grow_data ( trans , new_size ) ) {
2004-12-20 06:12:09 +03:00
return False ;
}
2003-08-13 05:53:07 +04:00
if ( new_size > old_size ) {
memset ( trans - > out . data . data + old_size , 0 , new_size - old_size ) ;
}
2004-12-20 06:12:09 +03:00
return True ;
2003-08-13 05:53:07 +04:00
}
/* setup a trans2 reply, given the data and params sizes */
2006-03-17 12:42:04 +03:00
static void trans2_setup_reply ( struct smb_trans2 * trans ,
2004-05-25 21:24:24 +04:00
uint16_t param_size , uint16_t data_size ,
uint16_t setup_count )
2003-08-13 05:53:07 +04:00
{
trans - > out . setup_count = setup_count ;
if ( setup_count ! = 0 ) {
2006-03-17 12:42:04 +03:00
trans - > out . setup = talloc_zero_array ( trans , uint16_t , setup_count ) ;
2003-08-13 05:53:07 +04:00
}
2006-03-17 12:42:04 +03:00
trans - > out . params = data_blob_talloc ( trans , NULL , param_size ) ;
trans - > out . data = data_blob_talloc ( trans , NULL , data_size ) ;
2003-08-13 05:53:07 +04:00
}
/*
pull a string from a blob in a trans2 request
*/
2004-06-28 12:39:00 +04:00
static size_t trans2_pull_blob_string ( struct smbsrv_request * req ,
2003-08-13 05:53:07 +04:00
const DATA_BLOB * blob ,
2004-05-25 21:24:24 +04:00
uint16_t offset ,
2003-08-13 05:53:07 +04:00
const char * * str ,
int flags )
{
/* we use STR_NO_RANGE_CHECK because the params are allocated
separately in a DATA_BLOB , so we need to do our own range
checking */
if ( offset > = blob - > length ) {
* str = NULL ;
return 0 ;
}
return req_pull_string ( req , str ,
blob - > data + offset ,
blob - > length - offset ,
STR_NO_RANGE_CHECK | flags ) ;
}
/*
push a string into the data section of a trans2 request
return the number of bytes consumed in the output
*/
2004-06-28 12:39:00 +04:00
static size_t trans2_push_data_string ( struct smbsrv_request * req ,
2003-08-13 05:53:07 +04:00
struct smb_trans2 * trans ,
2004-12-29 02:28:02 +03:00
uint32_t len_offset ,
uint32_t offset ,
2006-03-11 13:25:59 +03:00
const struct smb_wire_string * str ,
2003-08-13 05:53:07 +04:00
int dest_len ,
int flags )
{
int alignment = 0 , ret = 0 , pkt_len ;
/* we use STR_NO_RANGE_CHECK because the params are allocated
separately in a DATA_BLOB , so we need to do our own range
checking */
if ( ! str - > s | | offset > = trans - > out . data . length ) {
if ( flags & STR_LEN8BIT ) {
SCVAL ( trans - > out . data . data , len_offset , 0 ) ;
} else {
SIVAL ( trans - > out . data . data , len_offset , 0 ) ;
}
return 0 ;
}
flags | = STR_NO_RANGE_CHECK ;
if ( dest_len = = - 1 | | ( dest_len > trans - > out . data . length - offset ) ) {
dest_len = trans - > out . data . length - offset ;
}
if ( ! ( flags & ( STR_ASCII | STR_UNICODE ) ) ) {
2003-08-16 00:19:30 +04:00
flags | = ( req - > flags2 & FLAGS2_UNICODE_STRINGS ) ? STR_UNICODE : STR_ASCII ;
2003-08-13 05:53:07 +04:00
}
if ( ( offset & 1 ) & & ( flags & STR_UNICODE ) & & ! ( flags & STR_NOALIGN ) ) {
alignment = 1 ;
if ( dest_len > 0 ) {
SCVAL ( trans - > out . data . data + offset , 0 , 0 ) ;
r2552: Character set conversion and string handling updates.
The intial motivation for this commit was to merge in some of the
bugfixes present in Samba3's chrcnv and string handling code into
Samba4. However, along the way I found a lot of unused functions, and
decided to do a bit more...
The strlen_m code now does not use a fixed buffer, but more work is
needed to finish off other functions in str_util.c. These fixed
length buffers hav caused very nasty, hard to chase down bugs at some
sites.
The strupper_m() function has a strupper_talloc() to replace it (we
need to go around and fix more uses, but it's a start). Use of these
new functions will avoid bugs where the upper or lowercase version of
a string is a different length.
I have removed the push_*_allocate functions, which are replaced by
calls to push_*_talloc. Likewise, pstring and other 'fixed length'
wrappers are removed, where possible.
I have removed the first ('base pointer') argument, used by push_ucs2,
as the Samba4 way of doing things ensures that this is always on an
even boundary anyway. (It was used in only one place, in any case).
(This used to be commit dfecb0150627b500cb026b8a4932fe87902ca392)
2004-09-23 04:51:45 +04:00
ret = push_string ( trans - > out . data . data + offset + 1 , str - > s , dest_len - 1 , flags ) ;
2003-08-13 05:53:07 +04:00
}
} else {
r2552: Character set conversion and string handling updates.
The intial motivation for this commit was to merge in some of the
bugfixes present in Samba3's chrcnv and string handling code into
Samba4. However, along the way I found a lot of unused functions, and
decided to do a bit more...
The strlen_m code now does not use a fixed buffer, but more work is
needed to finish off other functions in str_util.c. These fixed
length buffers hav caused very nasty, hard to chase down bugs at some
sites.
The strupper_m() function has a strupper_talloc() to replace it (we
need to go around and fix more uses, but it's a start). Use of these
new functions will avoid bugs where the upper or lowercase version of
a string is a different length.
I have removed the push_*_allocate functions, which are replaced by
calls to push_*_talloc. Likewise, pstring and other 'fixed length'
wrappers are removed, where possible.
I have removed the first ('base pointer') argument, used by push_ucs2,
as the Samba4 way of doing things ensures that this is always on an
even boundary anyway. (It was used in only one place, in any case).
(This used to be commit dfecb0150627b500cb026b8a4932fe87902ca392)
2004-09-23 04:51:45 +04:00
ret = push_string ( trans - > out . data . data + offset , str - > s , dest_len , flags ) ;
2003-08-13 05:53:07 +04:00
}
/* sometimes the string needs to be terminated, but the length
on the wire must not include the termination ! */
pkt_len = ret ;
if ( ( flags & STR_LEN_NOTERM ) & & ( flags & STR_TERMINATE ) ) {
if ( ( flags & STR_UNICODE ) & & ret > = 2 ) {
pkt_len = ret - 2 ;
}
if ( ( flags & STR_ASCII ) & & ret > = 1 ) {
pkt_len = ret - 1 ;
}
}
if ( flags & STR_LEN8BIT ) {
SCVAL ( trans - > out . data . data , len_offset , pkt_len ) ;
} else {
SIVAL ( trans - > out . data . data , len_offset , pkt_len ) ;
}
return ret + alignment ;
}
/*
append a string to the data section of a trans2 reply
len_offset points to the place in the packet where the length field
should go
*/
2004-06-28 12:39:00 +04:00
static void trans2_append_data_string ( struct smbsrv_request * req ,
2003-08-13 05:53:07 +04:00
struct smb_trans2 * trans ,
2006-03-11 13:25:59 +03:00
const struct smb_wire_string * str ,
2003-08-13 05:53:07 +04:00
uint_t len_offset ,
int flags )
{
size_t ret ;
2004-12-29 02:28:02 +03:00
uint32_t offset ;
2003-08-13 05:53:07 +04:00
const int max_bytes_per_char = 3 ;
offset = trans - > out . data . length ;
2006-03-17 12:42:04 +03:00
trans2_grow_data ( trans , offset + ( 2 + strlen_m ( str - > s ) ) * max_bytes_per_char ) ;
2003-08-13 05:53:07 +04:00
ret = trans2_push_data_string ( req , trans , len_offset , offset , str , - 1 , flags ) ;
2006-03-17 12:42:04 +03:00
trans2_grow_data ( trans , offset + ret ) ;
2003-08-13 05:53:07 +04:00
}
2004-10-02 16:16:46 +04:00
/*
align the end of the data section of a trans reply on an even boundary
*/
static void trans2_align_data ( struct smbsrv_request * req , struct smb_trans2 * trans )
{
if ( ( trans - > out . data . length & 1 ) = = 0 ) {
return ;
}
2006-03-17 12:42:04 +03:00
trans2_grow_data ( trans , trans - > out . data . length + 1 ) ;
2004-10-02 16:16:46 +04:00
SCVAL ( trans - > out . data . data , trans - > out . data . length - 1 , 0 ) ;
}
2003-08-13 05:53:07 +04:00
/*
2006-03-17 12:42:04 +03:00
trans2 qfsinfo implementation send
2003-08-13 05:53:07 +04:00
*/
2006-03-17 12:42:04 +03:00
static NTSTATUS trans2_qfsinfo_send ( struct trans_op * op )
2003-08-13 05:53:07 +04:00
{
2006-03-17 12:42:04 +03:00
struct smbsrv_request * req = op - > req ;
struct smb_trans2 * trans = op - > trans ;
union smb_fsinfo * fsinfo ;
2003-08-13 05:53:07 +04:00
NTSTATUS status ;
uint_t i ;
2003-12-16 12:02:58 +03:00
DATA_BLOB guid_blob ;
2003-08-13 05:53:07 +04:00
2006-03-18 14:10:21 +03:00
TRANS2_CHECK_ASYNC_STATUS ( fsinfo , union smb_fsinfo ) ;
2003-08-13 05:53:07 +04:00
2006-03-17 12:42:04 +03:00
switch ( fsinfo - > generic . level ) {
2003-08-13 05:53:07 +04:00
case SMB_QFS_ALLOCATION :
2006-03-17 12:42:04 +03:00
trans2_setup_reply ( trans , 0 , 18 , 0 ) ;
2003-08-13 05:53:07 +04:00
2006-03-17 12:42:04 +03:00
SIVAL ( trans - > out . data . data , 0 , fsinfo - > allocation . out . fs_id ) ;
SIVAL ( trans - > out . data . data , 4 , fsinfo - > allocation . out . sectors_per_unit ) ;
SIVAL ( trans - > out . data . data , 8 , fsinfo - > allocation . out . total_alloc_units ) ;
SIVAL ( trans - > out . data . data , 12 , fsinfo - > allocation . out . avail_alloc_units ) ;
SSVAL ( trans - > out . data . data , 16 , fsinfo - > allocation . out . bytes_per_sector ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
case SMB_QFS_VOLUME :
2006-03-17 12:42:04 +03:00
trans2_setup_reply ( trans , 0 , 5 , 0 ) ;
2003-08-13 05:53:07 +04:00
2006-03-17 12:42:04 +03:00
SIVAL ( trans - > out . data . data , 0 , fsinfo - > volume . out . serial_number ) ;
2003-08-13 05:53:07 +04:00
/* w2k3 implements this incorrectly for unicode - it
* leaves the last byte off the string */
trans2_append_data_string ( req , trans ,
2006-03-17 12:42:04 +03:00
& fsinfo - > volume . out . volume_name ,
2003-08-13 05:53:07 +04:00
4 , STR_LEN8BIT | STR_NOALIGN ) ;
return NT_STATUS_OK ;
case SMB_QFS_VOLUME_INFO :
case SMB_QFS_VOLUME_INFORMATION :
2006-03-17 12:42:04 +03:00
trans2_setup_reply ( trans , 0 , 18 , 0 ) ;
2003-08-13 05:53:07 +04:00
2006-03-17 12:42:04 +03:00
push_nttime ( trans - > out . data . data , 0 , fsinfo - > volume_info . out . create_time ) ;
SIVAL ( trans - > out . data . data , 8 , fsinfo - > volume_info . out . serial_number ) ;
2004-08-25 08:03:28 +04:00
SSVAL ( trans - > out . data . data , 16 , 0 ) ; /* padding */
2003-08-13 05:53:07 +04:00
trans2_append_data_string ( req , trans ,
2006-03-17 12:42:04 +03:00
& fsinfo - > volume_info . out . volume_name ,
2003-08-13 05:53:07 +04:00
12 , STR_UNICODE ) ;
return NT_STATUS_OK ;
case SMB_QFS_SIZE_INFO :
case SMB_QFS_SIZE_INFORMATION :
2006-03-17 12:42:04 +03:00
trans2_setup_reply ( trans , 0 , 24 , 0 ) ;
2003-08-13 05:53:07 +04:00
2006-03-17 12:42:04 +03:00
SBVAL ( trans - > out . data . data , 0 , fsinfo - > size_info . out . total_alloc_units ) ;
SBVAL ( trans - > out . data . data , 8 , fsinfo - > size_info . out . avail_alloc_units ) ;
SIVAL ( trans - > out . data . data , 16 , fsinfo - > size_info . out . sectors_per_unit ) ;
SIVAL ( trans - > out . data . data , 20 , fsinfo - > size_info . out . bytes_per_sector ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
case SMB_QFS_DEVICE_INFO :
case SMB_QFS_DEVICE_INFORMATION :
2006-03-17 12:42:04 +03:00
trans2_setup_reply ( trans , 0 , 8 , 0 ) ;
SIVAL ( trans - > out . data . data , 0 , fsinfo - > device_info . out . device_type ) ;
SIVAL ( trans - > out . data . data , 4 , fsinfo - > device_info . out . characteristics ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
case SMB_QFS_ATTRIBUTE_INFO :
case SMB_QFS_ATTRIBUTE_INFORMATION :
2006-03-17 12:42:04 +03:00
trans2_setup_reply ( trans , 0 , 12 , 0 ) ;
2003-08-13 05:53:07 +04:00
2006-03-17 12:42:04 +03:00
SIVAL ( trans - > out . data . data , 0 , fsinfo - > attribute_info . out . fs_attr ) ;
SIVAL ( trans - > out . data . data , 4 , fsinfo - > attribute_info . out . max_file_component_length ) ;
2003-08-13 05:53:07 +04:00
/* this must not be null terminated or win98 gets
confused ! also note that w2k3 returns this as
unicode even when ascii is negotiated */
trans2_append_data_string ( req , trans ,
2006-03-17 12:42:04 +03:00
& fsinfo - > attribute_info . out . fs_type ,
2003-08-13 05:53:07 +04:00
8 , STR_UNICODE ) ;
return NT_STATUS_OK ;
case SMB_QFS_QUOTA_INFORMATION :
2006-03-17 12:42:04 +03:00
trans2_setup_reply ( trans , 0 , 48 , 0 ) ;
2003-08-13 05:53:07 +04:00
2006-03-17 12:42:04 +03:00
SBVAL ( trans - > out . data . data , 0 , fsinfo - > quota_information . out . unknown [ 0 ] ) ;
SBVAL ( trans - > out . data . data , 8 , fsinfo - > quota_information . out . unknown [ 1 ] ) ;
SBVAL ( trans - > out . data . data , 16 , fsinfo - > quota_information . out . unknown [ 2 ] ) ;
SBVAL ( trans - > out . data . data , 24 , fsinfo - > quota_information . out . quota_soft ) ;
SBVAL ( trans - > out . data . data , 32 , fsinfo - > quota_information . out . quota_hard ) ;
SBVAL ( trans - > out . data . data , 40 , fsinfo - > quota_information . out . quota_flags ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
case SMB_QFS_FULL_SIZE_INFORMATION :
2006-03-17 12:42:04 +03:00
trans2_setup_reply ( trans , 0 , 32 , 0 ) ;
2003-08-13 05:53:07 +04:00
2006-03-17 12:42:04 +03:00
SBVAL ( trans - > out . data . data , 0 , fsinfo - > full_size_information . out . total_alloc_units ) ;
SBVAL ( trans - > out . data . data , 8 , fsinfo - > full_size_information . out . call_avail_alloc_units ) ;
SBVAL ( trans - > out . data . data , 16 , fsinfo - > full_size_information . out . actual_avail_alloc_units ) ;
SIVAL ( trans - > out . data . data , 24 , fsinfo - > full_size_information . out . sectors_per_unit ) ;
SIVAL ( trans - > out . data . data , 28 , fsinfo - > full_size_information . out . bytes_per_sector ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
case SMB_QFS_OBJECTID_INFORMATION :
2006-03-17 12:42:04 +03:00
trans2_setup_reply ( trans , 0 , 64 , 0 ) ;
2003-08-13 05:53:07 +04:00
2004-09-08 09:39:06 +04:00
status = ndr_push_struct_blob ( & guid_blob , req ,
2006-03-17 12:42:04 +03:00
& fsinfo - > objectid_information . out . guid ,
2003-12-16 12:02:58 +03:00
( ndr_push_flags_fn_t ) ndr_push_GUID ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2004-11-01 08:46:52 +03:00
memcpy ( trans - > out . data . data , guid_blob . data , guid_blob . length ) ;
2003-12-16 12:02:58 +03:00
2003-08-13 05:53:07 +04:00
for ( i = 0 ; i < 6 ; i + + ) {
2006-03-17 12:42:04 +03:00
SBVAL ( trans - > out . data . data , 16 + 8 * i , fsinfo - > objectid_information . out . unknown [ i ] ) ;
2003-08-13 05:53:07 +04:00
}
return NT_STATUS_OK ;
}
return NT_STATUS_INVALID_LEVEL ;
}
2006-03-17 12:42:04 +03:00
/*
trans2 qfsinfo implementation
*/
static NTSTATUS trans2_qfsinfo ( struct smbsrv_request * req , struct trans_op * op )
{
struct smb_trans2 * trans = op - > trans ;
union smb_fsinfo * fsinfo ;
uint16_t level ;
/* make sure we got enough parameters */
if ( trans - > in . params . length ! = 2 ) {
return NT_STATUS_FOOBAR ;
}
fsinfo = talloc ( op , union smb_fsinfo ) ;
NT_STATUS_HAVE_NO_MEMORY ( fsinfo ) ;
op - > op_info = fsinfo ;
op - > send_fn = trans2_qfsinfo_send ;
level = SVAL ( trans - > in . params . data , 0 ) ;
switch ( level ) {
case SMB_QFS_ALLOCATION :
fsinfo - > allocation . level = RAW_QFS_ALLOCATION ;
2006-03-18 14:10:21 +03:00
return ntvfs_fsinfo ( req - > ntvfs , fsinfo ) ;
2006-03-17 12:42:04 +03:00
case SMB_QFS_VOLUME :
fsinfo - > volume . level = RAW_QFS_VOLUME ;
2006-03-18 14:10:21 +03:00
return ntvfs_fsinfo ( req - > ntvfs , fsinfo ) ;
2006-03-17 12:42:04 +03:00
case SMB_QFS_VOLUME_INFO :
case SMB_QFS_VOLUME_INFORMATION :
fsinfo - > volume_info . level = RAW_QFS_VOLUME_INFO ;
2006-03-18 14:10:21 +03:00
return ntvfs_fsinfo ( req - > ntvfs , fsinfo ) ;
2006-03-17 12:42:04 +03:00
case SMB_QFS_SIZE_INFO :
case SMB_QFS_SIZE_INFORMATION :
fsinfo - > size_info . level = RAW_QFS_SIZE_INFO ;
2006-03-18 14:10:21 +03:00
return ntvfs_fsinfo ( req - > ntvfs , fsinfo ) ;
2006-03-17 12:42:04 +03:00
case SMB_QFS_DEVICE_INFO :
case SMB_QFS_DEVICE_INFORMATION :
fsinfo - > device_info . level = RAW_QFS_DEVICE_INFO ;
2006-03-18 14:10:21 +03:00
return ntvfs_fsinfo ( req - > ntvfs , fsinfo ) ;
2006-03-17 12:42:04 +03:00
case SMB_QFS_ATTRIBUTE_INFO :
case SMB_QFS_ATTRIBUTE_INFORMATION :
fsinfo - > attribute_info . level = RAW_QFS_ATTRIBUTE_INFO ;
2006-03-18 14:10:21 +03:00
return ntvfs_fsinfo ( req - > ntvfs , fsinfo ) ;
2006-03-17 12:42:04 +03:00
case SMB_QFS_QUOTA_INFORMATION :
fsinfo - > quota_information . level = RAW_QFS_QUOTA_INFORMATION ;
2006-03-18 14:10:21 +03:00
return ntvfs_fsinfo ( req - > ntvfs , fsinfo ) ;
2006-03-17 12:42:04 +03:00
case SMB_QFS_FULL_SIZE_INFORMATION :
fsinfo - > full_size_information . level = RAW_QFS_FULL_SIZE_INFORMATION ;
2006-03-18 14:10:21 +03:00
return ntvfs_fsinfo ( req - > ntvfs , fsinfo ) ;
2006-03-17 12:42:04 +03:00
case SMB_QFS_OBJECTID_INFORMATION :
fsinfo - > objectid_information . level = RAW_QFS_OBJECTID_INFORMATION ;
2006-03-18 14:10:21 +03:00
return ntvfs_fsinfo ( req - > ntvfs , fsinfo ) ;
2006-03-17 12:42:04 +03:00
}
return NT_STATUS_INVALID_LEVEL ;
}
/*
trans2 open implementation send
*/
static NTSTATUS trans2_open_send ( struct trans_op * op )
{
struct smbsrv_request * req = op - > req ;
struct smb_trans2 * trans = op - > trans ;
union smb_open * io ;
2006-03-18 14:10:21 +03:00
TRANS2_CHECK_ASYNC_STATUS ( io , union smb_open ) ;
2006-03-17 12:42:04 +03:00
trans2_setup_reply ( trans , 30 , 0 , 0 ) ;
SSVAL ( trans - > out . params . data , VWV ( 0 ) , io - > t2open . out . file . fnum ) ;
SSVAL ( trans - > out . params . data , VWV ( 1 ) , io - > t2open . out . attrib ) ;
srv_push_dos_date3 ( req - > smb_conn , trans - > out . params . data ,
VWV ( 2 ) , io - > t2open . out . write_time ) ;
SIVAL ( trans - > out . params . data , VWV ( 4 ) , io - > t2open . out . size ) ;
SSVAL ( trans - > out . params . data , VWV ( 6 ) , io - > t2open . out . access ) ;
SSVAL ( trans - > out . params . data , VWV ( 7 ) , io - > t2open . out . ftype ) ;
SSVAL ( trans - > out . params . data , VWV ( 8 ) , io - > t2open . out . devstate ) ;
SSVAL ( trans - > out . params . data , VWV ( 9 ) , io - > t2open . out . action ) ;
SIVAL ( trans - > out . params . data , VWV ( 10 ) , 0 ) ; /* reserved */
SSVAL ( trans - > out . params . data , VWV ( 12 ) , 0 ) ; /* EaErrorOffset */
SIVAL ( trans - > out . params . data , VWV ( 13 ) , 0 ) ; /* EaLength */
return NT_STATUS_OK ;
}
2004-11-06 10:58:45 +03:00
/*
trans2 open implementation
*/
2006-03-17 12:42:04 +03:00
static NTSTATUS trans2_open ( struct smbsrv_request * req , struct trans_op * op )
2004-11-06 10:58:45 +03:00
{
2006-03-17 12:42:04 +03:00
struct smb_trans2 * trans = op - > trans ;
2004-11-06 10:58:45 +03:00
union smb_open * io ;
NTSTATUS status ;
/* make sure we got enough parameters */
if ( trans - > in . params . length < 29 ) {
return NT_STATUS_FOOBAR ;
}
2006-03-17 12:42:04 +03:00
io = talloc ( op , union smb_open ) ;
NT_STATUS_HAVE_NO_MEMORY ( io ) ;
2004-11-06 10:58:45 +03:00
2005-07-17 16:57:14 +04:00
io - > t2open . level = RAW_OPEN_T2OPEN ;
io - > t2open . in . flags = SVAL ( trans - > in . params . data , VWV ( 0 ) ) ;
io - > t2open . in . open_mode = SVAL ( trans - > in . params . data , VWV ( 1 ) ) ;
io - > t2open . in . search_attrs = SVAL ( trans - > in . params . data , VWV ( 2 ) ) ;
io - > t2open . in . file_attrs = SVAL ( trans - > in . params . data , VWV ( 3 ) ) ;
io - > t2open . in . write_time = srv_pull_dos_date ( req - > smb_conn ,
2004-11-06 10:58:45 +03:00
trans - > in . params . data + VWV ( 4 ) ) ; ;
2005-07-17 16:57:14 +04:00
io - > t2open . in . open_func = SVAL ( trans - > in . params . data , VWV ( 6 ) ) ;
io - > t2open . in . size = IVAL ( trans - > in . params . data , VWV ( 7 ) ) ;
io - > t2open . in . timeout = IVAL ( trans - > in . params . data , VWV ( 9 ) ) ;
io - > t2open . in . num_eas = 0 ;
io - > t2open . in . eas = NULL ;
2004-11-06 10:58:45 +03:00
trans2_pull_blob_string ( req , & trans - > in . params , 28 , & io - > t2open . in . fname , 0 ) ;
status = ea_pull_list ( & trans - > in . data , io , & io - > t2open . in . num_eas , & io - > t2open . in . eas ) ;
2006-03-17 12:42:04 +03:00
NT_STATUS_NOT_OK_RETURN ( status ) ;
2004-11-06 10:58:45 +03:00
2006-03-17 12:42:04 +03:00
op - > op_info = io ;
op - > send_fn = trans2_open_send ;
2006-03-18 14:10:21 +03:00
return ntvfs_open ( req - > ntvfs , io ) ;
2006-03-17 12:42:04 +03:00
}
/*
trans2 simple send
*/
static NTSTATUS trans2_simple_send ( struct trans_op * op )
{
struct smbsrv_request * req = op - > req ;
struct smb_trans2 * trans = op - > trans ;
2006-03-18 14:10:21 +03:00
TRANS2_CHECK_ASYNC_STATUS_SIMPLE ;
2004-11-06 10:58:45 +03:00
2006-03-17 12:42:04 +03:00
trans2_setup_reply ( trans , 2 , 0 , 0 ) ;
2004-11-06 10:58:45 +03:00
2006-03-17 12:42:04 +03:00
SSVAL ( trans - > out . params . data , VWV ( 0 ) , 0 ) ;
2004-11-06 10:58:45 +03:00
2006-03-17 12:42:04 +03:00
return NT_STATUS_OK ;
2004-11-06 10:58:45 +03:00
}
2004-12-14 02:57:59 +03:00
/*
trans2 mkdir implementation
*/
2006-03-17 12:42:04 +03:00
static NTSTATUS trans2_mkdir ( struct smbsrv_request * req , struct trans_op * op )
2004-12-14 02:57:59 +03:00
{
2006-03-17 12:42:04 +03:00
struct smb_trans2 * trans = op - > trans ;
2004-12-14 02:57:59 +03:00
union smb_mkdir * io ;
NTSTATUS status ;
/* make sure we got enough parameters */
if ( trans - > in . params . length < 5 ) {
return NT_STATUS_FOOBAR ;
}
2006-03-17 12:42:04 +03:00
io = talloc ( op , union smb_mkdir ) ;
NT_STATUS_HAVE_NO_MEMORY ( io ) ;
2004-12-14 02:57:59 +03:00
io - > t2mkdir . level = RAW_MKDIR_T2MKDIR ;
trans2_pull_blob_string ( req , & trans - > in . params , 4 , & io - > t2mkdir . in . path , 0 ) ;
status = ea_pull_list ( & trans - > in . data , io ,
& io - > t2mkdir . in . num_eas ,
& io - > t2mkdir . in . eas ) ;
2006-03-17 12:42:04 +03:00
NT_STATUS_NOT_OK_RETURN ( status ) ;
2004-12-14 02:57:59 +03:00
2006-03-17 12:42:04 +03:00
op - > op_info = io ;
op - > send_fn = trans2_simple_send ;
2004-12-14 02:57:59 +03:00
2006-03-18 14:10:21 +03:00
return ntvfs_mkdir ( req - > ntvfs , io ) ;
2004-12-14 02:57:59 +03:00
}
2003-08-13 05:53:07 +04:00
/*
fill in the reply from a qpathinfo or qfileinfo call
*/
2006-03-17 12:42:04 +03:00
static NTSTATUS trans2_fileinfo_send ( struct trans_op * op )
2003-08-13 05:53:07 +04:00
{
2006-03-17 12:42:04 +03:00
struct smbsrv_request * req = op - > req ;
struct smb_trans2 * trans = op - > trans ;
union smb_fileinfo * st ;
2003-08-13 05:53:07 +04:00
uint_t i ;
2004-12-15 06:53:05 +03:00
uint32_t list_size ;
2006-03-17 12:42:04 +03:00
2006-03-18 14:10:21 +03:00
TRANS2_CHECK_ASYNC_STATUS ( st , union smb_fileinfo ) ;
2006-03-17 12:42:04 +03:00
2003-08-13 05:53:07 +04:00
switch ( st - > generic . level ) {
case RAW_FILEINFO_GENERIC :
case RAW_FILEINFO_GETATTR :
case RAW_FILEINFO_GETATTRE :
2004-11-18 04:41:43 +03:00
case RAW_FILEINFO_SEC_DESC :
2003-08-13 05:53:07 +04:00
/* handled elsewhere */
return NT_STATUS_INVALID_LEVEL ;
case RAW_FILEINFO_BASIC_INFO :
case RAW_FILEINFO_BASIC_INFORMATION :
2006-03-17 12:42:04 +03:00
trans2_setup_reply ( trans , 2 , 40 , 0 ) ;
2003-08-13 05:53:07 +04:00
SSVAL ( trans - > out . params . data , 0 , 0 ) ;
2004-05-25 17:57:39 +04:00
push_nttime ( trans - > out . data . data , 0 , st - > basic_info . out . create_time ) ;
push_nttime ( trans - > out . data . data , 8 , st - > basic_info . out . access_time ) ;
push_nttime ( trans - > out . data . data , 16 , st - > basic_info . out . write_time ) ;
push_nttime ( trans - > out . data . data , 24 , st - > basic_info . out . change_time ) ;
2003-08-13 05:53:07 +04:00
SIVAL ( trans - > out . data . data , 32 , st - > basic_info . out . attrib ) ;
SIVAL ( trans - > out . data . data , 36 , 0 ) ; /* padding */
return NT_STATUS_OK ;
case RAW_FILEINFO_STANDARD :
2006-03-17 12:42:04 +03:00
trans2_setup_reply ( trans , 2 , 22 , 0 ) ;
2003-08-13 05:53:07 +04:00
SSVAL ( trans - > out . params . data , 0 , 0 ) ;
2004-06-29 11:40:14 +04:00
srv_push_dos_date2 ( req - > smb_conn , trans - > out . data . data , 0 , st - > standard . out . create_time ) ;
srv_push_dos_date2 ( req - > smb_conn , trans - > out . data . data , 4 , st - > standard . out . access_time ) ;
srv_push_dos_date2 ( req - > smb_conn , trans - > out . data . data , 8 , st - > standard . out . write_time ) ;
2003-08-13 05:53:07 +04:00
SIVAL ( trans - > out . data . data , 12 , st - > standard . out . size ) ;
SIVAL ( trans - > out . data . data , 16 , st - > standard . out . alloc_size ) ;
SSVAL ( trans - > out . data . data , 20 , st - > standard . out . attrib ) ;
return NT_STATUS_OK ;
case RAW_FILEINFO_EA_SIZE :
2006-03-17 12:42:04 +03:00
trans2_setup_reply ( trans , 2 , 26 , 0 ) ;
2003-08-13 05:53:07 +04:00
SSVAL ( trans - > out . params . data , 0 , 0 ) ;
2004-06-29 11:40:14 +04:00
srv_push_dos_date2 ( req - > smb_conn , trans - > out . data . data , 0 , st - > ea_size . out . create_time ) ;
srv_push_dos_date2 ( req - > smb_conn , trans - > out . data . data , 4 , st - > ea_size . out . access_time ) ;
srv_push_dos_date2 ( req - > smb_conn , trans - > out . data . data , 8 , st - > ea_size . out . write_time ) ;
2003-08-13 05:53:07 +04:00
SIVAL ( trans - > out . data . data , 12 , st - > ea_size . out . size ) ;
SIVAL ( trans - > out . data . data , 16 , st - > ea_size . out . alloc_size ) ;
SSVAL ( trans - > out . data . data , 20 , st - > ea_size . out . attrib ) ;
SIVAL ( trans - > out . data . data , 22 , st - > ea_size . out . ea_size ) ;
return NT_STATUS_OK ;
case RAW_FILEINFO_NETWORK_OPEN_INFORMATION :
2006-03-17 12:42:04 +03:00
trans2_setup_reply ( trans , 2 , 56 , 0 ) ;
2003-08-13 05:53:07 +04:00
SSVAL ( trans - > out . params . data , 0 , 0 ) ;
2004-05-25 17:57:39 +04:00
push_nttime ( trans - > out . data . data , 0 , st - > network_open_information . out . create_time ) ;
push_nttime ( trans - > out . data . data , 8 , st - > network_open_information . out . access_time ) ;
push_nttime ( trans - > out . data . data , 16 , st - > network_open_information . out . write_time ) ;
push_nttime ( trans - > out . data . data , 24 , st - > network_open_information . out . change_time ) ;
2003-08-13 05:53:07 +04:00
SBVAL ( trans - > out . data . data , 32 , st - > network_open_information . out . alloc_size ) ;
SBVAL ( trans - > out . data . data , 40 , st - > network_open_information . out . size ) ;
SIVAL ( trans - > out . data . data , 48 , st - > network_open_information . out . attrib ) ;
SIVAL ( trans - > out . data . data , 52 , 0 ) ; /* padding */
return NT_STATUS_OK ;
case RAW_FILEINFO_STANDARD_INFO :
case RAW_FILEINFO_STANDARD_INFORMATION :
2006-03-17 12:42:04 +03:00
trans2_setup_reply ( trans , 2 , 24 , 0 ) ;
2003-08-13 05:53:07 +04:00
SSVAL ( trans - > out . params . data , 0 , 0 ) ;
SBVAL ( trans - > out . data . data , 0 , st - > standard_info . out . alloc_size ) ;
SBVAL ( trans - > out . data . data , 8 , st - > standard_info . out . size ) ;
SIVAL ( trans - > out . data . data , 16 , st - > standard_info . out . nlink ) ;
SCVAL ( trans - > out . data . data , 20 , st - > standard_info . out . delete_pending ) ;
SCVAL ( trans - > out . data . data , 21 , st - > standard_info . out . directory ) ;
SSVAL ( trans - > out . data . data , 22 , 0 ) ; /* padding */
return NT_STATUS_OK ;
case RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION :
2006-03-17 12:42:04 +03:00
trans2_setup_reply ( trans , 2 , 8 , 0 ) ;
2003-08-13 05:53:07 +04:00
SSVAL ( trans - > out . params . data , 0 , 0 ) ;
SIVAL ( trans - > out . data . data , 0 , st - > attribute_tag_information . out . attrib ) ;
SIVAL ( trans - > out . data . data , 4 , st - > attribute_tag_information . out . reparse_tag ) ;
return NT_STATUS_OK ;
case RAW_FILEINFO_EA_INFO :
case RAW_FILEINFO_EA_INFORMATION :
2006-03-17 12:42:04 +03:00
trans2_setup_reply ( trans , 2 , 4 , 0 ) ;
2003-08-13 05:53:07 +04:00
SSVAL ( trans - > out . params . data , 0 , 0 ) ;
SIVAL ( trans - > out . data . data , 0 , st - > ea_info . out . ea_size ) ;
return NT_STATUS_OK ;
case RAW_FILEINFO_MODE_INFORMATION :
2006-03-17 12:42:04 +03:00
trans2_setup_reply ( trans , 2 , 4 , 0 ) ;
2003-08-13 05:53:07 +04:00
SSVAL ( trans - > out . params . data , 0 , 0 ) ;
SIVAL ( trans - > out . data . data , 0 , st - > mode_information . out . mode ) ;
return NT_STATUS_OK ;
case RAW_FILEINFO_ALIGNMENT_INFORMATION :
2006-03-17 12:42:04 +03:00
trans2_setup_reply ( trans , 2 , 4 , 0 ) ;
2003-08-13 05:53:07 +04:00
SSVAL ( trans - > out . params . data , 0 , 0 ) ;
SIVAL ( trans - > out . data . data , 0 ,
st - > alignment_information . out . alignment_requirement ) ;
return NT_STATUS_OK ;
2004-12-18 01:47:49 +03:00
case RAW_FILEINFO_EA_LIST :
list_size = ea_list_size ( st - > ea_list . out . num_eas ,
st - > ea_list . out . eas ) ;
2006-03-17 12:42:04 +03:00
trans2_setup_reply ( trans , 2 , list_size , 0 ) ;
2004-12-18 01:47:49 +03:00
SSVAL ( trans - > out . params . data , 0 , 0 ) ;
ea_put_list ( trans - > out . data . data ,
st - > ea_list . out . num_eas , st - > ea_list . out . eas ) ;
return NT_STATUS_OK ;
2003-08-13 05:53:07 +04:00
case RAW_FILEINFO_ALL_EAS :
2004-12-15 06:53:05 +03:00
list_size = ea_list_size ( st - > all_eas . out . num_eas ,
2004-12-16 15:31:34 +03:00
st - > all_eas . out . eas ) ;
2006-03-17 12:42:04 +03:00
trans2_setup_reply ( trans , 2 , list_size , 0 ) ;
2004-12-16 15:31:34 +03:00
SSVAL ( trans - > out . params . data , 0 , 0 ) ;
ea_put_list ( trans - > out . data . data ,
st - > all_eas . out . num_eas , st - > all_eas . out . eas ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
case RAW_FILEINFO_ACCESS_INFORMATION :
2006-03-17 12:42:04 +03:00
trans2_setup_reply ( trans , 2 , 4 , 0 ) ;
2003-08-13 05:53:07 +04:00
SSVAL ( trans - > out . params . data , 0 , 0 ) ;
SIVAL ( trans - > out . data . data , 0 , st - > access_information . out . access_flags ) ;
return NT_STATUS_OK ;
case RAW_FILEINFO_POSITION_INFORMATION :
2006-03-17 12:42:04 +03:00
trans2_setup_reply ( trans , 2 , 8 , 0 ) ;
2003-08-13 05:53:07 +04:00
SSVAL ( trans - > out . params . data , 0 , 0 ) ;
SBVAL ( trans - > out . data . data , 0 , st - > position_information . out . position ) ;
return NT_STATUS_OK ;
case RAW_FILEINFO_COMPRESSION_INFO :
case RAW_FILEINFO_COMPRESSION_INFORMATION :
2006-03-17 12:42:04 +03:00
trans2_setup_reply ( trans , 2 , 16 , 0 ) ;
2003-08-13 05:53:07 +04:00
SSVAL ( trans - > out . params . data , 0 , 0 ) ;
SBVAL ( trans - > out . data . data , 0 , st - > compression_info . out . compressed_size ) ;
SSVAL ( trans - > out . data . data , 8 , st - > compression_info . out . format ) ;
SCVAL ( trans - > out . data . data , 10 , st - > compression_info . out . unit_shift ) ;
SCVAL ( trans - > out . data . data , 11 , st - > compression_info . out . chunk_shift ) ;
SCVAL ( trans - > out . data . data , 12 , st - > compression_info . out . cluster_shift ) ;
SSVAL ( trans - > out . data . data , 13 , 0 ) ; /* 3 bytes padding */
SCVAL ( trans - > out . data . data , 15 , 0 ) ;
return NT_STATUS_OK ;
case RAW_FILEINFO_IS_NAME_VALID :
2006-03-17 12:42:04 +03:00
trans2_setup_reply ( trans , 2 , 0 , 0 ) ;
2003-08-13 05:53:07 +04:00
SSVAL ( trans - > out . params . data , 0 , 0 ) ;
return NT_STATUS_OK ;
case RAW_FILEINFO_INTERNAL_INFORMATION :
2006-03-17 12:42:04 +03:00
trans2_setup_reply ( trans , 2 , 8 , 0 ) ;
2003-08-13 05:53:07 +04:00
SSVAL ( trans - > out . params . data , 0 , 0 ) ;
2003-09-02 08:37:33 +04:00
SBVAL ( trans - > out . data . data , 0 , st - > internal_information . out . file_id ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
case RAW_FILEINFO_ALL_INFO :
case RAW_FILEINFO_ALL_INFORMATION :
2006-03-17 12:42:04 +03:00
trans2_setup_reply ( trans , 2 , 72 , 0 ) ;
2003-08-13 05:53:07 +04:00
SSVAL ( trans - > out . params . data , 0 , 0 ) ;
2004-05-25 17:57:39 +04:00
push_nttime ( trans - > out . data . data , 0 , st - > all_info . out . create_time ) ;
push_nttime ( trans - > out . data . data , 8 , st - > all_info . out . access_time ) ;
push_nttime ( trans - > out . data . data , 16 , st - > all_info . out . write_time ) ;
push_nttime ( trans - > out . data . data , 24 , st - > all_info . out . change_time ) ;
2003-08-13 05:53:07 +04:00
SIVAL ( trans - > out . data . data , 32 , st - > all_info . out . attrib ) ;
2004-08-25 08:03:28 +04:00
SIVAL ( trans - > out . data . data , 36 , 0 ) ;
2003-08-13 05:53:07 +04:00
SBVAL ( trans - > out . data . data , 40 , st - > all_info . out . alloc_size ) ;
SBVAL ( trans - > out . data . data , 48 , st - > all_info . out . size ) ;
SIVAL ( trans - > out . data . data , 56 , st - > all_info . out . nlink ) ;
SCVAL ( trans - > out . data . data , 60 , st - > all_info . out . delete_pending ) ;
SCVAL ( trans - > out . data . data , 61 , st - > all_info . out . directory ) ;
SSVAL ( trans - > out . data . data , 62 , 0 ) ; /* padding */
SIVAL ( trans - > out . data . data , 64 , st - > all_info . out . ea_size ) ;
trans2_append_data_string ( req , trans , & st - > all_info . out . fname ,
2003-08-16 00:19:30 +04:00
68 , STR_UNICODE ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
case RAW_FILEINFO_NAME_INFO :
case RAW_FILEINFO_NAME_INFORMATION :
2006-03-17 12:42:04 +03:00
trans2_setup_reply ( trans , 2 , 4 , 0 ) ;
2003-08-13 05:53:07 +04:00
SSVAL ( trans - > out . params . data , 0 , 0 ) ;
2003-08-16 00:19:30 +04:00
trans2_append_data_string ( req , trans , & st - > name_info . out . fname , 0 , STR_UNICODE ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
case RAW_FILEINFO_ALT_NAME_INFO :
case RAW_FILEINFO_ALT_NAME_INFORMATION :
2006-03-17 12:42:04 +03:00
trans2_setup_reply ( trans , 2 , 4 , 0 ) ;
2003-08-13 05:53:07 +04:00
SSVAL ( trans - > out . params . data , 0 , 0 ) ;
2003-08-16 00:19:30 +04:00
trans2_append_data_string ( req , trans , & st - > alt_name_info . out . fname , 0 , STR_UNICODE ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
case RAW_FILEINFO_STREAM_INFO :
case RAW_FILEINFO_STREAM_INFORMATION :
2006-03-17 12:42:04 +03:00
trans2_setup_reply ( trans , 2 , 0 , 0 ) ;
2003-08-13 05:53:07 +04:00
SSVAL ( trans - > out . params . data , 0 , 0 ) ;
for ( i = 0 ; i < st - > stream_info . out . num_streams ; i + + ) {
2004-12-29 02:28:02 +03:00
uint32_t data_size = trans - > out . data . length ;
2004-11-25 23:01:47 +03:00
uint8_t * data ;
2003-08-13 05:53:07 +04:00
2006-03-17 12:42:04 +03:00
trans2_grow_data ( trans , data_size + 24 ) ;
2003-08-13 05:53:07 +04:00
data = trans - > out . data . data + data_size ;
SBVAL ( data , 8 , st - > stream_info . out . streams [ i ] . size ) ;
SBVAL ( data , 16 , st - > stream_info . out . streams [ i ] . alloc_size ) ;
trans2_append_data_string ( req , trans ,
& st - > stream_info . out . streams [ i ] . stream_name ,
data_size + 4 , STR_UNICODE ) ;
if ( i = = st - > stream_info . out . num_streams - 1 ) {
SIVAL ( trans - > out . data . data , data_size , 0 ) ;
} else {
2006-03-17 12:42:04 +03:00
trans2_grow_data_fill ( trans , ( trans - > out . data . length + 7 ) & ~ 7 ) ;
2003-08-13 05:53:07 +04:00
SIVAL ( trans - > out . data . data , data_size ,
trans - > out . data . length - data_size ) ;
}
}
return NT_STATUS_OK ;
2005-09-16 11:15:40 +04:00
case RAW_FILEINFO_UNIX_BASIC :
case RAW_FILEINFO_UNIX_LINK :
return NT_STATUS_INVALID_LEVEL ;
2005-12-06 15:33:32 +03:00
case RAW_FILEINFO_SMB2_ALL_EAS :
case RAW_FILEINFO_SMB2_ALL_INFORMATION :
return NT_STATUS_INVALID_LEVEL ;
2003-08-13 05:53:07 +04:00
}
return NT_STATUS_INVALID_LEVEL ;
}
/*
trans2 qpathinfo implementation
*/
2006-03-17 12:42:04 +03:00
static NTSTATUS trans2_qpathinfo ( struct smbsrv_request * req , struct trans_op * op )
2003-08-13 05:53:07 +04:00
{
2006-03-17 12:42:04 +03:00
struct smb_trans2 * trans = op - > trans ;
union smb_fileinfo * st ;
2003-08-13 05:53:07 +04:00
NTSTATUS status ;
2004-05-25 21:24:24 +04:00
uint16_t level ;
2003-08-13 05:53:07 +04:00
/* make sure we got enough parameters */
2004-10-02 16:16:46 +04:00
if ( trans - > in . params . length < 2 ) {
2003-08-13 05:53:07 +04:00
return NT_STATUS_FOOBAR ;
}
2006-03-17 12:42:04 +03:00
st = talloc ( op , union smb_fileinfo ) ;
NT_STATUS_HAVE_NO_MEMORY ( st ) ;
2003-08-13 05:53:07 +04:00
level = SVAL ( trans - > in . params . data , 0 ) ;
2006-03-17 12:42:04 +03:00
trans2_pull_blob_string ( req , & trans - > in . params , 6 , & st - > generic . in . file . path , 0 ) ;
if ( st - > generic . in . file . path = = NULL ) {
2003-08-13 05:53:07 +04:00
return NT_STATUS_FOOBAR ;
}
/* work out the backend level - we make it 1-1 in the header */
2006-03-17 12:42:04 +03:00
st - > generic . level = ( enum smb_fileinfo_level ) level ;
if ( st - > generic . level > = RAW_FILEINFO_GENERIC ) {
2003-08-13 05:53:07 +04:00
return NT_STATUS_INVALID_LEVEL ;
}
2006-03-17 12:42:04 +03:00
if ( st - > generic . level = = RAW_FILEINFO_EA_LIST ) {
2004-12-18 01:47:49 +03:00
status = ea_pull_name_list ( & trans - > in . data , req ,
2006-03-17 12:42:04 +03:00
& st - > ea_list . in . num_names ,
& st - > ea_list . in . ea_names ) ;
NT_STATUS_NOT_OK_RETURN ( status ) ;
2003-08-13 05:53:07 +04:00
}
2006-03-17 12:42:04 +03:00
op - > op_info = st ;
op - > send_fn = trans2_fileinfo_send ;
2003-08-13 05:53:07 +04:00
2006-03-18 14:10:21 +03:00
return ntvfs_qpathinfo ( req - > ntvfs , st ) ;
2003-08-13 05:53:07 +04:00
}
/*
trans2 qpathinfo implementation
*/
2006-03-17 12:42:04 +03:00
static NTSTATUS trans2_qfileinfo ( struct smbsrv_request * req , struct trans_op * op )
2003-08-13 05:53:07 +04:00
{
2006-03-17 12:42:04 +03:00
struct smb_trans2 * trans = op - > trans ;
union smb_fileinfo * st ;
2003-08-13 05:53:07 +04:00
NTSTATUS status ;
2006-03-17 12:42:04 +03:00
uint16_t level , fnum ;
2003-08-13 05:53:07 +04:00
/* make sure we got enough parameters */
if ( trans - > in . params . length < 4 ) {
return NT_STATUS_FOOBAR ;
}
2006-03-17 12:42:04 +03:00
st = talloc ( op , union smb_fileinfo ) ;
NT_STATUS_HAVE_NO_MEMORY ( st ) ;
fnum = SVAL ( trans - > in . params . data , 0 ) ;
2003-08-13 05:53:07 +04:00
level = SVAL ( trans - > in . params . data , 2 ) ;
2006-03-17 12:42:04 +03:00
st - > generic . in . file . fnum = fnum ;
2003-08-13 05:53:07 +04:00
/* work out the backend level - we make it 1-1 in the header */
2006-03-17 12:42:04 +03:00
st - > generic . level = ( enum smb_fileinfo_level ) level ;
if ( st - > generic . level > = RAW_FILEINFO_GENERIC ) {
2003-08-13 05:53:07 +04:00
return NT_STATUS_INVALID_LEVEL ;
}
2006-03-17 12:42:04 +03:00
if ( st - > generic . level = = RAW_FILEINFO_EA_LIST ) {
2004-12-18 01:47:49 +03:00
status = ea_pull_name_list ( & trans - > in . data , req ,
2006-03-17 12:42:04 +03:00
& st - > ea_list . in . num_names ,
& st - > ea_list . in . ea_names ) ;
NT_STATUS_NOT_OK_RETURN ( status ) ;
2004-12-18 01:47:49 +03:00
}
2006-03-17 12:42:04 +03:00
op - > op_info = st ;
op - > send_fn = trans2_fileinfo_send ;
2003-08-13 05:53:07 +04:00
2006-03-18 14:10:21 +03:00
return ntvfs_qfileinfo ( req - > ntvfs , st ) ;
2003-08-13 05:53:07 +04:00
}
/*
parse a trans2 setfileinfo / setpathinfo data blob
*/
2004-06-28 12:39:00 +04:00
static NTSTATUS trans2_parse_sfileinfo ( struct smbsrv_request * req ,
2003-08-13 05:53:07 +04:00
union smb_setfileinfo * st ,
const DATA_BLOB * blob )
{
2004-05-25 20:24:13 +04:00
uint32_t len ;
2003-08-13 05:53:07 +04:00
switch ( st - > generic . level ) {
case RAW_SFILEINFO_GENERIC :
case RAW_SFILEINFO_SETATTR :
case RAW_SFILEINFO_SETATTRE :
2004-11-18 04:41:43 +03:00
case RAW_SFILEINFO_SEC_DESC :
2003-08-13 05:53:07 +04:00
/* handled elsewhere */
return NT_STATUS_INVALID_LEVEL ;
case RAW_SFILEINFO_STANDARD :
CHECK_MIN_BLOB_SIZE ( blob , 12 ) ;
2004-06-29 11:40:14 +04:00
st - > standard . in . create_time = srv_pull_dos_date2 ( req - > smb_conn , blob - > data + 0 ) ;
st - > standard . in . access_time = srv_pull_dos_date2 ( req - > smb_conn , blob - > data + 4 ) ;
st - > standard . in . write_time = srv_pull_dos_date2 ( req - > smb_conn , blob - > data + 8 ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
case RAW_SFILEINFO_EA_SET :
2004-12-17 07:51:23 +03:00
return ea_pull_list ( blob , req ,
& st - > ea_set . in . num_eas ,
& st - > ea_set . in . eas ) ;
2003-08-13 05:53:07 +04:00
case SMB_SFILEINFO_BASIC_INFO :
case SMB_SFILEINFO_BASIC_INFORMATION :
CHECK_MIN_BLOB_SIZE ( blob , 36 ) ;
st - > basic_info . in . create_time = pull_nttime ( blob - > data , 0 ) ;
st - > basic_info . in . access_time = pull_nttime ( blob - > data , 8 ) ;
st - > basic_info . in . write_time = pull_nttime ( blob - > data , 16 ) ;
st - > basic_info . in . change_time = pull_nttime ( blob - > data , 24 ) ;
st - > basic_info . in . attrib = IVAL ( blob - > data , 32 ) ;
return NT_STATUS_OK ;
case SMB_SFILEINFO_DISPOSITION_INFO :
case SMB_SFILEINFO_DISPOSITION_INFORMATION :
CHECK_MIN_BLOB_SIZE ( blob , 1 ) ;
st - > disposition_info . in . delete_on_close = CVAL ( blob - > data , 0 ) ;
return NT_STATUS_OK ;
case SMB_SFILEINFO_ALLOCATION_INFO :
case SMB_SFILEINFO_ALLOCATION_INFORMATION :
CHECK_MIN_BLOB_SIZE ( blob , 8 ) ;
st - > allocation_info . in . alloc_size = BVAL ( blob - > data , 0 ) ;
return NT_STATUS_OK ;
case RAW_SFILEINFO_END_OF_FILE_INFO :
case RAW_SFILEINFO_END_OF_FILE_INFORMATION :
CHECK_MIN_BLOB_SIZE ( blob , 8 ) ;
st - > end_of_file_info . in . size = BVAL ( blob - > data , 0 ) ;
return NT_STATUS_OK ;
case RAW_SFILEINFO_RENAME_INFORMATION : {
DATA_BLOB blob2 ;
CHECK_MIN_BLOB_SIZE ( blob , 12 ) ;
st - > rename_information . in . overwrite = CVAL ( blob - > data , 0 ) ;
st - > rename_information . in . root_fid = IVAL ( blob - > data , 4 ) ;
len = IVAL ( blob - > data , 8 ) ;
blob2 . data = blob - > data + 12 ;
blob2 . length = MIN ( blob - > length , len ) ;
trans2_pull_blob_string ( req , & blob2 , 0 ,
2003-08-31 07:16:52 +04:00
& st - > rename_information . in . new_name , STR_UNICODE ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
}
case RAW_SFILEINFO_POSITION_INFORMATION :
CHECK_MIN_BLOB_SIZE ( blob , 8 ) ;
st - > position_information . in . position = BVAL ( blob - > data , 0 ) ;
return NT_STATUS_OK ;
case RAW_SFILEINFO_MODE_INFORMATION :
CHECK_MIN_BLOB_SIZE ( blob , 4 ) ;
st - > mode_information . in . mode = IVAL ( blob - > data , 0 ) ;
return NT_STATUS_OK ;
2005-09-16 11:15:40 +04:00
case RAW_SFILEINFO_UNIX_BASIC :
case RAW_SFILEINFO_UNIX_LINK :
case RAW_SFILEINFO_UNIX_HLINK :
case RAW_SFILEINFO_1023 :
case RAW_SFILEINFO_1025 :
case RAW_SFILEINFO_1029 :
case RAW_SFILEINFO_1032 :
case RAW_SFILEINFO_1039 :
case RAW_SFILEINFO_1040 :
return NT_STATUS_INVALID_LEVEL ;
2003-08-13 05:53:07 +04:00
}
return NT_STATUS_INVALID_LEVEL ;
}
/*
trans2 setfileinfo implementation
*/
2006-03-17 12:42:04 +03:00
static NTSTATUS trans2_setfileinfo ( struct smbsrv_request * req , struct trans_op * op )
2003-08-13 05:53:07 +04:00
{
2006-03-17 12:42:04 +03:00
struct smb_trans2 * trans = op - > trans ;
union smb_setfileinfo * st ;
2003-08-13 05:53:07 +04:00
NTSTATUS status ;
2004-05-25 21:24:24 +04:00
uint16_t level , fnum ;
2003-08-13 05:53:07 +04:00
/* make sure we got enough parameters */
if ( trans - > in . params . length < 4 ) {
return NT_STATUS_FOOBAR ;
}
2006-03-17 12:42:04 +03:00
st = talloc ( op , union smb_setfileinfo ) ;
NT_STATUS_HAVE_NO_MEMORY ( st ) ;
2003-08-13 05:53:07 +04:00
fnum = SVAL ( trans - > in . params . data , 0 ) ;
level = SVAL ( trans - > in . params . data , 2 ) ;
2006-03-17 12:42:04 +03:00
st - > generic . in . file . fnum = fnum ;
/* work out the backend level - we make it 1-1 in the header */
st - > generic . level = ( enum smb_setfileinfo_level ) level ;
if ( st - > generic . level > = RAW_SFILEINFO_GENERIC ) {
return NT_STATUS_INVALID_LEVEL ;
2003-08-13 05:53:07 +04:00
}
2006-03-17 12:42:04 +03:00
status = trans2_parse_sfileinfo ( req , st , & trans - > in . data ) ;
NT_STATUS_NOT_OK_RETURN ( status ) ;
2003-08-13 05:53:07 +04:00
2006-03-17 12:42:04 +03:00
op - > op_info = st ;
op - > send_fn = trans2_simple_send ;
2006-03-18 14:10:21 +03:00
return ntvfs_setfileinfo ( req - > ntvfs , st ) ;
2003-08-13 05:53:07 +04:00
}
/*
trans2 setpathinfo implementation
*/
2006-03-17 12:42:04 +03:00
static NTSTATUS trans2_setpathinfo ( struct smbsrv_request * req , struct trans_op * op )
2003-08-13 05:53:07 +04:00
{
2006-03-17 12:42:04 +03:00
struct smb_trans2 * trans = op - > trans ;
union smb_setfileinfo * st ;
2003-08-13 05:53:07 +04:00
NTSTATUS status ;
2004-05-25 21:24:24 +04:00
uint16_t level ;
2003-08-13 05:53:07 +04:00
/* make sure we got enough parameters */
if ( trans - > in . params . length < 4 ) {
return NT_STATUS_FOOBAR ;
}
2006-03-17 12:42:04 +03:00
st = talloc ( op , union smb_setfileinfo ) ;
NT_STATUS_HAVE_NO_MEMORY ( st ) ;
2003-08-13 05:53:07 +04:00
level = SVAL ( trans - > in . params . data , 0 ) ;
2006-03-17 12:42:04 +03:00
trans2_pull_blob_string ( req , & trans - > in . params , 6 , & st - > generic . in . file . path , 0 ) ;
if ( st - > generic . in . file . path = = NULL ) {
2003-08-13 05:53:07 +04:00
return NT_STATUS_FOOBAR ;
}
2006-03-17 12:42:04 +03:00
/* work out the backend level - we make it 1-1 in the header */
st - > generic . level = ( enum smb_setfileinfo_level ) level ;
if ( st - > generic . level > = RAW_SFILEINFO_GENERIC ) {
return NT_STATUS_INVALID_LEVEL ;
2003-08-13 05:53:07 +04:00
}
2006-03-17 12:42:04 +03:00
status = trans2_parse_sfileinfo ( req , st , & trans - > in . data ) ;
NT_STATUS_NOT_OK_RETURN ( status ) ;
2003-08-13 05:53:07 +04:00
2006-03-17 12:42:04 +03:00
op - > op_info = st ;
op - > send_fn = trans2_simple_send ;
2006-03-18 14:10:21 +03:00
return ntvfs_setpathinfo ( req - > ntvfs , st ) ;
2003-08-13 05:53:07 +04:00
}
/* a structure to encapsulate the state information about an in-progress ffirst/fnext operation */
struct find_state {
2006-03-17 12:42:04 +03:00
struct trans_op * op ;
void * search ;
2004-07-19 14:35:05 +04:00
enum smb_search_level level ;
2004-05-25 21:24:24 +04:00
uint16_t last_entry_offset ;
uint16_t flags ;
2003-08-13 05:53:07 +04:00
} ;
/*
fill a single entry in a trans2 find reply
*/
2006-03-17 12:42:04 +03:00
static BOOL find_fill_info ( struct find_state * state ,
2003-08-13 05:53:07 +04:00
union smb_search_data * file )
{
2006-03-17 12:42:04 +03:00
struct smbsrv_request * req = state - > op - > req ;
struct smb_trans2 * trans = state - > op - > trans ;
2004-11-25 23:01:47 +03:00
uint8_t * data ;
2003-08-13 05:53:07 +04:00
uint_t ofs = trans - > out . data . length ;
2004-12-18 07:38:43 +03:00
uint32_t ea_size ;
2003-08-13 05:53:07 +04:00
2003-08-31 07:16:52 +04:00
switch ( state - > level ) {
2003-08-13 05:53:07 +04:00
case RAW_SEARCH_SEARCH :
2004-09-21 12:46:47 +04:00
case RAW_SEARCH_FFIRST :
case RAW_SEARCH_FUNIQUE :
2003-08-13 05:53:07 +04:00
case RAW_SEARCH_GENERIC :
/* handled elsewhere */
break ;
case RAW_SEARCH_STANDARD :
2003-08-31 07:16:52 +04:00
if ( state - > flags & FLAG_TRANS2_FIND_REQUIRE_RESUME ) {
2006-03-17 12:42:04 +03:00
trans2_grow_data ( trans , ofs + 27 ) ;
2003-08-31 07:16:52 +04:00
SIVAL ( trans - > out . data . data , ofs , file - > standard . resume_key ) ;
ofs + = 4 ;
} else {
2006-03-17 12:42:04 +03:00
trans2_grow_data ( trans , ofs + 23 ) ;
2003-08-31 07:16:52 +04:00
}
2003-08-13 05:53:07 +04:00
data = trans - > out . data . data + ofs ;
2004-06-29 11:40:14 +04:00
srv_push_dos_date2 ( req - > smb_conn , data , 0 , file - > standard . create_time ) ;
srv_push_dos_date2 ( req - > smb_conn , data , 4 , file - > standard . access_time ) ;
srv_push_dos_date2 ( req - > smb_conn , data , 8 , file - > standard . write_time ) ;
2003-08-13 05:53:07 +04:00
SIVAL ( data , 12 , file - > standard . size ) ;
SIVAL ( data , 16 , file - > standard . alloc_size ) ;
SSVAL ( data , 20 , file - > standard . attrib ) ;
trans2_append_data_string ( req , trans , & file - > standard . name ,
ofs + 22 , STR_LEN8BIT | STR_TERMINATE | STR_LEN_NOTERM ) ;
break ;
case RAW_SEARCH_EA_SIZE :
2003-08-31 07:16:52 +04:00
if ( state - > flags & FLAG_TRANS2_FIND_REQUIRE_RESUME ) {
2006-03-17 12:42:04 +03:00
trans2_grow_data ( trans , ofs + 31 ) ;
2003-08-31 07:16:52 +04:00
SIVAL ( trans - > out . data . data , ofs , file - > ea_size . resume_key ) ;
ofs + = 4 ;
} else {
2006-03-17 12:42:04 +03:00
trans2_grow_data ( trans , ofs + 27 ) ;
2003-08-31 07:16:52 +04:00
}
2003-08-13 05:53:07 +04:00
data = trans - > out . data . data + ofs ;
2004-06-29 11:40:14 +04:00
srv_push_dos_date2 ( req - > smb_conn , data , 0 , file - > ea_size . create_time ) ;
srv_push_dos_date2 ( req - > smb_conn , data , 4 , file - > ea_size . access_time ) ;
srv_push_dos_date2 ( req - > smb_conn , data , 8 , file - > ea_size . write_time ) ;
2003-08-13 05:53:07 +04:00
SIVAL ( data , 12 , file - > ea_size . size ) ;
SIVAL ( data , 16 , file - > ea_size . alloc_size ) ;
SSVAL ( data , 20 , file - > ea_size . attrib ) ;
SIVAL ( data , 22 , file - > ea_size . ea_size ) ;
trans2_append_data_string ( req , trans , & file - > ea_size . name ,
2004-08-25 08:16:48 +04:00
ofs + 26 , STR_LEN8BIT | STR_NOALIGN ) ;
2006-03-17 12:42:04 +03:00
trans2_grow_data ( trans , trans - > out . data . length + 1 ) ;
2004-09-21 12:46:47 +04:00
trans - > out . data . data [ trans - > out . data . length - 1 ] = 0 ;
2003-08-13 05:53:07 +04:00
break ;
2004-12-18 07:38:43 +03:00
case RAW_SEARCH_EA_LIST :
ea_size = ea_list_size ( file - > ea_list . eas . num_eas , file - > ea_list . eas . eas ) ;
if ( state - > flags & FLAG_TRANS2_FIND_REQUIRE_RESUME ) {
2006-03-17 12:42:04 +03:00
if ( ! trans2_grow_data ( trans , ofs + 27 + ea_size ) ) {
2004-12-20 06:12:09 +03:00
return False ;
}
2004-12-18 07:38:43 +03:00
SIVAL ( trans - > out . data . data , ofs , file - > ea_list . resume_key ) ;
ofs + = 4 ;
} else {
2006-03-17 12:42:04 +03:00
if ( ! trans2_grow_data ( trans , ofs + 23 + ea_size ) ) {
2004-12-20 06:12:09 +03:00
return False ;
}
2004-12-18 07:38:43 +03:00
}
data = trans - > out . data . data + ofs ;
srv_push_dos_date2 ( req - > smb_conn , data , 0 , file - > ea_list . create_time ) ;
srv_push_dos_date2 ( req - > smb_conn , data , 4 , file - > ea_list . access_time ) ;
srv_push_dos_date2 ( req - > smb_conn , data , 8 , file - > ea_list . write_time ) ;
SIVAL ( data , 12 , file - > ea_list . size ) ;
SIVAL ( data , 16 , file - > ea_list . alloc_size ) ;
SSVAL ( data , 20 , file - > ea_list . attrib ) ;
ea_put_list ( data + 22 , file - > ea_list . eas . num_eas , file - > ea_list . eas . eas ) ;
trans2_append_data_string ( req , trans , & file - > ea_list . name ,
ofs + 22 + ea_size , STR_LEN8BIT | STR_NOALIGN ) ;
2006-03-17 12:42:04 +03:00
trans2_grow_data ( trans , trans - > out . data . length + 1 ) ;
2004-12-18 07:38:43 +03:00
trans - > out . data . data [ trans - > out . data . length - 1 ] = 0 ;
break ;
2003-08-13 05:53:07 +04:00
case RAW_SEARCH_DIRECTORY_INFO :
2006-03-17 12:42:04 +03:00
trans2_grow_data ( trans , ofs + 64 ) ;
2003-08-13 05:53:07 +04:00
data = trans - > out . data . data + ofs ;
SIVAL ( data , 4 , file - > directory_info . file_index ) ;
2004-05-25 17:57:39 +04:00
push_nttime ( data , 8 , file - > directory_info . create_time ) ;
push_nttime ( data , 16 , file - > directory_info . access_time ) ;
push_nttime ( data , 24 , file - > directory_info . write_time ) ;
push_nttime ( data , 32 , file - > directory_info . change_time ) ;
2003-08-13 05:53:07 +04:00
SBVAL ( data , 40 , file - > directory_info . size ) ;
SBVAL ( data , 48 , file - > directory_info . alloc_size ) ;
SIVAL ( data , 56 , file - > directory_info . attrib ) ;
trans2_append_data_string ( req , trans , & file - > directory_info . name ,
2003-08-16 01:11:13 +04:00
ofs + 60 , STR_TERMINATE_ASCII ) ;
2003-08-13 05:53:07 +04:00
data = trans - > out . data . data + ofs ;
SIVAL ( data , 0 , trans - > out . data . length - ofs ) ;
break ;
case RAW_SEARCH_FULL_DIRECTORY_INFO :
2006-03-17 12:42:04 +03:00
trans2_grow_data ( trans , ofs + 68 ) ;
2003-08-13 05:53:07 +04:00
data = trans - > out . data . data + ofs ;
SIVAL ( data , 4 , file - > full_directory_info . file_index ) ;
2004-05-25 17:57:39 +04:00
push_nttime ( data , 8 , file - > full_directory_info . create_time ) ;
push_nttime ( data , 16 , file - > full_directory_info . access_time ) ;
push_nttime ( data , 24 , file - > full_directory_info . write_time ) ;
push_nttime ( data , 32 , file - > full_directory_info . change_time ) ;
2003-08-13 05:53:07 +04:00
SBVAL ( data , 40 , file - > full_directory_info . size ) ;
SBVAL ( data , 48 , file - > full_directory_info . alloc_size ) ;
SIVAL ( data , 56 , file - > full_directory_info . attrib ) ;
SIVAL ( data , 64 , file - > full_directory_info . ea_size ) ;
trans2_append_data_string ( req , trans , & file - > full_directory_info . name ,
2003-08-16 01:11:13 +04:00
ofs + 60 , STR_TERMINATE_ASCII ) ;
2003-08-13 05:53:07 +04:00
data = trans - > out . data . data + ofs ;
SIVAL ( data , 0 , trans - > out . data . length - ofs ) ;
break ;
case RAW_SEARCH_NAME_INFO :
2006-03-17 12:42:04 +03:00
trans2_grow_data ( trans , ofs + 12 ) ;
2003-08-13 05:53:07 +04:00
data = trans - > out . data . data + ofs ;
SIVAL ( data , 4 , file - > name_info . file_index ) ;
trans2_append_data_string ( req , trans , & file - > name_info . name ,
2003-08-16 01:11:13 +04:00
ofs + 8 , STR_TERMINATE_ASCII ) ;
2003-08-13 05:53:07 +04:00
data = trans - > out . data . data + ofs ;
SIVAL ( data , 0 , trans - > out . data . length - ofs ) ;
break ;
case RAW_SEARCH_BOTH_DIRECTORY_INFO :
2006-03-17 12:42:04 +03:00
trans2_grow_data ( trans , ofs + 94 ) ;
2003-08-13 05:53:07 +04:00
data = trans - > out . data . data + ofs ;
SIVAL ( data , 4 , file - > both_directory_info . file_index ) ;
2004-05-25 17:57:39 +04:00
push_nttime ( data , 8 , file - > both_directory_info . create_time ) ;
push_nttime ( data , 16 , file - > both_directory_info . access_time ) ;
push_nttime ( data , 24 , file - > both_directory_info . write_time ) ;
push_nttime ( data , 32 , file - > both_directory_info . change_time ) ;
2003-08-13 05:53:07 +04:00
SBVAL ( data , 40 , file - > both_directory_info . size ) ;
SBVAL ( data , 48 , file - > both_directory_info . alloc_size ) ;
SIVAL ( data , 56 , file - > both_directory_info . attrib ) ;
SIVAL ( data , 64 , file - > both_directory_info . ea_size ) ;
SCVAL ( data , 69 , 0 ) ; /* reserved */
memset ( data + 70 , 0 , 24 ) ;
trans2_push_data_string ( req , trans ,
68 + ofs , 70 + ofs ,
& file - > both_directory_info . short_name ,
24 , STR_UNICODE | STR_LEN8BIT ) ;
trans2_append_data_string ( req , trans , & file - > both_directory_info . name ,
2003-08-16 01:11:13 +04:00
ofs + 60 , STR_TERMINATE_ASCII ) ;
2004-10-02 16:16:46 +04:00
trans2_align_data ( req , trans ) ;
2003-08-13 05:53:07 +04:00
data = trans - > out . data . data + ofs ;
SIVAL ( data , 0 , trans - > out . data . length - ofs ) ;
break ;
2003-09-02 08:37:33 +04:00
case RAW_SEARCH_ID_FULL_DIRECTORY_INFO :
2006-03-17 12:42:04 +03:00
trans2_grow_data ( trans , ofs + 80 ) ;
2003-08-13 05:53:07 +04:00
data = trans - > out . data . data + ofs ;
2003-09-02 08:37:33 +04:00
SIVAL ( data , 4 , file - > id_full_directory_info . file_index ) ;
2004-05-25 17:57:39 +04:00
push_nttime ( data , 8 , file - > id_full_directory_info . create_time ) ;
push_nttime ( data , 16 , file - > id_full_directory_info . access_time ) ;
push_nttime ( data , 24 , file - > id_full_directory_info . write_time ) ;
push_nttime ( data , 32 , file - > id_full_directory_info . change_time ) ;
2003-09-02 08:37:33 +04:00
SBVAL ( data , 40 , file - > id_full_directory_info . size ) ;
SBVAL ( data , 48 , file - > id_full_directory_info . alloc_size ) ;
SIVAL ( data , 56 , file - > id_full_directory_info . attrib ) ;
SIVAL ( data , 64 , file - > id_full_directory_info . ea_size ) ;
SIVAL ( data , 68 , 0 ) ; /* padding */
SBVAL ( data , 72 , file - > id_full_directory_info . file_id ) ;
trans2_append_data_string ( req , trans , & file - > id_full_directory_info . name ,
2003-08-16 01:11:13 +04:00
ofs + 60 , STR_TERMINATE_ASCII ) ;
2003-08-13 05:53:07 +04:00
data = trans - > out . data . data + ofs ;
SIVAL ( data , 0 , trans - > out . data . length - ofs ) ;
break ;
2003-09-02 08:37:33 +04:00
case RAW_SEARCH_ID_BOTH_DIRECTORY_INFO :
2006-03-17 12:42:04 +03:00
trans2_grow_data ( trans , ofs + 104 ) ;
2003-08-13 05:53:07 +04:00
data = trans - > out . data . data + ofs ;
2003-09-02 08:37:33 +04:00
SIVAL ( data , 4 , file - > id_both_directory_info . file_index ) ;
2004-05-25 17:57:39 +04:00
push_nttime ( data , 8 , file - > id_both_directory_info . create_time ) ;
push_nttime ( data , 16 , file - > id_both_directory_info . access_time ) ;
push_nttime ( data , 24 , file - > id_both_directory_info . write_time ) ;
push_nttime ( data , 32 , file - > id_both_directory_info . change_time ) ;
2003-09-02 08:37:33 +04:00
SBVAL ( data , 40 , file - > id_both_directory_info . size ) ;
SBVAL ( data , 48 , file - > id_both_directory_info . alloc_size ) ;
SIVAL ( data , 56 , file - > id_both_directory_info . attrib ) ;
SIVAL ( data , 64 , file - > id_both_directory_info . ea_size ) ;
2003-08-13 05:53:07 +04:00
SCVAL ( data , 69 , 0 ) ; /* reserved */
2004-08-25 08:16:48 +04:00
memset ( data + 70 , 0 , 26 ) ;
2003-08-13 05:53:07 +04:00
trans2_push_data_string ( req , trans ,
68 + ofs , 70 + ofs ,
2003-09-02 08:37:33 +04:00
& file - > id_both_directory_info . short_name ,
2003-08-13 05:53:07 +04:00
24 , STR_UNICODE | STR_LEN8BIT ) ;
2004-08-25 08:16:48 +04:00
SBVAL ( data , 96 , file - > id_both_directory_info . file_id ) ;
2003-09-02 08:37:33 +04:00
trans2_append_data_string ( req , trans , & file - > id_both_directory_info . name ,
2003-08-16 01:11:13 +04:00
ofs + 60 , STR_TERMINATE_ASCII ) ;
2003-08-13 05:53:07 +04:00
data = trans - > out . data . data + ofs ;
SIVAL ( data , 0 , trans - > out . data . length - ofs ) ;
break ;
}
2004-12-20 06:12:09 +03:00
return True ;
2003-08-13 05:53:07 +04:00
}
/* callback function for trans2 findfirst/findnext */
static BOOL find_callback ( void * private , union smb_search_data * file )
{
2006-03-17 12:42:04 +03:00
struct find_state * state = talloc_get_type ( private , struct find_state ) ;
struct smb_trans2 * trans = state - > op - > trans ;
2003-08-13 05:53:07 +04:00
uint_t old_length ;
old_length = trans - > out . data . length ;
2006-03-17 12:42:04 +03:00
if ( ! find_fill_info ( state , file ) | |
2004-12-20 06:12:09 +03:00
trans - > out . data . length > trans - > in . max_data ) {
2003-08-13 05:53:07 +04:00
/* restore the old length and tell the backend to stop */
2006-03-17 12:42:04 +03:00
trans2_grow_data ( trans , old_length ) ;
2003-08-13 05:53:07 +04:00
return False ;
}
state - > last_entry_offset = old_length ;
return True ;
}
2006-03-17 12:42:04 +03:00
/*
trans2 findfirst send
*/
static NTSTATUS trans2_findfirst_send ( struct trans_op * op )
{
struct smbsrv_request * req = op - > req ;
struct smb_trans2 * trans = op - > trans ;
union smb_search_first * search ;
struct find_state * state ;
uint8_t * param ;
2006-03-18 14:10:21 +03:00
TRANS2_CHECK_ASYNC_STATUS ( state , struct find_state ) ;
2006-03-17 12:42:04 +03:00
search = talloc_get_type ( state - > search , union smb_search_first ) ;
/* fill in the findfirst reply header */
param = trans - > out . params . data ;
SSVAL ( param , VWV ( 0 ) , search - > t2ffirst . out . handle ) ;
SSVAL ( param , VWV ( 1 ) , search - > t2ffirst . out . count ) ;
SSVAL ( param , VWV ( 2 ) , search - > t2ffirst . out . end_of_search ) ;
SSVAL ( param , VWV ( 3 ) , 0 ) ;
SSVAL ( param , VWV ( 4 ) , state - > last_entry_offset ) ;
return NT_STATUS_OK ;
}
2003-08-13 05:53:07 +04:00
/*
trans2 findfirst implementation
*/
2006-03-17 12:42:04 +03:00
static NTSTATUS trans2_findfirst ( struct smbsrv_request * req , struct trans_op * op )
2003-08-13 05:53:07 +04:00
{
2006-03-17 12:42:04 +03:00
struct smb_trans2 * trans = op - > trans ;
union smb_search_first * search ;
2003-08-13 05:53:07 +04:00
NTSTATUS status ;
2004-05-25 21:24:24 +04:00
uint16_t level ;
2006-03-17 12:42:04 +03:00
struct find_state * state ;
2003-08-13 05:53:07 +04:00
/* make sure we got all the parameters */
if ( trans - > in . params . length < 14 ) {
return NT_STATUS_FOOBAR ;
}
2006-03-17 12:42:04 +03:00
search = talloc ( op , union smb_search_first ) ;
NT_STATUS_HAVE_NO_MEMORY ( search ) ;
2003-08-13 05:53:07 +04:00
2006-03-17 12:42:04 +03:00
search - > t2ffirst . in . search_attrib = SVAL ( trans - > in . params . data , 0 ) ;
search - > t2ffirst . in . max_count = SVAL ( trans - > in . params . data , 2 ) ;
search - > t2ffirst . in . flags = SVAL ( trans - > in . params . data , 4 ) ;
level = SVAL ( trans - > in . params . data , 6 ) ;
search - > t2ffirst . in . storage_type = IVAL ( trans - > in . params . data , 8 ) ;
trans2_pull_blob_string ( req , & trans - > in . params , 12 , & search - > t2ffirst . in . pattern , 0 ) ;
if ( search - > t2ffirst . in . pattern = = NULL ) {
2003-08-13 05:53:07 +04:00
return NT_STATUS_FOOBAR ;
}
2006-03-17 12:42:04 +03:00
search - > t2ffirst . level = ( enum smb_search_level ) level ;
if ( search - > t2ffirst . level > = RAW_SEARCH_GENERIC ) {
2003-08-13 05:53:07 +04:00
return NT_STATUS_INVALID_LEVEL ;
}
2006-03-17 12:42:04 +03:00
if ( search - > t2ffirst . level = = RAW_SEARCH_EA_LIST ) {
2004-12-18 07:38:43 +03:00
status = ea_pull_name_list ( & trans - > in . data , req ,
2006-03-17 12:42:04 +03:00
& search - > t2ffirst . in . num_names ,
& search - > t2ffirst . in . ea_names ) ;
NT_STATUS_NOT_OK_RETURN ( status ) ;
2004-12-18 07:38:43 +03:00
}
2004-12-29 02:28:02 +03:00
/* setup the private state structure that the backend will
give us in the callback */
2006-03-17 12:42:04 +03:00
state = talloc ( op , struct find_state ) ;
NT_STATUS_HAVE_NO_MEMORY ( state ) ;
state - > op = op ;
state - > search = search ;
state - > level = search - > t2ffirst . level ;
state - > last_entry_offset = 0 ;
state - > flags = search - > t2ffirst . in . flags ;
2003-08-13 05:53:07 +04:00
/* setup for just a header in the reply */
2006-03-17 12:42:04 +03:00
trans2_setup_reply ( trans , 10 , 0 , 0 ) ;
2003-08-13 05:53:07 +04:00
2006-03-17 12:42:04 +03:00
op - > op_info = state ;
op - > send_fn = trans2_findfirst_send ;
2006-03-18 14:10:21 +03:00
return ntvfs_search_first ( req - > ntvfs , search , state , find_callback ) ;
2006-03-17 12:42:04 +03:00
}
/*
trans2 findnext send
*/
static NTSTATUS trans2_findnext_send ( struct trans_op * op )
{
struct smbsrv_request * req = op - > req ;
struct smb_trans2 * trans = op - > trans ;
union smb_search_next * search ;
struct find_state * state ;
uint8_t * param ;
2006-03-18 14:10:21 +03:00
TRANS2_CHECK_ASYNC_STATUS ( state , struct find_state ) ;
2006-03-17 12:42:04 +03:00
search = talloc_get_type ( state - > search , union smb_search_next ) ;
2003-08-13 05:53:07 +04:00
/* fill in the findfirst reply header */
param = trans - > out . params . data ;
2006-03-17 12:42:04 +03:00
SSVAL ( param , VWV ( 0 ) , search - > t2fnext . out . count ) ;
SSVAL ( param , VWV ( 1 ) , search - > t2fnext . out . end_of_search ) ;
SSVAL ( param , VWV ( 2 ) , 0 ) ;
SSVAL ( param , VWV ( 3 ) , state - > last_entry_offset ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
}
/*
trans2 findnext implementation
*/
2006-03-17 12:42:04 +03:00
static NTSTATUS trans2_findnext ( struct smbsrv_request * req , struct trans_op * op )
2003-08-13 05:53:07 +04:00
{
2006-03-17 12:42:04 +03:00
struct smb_trans2 * trans = op - > trans ;
union smb_search_next * search ;
2003-08-13 05:53:07 +04:00
NTSTATUS status ;
2004-05-25 21:24:24 +04:00
uint16_t level ;
2006-03-17 12:42:04 +03:00
struct find_state * state ;
2003-08-13 05:53:07 +04:00
/* make sure we got all the parameters */
if ( trans - > in . params . length < 12 ) {
return NT_STATUS_FOOBAR ;
}
2006-03-17 12:42:04 +03:00
search = talloc ( op , union smb_search_next ) ;
NT_STATUS_HAVE_NO_MEMORY ( search ) ;
search - > t2fnext . in . handle = SVAL ( trans - > in . params . data , 0 ) ;
search - > t2fnext . in . max_count = SVAL ( trans - > in . params . data , 2 ) ;
level = SVAL ( trans - > in . params . data , 4 ) ;
search - > t2fnext . in . resume_key = IVAL ( trans - > in . params . data , 6 ) ;
search - > t2fnext . in . flags = SVAL ( trans - > in . params . data , 10 ) ;
2003-08-13 05:53:07 +04:00
2006-03-17 12:42:04 +03:00
trans2_pull_blob_string ( req , & trans - > in . params , 12 , & search - > t2fnext . in . last_name , 0 ) ;
if ( search - > t2fnext . in . last_name = = NULL ) {
2003-08-13 05:53:07 +04:00
return NT_STATUS_FOOBAR ;
}
2006-03-17 12:42:04 +03:00
search - > t2fnext . level = ( enum smb_search_level ) level ;
if ( search - > t2fnext . level > = RAW_SEARCH_GENERIC ) {
2003-08-13 05:53:07 +04:00
return NT_STATUS_INVALID_LEVEL ;
}
2006-03-17 12:42:04 +03:00
if ( search - > t2fnext . level = = RAW_SEARCH_EA_LIST ) {
2004-12-18 07:38:43 +03:00
status = ea_pull_name_list ( & trans - > in . data , req ,
2006-03-17 12:42:04 +03:00
& search - > t2fnext . in . num_names ,
& search - > t2fnext . in . ea_names ) ;
NT_STATUS_NOT_OK_RETURN ( status ) ;
2004-12-18 07:38:43 +03:00
}
2003-08-13 05:53:07 +04:00
/* setup the private state structure that the backend will give us in the callback */
2006-03-17 12:42:04 +03:00
state = talloc ( op , struct find_state ) ;
NT_STATUS_HAVE_NO_MEMORY ( state ) ;
state - > op = op ;
state - > search = search ;
state - > level = search - > t2fnext . level ;
state - > last_entry_offset = 0 ;
state - > flags = search - > t2fnext . in . flags ;
2003-08-13 05:53:07 +04:00
/* setup for just a header in the reply */
2006-03-17 12:42:04 +03:00
trans2_setup_reply ( trans , 8 , 0 , 0 ) ;
2003-08-13 05:53:07 +04:00
2006-03-17 12:42:04 +03:00
op - > op_info = state ;
op - > send_fn = trans2_findnext_send ;
2003-08-13 05:53:07 +04:00
2006-03-18 14:10:21 +03:00
return ntvfs_search_next ( req - > ntvfs , search , state , find_callback ) ;
2003-08-13 05:53:07 +04:00
}
/*
backend for trans2 requests
*/
2006-03-17 12:42:04 +03:00
static NTSTATUS trans2_backend ( struct smbsrv_request * req , struct trans_op * op )
2003-08-13 05:53:07 +04:00
{
2006-03-17 12:42:04 +03:00
struct smb_trans2 * trans = op - > trans ;
2004-09-29 17:17:09 +04:00
NTSTATUS status ;
/* direct trans2 pass thru */
2006-03-18 14:10:21 +03:00
status = ntvfs_trans2 ( req - > ntvfs , trans ) ;
2004-09-29 17:17:09 +04:00
if ( ! NT_STATUS_EQUAL ( NT_STATUS_NOT_IMPLEMENTED , status ) ) {
return status ;
2003-08-13 05:53:07 +04:00
}
/* must have at least one setup word */
if ( trans - > in . setup_count < 1 ) {
return NT_STATUS_FOOBAR ;
}
/* the trans2 command is in setup[0] */
switch ( trans - > in . setup [ 0 ] ) {
case TRANSACT2_FINDFIRST :
2006-03-17 12:42:04 +03:00
return trans2_findfirst ( req , op ) ;
2003-08-13 05:53:07 +04:00
case TRANSACT2_FINDNEXT :
2006-03-17 12:42:04 +03:00
return trans2_findnext ( req , op ) ;
2003-08-13 05:53:07 +04:00
case TRANSACT2_QPATHINFO :
2006-03-17 12:42:04 +03:00
return trans2_qpathinfo ( req , op ) ;
2003-08-13 05:53:07 +04:00
case TRANSACT2_QFILEINFO :
2006-03-17 12:42:04 +03:00
return trans2_qfileinfo ( req , op ) ;
2003-08-13 05:53:07 +04:00
case TRANSACT2_SETFILEINFO :
2006-03-17 12:42:04 +03:00
return trans2_setfileinfo ( req , op ) ;
2003-08-13 05:53:07 +04:00
case TRANSACT2_SETPATHINFO :
2006-03-17 12:42:04 +03:00
return trans2_setpathinfo ( req , op ) ;
2003-08-13 05:53:07 +04:00
case TRANSACT2_QFSINFO :
2006-03-17 12:42:04 +03:00
return trans2_qfsinfo ( req , op ) ;
2004-11-06 10:58:45 +03:00
case TRANSACT2_OPEN :
2006-03-17 12:42:04 +03:00
return trans2_open ( req , op ) ;
2004-12-14 02:57:59 +03:00
case TRANSACT2_MKDIR :
2006-03-17 12:42:04 +03:00
return trans2_mkdir ( req , op ) ;
2003-08-13 05:53:07 +04:00
}
/* an unknown trans2 command */
return NT_STATUS_FOOBAR ;
}
2004-12-16 15:31:34 +03:00
/*
send a continue request
*/
2006-03-17 12:42:04 +03:00
static void reply_trans_continue ( struct smbsrv_request * req , uint8_t command ,
2004-12-16 15:31:34 +03:00
struct smb_trans2 * trans )
2003-08-13 05:53:07 +04:00
{
2004-12-16 15:31:34 +03:00
struct smbsrv_trans_partial * tp ;
int count ;
2003-08-13 05:53:07 +04:00
2004-12-16 15:31:34 +03:00
/* make sure they don't flood us */
for ( count = 0 , tp = req - > smb_conn - > trans_partial ; tp ; tp = tp - > next ) count + + ;
if ( count > 100 ) {
2006-03-06 19:19:27 +03:00
smbsrv_send_error ( req , NT_STATUS_INSUFFICIENT_RESOURCES ) ;
2003-08-13 05:53:07 +04:00
return ;
}
2005-01-27 10:08:20 +03:00
tp = talloc ( req , struct smbsrv_trans_partial ) ;
2003-08-13 05:53:07 +04:00
2004-12-16 15:31:34 +03:00
tp - > req = talloc_reference ( tp , req ) ;
tp - > trans = trans ;
tp - > command = command ;
2003-08-13 05:53:07 +04:00
2004-12-16 15:31:34 +03:00
DLIST_ADD ( req - > smb_conn - > trans_partial , tp ) ;
2003-12-11 12:07:45 +03:00
2004-12-16 15:31:34 +03:00
/* send a 'please continue' reply */
2006-03-06 19:19:27 +03:00
smbsrv_setup_reply ( req , 0 , 0 ) ;
smbsrv_send_reply ( req ) ;
2004-12-16 15:31:34 +03:00
}
2003-08-13 05:53:07 +04:00
2004-12-16 15:31:34 +03:00
/*
answer a reconstructed trans request
*/
2006-03-18 14:10:21 +03:00
static void reply_trans_send ( struct ntvfs_request * ntvfs )
2004-12-16 15:31:34 +03:00
{
2006-03-18 14:10:21 +03:00
struct smbsrv_request * req ;
2006-03-17 12:42:04 +03:00
struct trans_op * op ;
struct smb_trans2 * trans ;
2004-12-16 15:31:34 +03:00
uint16_t params_left , data_left ;
uint8_t * params , * data ;
int i ;
2003-08-13 05:53:07 +04:00
2006-03-18 14:10:21 +03:00
SMBSRV_CHECK_ASYNC_STATUS_ERR ( op , struct trans_op ) ;
2006-03-17 12:42:04 +03:00
trans = op - > trans ;
/* if this function needs work to form the nttrans reply buffer, then
call that now */
if ( op - > send_fn ! = NULL ) {
NTSTATUS status ;
status = op - > send_fn ( op ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
smbsrv_send_error ( req , status ) ;
return ;
}
2003-08-13 05:53:07 +04:00
}
2004-12-16 15:31:34 +03:00
params_left = trans - > out . params . length ;
data_left = trans - > out . data . length ;
params = trans - > out . params . data ;
data = trans - > out . data . data ;
2004-10-29 07:48:49 +04:00
2006-03-06 19:19:27 +03:00
smbsrv_setup_reply ( req , 10 + trans - > out . setup_count , 0 ) ;
2004-10-29 07:48:49 +04:00
2006-03-18 14:10:21 +03:00
if ( ! NT_STATUS_IS_OK ( req - > ntvfs - > async_states - > status ) ) {
smbsrv_setup_error ( req , req - > ntvfs - > async_states - > status ) ;
2004-10-29 07:48:49 +04:00
}
2003-08-13 05:53:07 +04:00
/* we need to divide up the reply into chunks that fit into
the negotiated buffer size */
do {
2004-05-25 21:24:24 +04:00
uint16_t this_data , this_param , max_bytes ;
2003-08-13 05:53:07 +04:00
uint_t align1 = 1 , align2 = ( params_left ? 2 : 0 ) ;
2004-10-29 07:48:49 +04:00
struct smbsrv_request * this_req ;
2003-08-13 05:53:07 +04:00
max_bytes = req_max_data ( req ) - ( align1 + align2 ) ;
this_param = params_left ;
if ( this_param > max_bytes ) {
this_param = max_bytes ;
}
max_bytes - = this_param ;
this_data = data_left ;
if ( this_data > max_bytes ) {
this_data = max_bytes ;
}
2004-10-29 07:48:49 +04:00
/* don't destroy unless this is the last chunk */
if ( params_left - this_param ! = 0 | |
data_left - this_data ! = 0 ) {
2006-03-06 19:19:27 +03:00
this_req = smbsrv_setup_secondary_request ( req ) ;
2004-10-29 07:48:49 +04:00
} else {
this_req = req ;
}
req_grow_data ( this_req , this_param + this_data + ( align1 + align2 ) ) ;
2003-08-13 05:53:07 +04:00
2004-12-16 15:31:34 +03:00
SSVAL ( this_req - > out . vwv , VWV ( 0 ) , trans - > out . params . length ) ;
SSVAL ( this_req - > out . vwv , VWV ( 1 ) , trans - > out . data . length ) ;
2004-10-29 07:48:49 +04:00
SSVAL ( this_req - > out . vwv , VWV ( 2 ) , 0 ) ;
2003-08-13 05:53:07 +04:00
2004-10-29 07:48:49 +04:00
SSVAL ( this_req - > out . vwv , VWV ( 3 ) , this_param ) ;
SSVAL ( this_req - > out . vwv , VWV ( 4 ) , align1 + PTR_DIFF ( this_req - > out . data , this_req - > out . hdr ) ) ;
2004-12-16 15:31:34 +03:00
SSVAL ( this_req - > out . vwv , VWV ( 5 ) , PTR_DIFF ( params , trans - > out . params . data ) ) ;
2003-08-13 05:53:07 +04:00
2004-10-29 07:48:49 +04:00
SSVAL ( this_req - > out . vwv , VWV ( 6 ) , this_data ) ;
SSVAL ( this_req - > out . vwv , VWV ( 7 ) , align1 + align2 +
PTR_DIFF ( this_req - > out . data + this_param , this_req - > out . hdr ) ) ;
2004-12-16 15:31:34 +03:00
SSVAL ( this_req - > out . vwv , VWV ( 8 ) , PTR_DIFF ( data , trans - > out . data . data ) ) ;
2003-08-13 05:53:07 +04:00
2004-12-16 15:31:34 +03:00
SSVAL ( this_req - > out . vwv , VWV ( 9 ) , trans - > out . setup_count ) ;
for ( i = 0 ; i < trans - > out . setup_count ; i + + ) {
SSVAL ( this_req - > out . vwv , VWV ( 10 + i ) , trans - > out . setup [ i ] ) ;
2003-08-13 05:53:07 +04:00
}
2004-10-29 07:48:49 +04:00
memset ( this_req - > out . data , 0 , align1 ) ;
2003-08-13 05:53:07 +04:00
if ( this_param ! = 0 ) {
2004-10-29 07:48:49 +04:00
memcpy ( this_req - > out . data + align1 , params , this_param ) ;
2003-08-13 05:53:07 +04:00
}
2004-10-29 07:48:49 +04:00
memset ( this_req - > out . data + this_param + align1 , 0 , align2 ) ;
2003-08-13 05:53:07 +04:00
if ( this_data ! = 0 ) {
2004-10-29 07:48:49 +04:00
memcpy ( this_req - > out . data + this_param + align1 + align2 , data , this_data ) ;
2003-08-13 05:53:07 +04:00
}
params_left - = this_param ;
data_left - = this_data ;
params + = this_param ;
data + = this_data ;
2006-03-06 19:19:27 +03:00
smbsrv_send_reply ( this_req ) ;
2003-08-13 05:53:07 +04:00
} while ( params_left ! = 0 | | data_left ! = 0 ) ;
}
2003-12-11 12:07:45 +03:00
2006-03-17 12:42:04 +03:00
/*
answer a reconstructed trans request
*/
static void reply_trans_complete ( struct smbsrv_request * req , uint8_t command ,
struct smb_trans2 * trans )
{
struct trans_op * op ;
2006-03-18 14:10:21 +03:00
SMBSRV_TALLOC_IO_PTR ( op , struct trans_op ) ;
SMBSRV_SETUP_NTVFS_REQUEST ( reply_trans_send , NTVFS_ASYNC_STATE_MAY_ASYNC ) ;
2006-03-17 12:42:04 +03:00
op - > req = req ;
op - > trans = trans ;
op - > command = command ;
op - > op_info = NULL ;
op - > send_fn = NULL ;
/* its a full request, give it to the backend */
if ( command = = SMBtrans ) {
2006-03-18 14:10:21 +03:00
SMBSRV_CALL_NTVFS_BACKEND ( ntvfs_trans ( req - > ntvfs , trans ) ) ;
return ;
2006-03-17 12:42:04 +03:00
} else {
2006-03-18 14:10:21 +03:00
SMBSRV_CALL_NTVFS_BACKEND ( trans2_backend ( req , op ) ) ;
return ;
2006-03-17 12:42:04 +03:00
}
}
2004-12-16 15:31:34 +03:00
/*
Reply to an SMBtrans or SMBtrans2 request
*/
2006-03-06 18:04:59 +03:00
static void reply_trans_generic ( struct smbsrv_request * req , uint8_t command )
2004-12-16 15:31:34 +03:00
{
struct smb_trans2 * trans ;
int i ;
uint16_t param_ofs , data_ofs ;
uint16_t param_count , data_count ;
uint16_t param_total , data_total ;
/* parse request */
if ( req - > in . wct < 14 ) {
2006-03-06 19:19:27 +03:00
smbsrv_send_error ( req , NT_STATUS_INVALID_PARAMETER ) ;
2004-12-16 15:31:34 +03:00
return ;
}
2006-03-17 12:42:04 +03:00
trans = talloc ( req , struct smb_trans2 ) ;
if ( trans = = NULL ) {
smbsrv_send_error ( req , NT_STATUS_NO_MEMORY ) ;
return ;
}
2004-12-16 15:31:34 +03:00
param_total = SVAL ( req - > in . vwv , VWV ( 0 ) ) ;
data_total = SVAL ( req - > in . vwv , VWV ( 1 ) ) ;
trans - > in . max_param = SVAL ( req - > in . vwv , VWV ( 2 ) ) ;
trans - > in . max_data = SVAL ( req - > in . vwv , VWV ( 3 ) ) ;
trans - > in . max_setup = CVAL ( req - > in . vwv , VWV ( 4 ) ) ;
trans - > in . flags = SVAL ( req - > in . vwv , VWV ( 5 ) ) ;
trans - > in . timeout = IVAL ( req - > in . vwv , VWV ( 6 ) ) ;
param_count = SVAL ( req - > in . vwv , VWV ( 9 ) ) ;
param_ofs = SVAL ( req - > in . vwv , VWV ( 10 ) ) ;
data_count = SVAL ( req - > in . vwv , VWV ( 11 ) ) ;
data_ofs = SVAL ( req - > in . vwv , VWV ( 12 ) ) ;
trans - > in . setup_count = CVAL ( req - > in . vwv , VWV ( 13 ) ) ;
if ( req - > in . wct ! = 14 + trans - > in . setup_count ) {
2006-03-06 21:29:48 +03:00
smbsrv_send_error ( req , NT_STATUS_DOS ( ERRSRV , ERRerror ) ) ;
2004-12-16 15:31:34 +03:00
return ;
}
/* parse out the setup words */
2006-03-17 12:42:04 +03:00
trans - > in . setup = talloc_array ( trans , uint16_t , trans - > in . setup_count ) ;
2004-12-16 15:31:34 +03:00
if ( trans - > in . setup_count & & ! trans - > in . setup ) {
2006-03-06 19:19:27 +03:00
smbsrv_send_error ( req , NT_STATUS_NO_MEMORY ) ;
2004-12-16 15:31:34 +03:00
return ;
}
for ( i = 0 ; i < trans - > in . setup_count ; i + + ) {
trans - > in . setup [ i ] = SVAL ( req - > in . vwv , VWV ( 14 + i ) ) ;
}
if ( command = = SMBtrans ) {
req_pull_string ( req , & trans - > in . trans_name , req - > in . data , - 1 , STR_TERMINATE ) ;
}
if ( ! req_pull_blob ( req , req - > in . hdr + param_ofs , param_count , & trans - > in . params ) | |
! req_pull_blob ( req , req - > in . hdr + data_ofs , data_count , & trans - > in . data ) ) {
2006-03-06 19:19:27 +03:00
smbsrv_send_error ( req , NT_STATUS_FOOBAR ) ;
2004-12-16 15:31:34 +03:00
return ;
}
/* is it a partial request? if so, then send a 'send more' message */
if ( param_total > param_count | | data_total > data_count ) {
reply_trans_continue ( req , command , trans ) ;
return ;
}
reply_trans_complete ( req , command , trans ) ;
}
/*
Reply to an SMBtranss2 request
*/
static void reply_transs_generic ( struct smbsrv_request * req , uint8_t command )
{
struct smbsrv_trans_partial * tp ;
struct smb_trans2 * trans = NULL ;
uint16_t param_ofs , data_ofs ;
uint16_t param_count , data_count ;
uint16_t param_disp , data_disp ;
uint16_t param_total , data_total ;
DATA_BLOB params , data ;
2006-03-17 12:42:04 +03:00
/* parse request */
if ( req - > in . wct < 8 ) {
smbsrv_send_error ( req , NT_STATUS_INVALID_PARAMETER ) ;
return ;
}
2004-12-16 15:31:34 +03:00
for ( tp = req - > smb_conn - > trans_partial ; tp ; tp = tp - > next ) {
if ( tp - > command = = command & &
SVAL ( tp - > req - > in . hdr , HDR_MID ) = = SVAL ( req - > in . hdr , HDR_MID ) ) {
2006-03-17 12:42:04 +03:00
/* TODO: check the VUID, PID and TID too? */
2004-12-16 15:31:34 +03:00
break ;
}
}
if ( tp = = NULL ) {
2006-03-06 19:19:27 +03:00
smbsrv_send_error ( req , NT_STATUS_INVALID_PARAMETER ) ;
2004-12-16 15:31:34 +03:00
return ;
}
trans = tp - > trans ;
param_total = SVAL ( req - > in . vwv , VWV ( 0 ) ) ;
data_total = SVAL ( req - > in . vwv , VWV ( 1 ) ) ;
param_count = SVAL ( req - > in . vwv , VWV ( 2 ) ) ;
param_ofs = SVAL ( req - > in . vwv , VWV ( 3 ) ) ;
param_disp = SVAL ( req - > in . vwv , VWV ( 4 ) ) ;
data_count = SVAL ( req - > in . vwv , VWV ( 5 ) ) ;
data_ofs = SVAL ( req - > in . vwv , VWV ( 6 ) ) ;
data_disp = SVAL ( req - > in . vwv , VWV ( 7 ) ) ;
if ( ! req_pull_blob ( req , req - > in . hdr + param_ofs , param_count , & params ) | |
! req_pull_blob ( req , req - > in . hdr + data_ofs , data_count , & data ) ) {
2006-03-06 19:19:27 +03:00
smbsrv_send_error ( req , NT_STATUS_INVALID_PARAMETER ) ;
2004-12-16 15:31:34 +03:00
return ;
}
/* only allow contiguous requests */
if ( ( param_count ! = 0 & &
param_disp ! = trans - > in . params . length ) | |
( data_count ! = 0 & &
data_disp ! = trans - > in . data . length ) ) {
2006-03-06 19:19:27 +03:00
smbsrv_send_error ( req , NT_STATUS_INVALID_PARAMETER ) ;
2004-12-16 15:31:34 +03:00
return ;
}
/* add to the existing request */
if ( param_count ! = 0 ) {
2005-01-27 10:08:20 +03:00
trans - > in . params . data = talloc_realloc ( trans ,
2004-12-16 15:31:34 +03:00
trans - > in . params . data ,
uint8_t ,
param_disp + param_count ) ;
if ( trans - > in . params . data = = NULL ) {
goto failed ;
}
trans - > in . params . length = param_disp + param_count ;
}
if ( data_count ! = 0 ) {
2005-01-27 10:08:20 +03:00
trans - > in . data . data = talloc_realloc ( trans ,
2004-12-16 15:31:34 +03:00
trans - > in . data . data ,
uint8_t ,
data_disp + data_count ) ;
if ( trans - > in . data . data = = NULL ) {
goto failed ;
}
trans - > in . data . length = data_disp + data_count ;
}
memcpy ( trans - > in . params . data + param_disp , params . data , params . length ) ;
memcpy ( trans - > in . data . data + data_disp , data . data , data . length ) ;
/* the sequence number of the reply is taken from the last secondary
response */
tp - > req - > seq_num = req - > seq_num ;
/* we don't reply to Transs2 requests */
talloc_free ( req ) ;
if ( trans - > in . params . length = = param_total & &
trans - > in . data . length = = data_total ) {
/* its now complete */
DLIST_REMOVE ( tp - > req - > smb_conn - > trans_partial , tp ) ;
2005-12-06 03:12:32 +03:00
reply_trans_complete ( tp - > req , command , trans ) ;
2004-12-16 15:31:34 +03:00
}
return ;
failed :
2006-03-06 19:19:27 +03:00
smbsrv_send_error ( tp - > req , NT_STATUS_NO_MEMORY ) ;
2004-12-16 15:31:34 +03:00
DLIST_REMOVE ( req - > smb_conn - > trans_partial , tp ) ;
talloc_free ( req ) ;
talloc_free ( tp ) ;
}
/*
Reply to an SMBtrans2
*/
2006-03-06 18:31:01 +03:00
void smbsrv_reply_trans2 ( struct smbsrv_request * req )
2003-12-11 12:07:45 +03:00
{
reply_trans_generic ( req , SMBtrans2 ) ;
}
2004-12-16 15:31:34 +03:00
/*
Reply to an SMBtrans
*/
2006-03-06 18:31:01 +03:00
void smbsrv_reply_trans ( struct smbsrv_request * req )
2003-12-11 12:07:45 +03:00
{
reply_trans_generic ( req , SMBtrans ) ;
}
2004-12-16 15:31:34 +03:00
/*
Reply to an SMBtranss request
*/
2006-03-06 18:31:01 +03:00
void smbsrv_reply_transs ( struct smbsrv_request * req )
2003-12-11 12:07:45 +03:00
{
2004-12-16 15:31:34 +03:00
reply_transs_generic ( req , SMBtrans ) ;
2003-12-11 12:07:45 +03:00
}
2004-12-16 15:31:34 +03:00
/*
Reply to an SMBtranss2 request
*/
2006-03-06 18:31:01 +03:00
void smbsrv_reply_transs2 ( struct smbsrv_request * req )
2004-12-16 15:31:34 +03:00
{
reply_transs_generic ( req , SMBtrans2 ) ;
}