]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
r23997: Check in the infrastructure for getting rid of the global InBuffer/OutBuffer
authorVolker Lendecke <vlendec@samba.org>
Mon, 23 Jul 2007 09:36:09 +0000 (09:36 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:28:53 +0000 (12:28 -0500)
The complete history of this patch can be found under
http://www.samba.org/~vlendec/inbuf-checkin/.

Jeremy, Jerry: If possible I would like to see this in 3.2.0. I'm only
checking into 3_2 at the moment, as it currently will slow down operations for
all non-converted (i.e. all at this moment) operations, as it will copy the
talloc'ed inbuf over the global InBuffer. It will need quite a bit of effort
to convert everything necessary for the normal operations an XP box does.

I have patches for negprot, session setup, tcon_and_X, open_and_X, close. More
to come, but I would appreciate some help here.

Volker
(This used to be commit 5594af2b208c860d3f4b453af6a649d9e4295d1c)

source3/include/smb.h
source3/include/smb_macros.h
source3/lib/util_sock.c
source3/smbd/blocking.c
source3/smbd/error.c
source3/smbd/nttrans.c
source3/smbd/pipes.c
source3/smbd/process.c
source3/smbd/reply.c
source3/smbd/sesssetup.c

index b16d8a765ac3a48cbdc9cc961dfa099ba669d2a5..4e03d333d9caa6fd5ba06c65629093160cc0ad48 100644 (file)
@@ -686,6 +686,10 @@ struct smb_request {
        uint16 smbpid;
        uint16 mid;
        uint16 vuid;
+       uint16 tid;
+       uint8  wct;
+       const uint8 *inbuf;
+       uint8 *outbuf;
 };
 
 /* Defines for the sent_oplock_break field above. */
index 3221d2f951d7910a9841e4ca6f109b32cef7a417..a47eff2f64ffc8b861be1c33dd15a6ce1d381ba1 100644 (file)
 #define ERROR_FORCE_NT(status) error_packet(inbuf,outbuf,-1,-1,status,__LINE__,__FILE__)
 #define ERROR_BOTH(status,class,code) error_packet(inbuf,outbuf,class,code,status,__LINE__,__FILE__)
 
+#define reply_nterror(req,status) reply_nt_error(req,status,__LINE__,__FILE__)
+#define reply_doserror(req,eclass,ecode) reply_dos_error(req,eclass,ecode,__LINE__,__FILE__)
+#define reply_botherror(req,status,eclass,ecode) reply_both_error(req,eclass,ecode,status,__LINE__,__FILE__)
+
 /* this is how errors are generated */
 #define UNIXERROR(defclass,deferror) unix_error_packet(inbuf,outbuf,defclass,deferror,NT_STATUS_OK,__LINE__,__FILE__)
 
index 46d640cd55f58c5c5d7d3f7afff1a87719271a14..9dcbdd9f02552753f69fc98146308594573d215c 100644 (file)
@@ -730,6 +730,85 @@ ssize_t receive_smb_raw(int fd, char *buffer, unsigned int timeout, size_t maxle
        return len;
 }
 
+static ssize_t receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, int fd,
+                                     char **buffer, unsigned int timeout)
+{
+       char lenbuf[4];
+       ssize_t len,ret;
+
+       smb_read_error = 0;
+
+       len = read_smb_length_return_keepalive(fd, lenbuf, timeout);
+       if (len < 0) {
+               DEBUG(10,("receive_smb_raw: length < 0!\n"));
+
+               /*
+                * Correct fix. smb_read_error may have already been
+                * set. Only set it here if not already set. Global
+                * variables still suck :-). JRA.
+                */
+
+               if (smb_read_error == 0)
+                       smb_read_error = READ_ERROR;
+               return -1;
+       }
+
+       /*
+        * A WRITEX with CAP_LARGE_WRITEX can be 64k worth of data plus 65 bytes
+        * of header. Don't print the error if this fits.... JRA.
+        */
+
+       if (len > (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE)) {
+               DEBUG(0,("Invalid packet length! (%lu bytes).\n",(unsigned long)len));
+               if (len > BUFFER_SIZE + (SAFETY_MARGIN/2)) {
+
+                       /*
+                        * Correct fix. smb_read_error may have already been
+                        * set. Only set it here if not already set. Global
+                        * variables still suck :-). JRA.
+                        */
+
+                       if (smb_read_error == 0)
+                               smb_read_error = READ_ERROR;
+                       return -1;
+               }
+       }
+
+       /*
+        * The +4 here can't wrap, we've checked the length above already.
+        */
+
+       *buffer = TALLOC_ARRAY(mem_ctx, char, len+4);
+
+       if (*buffer == NULL) {
+               DEBUG(0, ("Could not allocate inbuf of length %d\n",
+                         (int)len+4));
+               if (smb_read_error == 0)
+                       smb_read_error = READ_ERROR;
+               return -1;
+       }
+
+       memcpy(*buffer, lenbuf, sizeof(lenbuf));
+
+       if(len > 0) {
+               if (timeout > 0) {
+                       ret = read_socket_with_timeout(fd,(*buffer)+4, len,
+                                                      len, timeout);
+               } else {
+                       ret = read_data(fd, (*buffer)+4, len);
+               }
+
+               if (ret != len) {
+                       if (smb_read_error == 0) {
+                               smb_read_error = READ_ERROR;
+                       }
+                       return -1;
+               }
+       }
+
+       return len + 4;
+}
+
 /****************************************************************************
  Wrapper for receive_smb_raw().
  Checks the MAC on signed packets.
@@ -765,6 +844,43 @@ BOOL receive_smb(int fd, char *buffer, unsigned int timeout)
        return True;
 }
 
+ssize_t receive_smb_talloc(TALLOC_CTX *mem_ctx, int fd, char **buffer,
+                          unsigned int timeout)
+{
+       ssize_t len;
+
+       len = receive_smb_raw_talloc(mem_ctx, fd, buffer, timeout);
+
+       if (len < 0) {
+               return -1;
+       }
+
+       if (srv_encryption_on()) {
+               NTSTATUS status = srv_decrypt_buffer(*buffer);
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(0, ("receive_smb: SMB decryption failed on "
+                                 "incoming packet! Error %s\n",
+                                 nt_errstr(status) ));
+                       if (smb_read_error == 0) {
+                               smb_read_error = READ_BAD_DECRYPT;
+                       }
+                       return -1;
+               }
+       }
+
+       /* Check the incoming SMB signature. */
+       if (!srv_check_sign_mac(*buffer, True)) {
+               DEBUG(0, ("receive_smb: SMB Signature verification failed on "
+                         "incoming packet!\n"));
+               if (smb_read_error == 0) {
+                       smb_read_error = READ_BAD_SIG;
+               }
+               return -1;
+       }
+
+       return len;
+}
+
 /****************************************************************************
  Send an smb to a fd.
 ****************************************************************************/
index ed1977e3bec9297a0c1da5550a64a4c47cc74afc..09d16337cd5a63341936158958363dbb87303541 100644 (file)
@@ -286,7 +286,7 @@ static void reply_lockingX_success(blocking_lock_record *blr)
         * that here and must set up the chain info manually.
         */
 
-       outsize = chain_reply(inbuf,outbuf,blr->length,bufsize);
+       outsize = chain_reply(inbuf,&outbuf,blr->length,bufsize);
 
        outsize += chain_size;
 
index 12b57d5ab44c905d9cac9d65f5a81f6dc706fa54..d00c61487a09c25cd31e92661975df410583a832 100644 (file)
@@ -131,3 +131,29 @@ int error_packet(const char *inbuf, char *outbuf, uint8 eclass, uint32 ecode, NT
        error_packet_set(outbuf, eclass, ecode, ntstatus, line, file);
        return outsize;
 }
+
+void reply_nt_error(struct smb_request *req, NTSTATUS ntstatus,
+                   int line, const char *file)
+{
+       TALLOC_FREE(req->outbuf);
+       reply_outbuf(req, 0, 0);
+       error_packet_set((char *)req->outbuf, 0, 0, ntstatus, line, file);
+}
+
+void reply_dos_error(struct smb_request *req, uint8 eclass, uint32 ecode,
+                   int line, const char *file)
+{
+       TALLOC_FREE(req->outbuf);
+       reply_outbuf(req, 0, 0);
+       error_packet_set((char *)req->outbuf, eclass, ecode, NT_STATUS_OK, line,
+                        file);
+}
+
+void reply_both_error(struct smb_request *req, uint8 eclass, uint32 ecode,
+                     NTSTATUS status, int line, const char *file)
+{
+       TALLOC_FREE(req->outbuf);
+       reply_outbuf(req, 0, 0);
+       error_packet_set((char *)req->outbuf, eclass, ecode, status,
+                        line, file);
+}
index 64b6d33eee1cd262e87b46f3d55772ffef210b8c..e435e1b6fb9d63458934a8eb1a66608b5676d05a 100644 (file)
@@ -433,7 +433,7 @@ static int do_ntcreate_pipe_open(connection_struct *conn,
 
        DEBUG(5,("do_ntcreate_pipe_open: open pipe = %s\n", fname));
 
-       return chain_reply(inbuf,outbuf,length,bufsize);
+       return chain_reply(inbuf,&outbuf,length,bufsize);
 }
 
 /****************************************************************************
@@ -471,7 +471,7 @@ int reply_ntcreate_and_X_quota(connection_struct *conn,
 
        DEBUG(5,("reply_ntcreate_and_X_quota: fnum = %d, open name = %s\n", fsp->fnum, fsp->fsp_name));
 
-       result = chain_reply(inbuf,outbuf,length,bufsize);
+       result = chain_reply(inbuf,&outbuf,length,bufsize);
        return result;
 }
 
@@ -987,7 +987,7 @@ int reply_ntcreate_and_X(connection_struct *conn,
 
        DEBUG(5,("reply_ntcreate_and_X: fnum = %d, open name = %s\n", fsp->fnum, fsp->fsp_name));
 
-       result = chain_reply(inbuf,outbuf,length,bufsize);
+       result = chain_reply(inbuf,&outbuf,length,bufsize);
        END_PROFILE(SMBntcreateX);
        return result;
 }
index 1ea3e052b280170c51c26ade282699d0ffb3e5d1..a6cdc3a989f168536bff46810a6c3656ebd7e6b8 100644 (file)
@@ -126,7 +126,7 @@ int reply_open_pipe_and_X(connection_struct *conn,
        SSVAL(outbuf,smb_vwv8,rmode);
        SSVAL(outbuf,smb_vwv11,0x0001);
 
-       return chain_reply(inbuf,outbuf,length,bufsize);
+       return chain_reply(inbuf,&outbuf,length,bufsize);
 }
 
 /****************************************************************************
@@ -231,7 +231,7 @@ int reply_pipe_write_and_X(char *inbuf,char *outbuf,int length,int bufsize)
   
        DEBUG(3,("writeX-IPC pnum=%04x nwritten=%d\n", p->pnum, nwritten));
 
-       return chain_reply(inbuf,outbuf,length,bufsize);
+       return chain_reply(inbuf,&outbuf,length,bufsize);
 }
 
 /****************************************************************************
@@ -278,7 +278,7 @@ int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize)
 
        /* Ensure we set up the message length to include the data length read. */
        set_message_bcc(inbuf,outbuf,nread);
-       return chain_reply(inbuf,outbuf,length,bufsize);
+       return chain_reply(inbuf,&outbuf,length,bufsize);
 }
 
 /****************************************************************************
index 558d403948aaee7383c3e50627640b295f69989f..4a846e970879311a6ba0945c828a8ed69680ad2f 100644 (file)
 extern struct auth_context *negprot_global_auth_context;
 extern int smb_echo_count;
 
+const int total_buffer_size = (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN);
+
 static char *InBuffer = NULL;
 static char *OutBuffer = NULL;
-static char *current_inbuf = NULL;
+static const char *current_inbuf = NULL;
+
+static char *NewInBuffer(char **old_inbuf);
+static char *NewOutBuffer(char **old_outbuf);
 
 /* 
  * Size of data we can send to client. Set
@@ -56,6 +61,10 @@ void init_smb_request(struct smb_request *req, const uint8 *inbuf)
        req->smbpid = SVAL(inbuf, smb_pid);
        req->mid    = SVAL(inbuf, smb_mid);
        req->vuid   = SVAL(inbuf, smb_uid);
+       req->tid    = SVAL(inbuf, smb_tid);
+       req->wct    = CVAL(inbuf, smb_wct);
+       req->inbuf  = inbuf;
+       req->outbuf = NULL;
 }
 
 /****************************************************************************
@@ -70,7 +79,7 @@ static struct pending_message_list *deferred_open_queue;
  ready for processing.
 ****************************************************************************/
 
-static BOOL push_queued_message(char *buf, int msg_len,
+static BOOL push_queued_message(const char *buf, int msg_len,
                                struct timeval request_time,
                                struct timeval end_time,
                                char *private_data, size_t private_len)
@@ -357,12 +366,14 @@ static int select_on_fd(int fd, int maxfd, fd_set *fds)
 The timeout is in milliseconds
 ****************************************************************************/
 
-static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
+static BOOL receive_message_or_smb(TALLOC_CTX *mem_ctx, char **buffer,
+                                  size_t *buffer_len, int timeout)
 {
        fd_set r_fds, w_fds;
        int selrtn;
        struct timeval to;
        int maxfd = 0;
+       ssize_t len;
 
        smb_read_error = 0;
 
@@ -413,8 +424,16 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
                }
 
                if (pop_message) {
-                       memcpy(buffer, msg->buf.data, MIN(buffer_len, msg->buf.length));
-  
+
+                       *buffer = (char *)talloc_memdup(mem_ctx, msg->buf.data,
+                                                       msg->buf.length);
+                       if (*buffer == NULL) {
+                               DEBUG(0, ("talloc failed\n"));
+                               smb_read_error = READ_ERROR;
+                               return False;
+                       }
+                       *buffer_len = msg->buf.length;
+
                        /* We leave this message on the queue so the open code can
                           know this is a retry. */
                        DEBUG(5,("receive_message_or_smb: returning deferred open smb message.\n"));
@@ -530,7 +549,15 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
                goto again;
        }
 
-       return receive_smb(smbd_server_fd(), buffer, 0);
+       len = receive_smb_talloc(mem_ctx, smbd_server_fd(), buffer, 0);
+
+       if (len == -1) {
+               return False;
+       }
+
+       *buffer_len = (size_t)len;
+
+       return True;
 }
 
 /*
@@ -603,273 +630,301 @@ force write permissions on print services.
 static const struct smb_message_struct {
        const char *name;
        int (*fn)(connection_struct *conn, char *, char *, int, int);
+       void (*fn_new)(connection_struct *conn, struct smb_request *req);
        int flags;
 } smb_messages[256] = {
 
-/* 0x00 */ { "SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
-/* 0x01 */ { "SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
-/* 0x02 */ { "SMBopen",reply_open,AS_USER },
-/* 0x03 */ { "SMBcreate",reply_mknew,AS_USER},
-/* 0x04 */ { "SMBclose",reply_close,AS_USER | CAN_IPC },
-/* 0x05 */ { "SMBflush",reply_flush,AS_USER},
-/* 0x06 */ { "SMBunlink",reply_unlink,AS_USER | NEED_WRITE }, 
-/* 0x07 */ { "SMBmv",reply_mv,AS_USER | NEED_WRITE },
-/* 0x08 */ { "SMBgetatr",reply_getatr,AS_USER},
-/* 0x09 */ { "SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
-/* 0x0a */ { "SMBread",reply_read,AS_USER},
-/* 0x0b */ { "SMBwrite",reply_write,AS_USER | CAN_IPC },
-/* 0x0c */ { "SMBlock",reply_lock,AS_USER},
-/* 0x0d */ { "SMBunlock",reply_unlock,AS_USER},
-/* 0x0e */ { "SMBctemp",reply_ctemp,AS_USER },
-/* 0x0f */ { "SMBmknew",reply_mknew,AS_USER}, 
-/* 0x10 */ { "SMBcheckpath",reply_checkpath,AS_USER},
-/* 0x11 */ { "SMBexit",reply_exit,DO_CHDIR},
-/* 0x12 */ { "SMBlseek",reply_lseek,AS_USER},
-/* 0x13 */ { "SMBlockread",reply_lockread,AS_USER},
-/* 0x14 */ { "SMBwriteunlock",reply_writeunlock,AS_USER},
-/* 0x15 */ { NULL, NULL, 0 },
-/* 0x16 */ { NULL, NULL, 0 },
-/* 0x17 */ { NULL, NULL, 0 },
-/* 0x18 */ { NULL, NULL, 0 },
-/* 0x19 */ { NULL, NULL, 0 },
-/* 0x1a */ { "SMBreadbraw",reply_readbraw,AS_USER},
-/* 0x1b */ { "SMBreadBmpx",reply_readbmpx,AS_USER},
-/* 0x1c */ { "SMBreadBs",NULL,0 },
-/* 0x1d */ { "SMBwritebraw",reply_writebraw,AS_USER},
-/* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,AS_USER},
-/* 0x1f */ { "SMBwriteBs",reply_writebs,AS_USER},
-/* 0x20 */ { "SMBwritec",NULL,0},
-/* 0x21 */ { NULL, NULL, 0 },
-/* 0x22 */ { "SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE },
-/* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER },
-/* 0x24 */ { "SMBlockingX",reply_lockingX,AS_USER },
-/* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC },
-/* 0x26 */ { "SMBtranss",reply_transs,AS_USER | CAN_IPC},
-/* 0x27 */ { "SMBioctl",reply_ioctl,0},
-/* 0x28 */ { "SMBioctls",NULL,AS_USER},
-/* 0x29 */ { "SMBcopy",reply_copy,AS_USER | NEED_WRITE },
-/* 0x2a */ { "SMBmove",NULL,AS_USER | NEED_WRITE },
-/* 0x2b */ { "SMBecho",reply_echo,0},
-/* 0x2c */ { "SMBwriteclose",reply_writeclose,AS_USER},
-/* 0x2d */ { "SMBopenX",reply_open_and_X,AS_USER | CAN_IPC },
-/* 0x2e */ { "SMBreadX",reply_read_and_X,AS_USER | CAN_IPC },
-/* 0x2f */ { "SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC },
-/* 0x30 */ { NULL, NULL, 0 },
-/* 0x31 */ { NULL, NULL, 0 },
-/* 0x32 */ { "SMBtrans2", reply_trans2, AS_USER | CAN_IPC },
-/* 0x33 */ { "SMBtranss2", reply_transs2, AS_USER},
-/* 0x34 */ { "SMBfindclose", reply_findclose,AS_USER},
-/* 0x35 */ { "SMBfindnclose", reply_findnclose, AS_USER},
-/* 0x36 */ { NULL, NULL, 0 },
-/* 0x37 */ { NULL, NULL, 0 },
-/* 0x38 */ { NULL, NULL, 0 },
-/* 0x39 */ { NULL, NULL, 0 },
-/* 0x3a */ { NULL, NULL, 0 },
-/* 0x3b */ { NULL, NULL, 0 },
-/* 0x3c */ { NULL, NULL, 0 },
-/* 0x3d */ { NULL, NULL, 0 },
-/* 0x3e */ { NULL, NULL, 0 },
-/* 0x3f */ { NULL, NULL, 0 },
-/* 0x40 */ { NULL, NULL, 0 },
-/* 0x41 */ { NULL, NULL, 0 },
-/* 0x42 */ { NULL, NULL, 0 },
-/* 0x43 */ { NULL, NULL, 0 },
-/* 0x44 */ { NULL, NULL, 0 },
-/* 0x45 */ { NULL, NULL, 0 },
-/* 0x46 */ { NULL, NULL, 0 },
-/* 0x47 */ { NULL, NULL, 0 },
-/* 0x48 */ { NULL, NULL, 0 },
-/* 0x49 */ { NULL, NULL, 0 },
-/* 0x4a */ { NULL, NULL, 0 },
-/* 0x4b */ { NULL, NULL, 0 },
-/* 0x4c */ { NULL, NULL, 0 },
-/* 0x4d */ { NULL, NULL, 0 },
-/* 0x4e */ { NULL, NULL, 0 },
-/* 0x4f */ { NULL, NULL, 0 },
-/* 0x50 */ { NULL, NULL, 0 },
-/* 0x51 */ { NULL, NULL, 0 },
-/* 0x52 */ { NULL, NULL, 0 },
-/* 0x53 */ { NULL, NULL, 0 },
-/* 0x54 */ { NULL, NULL, 0 },
-/* 0x55 */ { NULL, NULL, 0 },
-/* 0x56 */ { NULL, NULL, 0 },
-/* 0x57 */ { NULL, NULL, 0 },
-/* 0x58 */ { NULL, NULL, 0 },
-/* 0x59 */ { NULL, NULL, 0 },
-/* 0x5a */ { NULL, NULL, 0 },
-/* 0x5b */ { NULL, NULL, 0 },
-/* 0x5c */ { NULL, NULL, 0 },
-/* 0x5d */ { NULL, NULL, 0 },
-/* 0x5e */ { NULL, NULL, 0 },
-/* 0x5f */ { NULL, NULL, 0 },
-/* 0x60 */ { NULL, NULL, 0 },
-/* 0x61 */ { NULL, NULL, 0 },
-/* 0x62 */ { NULL, NULL, 0 },
-/* 0x63 */ { NULL, NULL, 0 },
-/* 0x64 */ { NULL, NULL, 0 },
-/* 0x65 */ { NULL, NULL, 0 },
-/* 0x66 */ { NULL, NULL, 0 },
-/* 0x67 */ { NULL, NULL, 0 },
-/* 0x68 */ { NULL, NULL, 0 },
-/* 0x69 */ { NULL, NULL, 0 },
-/* 0x6a */ { NULL, NULL, 0 },
-/* 0x6b */ { NULL, NULL, 0 },
-/* 0x6c */ { NULL, NULL, 0 },
-/* 0x6d */ { NULL, NULL, 0 },
-/* 0x6e */ { NULL, NULL, 0 },
-/* 0x6f */ { NULL, NULL, 0 },
-/* 0x70 */ { "SMBtcon",reply_tcon,0},
-/* 0x71 */ { "SMBtdis",reply_tdis,DO_CHDIR},
-/* 0x72 */ { "SMBnegprot",reply_negprot,0},
-/* 0x73 */ { "SMBsesssetupX",reply_sesssetup_and_X,0},
-/* 0x74 */ { "SMBulogoffX", reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
-/* 0x75 */ { "SMBtconX",reply_tcon_and_X,0},
-/* 0x76 */ { NULL, NULL, 0 },
-/* 0x77 */ { NULL, NULL, 0 },
-/* 0x78 */ { NULL, NULL, 0 },
-/* 0x79 */ { NULL, NULL, 0 },
-/* 0x7a */ { NULL, NULL, 0 },
-/* 0x7b */ { NULL, NULL, 0 },
-/* 0x7c */ { NULL, NULL, 0 },
-/* 0x7d */ { NULL, NULL, 0 },
-/* 0x7e */ { NULL, NULL, 0 },
-/* 0x7f */ { NULL, NULL, 0 },
-/* 0x80 */ { "SMBdskattr",reply_dskattr,AS_USER},
-/* 0x81 */ { "SMBsearch",reply_search,AS_USER},
-/* 0x82 */ { "SMBffirst",reply_search,AS_USER},
-/* 0x83 */ { "SMBfunique",reply_search,AS_USER},
-/* 0x84 */ { "SMBfclose",reply_fclose,AS_USER},
-/* 0x85 */ { NULL, NULL, 0 },
-/* 0x86 */ { NULL, NULL, 0 },
-/* 0x87 */ { NULL, NULL, 0 },
-/* 0x88 */ { NULL, NULL, 0 },
-/* 0x89 */ { NULL, NULL, 0 },
-/* 0x8a */ { NULL, NULL, 0 },
-/* 0x8b */ { NULL, NULL, 0 },
-/* 0x8c */ { NULL, NULL, 0 },
-/* 0x8d */ { NULL, NULL, 0 },
-/* 0x8e */ { NULL, NULL, 0 },
-/* 0x8f */ { NULL, NULL, 0 },
-/* 0x90 */ { NULL, NULL, 0 },
-/* 0x91 */ { NULL, NULL, 0 },
-/* 0x92 */ { NULL, NULL, 0 },
-/* 0x93 */ { NULL, NULL, 0 },
-/* 0x94 */ { NULL, NULL, 0 },
-/* 0x95 */ { NULL, NULL, 0 },
-/* 0x96 */ { NULL, NULL, 0 },
-/* 0x97 */ { NULL, NULL, 0 },
-/* 0x98 */ { NULL, NULL, 0 },
-/* 0x99 */ { NULL, NULL, 0 },
-/* 0x9a */ { NULL, NULL, 0 },
-/* 0x9b */ { NULL, NULL, 0 },
-/* 0x9c */ { NULL, NULL, 0 },
-/* 0x9d */ { NULL, NULL, 0 },
-/* 0x9e */ { NULL, NULL, 0 },
-/* 0x9f */ { NULL, NULL, 0 },
-/* 0xa0 */ { "SMBnttrans", reply_nttrans, AS_USER | CAN_IPC },
-/* 0xa1 */ { "SMBnttranss", reply_nttranss, AS_USER | CAN_IPC },
-/* 0xa2 */ { "SMBntcreateX", reply_ntcreate_and_X, AS_USER | CAN_IPC },
-/* 0xa3 */ { NULL, NULL, 0 },
-/* 0xa4 */ { "SMBntcancel", reply_ntcancel, 0 },
-/* 0xa5 */ { "SMBntrename", reply_ntrename, AS_USER | NEED_WRITE },
-/* 0xa6 */ { NULL, NULL, 0 },
-/* 0xa7 */ { NULL, NULL, 0 },
-/* 0xa8 */ { NULL, NULL, 0 },
-/* 0xa9 */ { NULL, NULL, 0 },
-/* 0xaa */ { NULL, NULL, 0 },
-/* 0xab */ { NULL, NULL, 0 },
-/* 0xac */ { NULL, NULL, 0 },
-/* 0xad */ { NULL, NULL, 0 },
-/* 0xae */ { NULL, NULL, 0 },
-/* 0xaf */ { NULL, NULL, 0 },
-/* 0xb0 */ { NULL, NULL, 0 },
-/* 0xb1 */ { NULL, NULL, 0 },
-/* 0xb2 */ { NULL, NULL, 0 },
-/* 0xb3 */ { NULL, NULL, 0 },
-/* 0xb4 */ { NULL, NULL, 0 },
-/* 0xb5 */ { NULL, NULL, 0 },
-/* 0xb6 */ { NULL, NULL, 0 },
-/* 0xb7 */ { NULL, NULL, 0 },
-/* 0xb8 */ { NULL, NULL, 0 },
-/* 0xb9 */ { NULL, NULL, 0 },
-/* 0xba */ { NULL, NULL, 0 },
-/* 0xbb */ { NULL, NULL, 0 },
-/* 0xbc */ { NULL, NULL, 0 },
-/* 0xbd */ { NULL, NULL, 0 },
-/* 0xbe */ { NULL, NULL, 0 },
-/* 0xbf */ { NULL, NULL, 0 },
-/* 0xc0 */ { "SMBsplopen",reply_printopen,AS_USER},
-/* 0xc1 */ { "SMBsplwr",reply_printwrite,AS_USER},
-/* 0xc2 */ { "SMBsplclose",reply_printclose,AS_USER},
-/* 0xc3 */ { "SMBsplretq",reply_printqueue,AS_USER},
-/* 0xc4 */ { NULL, NULL, 0 },
-/* 0xc5 */ { NULL, NULL, 0 },
-/* 0xc6 */ { NULL, NULL, 0 },
-/* 0xc7 */ { NULL, NULL, 0 },
-/* 0xc8 */ { NULL, NULL, 0 },
-/* 0xc9 */ { NULL, NULL, 0 },
-/* 0xca */ { NULL, NULL, 0 },
-/* 0xcb */ { NULL, NULL, 0 },
-/* 0xcc */ { NULL, NULL, 0 },
-/* 0xcd */ { NULL, NULL, 0 },
-/* 0xce */ { NULL, NULL, 0 },
-/* 0xcf */ { NULL, NULL, 0 },
-/* 0xd0 */ { "SMBsends",reply_sends,AS_GUEST},
-/* 0xd1 */ { "SMBsendb",NULL,AS_GUEST},
-/* 0xd2 */ { "SMBfwdname",NULL,AS_GUEST},
-/* 0xd3 */ { "SMBcancelf",NULL,AS_GUEST},
-/* 0xd4 */ { "SMBgetmac",NULL,AS_GUEST},
-/* 0xd5 */ { "SMBsendstrt",reply_sendstrt,AS_GUEST},
-/* 0xd6 */ { "SMBsendend",reply_sendend,AS_GUEST},
-/* 0xd7 */ { "SMBsendtxt",reply_sendtxt,AS_GUEST},
-/* 0xd8 */ { NULL, NULL, 0 },
-/* 0xd9 */ { NULL, NULL, 0 },
-/* 0xda */ { NULL, NULL, 0 },
-/* 0xdb */ { NULL, NULL, 0 },
-/* 0xdc */ { NULL, NULL, 0 },
-/* 0xdd */ { NULL, NULL, 0 },
-/* 0xde */ { NULL, NULL, 0 },
-/* 0xdf */ { NULL, NULL, 0 },
-/* 0xe0 */ { NULL, NULL, 0 },
-/* 0xe1 */ { NULL, NULL, 0 },
-/* 0xe2 */ { NULL, NULL, 0 },
-/* 0xe3 */ { NULL, NULL, 0 },
-/* 0xe4 */ { NULL, NULL, 0 },
-/* 0xe5 */ { NULL, NULL, 0 },
-/* 0xe6 */ { NULL, NULL, 0 },
-/* 0xe7 */ { NULL, NULL, 0 },
-/* 0xe8 */ { NULL, NULL, 0 },
-/* 0xe9 */ { NULL, NULL, 0 },
-/* 0xea */ { NULL, NULL, 0 },
-/* 0xeb */ { NULL, NULL, 0 },
-/* 0xec */ { NULL, NULL, 0 },
-/* 0xed */ { NULL, NULL, 0 },
-/* 0xee */ { NULL, NULL, 0 },
-/* 0xef */ { NULL, NULL, 0 },
-/* 0xf0 */ { NULL, NULL, 0 },
-/* 0xf1 */ { NULL, NULL, 0 },
-/* 0xf2 */ { NULL, NULL, 0 },
-/* 0xf3 */ { NULL, NULL, 0 },
-/* 0xf4 */ { NULL, NULL, 0 },
-/* 0xf5 */ { NULL, NULL, 0 },
-/* 0xf6 */ { NULL, NULL, 0 },
-/* 0xf7 */ { NULL, NULL, 0 },
-/* 0xf8 */ { NULL, NULL, 0 },
-/* 0xf9 */ { NULL, NULL, 0 },
-/* 0xfa */ { NULL, NULL, 0 },
-/* 0xfb */ { NULL, NULL, 0 },
-/* 0xfc */ { NULL, NULL, 0 },
-/* 0xfd */ { NULL, NULL, 0 },
-/* 0xfe */ { NULL, NULL, 0 },
-/* 0xff */ { NULL, NULL, 0 }
+/* 0x00 */ { "SMBmkdir",reply_mkdir,NULL,AS_USER | NEED_WRITE},
+/* 0x01 */ { "SMBrmdir",reply_rmdir,NULL,AS_USER | NEED_WRITE},
+/* 0x02 */ { "SMBopen",reply_open,NULL,AS_USER },
+/* 0x03 */ { "SMBcreate",reply_mknew,NULL,AS_USER},
+/* 0x04 */ { "SMBclose",reply_close,NULL,AS_USER | CAN_IPC },
+/* 0x05 */ { "SMBflush",reply_flush,NULL,AS_USER},
+/* 0x06 */ { "SMBunlink",reply_unlink,NULL,AS_USER | NEED_WRITE },
+/* 0x07 */ { "SMBmv",reply_mv,NULL,AS_USER | NEED_WRITE },
+/* 0x08 */ { "SMBgetatr",reply_getatr,NULL,AS_USER},
+/* 0x09 */ { "SMBsetatr",reply_setatr,NULL,AS_USER | NEED_WRITE},
+/* 0x0a */ { "SMBread",reply_read,NULL,AS_USER},
+/* 0x0b */ { "SMBwrite",reply_write,NULL,AS_USER | CAN_IPC },
+/* 0x0c */ { "SMBlock",reply_lock,NULL,AS_USER},
+/* 0x0d */ { "SMBunlock",reply_unlock,NULL,AS_USER},
+/* 0x0e */ { "SMBctemp",reply_ctemp,NULL,AS_USER },
+/* 0x0f */ { "SMBmknew",reply_mknew,NULL,AS_USER},
+/* 0x10 */ { "SMBcheckpath",reply_checkpath,NULL,AS_USER},
+/* 0x11 */ { "SMBexit",reply_exit,NULL,DO_CHDIR},
+/* 0x12 */ { "SMBlseek",reply_lseek,NULL,AS_USER},
+/* 0x13 */ { "SMBlockread",reply_lockread,NULL,AS_USER},
+/* 0x14 */ { "SMBwriteunlock",reply_writeunlock,NULL,AS_USER},
+/* 0x15 */ { NULL, NULL, NULL, 0 },
+/* 0x16 */ { NULL, NULL, NULL, 0 },
+/* 0x17 */ { NULL, NULL, NULL, 0 },
+/* 0x18 */ { NULL, NULL, NULL, 0 },
+/* 0x19 */ { NULL, NULL, NULL, 0 },
+/* 0x1a */ { "SMBreadbraw",reply_readbraw,NULL,AS_USER},
+/* 0x1b */ { "SMBreadBmpx",reply_readbmpx,NULL,AS_USER},
+/* 0x1c */ { "SMBreadBs",NULL, NULL,0 },
+/* 0x1d */ { "SMBwritebraw",reply_writebraw,NULL,AS_USER},
+/* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,NULL,AS_USER},
+/* 0x1f */ { "SMBwriteBs",reply_writebs,NULL,AS_USER},
+/* 0x20 */ { "SMBwritec",NULL, NULL,0},
+/* 0x21 */ { NULL, NULL, NULL, 0 },
+/* 0x22 */ { "SMBsetattrE",reply_setattrE,NULL,AS_USER | NEED_WRITE },
+/* 0x23 */ { "SMBgetattrE",reply_getattrE,NULL,AS_USER },
+/* 0x24 */ { "SMBlockingX",reply_lockingX,NULL,AS_USER },
+/* 0x25 */ { "SMBtrans",reply_trans,NULL,AS_USER | CAN_IPC },
+/* 0x26 */ { "SMBtranss",reply_transs,NULL,AS_USER | CAN_IPC},
+/* 0x27 */ { "SMBioctl",reply_ioctl,NULL,0},
+/* 0x28 */ { "SMBioctls",NULL, NULL,AS_USER},
+/* 0x29 */ { "SMBcopy",reply_copy,NULL,AS_USER | NEED_WRITE },
+/* 0x2a */ { "SMBmove",NULL, NULL,AS_USER | NEED_WRITE },
+/* 0x2b */ { "SMBecho",reply_echo,NULL,0},
+/* 0x2c */ { "SMBwriteclose",reply_writeclose,NULL,AS_USER},
+/* 0x2d */ { "SMBopenX",reply_open_and_X,NULL,AS_USER | CAN_IPC },
+/* 0x2e */ { "SMBreadX",reply_read_and_X,NULL,AS_USER | CAN_IPC },
+/* 0x2f */ { "SMBwriteX",reply_write_and_X,NULL,AS_USER | CAN_IPC },
+/* 0x30 */ { NULL, NULL, NULL, 0 },
+/* 0x31 */ { NULL, NULL, NULL, 0 },
+/* 0x32 */ { "SMBtrans2", reply_trans2,NULL, AS_USER | CAN_IPC },
+/* 0x33 */ { "SMBtranss2", reply_transs2,NULL, AS_USER},
+/* 0x34 */ { "SMBfindclose", reply_findclose,NULL,AS_USER},
+/* 0x35 */ { "SMBfindnclose", reply_findnclose,NULL, AS_USER},
+/* 0x36 */ { NULL, NULL, NULL, 0 },
+/* 0x37 */ { NULL, NULL, NULL, 0 },
+/* 0x38 */ { NULL, NULL, NULL, 0 },
+/* 0x39 */ { NULL, NULL, NULL, 0 },
+/* 0x3a */ { NULL, NULL, NULL, 0 },
+/* 0x3b */ { NULL, NULL, NULL, 0 },
+/* 0x3c */ { NULL, NULL, NULL, 0 },
+/* 0x3d */ { NULL, NULL, NULL, 0 },
+/* 0x3e */ { NULL, NULL, NULL, 0 },
+/* 0x3f */ { NULL, NULL, NULL, 0 },
+/* 0x40 */ { NULL, NULL, NULL, 0 },
+/* 0x41 */ { NULL, NULL, NULL, 0 },
+/* 0x42 */ { NULL, NULL, NULL, 0 },
+/* 0x43 */ { NULL, NULL, NULL, 0 },
+/* 0x44 */ { NULL, NULL, NULL, 0 },
+/* 0x45 */ { NULL, NULL, NULL, 0 },
+/* 0x46 */ { NULL, NULL, NULL, 0 },
+/* 0x47 */ { NULL, NULL, NULL, 0 },
+/* 0x48 */ { NULL, NULL, NULL, 0 },
+/* 0x49 */ { NULL, NULL, NULL, 0 },
+/* 0x4a */ { NULL, NULL, NULL, 0 },
+/* 0x4b */ { NULL, NULL, NULL, 0 },
+/* 0x4c */ { NULL, NULL, NULL, 0 },
+/* 0x4d */ { NULL, NULL, NULL, 0 },
+/* 0x4e */ { NULL, NULL, NULL, 0 },
+/* 0x4f */ { NULL, NULL, NULL, 0 },
+/* 0x50 */ { NULL, NULL, NULL, 0 },
+/* 0x51 */ { NULL, NULL, NULL, 0 },
+/* 0x52 */ { NULL, NULL, NULL, 0 },
+/* 0x53 */ { NULL, NULL, NULL, 0 },
+/* 0x54 */ { NULL, NULL, NULL, 0 },
+/* 0x55 */ { NULL, NULL, NULL, 0 },
+/* 0x56 */ { NULL, NULL, NULL, 0 },
+/* 0x57 */ { NULL, NULL, NULL, 0 },
+/* 0x58 */ { NULL, NULL, NULL, 0 },
+/* 0x59 */ { NULL, NULL, NULL, 0 },
+/* 0x5a */ { NULL, NULL, NULL, 0 },
+/* 0x5b */ { NULL, NULL, NULL, 0 },
+/* 0x5c */ { NULL, NULL, NULL, 0 },
+/* 0x5d */ { NULL, NULL, NULL, 0 },
+/* 0x5e */ { NULL, NULL, NULL, 0 },
+/* 0x5f */ { NULL, NULL, NULL, 0 },
+/* 0x60 */ { NULL, NULL, NULL, 0 },
+/* 0x61 */ { NULL, NULL, NULL, 0 },
+/* 0x62 */ { NULL, NULL, NULL, 0 },
+/* 0x63 */ { NULL, NULL, NULL, 0 },
+/* 0x64 */ { NULL, NULL, NULL, 0 },
+/* 0x65 */ { NULL, NULL, NULL, 0 },
+/* 0x66 */ { NULL, NULL, NULL, 0 },
+/* 0x67 */ { NULL, NULL, NULL, 0 },
+/* 0x68 */ { NULL, NULL, NULL, 0 },
+/* 0x69 */ { NULL, NULL, NULL, 0 },
+/* 0x6a */ { NULL, NULL, NULL, 0 },
+/* 0x6b */ { NULL, NULL, NULL, 0 },
+/* 0x6c */ { NULL, NULL, NULL, 0 },
+/* 0x6d */ { NULL, NULL, NULL, 0 },
+/* 0x6e */ { NULL, NULL, NULL, 0 },
+/* 0x6f */ { NULL, NULL, NULL, 0 },
+/* 0x70 */ { "SMBtcon",reply_tcon,NULL,0},
+/* 0x71 */ { "SMBtdis",reply_tdis,NULL,DO_CHDIR},
+/* 0x72 */ { "SMBnegprot",reply_negprot,NULL,0},
+/* 0x73 */ { "SMBsesssetupX",reply_sesssetup_and_X,NULL,0},
+/* 0x74 */ { "SMBulogoffX", reply_ulogoffX,NULL, 0}, /* ulogoff doesn't give a valid TID */
+/* 0x75 */ { "SMBtconX",reply_tcon_and_X,NULL,0},
+/* 0x76 */ { NULL, NULL, NULL, 0 },
+/* 0x77 */ { NULL, NULL, NULL, 0 },
+/* 0x78 */ { NULL, NULL, NULL, 0 },
+/* 0x79 */ { NULL, NULL, NULL, 0 },
+/* 0x7a */ { NULL, NULL, NULL, 0 },
+/* 0x7b */ { NULL, NULL, NULL, 0 },
+/* 0x7c */ { NULL, NULL, NULL, 0 },
+/* 0x7d */ { NULL, NULL, NULL, 0 },
+/* 0x7e */ { NULL, NULL, NULL, 0 },
+/* 0x7f */ { NULL, NULL, NULL, 0 },
+/* 0x80 */ { "SMBdskattr",reply_dskattr,NULL,AS_USER},
+/* 0x81 */ { "SMBsearch",reply_search,NULL,AS_USER},
+/* 0x82 */ { "SMBffirst",reply_search,NULL,AS_USER},
+/* 0x83 */ { "SMBfunique",reply_search,NULL,AS_USER},
+/* 0x84 */ { "SMBfclose",reply_fclose,NULL,AS_USER},
+/* 0x85 */ { NULL, NULL, NULL, 0 },
+/* 0x86 */ { NULL, NULL, NULL, 0 },
+/* 0x87 */ { NULL, NULL, NULL, 0 },
+/* 0x88 */ { NULL, NULL, NULL, 0 },
+/* 0x89 */ { NULL, NULL, NULL, 0 },
+/* 0x8a */ { NULL, NULL, NULL, 0 },
+/* 0x8b */ { NULL, NULL, NULL, 0 },
+/* 0x8c */ { NULL, NULL, NULL, 0 },
+/* 0x8d */ { NULL, NULL, NULL, 0 },
+/* 0x8e */ { NULL, NULL, NULL, 0 },
+/* 0x8f */ { NULL, NULL, NULL, 0 },
+/* 0x90 */ { NULL, NULL, NULL, 0 },
+/* 0x91 */ { NULL, NULL, NULL, 0 },
+/* 0x92 */ { NULL, NULL, NULL, 0 },
+/* 0x93 */ { NULL, NULL, NULL, 0 },
+/* 0x94 */ { NULL, NULL, NULL, 0 },
+/* 0x95 */ { NULL, NULL, NULL, 0 },
+/* 0x96 */ { NULL, NULL, NULL, 0 },
+/* 0x97 */ { NULL, NULL, NULL, 0 },
+/* 0x98 */ { NULL, NULL, NULL, 0 },
+/* 0x99 */ { NULL, NULL, NULL, 0 },
+/* 0x9a */ { NULL, NULL, NULL, 0 },
+/* 0x9b */ { NULL, NULL, NULL, 0 },
+/* 0x9c */ { NULL, NULL, NULL, 0 },
+/* 0x9d */ { NULL, NULL, NULL, 0 },
+/* 0x9e */ { NULL, NULL, NULL, 0 },
+/* 0x9f */ { NULL, NULL, NULL, 0 },
+/* 0xa0 */ { "SMBnttrans", reply_nttrans,NULL, AS_USER | CAN_IPC },
+/* 0xa1 */ { "SMBnttranss", reply_nttranss,NULL, AS_USER | CAN_IPC },
+/* 0xa2 */ { "SMBntcreateX", reply_ntcreate_and_X,NULL, AS_USER | CAN_IPC },
+/* 0xa3 */ { NULL, NULL, NULL, 0 },
+/* 0xa4 */ { "SMBntcancel", reply_ntcancel,NULL, 0 },
+/* 0xa5 */ { "SMBntrename", reply_ntrename,NULL, AS_USER | NEED_WRITE },
+/* 0xa6 */ { NULL, NULL, NULL, 0 },
+/* 0xa7 */ { NULL, NULL, NULL, 0 },
+/* 0xa8 */ { NULL, NULL, NULL, 0 },
+/* 0xa9 */ { NULL, NULL, NULL, 0 },
+/* 0xaa */ { NULL, NULL, NULL, 0 },
+/* 0xab */ { NULL, NULL, NULL, 0 },
+/* 0xac */ { NULL, NULL, NULL, 0 },
+/* 0xad */ { NULL, NULL, NULL, 0 },
+/* 0xae */ { NULL, NULL, NULL, 0 },
+/* 0xaf */ { NULL, NULL, NULL, 0 },
+/* 0xb0 */ { NULL, NULL, NULL, 0 },
+/* 0xb1 */ { NULL, NULL, NULL, 0 },
+/* 0xb2 */ { NULL, NULL, NULL, 0 },
+/* 0xb3 */ { NULL, NULL, NULL, 0 },
+/* 0xb4 */ { NULL, NULL, NULL, 0 },
+/* 0xb5 */ { NULL, NULL, NULL, 0 },
+/* 0xb6 */ { NULL, NULL, NULL, 0 },
+/* 0xb7 */ { NULL, NULL, NULL, 0 },
+/* 0xb8 */ { NULL, NULL, NULL, 0 },
+/* 0xb9 */ { NULL, NULL, NULL, 0 },
+/* 0xba */ { NULL, NULL, NULL, 0 },
+/* 0xbb */ { NULL, NULL, NULL, 0 },
+/* 0xbc */ { NULL, NULL, NULL, 0 },
+/* 0xbd */ { NULL, NULL, NULL, 0 },
+/* 0xbe */ { NULL, NULL, NULL, 0 },
+/* 0xbf */ { NULL, NULL, NULL, 0 },
+/* 0xc0 */ { "SMBsplopen",reply_printopen,NULL,AS_USER},
+/* 0xc1 */ { "SMBsplwr",reply_printwrite,NULL,AS_USER},
+/* 0xc2 */ { "SMBsplclose",reply_printclose,NULL,AS_USER},
+/* 0xc3 */ { "SMBsplretq",reply_printqueue,NULL,AS_USER},
+/* 0xc4 */ { NULL, NULL, NULL, 0 },
+/* 0xc5 */ { NULL, NULL, NULL, 0 },
+/* 0xc6 */ { NULL, NULL, NULL, 0 },
+/* 0xc7 */ { NULL, NULL, NULL, 0 },
+/* 0xc8 */ { NULL, NULL, NULL, 0 },
+/* 0xc9 */ { NULL, NULL, NULL, 0 },
+/* 0xca */ { NULL, NULL, NULL, 0 },
+/* 0xcb */ { NULL, NULL, NULL, 0 },
+/* 0xcc */ { NULL, NULL, NULL, 0 },
+/* 0xcd */ { NULL, NULL, NULL, 0 },
+/* 0xce */ { NULL, NULL, NULL, 0 },
+/* 0xcf */ { NULL, NULL, NULL, 0 },
+/* 0xd0 */ { "SMBsends",reply_sends,NULL,AS_GUEST},
+/* 0xd1 */ { "SMBsendb",NULL, NULL,AS_GUEST},
+/* 0xd2 */ { "SMBfwdname",NULL, NULL,AS_GUEST},
+/* 0xd3 */ { "SMBcancelf",NULL, NULL,AS_GUEST},
+/* 0xd4 */ { "SMBgetmac",NULL, NULL,AS_GUEST},
+/* 0xd5 */ { "SMBsendstrt",reply_sendstrt,NULL,AS_GUEST},
+/* 0xd6 */ { "SMBsendend",reply_sendend,NULL,AS_GUEST},
+/* 0xd7 */ { "SMBsendtxt",reply_sendtxt,NULL,AS_GUEST},
+/* 0xd8 */ { NULL, NULL, NULL, 0 },
+/* 0xd9 */ { NULL, NULL, NULL, 0 },
+/* 0xda */ { NULL, NULL, NULL, 0 },
+/* 0xdb */ { NULL, NULL, NULL, 0 },
+/* 0xdc */ { NULL, NULL, NULL, 0 },
+/* 0xdd */ { NULL, NULL, NULL, 0 },
+/* 0xde */ { NULL, NULL, NULL, 0 },
+/* 0xdf */ { NULL, NULL, NULL, 0 },
+/* 0xe0 */ { NULL, NULL, NULL, 0 },
+/* 0xe1 */ { NULL, NULL, NULL, 0 },
+/* 0xe2 */ { NULL, NULL, NULL, 0 },
+/* 0xe3 */ { NULL, NULL, NULL, 0 },
+/* 0xe4 */ { NULL, NULL, NULL, 0 },
+/* 0xe5 */ { NULL, NULL, NULL, 0 },
+/* 0xe6 */ { NULL, NULL, NULL, 0 },
+/* 0xe7 */ { NULL, NULL, NULL, 0 },
+/* 0xe8 */ { NULL, NULL, NULL, 0 },
+/* 0xe9 */ { NULL, NULL, NULL, 0 },
+/* 0xea */ { NULL, NULL, NULL, 0 },
+/* 0xeb */ { NULL, NULL, NULL, 0 },
+/* 0xec */ { NULL, NULL, NULL, 0 },
+/* 0xed */ { NULL, NULL, NULL, 0 },
+/* 0xee */ { NULL, NULL, NULL, 0 },
+/* 0xef */ { NULL, NULL, NULL, 0 },
+/* 0xf0 */ { NULL, NULL, NULL, 0 },
+/* 0xf1 */ { NULL, NULL, NULL, 0 },
+/* 0xf2 */ { NULL, NULL, NULL, 0 },
+/* 0xf3 */ { NULL, NULL, NULL, 0 },
+/* 0xf4 */ { NULL, NULL, NULL, 0 },
+/* 0xf5 */ { NULL, NULL, NULL, 0 },
+/* 0xf6 */ { NULL, NULL, NULL, 0 },
+/* 0xf7 */ { NULL, NULL, NULL, 0 },
+/* 0xf8 */ { NULL, NULL, NULL, 0 },
+/* 0xf9 */ { NULL, NULL, NULL, 0 },
+/* 0xfa */ { NULL, NULL, NULL, 0 },
+/* 0xfb */ { NULL, NULL, NULL, 0 },
+/* 0xfc */ { NULL, NULL, NULL, 0 },
+/* 0xfd */ { NULL, NULL, NULL, 0 },
+/* 0xfe */ { NULL, NULL, NULL, 0 },
+/* 0xff */ { NULL, NULL, NULL, 0 }
 
 };
 
+/*******************************************************************
+ allocate and initialize a reply packet
+********************************************************************/
+
+void reply_outbuf(struct smb_request *req, uint8 num_words, uint16 num_bytes)
+{
+       if (!(req->outbuf = TALLOC_ARRAY(
+                     req, uint8,
+                     smb_size + num_words*2 + num_bytes))) {
+               smb_panic("could not allocate output buffer\n");
+       }
+
+       construct_reply_common((char *)req->inbuf, (char *)req->outbuf);
+       set_message((char *)req->inbuf, (char *)req->outbuf,
+                   num_words, num_bytes, False);
+       /*
+        * Zero out the word area, the caller has to take care of the bcc area
+        * himself
+        */
+       if (num_words != 0) {
+               memset(req->outbuf + smb_vwv0, 0, num_words*2);
+       }
+
+       return;
+}
+
+
 /*******************************************************************
  Dump a packet to a file.
 ********************************************************************/
 
-static void smb_dump(const char *name, int type, char *data, ssize_t len)
+static void smb_dump(const char *name, int type, const char *data, ssize_t len)
 {
        int fd, i;
        pstring fname;
@@ -891,37 +946,47 @@ static void smb_dump(const char *name, int type, char *data, ssize_t len)
        }
 }
 
-
 /****************************************************************************
- Do a switch on the message type, and return the response size
+ Prepare everything for calling the actual request function, and potentially
+ call the request function via the "new" interface.
+
+ Return False if the "legacy" function needs to be called, everything is
+ prepared.
+
+ Return True if we're done.
+
+ I know this API sucks, but it is the one with the least code change I could
+ find.
 ****************************************************************************/
 
-static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize)
+static BOOL switch_message_new(uint8 type, struct smb_request *req, int size,
+                              connection_struct **pconn)
 {
-       int outsize = 0;
        int flags;
        uint16 session_tag;
        connection_struct *conn;
 
        static uint16 last_session_tag = UID_FIELD_INVALID;
 
-       type &= 0xff;
-
        errno = 0;
 
        last_message = type;
 
-       /* Make sure this is an SMB packet. smb_size contains NetBIOS header so subtract 4 from it. */
-       if ((strncmp(smb_base(inbuf),"\377SMB",4) != 0) || (size < (smb_size - 4))) {
-               DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",smb_len(inbuf)));
+       /* Make sure this is an SMB packet. smb_size contains NetBIOS header
+        * so subtract 4 from it. */
+       if ((strncmp(smb_base(req->inbuf),"\377SMB",4) != 0)
+           || (size < (smb_size - 4))) {
+               DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",
+                        smb_len(req->inbuf)));
                exit_server_cleanly("Non-SMB packet");
-               return(-1);
+               return True;
        }
 
-       if (smb_messages[type].fn == NULL) {
+       if ((smb_messages[type].fn == NULL)
+           && (smb_messages[type].fn_new == NULL)) {
                DEBUG(0,("Unknown message type %d!\n",type));
-               smb_dump("Unknown", 1, inbuf, size);
-               outsize = reply_unknown(inbuf,outbuf);
+               smb_dump("Unknown", 1, (char *)req->inbuf, size);
+               reply_unknown_new(req, type);
                goto done;
        }
 
@@ -929,16 +994,16 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize
 
        /* In share mode security we must ignore the vuid. */
        session_tag = (lp_security() == SEC_SHARE)
-               ? UID_FIELD_INVALID : SVAL(inbuf,smb_uid);
-       conn = conn_find(SVAL(inbuf,smb_tid));
+               ? UID_FIELD_INVALID : req->vuid;
+       conn = conn_find(req->tid);
 
        DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n", smb_fn_name(type),
                 (int)sys_getpid(), (unsigned long)conn));
 
-       smb_dump(smb_fn_name(type), 1, inbuf, size);
+       smb_dump(smb_fn_name(type), 1, (char *)req->inbuf, size);
 
        /* Ensure this value is replaced in the incoming packet. */
-       SSVAL(inbuf,smb_uid,session_tag);
+       SSVAL(req->inbuf,smb_uid,session_tag);
 
        /*
         * Ensure the correct username is in current_user_info.  This is a
@@ -971,26 +1036,30 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize
                         * (from Samba4).
                         */
                        if (type == SMBntcreateX) {
-                               return ERROR_NT(NT_STATUS_INVALID_HANDLE);
+                               reply_nterror(req, NT_STATUS_INVALID_HANDLE);
                        } else {
-                               return ERROR_DOS(ERRSRV, ERRinvnid);
+                               reply_doserror(req, ERRSRV, ERRinvnid);
                        }
+                       goto done;
                }
 
                if (!change_to_user(conn,session_tag)) {
-                       return(ERROR_NT(NT_STATUS_DOS(ERRSRV,ERRbaduid)));
+                       reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRbaduid));
+                       goto done;
                }
 
                /* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */
 
                /* Does it need write permission? */
                if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) {
-                       return ERROR_NT(NT_STATUS_MEDIA_WRITE_PROTECTED);
+                       reply_nterror(req, NT_STATUS_MEDIA_WRITE_PROTECTED);
+                       goto done;
                }
 
                /* IPC services are limited */
                if (IS_IPC(conn) && !(flags & CAN_IPC)) {
-                       return(ERROR_DOS(ERRSRV,ERRaccess));
+                       reply_doserror(req, ERRSRV,ERRaccess);
+                       goto done;
                }
        } else {
                /* This call needs to be run as root */
@@ -999,10 +1068,11 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize
 
        /* load service specific parameters */
        if (conn) {
-               if (!set_current_service(conn,SVAL(inbuf,smb_flg),
+               if (!set_current_service(conn,SVAL(req->inbuf,smb_flg),
                                         (flags & (AS_USER|DO_CHDIR)
                                          ?True:False))) {
-                       return(ERROR_DOS(ERRSRV,ERRaccess));
+                       reply_doserror(req, ERRSRV, ERRaccess);
+                       goto done;
                }
                conn->num_smb_operations++;
        }
@@ -1012,15 +1082,72 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize
            && (!change_to_guest() ||
                !check_access(smbd_server_fd(), lp_hostsallow(-1),
                              lp_hostsdeny(-1)))) {
-               return(ERROR_DOS(ERRSRV,ERRaccess));
+               reply_doserror(req, ERRSRV, ERRaccess);
+               goto done;
        }
 
-       current_inbuf = inbuf; /* In case we need to defer this message in
-                               * open... */
-       outsize = smb_messages[type].fn(conn, inbuf,outbuf,size,bufsize);
+       current_inbuf = (char *)req->inbuf; /* In case we need to defer this
+                                            * message in open... */
+
+       if (smb_messages[type].fn_new != NULL) {
+               smb_messages[type].fn_new(conn, req);
+               goto done;
+       }
+
+       /*
+        * Indicate the upper layer that there's still work.
+        */
+       *pconn = conn;
+       return False;
 
  done:
-       smb_dump(smb_fn_name(type), 0, outbuf, outsize);
+       return True;
+}
+
+
+/****************************************************************************
+ Do a switch on the message type, and return the response size
+****************************************************************************/
+
+static int switch_message(uint8 type, struct smb_request *req, char **outbuf,
+                         int size, int bufsize)
+{
+       int outsize = 0;
+       connection_struct *conn = NULL;
+
+       if (switch_message_new(type, req, size, &conn)) {
+               if (req->outbuf != NULL) {
+                       *outbuf = (char *)req->outbuf;
+                       return smb_len(req->outbuf)+4;
+               }
+               return -1;
+       }
+
+       if (InBuffer == NULL) {
+               DEBUG(1, ("have to alloc InBuffer for %s\n",
+                         smb_fn_name(type)));
+               if (NewInBuffer(NULL) == NULL) {
+                       smb_panic("Could not allocate InBuffer");
+               }
+       }
+
+       if ((OutBuffer == NULL) && (NewOutBuffer(NULL) == NULL)) {
+               smb_panic("Could not allocate OutBuffer");
+       }
+
+       clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer,
+                      total_buffer_size);
+
+       memcpy(InBuffer, req->inbuf, MIN(size, total_buffer_size));
+
+       construct_reply_common(InBuffer, OutBuffer);
+
+       outsize = smb_messages[type].fn(conn, InBuffer, OutBuffer, size,
+                                       bufsize);
+
+       smb_dump(smb_fn_name(type), 0, OutBuffer, outsize);
+
+       *outbuf = OutBuffer;
 
        return(outsize);
 }
@@ -1029,41 +1156,54 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize
  Construct a reply to the incoming packet.
 ****************************************************************************/
 
-static int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
+static void construct_reply(char *inbuf, int size)
 {
-       int type = CVAL(inbuf,smb_com);
+       uint8 type = CVAL(inbuf,smb_com);
        int outsize = 0;
-       int msg_type = CVAL(inbuf,0);
+       struct smb_request *req;
+       char *outbuf;
 
        chain_size = 0;
        file_chain_reset();
        reset_chain_p();
 
-       if (msg_type != 0)
-               return(reply_special(inbuf,outbuf));  
+       if (!(req = talloc(tmp_talloc_ctx(), struct smb_request))) {
+               smb_panic("could not allocate smb_request");
+       }
+       init_smb_request(req, (uint8 *)inbuf);
 
-       construct_reply_common(inbuf, outbuf);
+       outsize = switch_message(type, req, &outbuf, size, max_send);
 
-       outsize = switch_message(type,inbuf,outbuf,size,bufsize);
+       if (outsize > 4) {
+               smb_setlen(inbuf,outbuf,outsize - 4);
+       }
 
-       outsize += chain_size;
+       if (outsize > 0) {
+               if (CVAL(outbuf,0) == 0)
+                       show_msg(outbuf);
 
-       if(outsize > 4) {
-               smb_setlen(inbuf,outbuf,outsize - 4);
+               if (outsize != smb_len(outbuf) + 4) {
+                       DEBUG(0,("ERROR: Invalid message response size! "
+                                "%d %d\n", outsize, smb_len(outbuf)));
+               } else if (!send_smb(smbd_server_fd(),outbuf)) {
+                       exit_server_cleanly("construct_reply: send_smb "
+                                           "failed.");
+               }
        }
-       return(outsize);
+
+       TALLOC_FREE(req);
+
+       return;
 }
 
 /****************************************************************************
  Process an smb from the client
 ****************************************************************************/
 
-static void process_smb(char *inbuf, char *outbuf)
+static void process_smb(char *inbuf, size_t nread)
 {
        static int trans_num;
        int msg_type = CVAL(inbuf,0);
-       int32 len = smb_len(inbuf);
-       int nread = len + 4;
 
        DO_PROFILE_INC(smb_count);
 
@@ -1082,27 +1222,22 @@ static void process_smb(char *inbuf, char *outbuf)
                }
        }
 
-       DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type, len ) );
+       DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type,
+                   smb_len(inbuf) ) );
        DEBUG( 3, ( "Transaction %d of length %d\n", trans_num, nread ) );
 
-       if (msg_type == 0)
-               show_msg(inbuf);
-       else if(msg_type == SMBkeepalive)
-               return; /* Keepalive packet. */
+       if (msg_type != 0) {
+               /*
+                * NetBIOS session request, keepalive, etc.
+                */
+               reply_special(inbuf);
+               return;
+       }
 
-       nread = construct_reply(inbuf,outbuf,nread,max_send);
+       show_msg(inbuf);
+
+       construct_reply(inbuf,nread);
       
-       if(nread > 0) {
-               if (CVAL(outbuf,0) == 0)
-                       show_msg(outbuf);
-       
-               if (nread != smb_len(outbuf) + 4) {
-                       DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
-                               nread, smb_len(outbuf)));
-               } else if (!send_smb(smbd_server_fd(),outbuf)) {
-                       exit_server_cleanly("process_smb: send_smb failed.");
-               }
-       }
        trans_num++;
 }
 
@@ -1158,18 +1293,23 @@ void construct_reply_common(const char *inbuf, char *outbuf)
  Construct a chained reply and add it to the already made reply
 ****************************************************************************/
 
-int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
+int chain_reply(char *inbuf,char **poutbuf,int size,int bufsize)
 {
        static char *orig_inbuf;
-       static char *orig_outbuf;
        int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0);
        unsigned smb_off2 = SVAL(inbuf,smb_vwv1);
-       char *inbuf2, *outbuf2;
+       char *inbuf2;
        int outsize2;
        int new_size;
        char inbuf_saved[smb_wct];
-       char outbuf_saved[smb_wct];
-       int outsize = smb_len(outbuf) + 4;
+       char *outbuf = *poutbuf;
+       size_t outsize = smb_len(outbuf) + 4;
+       size_t outsize_padded;
+       size_t ofs, to_move;
+
+       struct smb_request *req;
+       size_t caller_outputlen;
+       char *caller_output;
 
        /* Maybe its not chained, or it's an error packet. */
        if (smb_com2 == 0xFF || SVAL(outbuf,smb_rcls) != 0) {
@@ -1180,7 +1320,20 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
        if (chain_size == 0) {
                /* this is the first part of the chain */
                orig_inbuf = inbuf;
-               orig_outbuf = outbuf;
+       }
+
+       /*
+        * We need to save the output the caller added to the chain so that we
+        * can splice it into the final output buffer later.
+        */
+
+       caller_outputlen = outsize - smb_wct;
+
+       caller_output = (char *)memdup(outbuf + smb_wct, caller_outputlen);
+
+       if (caller_output == NULL) {
+               /* TODO: NT_STATUS_NO_MEMORY */
+               smb_panic("could not dup outbuf");
        }
 
        /*
@@ -1189,27 +1342,25 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
         * 4 byte aligned. JRA.
         */
 
-       outsize = (outsize + 3) & ~3;
+       outsize_padded = (outsize + 3) & ~3;
 
-       /* we need to tell the client where the next part of the reply will be */
-       SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf));
-       SCVAL(outbuf,smb_vwv0,smb_com2);
-
-       /* remember how much the caller added to the chain, only counting stuff
-               after the parameter words */
-       chain_size += outsize - smb_wct;
+       /*
+        * remember how much the caller added to the chain, only counting
+        * stuff after the parameter words
+        */
+       chain_size += outsize_padded - smb_wct;
 
-       /* work out pointers into the original packets. The
-               headers on these need to be filled in */
+       /*
+        * work out pointers into the original packets. The
+        * headers on these need to be filled in
+        */
        inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct;
-       outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct;
 
        /* remember the original command type */
        smb_com1 = CVAL(orig_inbuf,smb_com);
 
        /* save the data which will be overwritten by the new headers */
        memcpy(inbuf_saved,inbuf2,smb_wct);
-       memcpy(outbuf_saved,outbuf2,smb_wct);
 
        /* give the new packet the same header as the last part of the SMB */
        memmove(inbuf2,inbuf,smb_wct);
@@ -1230,34 +1381,112 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
        /* And set it in the header. */
        smb_setlen(inbuf, inbuf2, new_size);
 
-       /* create the out buffer */
-       construct_reply_common(inbuf2, outbuf2);
-
        DEBUG(3,("Chained message\n"));
        show_msg(inbuf2);
 
+       if (!(req = talloc(tmp_talloc_ctx(), struct smb_request))) {
+               smb_panic("could not allocate smb_request");
+       }
+       init_smb_request(req, (uint8 *)inbuf2);
+
        /* process the request */
-       outsize2 = switch_message(smb_com2,inbuf2,outbuf2,new_size,
-                               bufsize-chain_size);
+       outsize2 = switch_message(smb_com2, req, &outbuf, new_size,
+                                 bufsize-chain_size);
 
-       /* copy the new reply and request headers over the old ones, but
-               preserve the smb_com field */
-       memmove(orig_outbuf,outbuf2,smb_wct);
-       SCVAL(orig_outbuf,smb_com,smb_com1);
+       /*
+        * We don't accept deferred operations in chained requests.
+        */
+       SMB_ASSERT(outsize2 >= smb_wct);
 
-       /* restore the saved data, being careful not to overwrite any
-               data from the reply header */
-       memcpy(inbuf2,inbuf_saved,smb_wct);
+       /*
+        * Move away the new command output so that caller_output fits in,
+        * copy in the caller_output saved above.
+        */
 
-       {
-               int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf);
-               if (ofs < 0) {
-                       ofs = 0;
+       SMB_ASSERT(outsize_padded >= smb_wct);
+
+       /*
+        * "ofs" is the space we need for caller_output. Equal to
+        * caller_outputlen plus the padding.
+        */
+
+       ofs = outsize_padded - smb_wct;
+
+       /*
+        * "to_move" is the amount of bytes the secondary routine gave us
+        */
+
+       to_move = outsize2 - smb_wct;
+
+       if (to_move + ofs + smb_wct + chain_size > max_send) {
+               smb_panic("replies too large -- would have to cut");
+       }
+
+       /*
+        * In the "new" API "outbuf" is allocated via reply_outbuf, just for
+        * the first request in the chain. So we have to re-allocate it. In
+        * the "old" API the only outbuf ever used is the global OutBuffer
+        * which is always large enough.
+        */
+
+       if (outbuf != OutBuffer) {
+               outbuf = TALLOC_REALLOC_ARRAY(NULL, outbuf, char,
+                                             to_move + ofs + smb_wct);
+               if (outbuf == NULL) {
+                       smb_panic("could not realloc outbuf");
                }
-               memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs);
        }
 
-       return outsize2;
+       *poutbuf = outbuf;
+
+       memmove(outbuf + smb_wct + ofs, outbuf + smb_wct, to_move);
+       memcpy(outbuf + smb_wct, caller_output, caller_outputlen);
+
+       /*
+        * The secondary function has overwritten smb_com
+        */
+
+       SCVAL(outbuf, smb_com, smb_com1);
+
+       /*
+        * We've just copied in the whole "wct" area from the secondary
+        * function. Fix up the chaining: com2 and the offset need to be
+        * readjusted.
+        */
+
+       SCVAL(outbuf, smb_vwv0, smb_com2);
+       SSVAL(outbuf, smb_vwv1, chain_size + smb_wct - 4);
+
+       if (outsize_padded > outsize) {
+
+               /*
+                * Due to padding we have some uninitialized bytes after the
+                * caller's output
+                */
+
+               memset(outbuf + outsize, 0, outsize_padded - outsize);
+       }
+
+       smb_setlen(NULL, outbuf, outsize2 + chain_size - 4);
+
+       /*
+        * restore the saved data, being careful not to overwrite any data
+        * from the reply header
+        */
+       memcpy(inbuf2,inbuf_saved,smb_wct);
+
+       SAFE_FREE(caller_output);
+       TALLOC_FREE(req);
+
+       return outsize2 + chain_size;
+}
+
+void chain_reply_new(struct smb_request *req)
+{
+       chain_reply(CONST_DISCARD(char *, req->inbuf),
+                   (char **)(void *)&req->outbuf,
+                   smb_len(req->inbuf)+4,
+                   smb_len(req->outbuf)+4);
 }
 
 /****************************************************************************
@@ -1450,8 +1679,6 @@ char *get_OutBuffer(void)
        return OutBuffer;
 }
 
-const int total_buffer_size = (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN);
-
 /****************************************************************************
  Allocate a new InBuffer. Returns the new and old ones.
 ****************************************************************************/
@@ -1501,16 +1728,13 @@ void smbd_process(void)
        time_t last_timeout_processing_time = time(NULL);
        unsigned int num_smbs = 0;
 
-       /* Allocate the primary Inbut/Output buffers. */
-
-       if ((NewInBuffer(NULL) == NULL) || (NewOutBuffer(NULL) == NULL)) 
-               return;
-
        max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
 
        while (True) {
                int select_timeout = setup_select_timeout();
                int num_echos;
+               char *inbuf;
+               size_t inbuf_len;
 
                errno = 0;      
                
@@ -1528,17 +1752,15 @@ void smbd_process(void)
 
                run_events(smbd_event_context(), 0, NULL, NULL);
 
-#if defined(DEVELOPER)
-               clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size);
-#endif
-
-               while (!receive_message_or_smb(InBuffer,BUFFER_SIZE+LARGE_WRITEX_HDR_SIZE,select_timeout)) {
+               while (!receive_message_or_smb(NULL, &inbuf, &inbuf_len,
+                                              select_timeout)) {
                        if(!timeout_processing(&select_timeout,
                                               &last_timeout_processing_time))
                                return;
                        num_smbs = 0; /* Reset smb counter. */
                }
 
+
                /*
                 * Ensure we do timeout processing if the SMB we just got was
                 * only an echo request. This allows us to set the select
@@ -1550,9 +1772,9 @@ void smbd_process(void)
                 */ 
                num_echos = smb_echo_count;
 
-               clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer, total_buffer_size);
+               process_smb(inbuf, inbuf_len);
 
-               process_smb(InBuffer, OutBuffer);
+               TALLOC_FREE(inbuf);
 
                if (smb_echo_count != num_echos) {
                        if(!timeout_processing( &select_timeout, &last_timeout_processing_time))
index f8d3bb8c48944d7b087d4ccca043a751c1408918..00e2bf59840570b2bbbaf498f9ee0871be8d1b83 100644 (file)
@@ -284,22 +284,28 @@ size_t srvstr_get_path(const char *inbuf, uint16 smb_flags2, char *dest,
 }
 
 /****************************************************************************
- Reply to a special message.
+ Reply to a (netbios-level) special message.
 ****************************************************************************/
 
-int reply_special(char *inbuf,char *outbuf)
+void reply_special(char *inbuf)
 {
-       int outsize = 4;
        int msg_type = CVAL(inbuf,0);
        int msg_flags = CVAL(inbuf,1);
        fstring name1,name2;
        char name_type = 0;
+
+       /*
+        * We only really use 4 bytes of the outbuf, but for the smb_setlen
+        * calculation & friends (send_smb uses that) we need the full smb
+        * header.
+        */
+       char outbuf[smb_size];
        
        static BOOL already_got_session = False;
 
        *name1 = *name2 = 0;
        
-       memset(outbuf,'\0',smb_size);
+       memset(outbuf, '\0', sizeof(outbuf));
 
        smb_setlen(inbuf,outbuf,0);
        
@@ -315,7 +321,7 @@ int reply_special(char *inbuf,char *outbuf)
                if (name_len(inbuf+4) > 50 || 
                    name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
                        DEBUG(0,("Invalid name length in session request\n"));
-                       return(0);
+                       return;
                }
                name_extract(inbuf,4,name1);
                name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
@@ -363,13 +369,14 @@ int reply_special(char *inbuf,char *outbuf)
                
        case SMBkeepalive: /* session keepalive */
        default:
-               return(0);
+               return;
        }
        
        DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
                    msg_type, msg_flags));
-       
-       return(outsize);
+
+       send_smb(smbd_server_fd(), outbuf);
+       return;
 }
 
 /****************************************************************************
@@ -613,7 +620,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
 
        TALLOC_FREE(ctx);
        END_PROFILE(SMBtconX);
-       return chain_reply(inbuf,outbuf,length,bufsize);
+       return chain_reply(inbuf,&outbuf,length,bufsize);
 }
 
 /****************************************************************************
@@ -631,6 +638,14 @@ int reply_unknown(char *inbuf,char *outbuf)
        return(ERROR_DOS(ERRSRV,ERRunknownsmb));
 }
 
+void reply_unknown_new(struct smb_request *req, uint8 type)
+{
+       DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
+                 smb_fn_name(type), type, type));
+       reply_doserror(req, ERRSRV, ERRunknownsmb);
+       return;
+}
+
 /****************************************************************************
  Reply to an ioctl.
  conn POINTER CAN BE NULL HERE !
@@ -1582,7 +1597,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
        }
 
        END_PROFILE(SMBopenX);
-       return chain_reply(inbuf,outbuf,length,bufsize);
+       return chain_reply(inbuf,&outbuf,length,bufsize);
 }
 
 /****************************************************************************
@@ -1611,7 +1626,7 @@ int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,
        DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
 
        END_PROFILE(SMBulogoffX);
-       return chain_reply(inbuf,outbuf,length,bufsize);
+       return chain_reply(inbuf,&outbuf,length,bufsize);
 }
 
 /****************************************************************************
@@ -2813,7 +2828,7 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
        nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
        /* Only call chain_reply if not an error. */
        if (nread != -1 && SVAL(outbuf,smb_rcls) == 0) {
-               nread = chain_reply(inbuf,outbuf,length,bufsize);
+               nread = chain_reply(inbuf,&outbuf,length,bufsize);
        }
 
        END_PROFILE(SMBreadX);
@@ -3254,7 +3269,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng
        }
 
        END_PROFILE(SMBwriteX);
-       return chain_reply(inbuf,outbuf,length,bufsize);
+       return chain_reply(inbuf,&outbuf,length,bufsize);
 }
 
 /****************************************************************************
@@ -5722,7 +5737,7 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
                  fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
        
        END_PROFILE(SMBlockingX);
-       return chain_reply(inbuf,outbuf,length,bufsize);
+       return chain_reply(inbuf,&outbuf,length,bufsize);
 }
 
 #undef DBGC_CLASS
index 320d2835752326f00879fda066cc36d396e11350..eb0d7b3e12bf1d31fe725262a24ec9d4036e2584 100644 (file)
@@ -1582,5 +1582,5 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
        done_sesssetup = True;
        
        END_PROFILE(SMBsesssetupX);
-       return chain_reply(inbuf,outbuf,length,bufsize);
+       return chain_reply(inbuf,&outbuf,length,bufsize);
 }