2005-11-18 14:13:49 +00:00
/*
Unix SMB2 implementation .
Copyright ( C ) Stefan Metzmacher 2005
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
2007-07-10 02:07:03 +00:00
the Free Software Foundation ; either version 3 of the License , or
2005-11-18 14:13:49 +00:00
( 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
2007-07-10 02:07:03 +00:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2005-11-18 14:13:49 +00:00
*/
# include "includes.h"
# include "libcli/smb2/smb2.h"
2006-05-20 17:06:28 +00:00
# include "libcli/smb2/smb2_calls.h"
# include "smb_server/smb_server.h"
# include "smb_server/service_smb_proto.h"
2005-11-18 14:13:49 +00:00
# include "smb_server/smb2/smb2_server.h"
2006-05-20 17:06:28 +00:00
# include "ntvfs/ntvfs.h"
2007-12-13 22:46:09 +01:00
# include "param/param.h"
2006-05-20 17:06:28 +00:00
static void smb2srv_create_send ( struct ntvfs_request * ntvfs )
{
struct smb2srv_request * req ;
union smb_open * io ;
SMB2SRV_CHECK_ASYNC_STATUS ( io , union smb_open ) ;
2007-10-06 22:10:49 +00:00
SMB2SRV_CHECK ( smb2srv_setup_reply ( req , 0x58 , true , io - > smb2 . out . blob . length ) ) ;
2006-05-20 17:06:28 +00:00
2008-02-13 15:05:44 +11:00
SCVAL ( req - > out . body , 0x02 , io - > smb2 . out . oplock_level ) ;
SCVAL ( req - > out . body , 0x03 , io - > smb2 . out . reserved ) ;
2006-05-20 17:06:28 +00:00
SIVAL ( req - > out . body , 0x04 , io - > smb2 . out . create_action ) ;
SBVAL ( req - > out . body , 0x08 , io - > smb2 . out . create_time ) ;
SBVAL ( req - > out . body , 0x10 , io - > smb2 . out . access_time ) ;
SBVAL ( req - > out . body , 0x18 , io - > smb2 . out . write_time ) ;
SBVAL ( req - > out . body , 0x20 , io - > smb2 . out . change_time ) ;
SBVAL ( req - > out . body , 0x28 , io - > smb2 . out . alloc_size ) ;
SBVAL ( req - > out . body , 0x30 , io - > smb2 . out . size ) ;
SIVAL ( req - > out . body , 0x38 , io - > smb2 . out . file_attr ) ;
2008-02-13 15:05:44 +11:00
SIVAL ( req - > out . body , 0x3C , io - > smb2 . out . reserved2 ) ;
2007-05-14 18:02:49 +00:00
smb2srv_push_handle ( req - > out . body , 0x40 , io - > smb2 . out . file . ntvfs ) ;
2006-05-21 10:42:29 +00:00
SMB2SRV_CHECK ( smb2_push_o32s32_blob ( & req - > out , 0x50 , io - > smb2 . out . blob ) ) ;
2006-05-20 17:06:28 +00:00
2007-05-14 18:02:49 +00:00
/* also setup the chained file handle */
req - > chained_file_handle = req - > _chained_file_handle ;
smb2srv_push_handle ( req - > chained_file_handle , 0 , io - > smb2 . out . file . ntvfs ) ;
2006-05-20 17:06:28 +00:00
smb2srv_send_reply ( req ) ;
}
2005-11-18 14:13:49 +00:00
void smb2srv_create_recv ( struct smb2srv_request * req )
{
2006-05-20 17:06:28 +00:00
union smb_open * io ;
DATA_BLOB blob ;
2007-10-06 22:10:49 +00:00
SMB2SRV_CHECK_BODY_SIZE ( req , 0x38 , true ) ;
2006-05-20 17:06:28 +00:00
SMB2SRV_TALLOC_IO_PTR ( io , union smb_open ) ;
SMB2SRV_SETUP_NTVFS_REQUEST ( smb2srv_create_send , NTVFS_ASYNC_STATE_MAY_ASYNC ) ;
io - > smb2 . level = RAW_OPEN_SMB2 ;
2008-02-13 15:05:44 +11:00
io - > smb2 . in . security_flags = CVAL ( req - > in . body , 0x02 ) ;
io - > smb2 . in . oplock_level = CVAL ( req - > in . body , 0x03 ) ;
io - > smb2 . in . impersonation_level = IVAL ( req - > in . body , 0x04 ) ;
io - > smb2 . in . create_flags = BVAL ( req - > in . body , 0x08 ) ;
io - > smb2 . in . reserved = BVAL ( req - > in . body , 0x10 ) ;
io - > smb2 . in . desired_access = IVAL ( req - > in . body , 0x18 ) ;
io - > smb2 . in . file_attributes = IVAL ( req - > in . body , 0x1C ) ;
2006-05-20 17:06:28 +00:00
io - > smb2 . in . share_access = IVAL ( req - > in . body , 0x20 ) ;
2008-02-13 15:05:44 +11:00
io - > smb2 . in . create_disposition = IVAL ( req - > in . body , 0x24 ) ;
2006-05-20 17:06:28 +00:00
io - > smb2 . in . create_options = IVAL ( req - > in . body , 0x28 ) ;
SMB2SRV_CHECK ( smb2_pull_o16s16_string ( & req - > in , io , req - > in . body + 0x2C , & io - > smb2 . in . fname ) ) ;
SMB2SRV_CHECK ( smb2_pull_o32s32_blob ( & req - > in , io , req - > in . body + 0x30 , & blob ) ) ;
/* TODO: parse the blob */
ZERO_STRUCT ( io - > smb2 . in . eas ) ;
2008-04-16 19:26:52 +02:00
ZERO_STRUCT ( io - > smb2 . in . blobs ) ;
2006-05-20 17:06:28 +00:00
2008-02-18 14:54:14 +11:00
/* the VFS backend does not yet handle NULL filenames */
if ( io - > smb2 . in . fname = = NULL ) {
io - > smb2 . in . fname = " " ;
}
2006-05-20 17:06:28 +00:00
SMB2SRV_CALL_NTVFS_BACKEND ( ntvfs_open ( req - > ntvfs , io ) ) ;
2005-11-18 14:13:49 +00:00
}
2006-05-20 17:20:34 +00:00
static void smb2srv_close_send ( struct ntvfs_request * ntvfs )
{
struct smb2srv_request * req ;
union smb_close * io ;
SMB2SRV_CHECK_ASYNC_STATUS ( io , union smb_close ) ;
2007-10-06 22:10:49 +00:00
SMB2SRV_CHECK ( smb2srv_setup_reply ( req , 0x3C , false , 0 ) ) ;
2006-05-20 17:20:34 +00:00
SSVAL ( req - > out . body , 0x02 , io - > smb2 . out . flags ) ;
SIVAL ( req - > out . body , 0x04 , io - > smb2 . out . _pad ) ;
SBVAL ( req - > out . body , 0x08 , io - > smb2 . out . create_time ) ;
SBVAL ( req - > out . body , 0x10 , io - > smb2 . out . access_time ) ;
SBVAL ( req - > out . body , 0x18 , io - > smb2 . out . write_time ) ;
SBVAL ( req - > out . body , 0x20 , io - > smb2 . out . change_time ) ;
SBVAL ( req - > out . body , 0x28 , io - > smb2 . out . alloc_size ) ;
SBVAL ( req - > out . body , 0x30 , io - > smb2 . out . size ) ;
SIVAL ( req - > out . body , 0x38 , io - > smb2 . out . file_attr ) ;
smb2srv_send_reply ( req ) ;
}
2005-11-18 14:13:49 +00:00
void smb2srv_close_recv ( struct smb2srv_request * req )
{
2006-05-20 17:20:34 +00:00
union smb_close * io ;
2007-10-06 22:10:49 +00:00
SMB2SRV_CHECK_BODY_SIZE ( req , 0x18 , false ) ;
2006-05-20 17:20:34 +00:00
SMB2SRV_TALLOC_IO_PTR ( io , union smb_close ) ;
SMB2SRV_SETUP_NTVFS_REQUEST ( smb2srv_close_send , NTVFS_ASYNC_STATE_MAY_ASYNC ) ;
io - > smb2 . level = RAW_CLOSE_SMB2 ;
io - > smb2 . in . flags = SVAL ( req - > in . body , 0x02 ) ;
io - > smb2 . in . _pad = IVAL ( req - > in . body , 0x04 ) ;
io - > smb2 . in . file . ntvfs = smb2srv_pull_handle ( req , req - > in . body , 0x08 ) ;
SMB2SRV_CHECK_FILE_HANDLE ( io - > smb2 . in . file . ntvfs ) ;
SMB2SRV_CALL_NTVFS_BACKEND ( ntvfs_close ( req - > ntvfs , io ) ) ;
2005-11-18 14:13:49 +00:00
}
2006-05-20 18:57:32 +00:00
static void smb2srv_flush_send ( struct ntvfs_request * ntvfs )
{
struct smb2srv_request * req ;
union smb_flush * io ;
SMB2SRV_CHECK_ASYNC_STATUS ( io , union smb_flush ) ;
2007-10-06 22:10:49 +00:00
SMB2SRV_CHECK ( smb2srv_setup_reply ( req , 0x04 , false , 0 ) ) ;
2006-05-20 18:57:32 +00:00
SSVAL ( req - > out . body , 0x02 , 0 ) ;
smb2srv_send_reply ( req ) ;
}
2005-12-06 13:26:24 +00:00
void smb2srv_flush_recv ( struct smb2srv_request * req )
{
2006-05-20 18:57:32 +00:00
union smb_flush * io ;
uint16_t _pad ;
2007-10-06 22:10:49 +00:00
SMB2SRV_CHECK_BODY_SIZE ( req , 0x18 , false ) ;
2006-05-20 18:57:32 +00:00
SMB2SRV_TALLOC_IO_PTR ( io , union smb_flush ) ;
SMB2SRV_SETUP_NTVFS_REQUEST ( smb2srv_flush_send , NTVFS_ASYNC_STATE_MAY_ASYNC ) ;
io - > smb2 . level = RAW_FLUSH_SMB2 ;
_pad = SVAL ( req - > in . body , 0x02 ) ;
io - > smb2 . in . unknown = IVAL ( req - > in . body , 0x04 ) ;
io - > smb2 . in . file . ntvfs = smb2srv_pull_handle ( req , req - > in . body , 0x08 ) ;
SMB2SRV_CHECK_FILE_HANDLE ( io - > smb2 . in . file . ntvfs ) ;
SMB2SRV_CALL_NTVFS_BACKEND ( ntvfs_flush ( req - > ntvfs , io ) ) ;
2005-12-06 13:26:24 +00:00
}
2006-05-20 19:03:06 +00:00
static void smb2srv_read_send ( struct ntvfs_request * ntvfs )
{
struct smb2srv_request * req ;
union smb_read * io ;
SMB2SRV_CHECK_ASYNC_STATUS ( io , union smb_read ) ;
2007-10-06 22:10:49 +00:00
SMB2SRV_CHECK ( smb2srv_setup_reply ( req , 0x10 , true , io - > smb2 . out . data . length ) ) ;
2006-05-20 19:03:06 +00:00
2007-05-14 11:50:51 +00:00
/* TODO: avoid the memcpy */
2006-05-20 19:03:06 +00:00
SMB2SRV_CHECK ( smb2_push_o16s32_blob ( & req - > out , 0x02 , io - > smb2 . out . data ) ) ;
2008-04-14 11:31:17 +02:00
SIVAL ( req - > out . body , 0x08 , io - > smb2 . out . remaining ) ;
SIVAL ( req - > out . body , 0x0C , io - > smb2 . out . reserved ) ;
2006-05-20 19:03:06 +00:00
smb2srv_send_reply ( req ) ;
}
2005-11-18 14:13:49 +00:00
void smb2srv_read_recv ( struct smb2srv_request * req )
{
2006-05-20 19:03:06 +00:00
union smb_read * io ;
2007-10-06 22:10:49 +00:00
SMB2SRV_CHECK_BODY_SIZE ( req , 0x30 , true ) ;
2006-05-20 19:03:06 +00:00
SMB2SRV_TALLOC_IO_PTR ( io , union smb_read ) ;
SMB2SRV_SETUP_NTVFS_REQUEST ( smb2srv_read_send , NTVFS_ASYNC_STATE_MAY_ASYNC ) ;
io - > smb2 . level = RAW_READ_SMB2 ;
io - > smb2 . in . _pad = SVAL ( req - > in . body , 0x02 ) ;
io - > smb2 . in . length = IVAL ( req - > in . body , 0x04 ) ;
io - > smb2 . in . offset = BVAL ( req - > in . body , 0x08 ) ;
io - > smb2 . in . file . ntvfs = smb2srv_pull_handle ( req , req - > in . body , 0x10 ) ;
2008-04-14 11:31:17 +02:00
io - > smb2 . in . min_count = IVAL ( req - > in . body , 0x20 ) ;
io - > smb2 . in . channel = IVAL ( req - > in . body , 0x24 ) ;
io - > smb2 . in . remaining = IVAL ( req - > in . body , 0x28 ) ;
io - > smb2 . in . channel_offset = SVAL ( req - > in . body , 0x2C ) ;
io - > smb2 . in . channel_length = SVAL ( req - > in . body , 0x2E ) ;
2006-05-20 19:03:06 +00:00
SMB2SRV_CHECK_FILE_HANDLE ( io - > smb2 . in . file . ntvfs ) ;
/* preallocate the buffer for the backends */
io - > smb2 . out . data = data_blob_talloc ( io , NULL , io - > smb2 . in . length ) ;
if ( io - > smb2 . out . data . length ! = io - > smb2 . in . length ) {
SMB2SRV_CHECK ( NT_STATUS_NO_MEMORY ) ;
}
SMB2SRV_CALL_NTVFS_BACKEND ( ntvfs_read ( req - > ntvfs , io ) ) ;
2005-11-18 14:13:49 +00:00
}
2006-05-20 18:56:08 +00:00
static void smb2srv_write_send ( struct ntvfs_request * ntvfs )
{
struct smb2srv_request * req ;
union smb_write * io ;
SMB2SRV_CHECK_ASYNC_STATUS ( io , union smb_write ) ;
2007-10-06 22:10:49 +00:00
SMB2SRV_CHECK ( smb2srv_setup_reply ( req , 0x10 , true , 0 ) ) ;
2006-05-20 18:56:08 +00:00
SSVAL ( req - > out . body , 0x02 , io - > smb2 . out . _pad ) ;
SIVAL ( req - > out . body , 0x04 , io - > smb2 . out . nwritten ) ;
SBVAL ( req - > out . body , 0x08 , io - > smb2 . out . unknown1 ) ;
smb2srv_send_reply ( req ) ;
}
2005-11-18 14:13:49 +00:00
void smb2srv_write_recv ( struct smb2srv_request * req )
{
2006-05-20 18:56:08 +00:00
union smb_write * io ;
2007-10-06 22:10:49 +00:00
SMB2SRV_CHECK_BODY_SIZE ( req , 0x30 , true ) ;
2006-05-20 18:56:08 +00:00
SMB2SRV_TALLOC_IO_PTR ( io , union smb_write ) ;
SMB2SRV_SETUP_NTVFS_REQUEST ( smb2srv_write_send , NTVFS_ASYNC_STATE_MAY_ASYNC ) ;
/* TODO: avoid the memcpy */
io - > smb2 . level = RAW_WRITE_SMB2 ;
SMB2SRV_CHECK ( smb2_pull_o16s32_blob ( & req - > in , io , req - > in . body + 0x02 , & io - > smb2 . in . data ) ) ;
io - > smb2 . in . offset = BVAL ( req - > in . body , 0x08 ) ;
io - > smb2 . in . file . ntvfs = smb2srv_pull_handle ( req , req - > in . body , 0x10 ) ;
io - > smb2 . in . unknown1 = BVAL ( req - > in . body , 0x20 ) ;
io - > smb2 . in . unknown2 = BVAL ( req - > in . body , 0x28 ) ;
SMB2SRV_CHECK_FILE_HANDLE ( io - > smb2 . in . file . ntvfs ) ;
SMB2SRV_CALL_NTVFS_BACKEND ( ntvfs_write ( req - > ntvfs , io ) ) ;
2005-11-18 14:13:49 +00:00
}
2007-05-14 11:50:51 +00:00
static void smb2srv_lock_send ( struct ntvfs_request * ntvfs )
{
struct smb2srv_request * req ;
union smb_lock * io ;
SMB2SRV_CHECK_ASYNC_STATUS_ERR ( io , union smb_lock ) ;
2007-10-06 22:10:49 +00:00
SMB2SRV_CHECK ( smb2srv_setup_reply ( req , 0x04 , false , 0 ) ) ;
2007-05-14 11:50:51 +00:00
SSVAL ( req - > out . body , 0x02 , io - > smb2 . out . unknown1 ) ;
smb2srv_send_reply ( req ) ;
}
2005-12-06 13:26:24 +00:00
void smb2srv_lock_recv ( struct smb2srv_request * req )
{
2007-05-14 11:50:51 +00:00
union smb_lock * io ;
2007-10-06 22:10:49 +00:00
SMB2SRV_CHECK_BODY_SIZE ( req , 0x30 , false ) ;
2007-05-14 11:50:51 +00:00
SMB2SRV_TALLOC_IO_PTR ( io , union smb_lock ) ;
SMB2SRV_SETUP_NTVFS_REQUEST ( smb2srv_lock_send , NTVFS_ASYNC_STATE_MAY_ASYNC ) ;
io - > smb2 . level = RAW_LOCK_SMB2 ;
io - > smb2 . in . unknown1 = SVAL ( req - > in . body , 0x02 ) ;
io - > smb2 . in . unknown2 = IVAL ( req - > in . body , 0x04 ) ;
io - > smb2 . in . file . ntvfs = smb2srv_pull_handle ( req , req - > in . body , 0x08 ) ;
io - > smb2 . in . offset = BVAL ( req - > in . body , 0x18 ) ;
io - > smb2 . in . count = BVAL ( req - > in . body , 0x20 ) ;
io - > smb2 . in . unknown5 = IVAL ( req - > in . body , 0x24 ) ;
io - > smb2 . in . flags = IVAL ( req - > in . body , 0x28 ) ;
SMB2SRV_CHECK_FILE_HANDLE ( io - > smb2 . in . file . ntvfs ) ;
SMB2SRV_CALL_NTVFS_BACKEND ( ntvfs_lock ( req - > ntvfs , io ) ) ;
2005-12-06 13:26:24 +00:00
}
2006-07-09 09:50:41 +00:00
static void smb2srv_ioctl_send ( struct ntvfs_request * ntvfs )
{
struct smb2srv_request * req ;
union smb_ioctl * io ;
SMB2SRV_CHECK_ASYNC_STATUS_ERR ( io , union smb_ioctl ) ;
2007-10-06 22:10:49 +00:00
SMB2SRV_CHECK ( smb2srv_setup_reply ( req , 0x30 , true , 0 ) ) ;
2006-07-09 09:50:41 +00:00
SSVAL ( req - > out . body , 0x02 , io - > smb2 . out . _pad ) ;
SIVAL ( req - > out . body , 0x04 , io - > smb2 . out . function ) ;
2006-07-10 14:01:53 +00:00
if ( io - > smb2 . level = = RAW_IOCTL_SMB2_NO_HANDLE ) {
struct smb2_handle h ;
h . data [ 0 ] = UINT64_MAX ;
h . data [ 1 ] = UINT64_MAX ;
smb2_push_handle ( req - > out . body + 0x08 , & h ) ;
} else {
smb2srv_push_handle ( req - > out . body , 0x08 , io - > smb2 . in . file . ntvfs ) ;
}
2006-07-09 09:50:41 +00:00
SMB2SRV_CHECK ( smb2_push_o32s32_blob ( & req - > out , 0x18 , io - > smb2 . out . in ) ) ;
SMB2SRV_CHECK ( smb2_push_o32s32_blob ( & req - > out , 0x20 , io - > smb2 . out . out ) ) ;
SIVAL ( req - > out . body , 0x28 , io - > smb2 . out . unknown2 ) ;
SIVAL ( req - > out . body , 0x2C , io - > smb2 . out . unknown3 ) ;
smb2srv_send_reply ( req ) ;
}
2005-12-06 13:26:24 +00:00
void smb2srv_ioctl_recv ( struct smb2srv_request * req )
{
2006-07-09 09:50:41 +00:00
union smb_ioctl * io ;
2006-07-10 14:01:53 +00:00
struct smb2_handle h ;
2006-07-09 09:50:41 +00:00
2007-10-06 22:10:49 +00:00
SMB2SRV_CHECK_BODY_SIZE ( req , 0x38 , true ) ;
2006-07-09 09:50:41 +00:00
SMB2SRV_TALLOC_IO_PTR ( io , union smb_ioctl ) ;
SMB2SRV_SETUP_NTVFS_REQUEST ( smb2srv_ioctl_send , NTVFS_ASYNC_STATE_MAY_ASYNC ) ;
/* TODO: avoid the memcpy */
io - > smb2 . in . _pad = SVAL ( req - > in . body , 0x02 ) ;
io - > smb2 . in . function = IVAL ( req - > in . body , 0x04 ) ;
2006-07-10 14:01:53 +00:00
/* file handle ... */
2006-07-09 09:50:41 +00:00
SMB2SRV_CHECK ( smb2_pull_o32s32_blob ( & req - > in , io , req - > in . body + 0x18 , & io - > smb2 . in . out ) ) ;
io - > smb2 . in . unknown2 = IVAL ( req - > in . body , 0x20 ) ;
SMB2SRV_CHECK ( smb2_pull_o32s32_blob ( & req - > in , io , req - > in . body + 0x24 , & io - > smb2 . in . in ) ) ;
io - > smb2 . in . max_response_size = IVAL ( req - > in . body , 0x2C ) ;
io - > smb2 . in . flags = BVAL ( req - > in . body , 0x30 ) ;
2006-07-10 14:01:53 +00:00
smb2_pull_handle ( req - > in . body + 0x08 , & h ) ;
if ( h . data [ 0 ] = = UINT64_MAX & & h . data [ 1 ] = = UINT64_MAX ) {
io - > smb2 . level = RAW_IOCTL_SMB2_NO_HANDLE ;
} else {
io - > smb2 . level = RAW_IOCTL_SMB2 ;
io - > smb2 . in . file . ntvfs = smb2srv_pull_handle ( req , req - > in . body , 0x08 ) ;
SMB2SRV_CHECK_FILE_HANDLE ( io - > smb2 . in . file . ntvfs ) ;
}
2006-07-09 09:50:41 +00:00
SMB2SRV_CALL_NTVFS_BACKEND ( ntvfs_ioctl ( req - > ntvfs , io ) ) ;
2005-12-06 13:26:24 +00:00
}
2006-07-12 17:14:32 +00:00
static void smb2srv_notify_send ( struct ntvfs_request * ntvfs )
{
struct smb2srv_request * req ;
union smb_notify * io ;
size_t size = 0 ;
int i ;
uint8_t * p ;
DATA_BLOB blob = data_blob ( NULL , 0 ) ;
SMB2SRV_CHECK_ASYNC_STATUS ( io , union smb_notify ) ;
2007-10-06 22:10:49 +00:00
SMB2SRV_CHECK ( smb2srv_setup_reply ( req , 0x08 , true , 0 ) ) ;
2006-07-12 17:14:32 +00:00
# define MAX_BYTES_PER_CHAR 3
/* work out how big the reply buffer could be */
for ( i = 0 ; i < io - > smb2 . out . num_changes ; i + + ) {
size + = 12 + 3 + ( 1 + strlen ( io - > smb2 . out . changes [ i ] . name . s ) ) * MAX_BYTES_PER_CHAR ;
}
blob = data_blob_talloc ( req , NULL , size ) ;
if ( size > 0 & & ! blob . data ) {
SMB2SRV_CHECK ( NT_STATUS_NO_MEMORY ) ;
}
p = blob . data ;
/* construct the changes buffer */
for ( i = 0 ; i < io - > smb2 . out . num_changes ; i + + ) {
uint32_t ofs ;
ssize_t len ;
SIVAL ( p , 4 , io - > smb2 . out . changes [ i ] . action ) ;
2008-01-05 19:03:43 -06:00
len = push_string ( lp_iconv_convenience ( ntvfs - > ctx - > lp_ctx ) , p + 12 , io - > smb2 . out . changes [ i ] . name . s ,
2006-07-12 17:14:32 +00:00
blob . length - ( p + 12 - blob . data ) , STR_UNICODE ) ;
SIVAL ( p , 8 , len ) ;
ofs = len + 12 ;
if ( ofs & 3 ) {
int pad = 4 - ( ofs & 3 ) ;
memset ( p + ofs , 0 , pad ) ;
ofs + = pad ;
}
if ( i = = io - > smb2 . out . num_changes - 1 ) {
SIVAL ( p , 0 , 0 ) ;
} else {
SIVAL ( p , 0 , ofs ) ;
}
p + = ofs ;
}
blob . length = p - blob . data ;
SMB2SRV_CHECK ( smb2_push_o16s32_blob ( & req - > out , 0x02 , blob ) ) ;
smb2srv_send_reply ( req ) ;
}
2005-11-18 14:13:49 +00:00
void smb2srv_notify_recv ( struct smb2srv_request * req )
{
2006-07-12 17:14:32 +00:00
union smb_notify * io ;
2007-10-06 22:10:49 +00:00
SMB2SRV_CHECK_BODY_SIZE ( req , 0x20 , false ) ;
2006-07-12 17:14:32 +00:00
SMB2SRV_TALLOC_IO_PTR ( io , union smb_notify ) ;
SMB2SRV_SETUP_NTVFS_REQUEST ( smb2srv_notify_send , NTVFS_ASYNC_STATE_MAY_ASYNC ) ;
io - > smb2 . level = RAW_NOTIFY_SMB2 ;
io - > smb2 . in . recursive = SVAL ( req - > in . body , 0x02 ) ;
io - > smb2 . in . buffer_size = IVAL ( req - > in . body , 0x04 ) ;
io - > smb2 . in . file . ntvfs = smb2srv_pull_handle ( req , req - > in . body , 0x08 ) ;
io - > smb2 . in . completion_filter = IVAL ( req - > in . body , 0x18 ) ;
io - > smb2 . in . unknown = BVAL ( req - > in . body , 0x1C ) ;
SMB2SRV_CHECK_FILE_HANDLE ( io - > smb2 . in . file . ntvfs ) ;
SMB2SRV_CALL_NTVFS_BACKEND ( ntvfs_notify ( req - > ntvfs , io ) ) ;
2005-11-18 14:13:49 +00:00
}
2006-06-26 15:24:10 +00:00
void smb2srv_break_recv ( struct smb2srv_request * req )
{
smb2srv_send_error ( req , NT_STATUS_NOT_IMPLEMENTED ) ;
}