RIP BOOL. Convert BOOL -> bool. I found a few interesting
[nivanova/samba-autobuild/.git] / source3 / smbd / process.c
index 9624ca0e49573a1c884b445107b7af1a3565c377..ed1bf762e99c96b1851f4754edd3522d99223a99 100644 (file)
@@ -25,13 +25,6 @@ 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 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
  *  by the client for all protocols above CORE.
@@ -48,7 +41,7 @@ extern int last_message;
 extern int smb_read_error;
 SIG_ATOMIC_T reload_after_sighup = 0;
 SIG_ATOMIC_T got_sig_term = 0;
-extern BOOL global_machine_password_needs_changing;
+extern bool global_machine_password_needs_changing;
 extern int max_send;
 
 /*
@@ -57,72 +50,39 @@ extern int max_send;
 
 void init_smb_request(struct smb_request *req, const uint8 *inbuf)
 {
+       size_t req_size = smb_len(inbuf) + 4;
+       /* Ensure we have at least smb_size bytes. */
+       if (req_size < smb_size) {
+               DEBUG(0,("init_smb_request: invalid request size %u\n",
+                       (unsigned int)req_size ));
+               exit_server_cleanly("Invalid SMB request");
+       }
        req->flags2 = SVAL(inbuf, smb_flg2);
        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);
+       /* Ensure we have at least wct words and 2 bytes of bcc. */
+       if (smb_size + req->wct*2 > req_size) {
+               DEBUG(0,("init_smb_request: invalid wct number %u (size %u)\n",
+                       (unsigned int)req->wct,
+                       (unsigned int)req_size));
+               exit_server_cleanly("Invalid SMB request");
+       }
+       /* Ensure bcc is correct. */
+       if (((uint8 *)smb_buf(inbuf)) + smb_buflen(inbuf) > inbuf + req_size) {
+               DEBUG(0,("init_smb_request: invalid bcc number %u "
+                       "(wct = %u, size %u)\n",
+                       (unsigned int)smb_buflen(inbuf),
+                       (unsigned int)req->wct,
+                       (unsigned int)req_size));
+               exit_server_cleanly("Invalid SMB request");
+       }
        req->inbuf  = inbuf;
        req->outbuf = NULL;
 }
 
-/*
- * From within a converted call you might have to call non-converted
- * subroutines that still take the old inbuf/outbuf/lenght/bufsize
- * parameters. This takes a struct smb_request and prepares the legacy
- * parameters.
- */
-
-BOOL reply_prep_legacy(struct smb_request *req,
-                      char **pinbuf, char **poutbuf,
-                      int *psize, int *pbufsize)
-{
-       const int bufsize = (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE
-                            + SAFETY_MARGIN);
-       char *inbuf, *outbuf;
-
-       DEBUG(1, ("reply_prep_legacy called\n"));
-
-       if (!(inbuf = TALLOC_ARRAY(req, char, bufsize))) {
-               DEBUG(0, ("Could not allocate legacy inbuf\n"));
-               return False;
-       }
-       memcpy(inbuf, req->inbuf, MIN(smb_len(req->inbuf)+4, bufsize));
-       req->inbuf = (uint8 *)inbuf;
-
-       if (!(outbuf = TALLOC_ARRAY(req, char, bufsize))) {
-               DEBUG(0, ("Could not allocate legacy outbuf\n"));
-               return False;
-       }
-       req->outbuf = (uint8 *)outbuf;
-
-       construct_reply_common(inbuf, outbuf);
-
-       *pinbuf   = inbuf;
-       *poutbuf  = outbuf;
-       *psize    = smb_len(inbuf)+4;
-       *pbufsize = bufsize;
-
-       return True;
-}
-
-/*
- * Post-process the output of the legacy routine so that the result fits into
- * the new reply_xxx API
- */
-
-void reply_post_legacy(struct smb_request *req, int outsize)
-{
-       if (outsize > 0) {
-               smb_setlen((char *)req->inbuf, (char *)req->outbuf,
-                          outsize);
-       }
-       else {
-               TALLOC_FREE(req->outbuf);
-       }
-}
-
 /****************************************************************************
  structure to hold a linked list of queued messages.
  for processing.
@@ -131,15 +91,16 @@ void reply_post_legacy(struct smb_request *req, int outsize)
 static struct pending_message_list *deferred_open_queue;
 
 /****************************************************************************
- Function to push a message onto the tail of a linked list of smb messages
ready for processing.
+ Function to push a message onto the tail of a linked list of smb messages ready
+ for processing.
 ****************************************************************************/
 
-static BOOL push_queued_message(const char *buf, int msg_len,
+static bool push_queued_message(struct smb_request *req,
                                struct timeval request_time,
                                struct timeval end_time,
                                char *private_data, size_t private_len)
 {
+       int msg_len = smb_len(req->inbuf) + 4;
        struct pending_message_list *msg;
 
        msg = TALLOC_ZERO_P(NULL, struct pending_message_list);
@@ -149,7 +110,7 @@ static BOOL push_queued_message(const char *buf, int msg_len,
                return False;
        }
 
-       msg->buf = data_blob_talloc(msg, buf, msg_len);
+       msg->buf = data_blob_talloc(msg, req->inbuf, msg_len);
        if(msg->buf.data == NULL) {
                DEBUG(0,("push_message: malloc fail (2)\n"));
                TALLOC_FREE(msg);
@@ -187,7 +148,7 @@ void remove_deferred_open_smb_message(uint16 mid)
 
        for (pml = deferred_open_queue; pml; pml = pml->next) {
                if (mid == SVAL(pml->buf.data,smb_mid)) {
-                       DEBUG(10,("remove_deferred_open_smb_message: "
+                       DEBUG(10,("remove_sharing_violation_open_smb_message: "
                                  "deleting mid %u len %u\n",
                                  (unsigned int)mid,
                                  (unsigned int)pml->buf.length ));
@@ -210,11 +171,11 @@ void schedule_deferred_open_smb_message(uint16 mid)
 
        for (pml = deferred_open_queue; pml; pml = pml->next) {
                uint16 msg_mid = SVAL(pml->buf.data,smb_mid);
-               DEBUG(10, ("schedule_deferred_open_smb_message: [%d] "
-                          "msg_mid = %u\n", i++, (unsigned int)msg_mid ));
+               DEBUG(10,("schedule_deferred_open_smb_message: [%d] msg_mid = %u\n", i++,
+                       (unsigned int)msg_mid ));
                if (mid == msg_mid) {
-                       DEBUG(10, ("schedule_deferred_open_smb_message: "
-                                  "scheduling mid %u\n", mid));
+                       DEBUG(10,("schedule_deferred_open_smb_message: scheduling mid %u\n",
+                               mid ));
                        pml->end_time.tv_sec = 0;
                        pml->end_time.tv_usec = 0;
                        DLIST_PROMOTE(deferred_open_queue, pml);
@@ -222,15 +183,15 @@ void schedule_deferred_open_smb_message(uint16 mid)
                }
        }
 
-       DEBUG(10, ("schedule_deferred_open_smb_message: failed to find "
-                  "message mid %u\n", mid ));
+       DEBUG(10,("schedule_deferred_open_smb_message: failed to find message mid %u\n",
+               mid ));
 }
 
 /****************************************************************************
  Return true if this mid is on the deferred queue.
 ****************************************************************************/
 
-BOOL open_was_deferred(uint16 mid)
+bool open_was_deferred(uint16 mid)
 {
        struct pending_message_list *pml;
 
@@ -263,7 +224,7 @@ struct pending_message_list *get_open_deferred_message(uint16 mid)
  messages ready for processing.
 ****************************************************************************/
 
-BOOL push_deferred_smb_message(uint16 mid,
+bool push_deferred_smb_message(struct smb_request *req,
                               struct timeval request_time,
                               struct timeval timeout,
                               char *private_data, size_t priv_len)
@@ -274,12 +235,11 @@ BOOL push_deferred_smb_message(uint16 mid,
 
        DEBUG(10,("push_deferred_open_smb_message: pushing message len %u mid %u "
                  "timeout time [%u.%06u]\n",
-                 (unsigned int) smb_len(current_inbuf)+4, (unsigned int)mid,
+                 (unsigned int) smb_len(req->inbuf)+4, (unsigned int)req->mid,
                  (unsigned int)end_time.tv_sec,
                  (unsigned int)end_time.tv_usec));
 
-       return push_queued_message(current_inbuf, smb_len(current_inbuf)+4,
-                                  request_time, end_time,
+       return push_queued_message(req, request_time, end_time,
                                   private_data, priv_len);
 }
 
@@ -287,7 +247,7 @@ struct idle_event {
        struct timed_event *te;
        struct timeval interval;
        char *name;
-       BOOL (*handler)(const struct timeval *now, void *private_data);
+       bool (*handler)(const struct timeval *now, void *private_data);
        void *private_data;
 };
 
@@ -320,7 +280,7 @@ struct idle_event *event_add_idle(struct event_context *event_ctx,
                                  TALLOC_CTX *mem_ctx,
                                  struct timeval interval,
                                  const char *name,
-                                 BOOL (*handler)(const struct timeval *now,
+                                 bool (*handler)(const struct timeval *now,
                                                  void *private_data),
                                  void *private_data)
 {
@@ -422,7 +382,7 @@ static int select_on_fd(int fd, int maxfd, fd_set *fds)
 The timeout is in milliseconds
 ****************************************************************************/
 
-static BOOL receive_message_or_smb(TALLOC_CTX *mem_ctx, char **buffer,
+static bool receive_message_or_smb(TALLOC_CTX *mem_ctx, char **buffer,
                                   size_t *buffer_len, int timeout)
 {
        fd_set r_fds, w_fds;
@@ -455,7 +415,7 @@ static BOOL receive_message_or_smb(TALLOC_CTX *mem_ctx, char **buffer,
         * and it's time to schedule.
         */
        if(deferred_open_queue != NULL) {
-               BOOL pop_message = False;
+               bool pop_message = False;
                struct pending_message_list *msg = deferred_open_queue;
 
                if (timeval_is_zero(&msg->end_time)) {
@@ -685,267 +645,266 @@ 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",NULL,reply_mkdir,AS_USER | NEED_WRITE},
-/* 0x01 */ { "SMBrmdir",NULL,reply_rmdir,AS_USER | NEED_WRITE},
-/* 0x02 */ { "SMBopen",reply_open,NULL,AS_USER },
-/* 0x03 */ { "SMBcreate",reply_mknew,NULL,AS_USER},
-/* 0x04 */ { "SMBclose",NULL,reply_close,AS_USER | CAN_IPC },
-/* 0x05 */ { "SMBflush",NULL,reply_flush,AS_USER},
-/* 0x06 */ { "SMBunlink",NULL,reply_unlink,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",NULL,reply_checkpath,AS_USER},
-/* 0x11 */ { "SMBexit",NULL,reply_exit,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",NULL,reply_trans,AS_USER | CAN_IPC },
-/* 0x26 */ { "SMBtranss",NULL,reply_transs,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",NULL,reply_echo,0},
-/* 0x2c */ { "SMBwriteclose",reply_writeclose,NULL,AS_USER},
-/* 0x2d */ { "SMBopenX",NULL,reply_open_and_X,AS_USER | CAN_IPC },
-/* 0x2e */ { "SMBreadX",NULL,reply_read_and_X,AS_USER | CAN_IPC },
-/* 0x2f */ { "SMBwriteX",NULL,reply_write_and_X,AS_USER | CAN_IPC },
-/* 0x30 */ { NULL, NULL, NULL, 0 },
-/* 0x31 */ { NULL, NULL, NULL, 0 },
-/* 0x32 */ { "SMBtrans2", NULL,reply_trans2, AS_USER | CAN_IPC },
-/* 0x33 */ { "SMBtranss2", NULL,reply_transs2, 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",NULL,reply_tdis,DO_CHDIR},
-/* 0x72 */ { "SMBnegprot",NULL,reply_negprot,0},
-/* 0x73 */ { "SMBsesssetupX",NULL,reply_sesssetup_and_X,0},
-/* 0x74 */ { "SMBulogoffX", NULL,reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
-/* 0x75 */ { "SMBtconX",NULL,reply_tcon_and_X,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",NULL,reply_dskattr,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", NULL,reply_ntcreate_and_X, AS_USER | CAN_IPC },
-/* 0xa3 */ { NULL, NULL, NULL, 0 },
-/* 0xa4 */ { "SMBntcancel", NULL,reply_ntcancel, 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 }
+/* 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",reply_readbs,AS_USER },
+/* 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 }
 
 };
 
@@ -953,8 +912,19 @@ static const struct smb_message_struct {
  allocate and initialize a reply packet
 ********************************************************************/
 
-void reply_outbuf(struct smb_request *req, uint8 num_words, uint16 num_bytes)
+void reply_outbuf(struct smb_request *req, uint8 num_words, uint32 num_bytes)
 {
+       /*
+         * Protect against integer wrap
+         */
+       if ((num_bytes > 0xffffff)
+           || ((num_bytes + smb_size + num_words*2) > 0xffffff)) {
+               char *msg;
+               asprintf(&msg, "num_bytes too large: %u",
+                        (unsigned)num_bytes);
+               smb_panic(msg);
+       }
+
        if (!(req->outbuf = TALLOC_ARRAY(
                      req, uint8,
                      smb_size + num_words*2 + num_bytes))) {
@@ -962,8 +932,7 @@ void reply_outbuf(struct smb_request *req, uint8 num_words, uint16 num_bytes)
        }
 
        construct_reply_common((char *)req->inbuf, (char *)req->outbuf);
-       set_message((char *)req->inbuf, (char *)req->outbuf,
-                   num_words, num_bytes, False);
+       set_message((char *)req->outbuf, num_words, num_bytes, False);
        /*
         * Zero out the word area, the caller has to take care of the bcc area
         * himself
@@ -1015,8 +984,7 @@ static void smb_dump(const char *name, int type, const char *data, ssize_t len)
  find.
 ****************************************************************************/
 
-static BOOL switch_message_new(uint8 type, struct smb_request *req, int size,
-                              connection_struct **pconn)
+static void switch_message(uint8 type, struct smb_request *req, int size)
 {
        int flags;
        uint16 session_tag;
@@ -1035,15 +1003,13 @@ static BOOL switch_message_new(uint8 type, struct smb_request *req, int size,
                DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",
                         smb_len(req->inbuf)));
                exit_server_cleanly("Non-SMB packet");
-               return True;
        }
 
-       if ((smb_messages[type].fn == NULL)
-           && (smb_messages[type].fn_new == NULL)) {
+       if (smb_messages[type].fn_new == NULL) {
                DEBUG(0,("Unknown message type %d!\n",type));
                smb_dump("Unknown", 1, (char *)req->inbuf, size);
                reply_unknown_new(req, type);
-               goto done;
+               return;
        }
 
        flags = smb_messages[type].flags;
@@ -1096,12 +1062,12 @@ static BOOL switch_message_new(uint8 type, struct smb_request *req, int size,
                        } else {
                                reply_doserror(req, ERRSRV, ERRinvnid);
                        }
-                       goto done;
+                       return;
                }
 
                if (!change_to_user(conn,session_tag)) {
                        reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRbaduid));
-                       goto done;
+                       return;
                }
 
                /* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */
@@ -1109,13 +1075,13 @@ static BOOL switch_message_new(uint8 type, struct smb_request *req, int size,
                /* Does it need write permission? */
                if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) {
                        reply_nterror(req, NT_STATUS_MEDIA_WRITE_PROTECTED);
-                       goto done;
+                       return;
                }
 
                /* IPC services are limited */
                if (IS_IPC(conn) && !(flags & CAN_IPC)) {
                        reply_doserror(req, ERRSRV,ERRaccess);
-                       goto done;
+                       return;
                }
        } else {
                /* This call needs to be run as root */
@@ -1128,7 +1094,7 @@ static BOOL switch_message_new(uint8 type, struct smb_request *req, int size,
                                         (flags & (AS_USER|DO_CHDIR)
                                          ?True:False))) {
                        reply_doserror(req, ERRSRV, ERRaccess);
-                       goto done;
+                       return;
                }
                conn->num_smb_operations++;
        }
@@ -1139,73 +1105,10 @@ static BOOL switch_message_new(uint8 type, struct smb_request *req, int size,
                !check_access(smbd_server_fd(), lp_hostsallow(-1),
                              lp_hostsdeny(-1)))) {
                reply_doserror(req, ERRSRV, ERRaccess);
-               goto done;
-       }
-
-       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:
-       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");
+               return;
        }
 
-       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);
+       smb_messages[type].fn_new(conn, req);
 }
 
 /****************************************************************************
@@ -1215,36 +1118,29 @@ static int switch_message(uint8 type, struct smb_request *req, char **outbuf,
 static void construct_reply(char *inbuf, int size)
 {
        uint8 type = CVAL(inbuf,smb_com);
-       int outsize = 0;
        struct smb_request *req;
-       char *outbuf;
 
        chain_size = 0;
        file_chain_reset();
        reset_chain_p();
 
-       if (!(req = talloc(tmp_talloc_ctx(), struct smb_request))) {
+       if (!(req = talloc(talloc_tos(), struct smb_request))) {
                smb_panic("could not allocate smb_request");
        }
        init_smb_request(req, (uint8 *)inbuf);
 
-       outsize = switch_message(type, req, &outbuf, size, max_send);
+       switch_message(type, req, size);
 
-       if (outsize > 4) {
-               smb_setlen(inbuf,outbuf,outsize - 4);
+       if (req->outbuf == NULL) {
+               return;
        }
 
-       if (outsize > 0) {
-               if (CVAL(outbuf,0) == 0)
-                       show_msg(outbuf);
+       if (CVAL(req->outbuf,0) == 0) {
+               show_msg((char *)req->outbuf);
+       }
 
-               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.");
-               }
+       if (!send_smb(smbd_server_fd(), (char *)req->outbuf)) {
+               exit_server_cleanly("construct_reply: send_smb failed.");
        }
 
        TALLOC_FREE(req);
@@ -1329,7 +1225,7 @@ void remove_from_common_flags2(uint32 v)
 
 void construct_reply_common(const char *inbuf, char *outbuf)
 {
-       set_message(inbuf,outbuf,0,0,False);
+       set_message(outbuf,0,0,False);
        
        SCVAL(outbuf,smb_com,CVAL(inbuf,smb_com));
        SIVAL(outbuf,smb_rcls,0);
@@ -1349,29 +1245,37 @@ 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 **poutbuf,int size,int bufsize)
+void chain_reply(struct smb_request *req)
 {
        static char *orig_inbuf;
+
+       /*
+        * Dirty little const_discard: We mess with req->inbuf, which is
+        * declared as const. If maybe at some point this routine gets
+        * rewritten, this const_discard could go away.
+        */
+       char *inbuf = CONST_DISCARD(char *, req->inbuf);
+       int size = smb_len(req->inbuf)+4;
+
        int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0);
        unsigned smb_off2 = SVAL(inbuf,smb_vwv1);
        char *inbuf2;
-       char *outbuf2 = NULL;
        int outsize2;
        int new_size;
        char inbuf_saved[smb_wct];
-       char *outbuf = *poutbuf;
+       char *outbuf = (char *)req->outbuf;
        size_t outsize = smb_len(outbuf) + 4;
        size_t outsize_padded;
        size_t ofs, to_move;
 
-       struct smb_request *req;
+       struct smb_request *req2;
        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) {
                SCVAL(outbuf,smb_vwv0,0xFF);
-               return outsize;
+               return;
        }
 
        if (chain_size == 0) {
@@ -1432,28 +1336,28 @@ int chain_reply(char *inbuf,char **poutbuf,int size,int bufsize)
                         "(orig size = %d, offset = %d)\n",
                         size, (int)(inbuf2 - inbuf) ));
                exit_server_cleanly("Bad chained packet");
-               return(-1);
+               return;
        }
 
        /* And set it in the header. */
-       smb_setlen(inbuf, inbuf2, new_size - 4);
+       smb_setlen(inbuf2, new_size - 4);
 
        DEBUG(3,("Chained message\n"));
        show_msg(inbuf2);
 
-       if (!(req = talloc(tmp_talloc_ctx(), struct smb_request))) {
+       if (!(req2 = talloc(talloc_tos(), struct smb_request))) {
                smb_panic("could not allocate smb_request");
        }
-       init_smb_request(req, (uint8 *)inbuf2);
+       init_smb_request(req2, (uint8 *)inbuf2);
 
        /* process the request */
-       outsize2 = switch_message(smb_com2, req, &outbuf2, new_size,
-                                 bufsize-chain_size);
+       switch_message(smb_com2, req2, new_size);
 
        /*
         * We don't accept deferred operations in chained requests.
         */
-       SMB_ASSERT(outsize2 >= smb_wct);
+       SMB_ASSERT(req2->outbuf != NULL);
+       outsize2 = smb_len(req2->outbuf)+4;
 
        /*
         * Move away the new command output so that caller_output fits in,
@@ -1486,23 +1390,22 @@ int chain_reply(char *inbuf,char **poutbuf,int size,int bufsize)
         * 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");
-               }
+       outbuf = TALLOC_REALLOC_ARRAY(NULL, outbuf, char,
+                                     to_move + ofs + smb_wct);
+       if (outbuf == NULL) {
+               smb_panic("could not realloc outbuf");
        }
 
-       *poutbuf = outbuf;
+       req->outbuf = (uint8 *)outbuf;
 
-       memmove(outbuf + smb_wct + ofs, outbuf2 + smb_wct, to_move);
+       memmove(outbuf + smb_wct + ofs, req2->outbuf + smb_wct, to_move);
        memcpy(outbuf + smb_wct, caller_output, caller_outputlen);
 
        /*
-        * The secondary function has overwritten smb_com
+        * copy the new reply header over the old one but preserve the smb_com
+        * field
         */
-
+       memmove(outbuf, req2->outbuf, smb_wct);
        SCVAL(outbuf, smb_com, smb_com1);
 
        /*
@@ -1524,7 +1427,7 @@ int chain_reply(char *inbuf,char **poutbuf,int size,int bufsize)
                memset(outbuf + outsize, 0, outsize_padded - outsize);
        }
 
-       smb_setlen(NULL, outbuf, outsize2 + chain_size - 4);
+       smb_setlen(outbuf, outsize2 + chain_size - 4);
 
        /*
         * restore the saved data, being careful not to overwrite any data
@@ -1533,17 +1436,9 @@ int chain_reply(char *inbuf,char **poutbuf,int size,int bufsize)
        memcpy(inbuf2,inbuf_saved,smb_wct);
 
        SAFE_FREE(caller_output);
-       TALLOC_FREE(req);
+       TALLOC_FREE(req2);
 
-       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);
+       return;
 }
 
 /****************************************************************************
@@ -1620,7 +1515,7 @@ void check_reload(time_t t)
  Process any timeout housekeeping. Return False if the caller should exit.
 ****************************************************************************/
 
-static BOOL timeout_processing(int *select_timeout,
+static bool timeout_processing(int *select_timeout,
                               time_t *last_timeout_processing_time)
 {
        time_t t;
@@ -1722,60 +1617,6 @@ machine %s in domain %s.\n", global_myname(), lp_workgroup()));
        return True;
 }
 
-/****************************************************************************
- Accessor functions for InBuffer, OutBuffer.
-****************************************************************************/
-
-char *get_InBuffer(void)
-{
-       return InBuffer;
-}
-
-char *get_OutBuffer(void)
-{
-       return OutBuffer;
-}
-
-/****************************************************************************
- Allocate a new InBuffer. Returns the new and old ones.
-****************************************************************************/
-
-static char *NewInBuffer(char **old_inbuf)
-{
-       char *new_inbuf = (char *)SMB_MALLOC(total_buffer_size);
-       if (!new_inbuf) {
-               return NULL;
-       }
-       if (old_inbuf) {
-               *old_inbuf = InBuffer;
-       }
-       InBuffer = new_inbuf;
-#if defined(DEVELOPER)
-       clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size);
-#endif
-       return InBuffer;
-}
-
-/****************************************************************************
- Allocate a new OutBuffer. Returns the new and old ones.
-****************************************************************************/
-
-static char *NewOutBuffer(char **old_outbuf)
-{
-       char *new_outbuf = (char *)SMB_MALLOC(total_buffer_size);
-       if (!new_outbuf) {
-               return NULL;
-       }
-       if (old_outbuf) {
-               *old_outbuf = OutBuffer;
-       }
-       OutBuffer = new_outbuf;
-#if defined(DEVELOPER)
-       clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer, total_buffer_size);
-#endif
-       return OutBuffer;
-}
-
 /****************************************************************************
  Process commands from the client
 ****************************************************************************/
@@ -1792,13 +1633,10 @@ void smbd_process(void)
                int num_echos;
                char *inbuf;
                size_t inbuf_len;
+               TALLOC_CTX *frame = talloc_stackframe();
 
                errno = 0;      
                
-               /* free up temporary memory */
-               lp_TALLOC_FREE();
-               main_loop_TALLOC_FREE();
-
                /* Did someone ask for immediate checks on things like blocking locks ? */
                if (select_timeout == 0) {
                        if(!timeout_processing(&select_timeout,
@@ -1871,5 +1709,6 @@ void smbd_process(void)
                        change_to_root_user();
                        check_log_size();
                }
+               TALLOC_FREE(frame);
        }
 }