c59ee2c2003c772e730a815767d84ea17054cd25
[samba.git] / source3 / smbd / process.c
1 /* 
2    Unix SMB/CIFS implementation.
3    process incoming packets - main loop
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Volker Lendecke 2005-2007
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22
23 extern struct auth_context *negprot_global_auth_context;
24 extern int smb_echo_count;
25
26 const int total_buffer_size = (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN);
27
28 static char *InBuffer = NULL;
29 static char *OutBuffer = NULL;
30 static const char *current_inbuf = NULL;
31
32 static char *NewInBuffer(char **old_inbuf);
33 static char *NewOutBuffer(char **old_outbuf);
34
35 /* 
36  * Size of data we can send to client. Set
37  *  by the client for all protocols above CORE.
38  *  Set by us for CORE protocol.
39  */
40 int max_send = BUFFER_SIZE;
41 /*
42  * Size of the data we can receive. Set by us.
43  * Can be modified by the max xmit parameter.
44  */
45 int max_recv = BUFFER_SIZE;
46
47 extern int last_message;
48 extern int smb_read_error;
49 SIG_ATOMIC_T reload_after_sighup = 0;
50 SIG_ATOMIC_T got_sig_term = 0;
51 extern BOOL global_machine_password_needs_changing;
52 extern int max_send;
53
54 /*
55  * Initialize a struct smb_request from an inbuf
56  */
57
58 void init_smb_request(struct smb_request *req, const uint8 *inbuf)
59 {
60         req->flags2 = SVAL(inbuf, smb_flg2);
61         req->smbpid = SVAL(inbuf, smb_pid);
62         req->mid    = SVAL(inbuf, smb_mid);
63         req->vuid   = SVAL(inbuf, smb_uid);
64         req->tid    = SVAL(inbuf, smb_tid);
65         req->wct    = CVAL(inbuf, smb_wct);
66         req->inbuf  = inbuf;
67         req->outbuf = NULL;
68 }
69
70 /*
71  * From within a converted call you might have to call non-converted
72  * subroutines that still take the old inbuf/outbuf/lenght/bufsize
73  * parameters. This takes a struct smb_request and prepares the legacy
74  * parameters.
75  */
76
77 BOOL reply_prep_legacy(struct smb_request *req,
78                        char **pinbuf, char **poutbuf,
79                        int *psize, int *pbufsize)
80 {
81         const int bufsize = (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE
82                              + SAFETY_MARGIN);
83         char *inbuf, *outbuf;
84
85         DEBUG(1, ("reply_prep_legacy called\n"));
86
87         if (!(inbuf = TALLOC_ARRAY(req, char, bufsize))) {
88                 DEBUG(0, ("Could not allocate legacy inbuf\n"));
89                 return False;
90         }
91         memcpy(inbuf, req->inbuf, MIN(smb_len(req->inbuf)+4, bufsize));
92         req->inbuf = (uint8 *)inbuf;
93
94         if (!(outbuf = TALLOC_ARRAY(req, char, bufsize))) {
95                 DEBUG(0, ("Could not allocate legacy outbuf\n"));
96                 return False;
97         }
98         req->outbuf = (uint8 *)outbuf;
99
100         construct_reply_common(inbuf, outbuf);
101
102         *pinbuf   = inbuf;
103         *poutbuf  = outbuf;
104         *psize    = smb_len(inbuf)+4;
105         *pbufsize = bufsize;
106
107         return True;
108 }
109
110 /*
111  * Post-process the output of the legacy routine so that the result fits into
112  * the new reply_xxx API
113  */
114
115 void reply_post_legacy(struct smb_request *req, int outsize)
116 {
117         if (outsize > 0) {
118                 smb_setlen((char *)req->inbuf, (char *)req->outbuf,
119                            outsize);
120         }
121         else {
122                 TALLOC_FREE(req->outbuf);
123         }
124 }
125
126 /****************************************************************************
127  structure to hold a linked list of queued messages.
128  for processing.
129 ****************************************************************************/
130
131 static struct pending_message_list *deferred_open_queue;
132
133 /****************************************************************************
134  Function to push a message onto the tail of a linked list of smb messages
135  ready for processing.
136 ****************************************************************************/
137
138 static BOOL push_queued_message(const char *buf, int msg_len,
139                                 struct timeval request_time,
140                                 struct timeval end_time,
141                                 char *private_data, size_t private_len)
142 {
143         struct pending_message_list *msg;
144
145         msg = TALLOC_ZERO_P(NULL, struct pending_message_list);
146
147         if(msg == NULL) {
148                 DEBUG(0,("push_message: malloc fail (1)\n"));
149                 return False;
150         }
151
152         msg->buf = data_blob_talloc(msg, buf, msg_len);
153         if(msg->buf.data == NULL) {
154                 DEBUG(0,("push_message: malloc fail (2)\n"));
155                 TALLOC_FREE(msg);
156                 return False;
157         }
158
159         msg->request_time = request_time;
160         msg->end_time = end_time;
161
162         if (private_data) {
163                 msg->private_data = data_blob_talloc(msg, private_data,
164                                                      private_len);
165                 if (msg->private_data.data == NULL) {
166                         DEBUG(0,("push_message: malloc fail (3)\n"));
167                         TALLOC_FREE(msg);
168                         return False;
169                 }
170         }
171
172         DLIST_ADD_END(deferred_open_queue, msg, struct pending_message_list *);
173
174         DEBUG(10,("push_message: pushed message length %u on "
175                   "deferred_open_queue\n", (unsigned int)msg_len));
176
177         return True;
178 }
179
180 /****************************************************************************
181  Function to delete a sharing violation open message by mid.
182 ****************************************************************************/
183
184 void remove_deferred_open_smb_message(uint16 mid)
185 {
186         struct pending_message_list *pml;
187
188         for (pml = deferred_open_queue; pml; pml = pml->next) {
189                 if (mid == SVAL(pml->buf.data,smb_mid)) {
190                         DEBUG(10,("remove_deferred_open_smb_message: "
191                                   "deleting mid %u len %u\n",
192                                   (unsigned int)mid,
193                                   (unsigned int)pml->buf.length ));
194                         DLIST_REMOVE(deferred_open_queue, pml);
195                         TALLOC_FREE(pml);
196                         return;
197                 }
198         }
199 }
200
201 /****************************************************************************
202  Move a sharing violation open retry message to the front of the list and
203  schedule it for immediate processing.
204 ****************************************************************************/
205
206 void schedule_deferred_open_smb_message(uint16 mid)
207 {
208         struct pending_message_list *pml;
209         int i = 0;
210
211         for (pml = deferred_open_queue; pml; pml = pml->next) {
212                 uint16 msg_mid = SVAL(pml->buf.data,smb_mid);
213                 DEBUG(10, ("schedule_deferred_open_smb_message: [%d] "
214                            "msg_mid = %u\n", i++, (unsigned int)msg_mid ));
215                 if (mid == msg_mid) {
216                         DEBUG(10, ("schedule_deferred_open_smb_message: "
217                                    "scheduling mid %u\n", mid));
218                         pml->end_time.tv_sec = 0;
219                         pml->end_time.tv_usec = 0;
220                         DLIST_PROMOTE(deferred_open_queue, pml);
221                         return;
222                 }
223         }
224
225         DEBUG(10, ("schedule_deferred_open_smb_message: failed to find "
226                    "message mid %u\n", mid ));
227 }
228
229 /****************************************************************************
230  Return true if this mid is on the deferred queue.
231 ****************************************************************************/
232
233 BOOL open_was_deferred(uint16 mid)
234 {
235         struct pending_message_list *pml;
236
237         for (pml = deferred_open_queue; pml; pml = pml->next) {
238                 if (SVAL(pml->buf.data,smb_mid) == mid) {
239                         return True;
240                 }
241         }
242         return False;
243 }
244
245 /****************************************************************************
246  Return the message queued by this mid.
247 ****************************************************************************/
248
249 struct pending_message_list *get_open_deferred_message(uint16 mid)
250 {
251         struct pending_message_list *pml;
252
253         for (pml = deferred_open_queue; pml; pml = pml->next) {
254                 if (SVAL(pml->buf.data,smb_mid) == mid) {
255                         return pml;
256                 }
257         }
258         return NULL;
259 }
260
261 /****************************************************************************
262  Function to push a deferred open smb message onto a linked list of local smb
263  messages ready for processing.
264 ****************************************************************************/
265
266 BOOL push_deferred_smb_message(uint16 mid,
267                                struct timeval request_time,
268                                struct timeval timeout,
269                                char *private_data, size_t priv_len)
270 {
271         struct timeval end_time;
272
273         end_time = timeval_sum(&request_time, &timeout);
274
275         DEBUG(10,("push_deferred_open_smb_message: pushing message len %u mid %u "
276                   "timeout time [%u.%06u]\n",
277                   (unsigned int) smb_len(current_inbuf)+4, (unsigned int)mid,
278                   (unsigned int)end_time.tv_sec,
279                   (unsigned int)end_time.tv_usec));
280
281         return push_queued_message(current_inbuf, smb_len(current_inbuf)+4,
282                                    request_time, end_time,
283                                    private_data, priv_len);
284 }
285
286 struct idle_event {
287         struct timed_event *te;
288         struct timeval interval;
289         char *name;
290         BOOL (*handler)(const struct timeval *now, void *private_data);
291         void *private_data;
292 };
293
294 static void idle_event_handler(struct event_context *ctx,
295                                struct timed_event *te,
296                                const struct timeval *now,
297                                void *private_data)
298 {
299         struct idle_event *event =
300                 talloc_get_type_abort(private_data, struct idle_event);
301
302         TALLOC_FREE(event->te);
303
304         if (!event->handler(now, event->private_data)) {
305                 /* Don't repeat, delete ourselves */
306                 TALLOC_FREE(event);
307                 return;
308         }
309
310         event->te = event_add_timed(ctx, event,
311                                     timeval_sum(now, &event->interval),
312                                     event->name,
313                                     idle_event_handler, event);
314
315         /* We can't do much but fail here. */
316         SMB_ASSERT(event->te != NULL);
317 }
318
319 struct idle_event *event_add_idle(struct event_context *event_ctx,
320                                   TALLOC_CTX *mem_ctx,
321                                   struct timeval interval,
322                                   const char *name,
323                                   BOOL (*handler)(const struct timeval *now,
324                                                   void *private_data),
325                                   void *private_data)
326 {
327         struct idle_event *result;
328         struct timeval now = timeval_current();
329
330         result = TALLOC_P(mem_ctx, struct idle_event);
331         if (result == NULL) {
332                 DEBUG(0, ("talloc failed\n"));
333                 return NULL;
334         }
335
336         result->interval = interval;
337         result->handler = handler;
338         result->private_data = private_data;
339
340         if (!(result->name = talloc_asprintf(result, "idle_evt(%s)", name))) {
341                 DEBUG(0, ("talloc failed\n"));
342                 TALLOC_FREE(result);
343                 return NULL;
344         }
345
346         result->te = event_add_timed(event_ctx, result,
347                                      timeval_sum(&now, &interval),
348                                      result->name,
349                                      idle_event_handler, result);
350         if (result->te == NULL) {
351                 DEBUG(0, ("event_add_timed failed\n"));
352                 TALLOC_FREE(result);
353                 return NULL;
354         }
355
356         return result;
357 }
358
359 /****************************************************************************
360  Do all async processing in here. This includes kernel oplock messages, change
361  notify events etc.
362 ****************************************************************************/
363
364 static void async_processing(fd_set *pfds)
365 {
366         DEBUG(10,("async_processing: Doing async processing.\n"));
367
368         process_aio_queue();
369
370         process_kernel_oplocks(smbd_messaging_context(), pfds);
371
372         /* Do the aio check again after receive_local_message as it does a
373            select and may have eaten our signal. */
374         /* Is this till true? -- vl */
375         process_aio_queue();
376
377         if (got_sig_term) {
378                 exit_server_cleanly("termination signal");
379         }
380
381         /* check for sighup processing */
382         if (reload_after_sighup) {
383                 change_to_root_user();
384                 DEBUG(1,("Reloading services after SIGHUP\n"));
385                 reload_services(False);
386                 reload_after_sighup = 0;
387         }
388 }
389
390 /****************************************************************************
391  Add a fd to the set we will be select(2)ing on.
392 ****************************************************************************/
393
394 static int select_on_fd(int fd, int maxfd, fd_set *fds)
395 {
396         if (fd != -1) {
397                 FD_SET(fd, fds);
398                 maxfd = MAX(maxfd, fd);
399         }
400
401         return maxfd;
402 }
403
404 /****************************************************************************
405   Do a select on an two fd's - with timeout. 
406
407   If a local udp message has been pushed onto the
408   queue (this can only happen during oplock break
409   processing) call async_processing()
410
411   If a pending smb message has been pushed onto the
412   queue (this can only happen during oplock break
413   processing) return this next.
414
415   If the first smbfd is ready then read an smb from it.
416   if the second (loopback UDP) fd is ready then read a message
417   from it and setup the buffer header to identify the length
418   and from address.
419   Returns False on timeout or error.
420   Else returns True.
421
422 The timeout is in milliseconds
423 ****************************************************************************/
424
425 static BOOL receive_message_or_smb(TALLOC_CTX *mem_ctx, char **buffer,
426                                    size_t *buffer_len, int timeout)
427 {
428         fd_set r_fds, w_fds;
429         int selrtn;
430         struct timeval to;
431         int maxfd = 0;
432         ssize_t len;
433
434         smb_read_error = 0;
435
436  again:
437
438         if (timeout >= 0) {
439                 to.tv_sec = timeout / 1000;
440                 to.tv_usec = (timeout % 1000) * 1000;
441         } else {
442                 to.tv_sec = SMBD_SELECT_TIMEOUT;
443                 to.tv_usec = 0;
444         }
445
446         /*
447          * Note that this call must be before processing any SMB
448          * messages as we need to synchronously process any messages
449          * we may have sent to ourselves from the previous SMB.
450          */
451         message_dispatch(smbd_messaging_context());
452
453         /*
454          * Check to see if we already have a message on the deferred open queue
455          * and it's time to schedule.
456          */
457         if(deferred_open_queue != NULL) {
458                 BOOL pop_message = False;
459                 struct pending_message_list *msg = deferred_open_queue;
460
461                 if (timeval_is_zero(&msg->end_time)) {
462                         pop_message = True;
463                 } else {
464                         struct timeval tv;
465                         SMB_BIG_INT tdif;
466
467                         GetTimeOfDay(&tv);
468                         tdif = usec_time_diff(&msg->end_time, &tv);
469                         if (tdif <= 0) {
470                                 /* Timed out. Schedule...*/
471                                 pop_message = True;
472                                 DEBUG(10,("receive_message_or_smb: queued message timed out.\n"));
473                         } else {
474                                 /* Make a more accurate select timeout. */
475                                 to.tv_sec = tdif / 1000000;
476                                 to.tv_usec = tdif % 1000000;
477                                 DEBUG(10,("receive_message_or_smb: select with timeout of [%u.%06u]\n",
478                                         (unsigned int)to.tv_sec, (unsigned int)to.tv_usec ));
479                         }
480                 }
481
482                 if (pop_message) {
483
484                         *buffer = (char *)talloc_memdup(mem_ctx, msg->buf.data,
485                                                         msg->buf.length);
486                         if (*buffer == NULL) {
487                                 DEBUG(0, ("talloc failed\n"));
488                                 smb_read_error = READ_ERROR;
489                                 return False;
490                         }
491                         *buffer_len = msg->buf.length;
492
493                         /* We leave this message on the queue so the open code can
494                            know this is a retry. */
495                         DEBUG(5,("receive_message_or_smb: returning deferred open smb message.\n"));
496                         return True;
497                 }
498         }
499
500         /*
501          * Setup the select fd sets.
502          */
503
504         FD_ZERO(&r_fds);
505         FD_ZERO(&w_fds);
506
507         /*
508          * Ensure we process oplock break messages by preference.
509          * We have to do this before the select, after the select
510          * and if the select returns EINTR. This is due to the fact
511          * that the selects called from async_processing can eat an EINTR
512          * caused by a signal (we can't take the break message there).
513          * This is hideously complex - *MUST* be simplified for 3.0 ! JRA.
514          */
515
516         if (oplock_message_waiting(&r_fds)) {
517                 DEBUG(10,("receive_message_or_smb: oplock_message is waiting.\n"));
518                 async_processing(&r_fds);
519                 /*
520                  * After async processing we must go and do the select again, as
521                  * the state of the flag in fds for the server file descriptor is
522                  * indeterminate - we may have done I/O on it in the oplock processing. JRA.
523                  */
524                 goto again;
525         }
526
527         /*
528          * Are there any timed events waiting ? If so, ensure we don't
529          * select for longer than it would take to wait for them.
530          */
531
532         {
533                 struct timeval now;
534                 GetTimeOfDay(&now);
535
536                 event_add_to_select_args(smbd_event_context(), &now,
537                                          &r_fds, &w_fds, &to, &maxfd);
538         }
539
540         if (timeval_is_zero(&to)) {
541                 /* Process a timed event now... */
542                 if (run_events(smbd_event_context(), 0, NULL, NULL)) {
543                         goto again;
544                 }
545         }
546         
547         {
548                 int sav;
549                 START_PROFILE(smbd_idle);
550
551                 maxfd = select_on_fd(smbd_server_fd(), maxfd, &r_fds);
552                 maxfd = select_on_fd(oplock_notify_fd(), maxfd, &r_fds);
553
554                 selrtn = sys_select(maxfd+1,&r_fds,&w_fds,NULL,&to);
555                 sav = errno;
556
557                 END_PROFILE(smbd_idle);
558                 errno = sav;
559         }
560
561         if (run_events(smbd_event_context(), selrtn, &r_fds, &w_fds)) {
562                 goto again;
563         }
564
565         /* if we get EINTR then maybe we have received an oplock
566            signal - treat this as select returning 1. This is ugly, but
567            is the best we can do until the oplock code knows more about
568            signals */
569         if (selrtn == -1 && errno == EINTR) {
570                 async_processing(&r_fds);
571                 /*
572                  * After async processing we must go and do the select again, as
573                  * the state of the flag in fds for the server file descriptor is
574                  * indeterminate - we may have done I/O on it in the oplock processing. JRA.
575                  */
576                 goto again;
577         }
578
579         /* Check if error */
580         if (selrtn == -1) {
581                 /* something is wrong. Maybe the socket is dead? */
582                 smb_read_error = READ_ERROR;
583                 return False;
584         } 
585     
586         /* Did we timeout ? */
587         if (selrtn == 0) {
588                 smb_read_error = READ_TIMEOUT;
589                 return False;
590         }
591
592         /*
593          * Ensure we process oplock break messages by preference.
594          * This is IMPORTANT ! Otherwise we can starve other processes
595          * sending us an oplock break message. JRA.
596          */
597
598         if (oplock_message_waiting(&r_fds)) {
599                 async_processing(&r_fds);
600                 /*
601                  * After async processing we must go and do the select again, as
602                  * the state of the flag in fds for the server file descriptor is
603                  * indeterminate - we may have done I/O on it in the oplock processing. JRA.
604                  */
605                 goto again;
606         }
607
608         len = receive_smb_talloc(mem_ctx, smbd_server_fd(), buffer, 0);
609
610         if (len == -1) {
611                 return False;
612         }
613
614         *buffer_len = (size_t)len;
615
616         return True;
617 }
618
619 /*
620  * Only allow 5 outstanding trans requests. We're allocating memory, so
621  * prevent a DoS.
622  */
623
624 NTSTATUS allow_new_trans(struct trans_state *list, int mid)
625 {
626         int count = 0;
627         for (; list != NULL; list = list->next) {
628
629                 if (list->mid == mid) {
630                         return NT_STATUS_INVALID_PARAMETER;
631                 }
632
633                 count += 1;
634         }
635         if (count > 5) {
636                 return NT_STATUS_INSUFFICIENT_RESOURCES;
637         }
638
639         return NT_STATUS_OK;
640 }
641
642 /****************************************************************************
643  We're terminating and have closed all our files/connections etc.
644  If there are any pending local messages we need to respond to them
645  before termination so that other smbds don't think we just died whilst
646  holding oplocks.
647 ****************************************************************************/
648
649 void respond_to_all_remaining_local_messages(void)
650 {
651         /*
652          * Assert we have no exclusive open oplocks.
653          */
654
655         if(get_number_of_exclusive_open_oplocks()) {
656                 DEBUG(0,("respond_to_all_remaining_local_messages: PANIC : we have %d exclusive oplocks.\n",
657                         get_number_of_exclusive_open_oplocks() ));
658                 return;
659         }
660
661         process_kernel_oplocks(smbd_messaging_context(), NULL);
662
663         return;
664 }
665
666
667 /*
668 These flags determine some of the permissions required to do an operation 
669
670 Note that I don't set NEED_WRITE on some write operations because they
671 are used by some brain-dead clients when printing, and I don't want to
672 force write permissions on print services.
673 */
674 #define AS_USER (1<<0)
675 #define NEED_WRITE (1<<1) /* Must be paired with AS_USER */
676 #define TIME_INIT (1<<2)
677 #define CAN_IPC (1<<3) /* Must be paired with AS_USER */
678 #define AS_GUEST (1<<5) /* Must *NOT* be paired with AS_USER */
679 #define DO_CHDIR (1<<6)
680
681 /* 
682    define a list of possible SMB messages and their corresponding
683    functions. Any message that has a NULL function is unimplemented -
684    please feel free to contribute implementations!
685 */
686 static const struct smb_message_struct {
687         const char *name;
688         int (*fn)(connection_struct *conn, char *, char *, int, int);
689         void (*fn_new)(connection_struct *conn, struct smb_request *req);
690         int flags;
691 } smb_messages[256] = {
692
693 /* 0x00 */ { "SMBmkdir",NULL,reply_mkdir,AS_USER | NEED_WRITE},
694 /* 0x01 */ { "SMBrmdir",NULL,reply_rmdir,AS_USER | NEED_WRITE},
695 /* 0x02 */ { "SMBopen",reply_open,NULL,AS_USER },
696 /* 0x03 */ { "SMBcreate",reply_mknew,NULL,AS_USER},
697 /* 0x04 */ { "SMBclose",NULL,reply_close,AS_USER | CAN_IPC },
698 /* 0x05 */ { "SMBflush",NULL,reply_flush,AS_USER},
699 /* 0x06 */ { "SMBunlink",NULL,reply_unlink,AS_USER | NEED_WRITE },
700 /* 0x07 */ { "SMBmv",reply_mv,NULL,AS_USER | NEED_WRITE },
701 /* 0x08 */ { "SMBgetatr",reply_getatr,NULL,AS_USER},
702 /* 0x09 */ { "SMBsetatr",reply_setatr,NULL,AS_USER | NEED_WRITE},
703 /* 0x0a */ { "SMBread",reply_read,NULL,AS_USER},
704 /* 0x0b */ { "SMBwrite",reply_write,NULL,AS_USER | CAN_IPC },
705 /* 0x0c */ { "SMBlock",reply_lock,NULL,AS_USER},
706 /* 0x0d */ { "SMBunlock",reply_unlock,NULL,AS_USER},
707 /* 0x0e */ { "SMBctemp",reply_ctemp,NULL,AS_USER },
708 /* 0x0f */ { "SMBmknew",reply_mknew,NULL,AS_USER},
709 /* 0x10 */ { "SMBcheckpath",NULL,reply_checkpath,AS_USER},
710 /* 0x11 */ { "SMBexit",NULL,reply_exit,DO_CHDIR},
711 /* 0x12 */ { "SMBlseek",reply_lseek,NULL,AS_USER},
712 /* 0x13 */ { "SMBlockread",reply_lockread,NULL,AS_USER},
713 /* 0x14 */ { "SMBwriteunlock",reply_writeunlock,NULL,AS_USER},
714 /* 0x15 */ { NULL, NULL, NULL, 0 },
715 /* 0x16 */ { NULL, NULL, NULL, 0 },
716 /* 0x17 */ { NULL, NULL, NULL, 0 },
717 /* 0x18 */ { NULL, NULL, NULL, 0 },
718 /* 0x19 */ { NULL, NULL, NULL, 0 },
719 /* 0x1a */ { "SMBreadbraw",reply_readbraw,NULL,AS_USER},
720 /* 0x1b */ { "SMBreadBmpx",reply_readbmpx,NULL,AS_USER},
721 /* 0x1c */ { "SMBreadBs",NULL, NULL,0 },
722 /* 0x1d */ { "SMBwritebraw",reply_writebraw,NULL,AS_USER},
723 /* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,NULL,AS_USER},
724 /* 0x1f */ { "SMBwriteBs",reply_writebs,NULL,AS_USER},
725 /* 0x20 */ { "SMBwritec",NULL, NULL,0},
726 /* 0x21 */ { NULL, NULL, NULL, 0 },
727 /* 0x22 */ { "SMBsetattrE",reply_setattrE,NULL,AS_USER | NEED_WRITE },
728 /* 0x23 */ { "SMBgetattrE",reply_getattrE,NULL,AS_USER },
729 /* 0x24 */ { "SMBlockingX",reply_lockingX,NULL,AS_USER },
730 /* 0x25 */ { "SMBtrans",NULL,reply_trans,AS_USER | CAN_IPC },
731 /* 0x26 */ { "SMBtranss",NULL,reply_transs,AS_USER | CAN_IPC},
732 /* 0x27 */ { "SMBioctl",reply_ioctl,NULL,0},
733 /* 0x28 */ { "SMBioctls",NULL, NULL,AS_USER},
734 /* 0x29 */ { "SMBcopy",reply_copy,NULL,AS_USER | NEED_WRITE },
735 /* 0x2a */ { "SMBmove",NULL, NULL,AS_USER | NEED_WRITE },
736 /* 0x2b */ { "SMBecho",NULL,reply_echo,0},
737 /* 0x2c */ { "SMBwriteclose",reply_writeclose,NULL,AS_USER},
738 /* 0x2d */ { "SMBopenX",NULL,reply_open_and_X,AS_USER | CAN_IPC },
739 /* 0x2e */ { "SMBreadX",NULL,reply_read_and_X,AS_USER | CAN_IPC },
740 /* 0x2f */ { "SMBwriteX",NULL,reply_write_and_X,AS_USER | CAN_IPC },
741 /* 0x30 */ { NULL, NULL, NULL, 0 },
742 /* 0x31 */ { NULL, NULL, NULL, 0 },
743 /* 0x32 */ { "SMBtrans2", NULL,reply_trans2, AS_USER | CAN_IPC },
744 /* 0x33 */ { "SMBtranss2", NULL,reply_transs2, AS_USER},
745 /* 0x34 */ { "SMBfindclose", reply_findclose,NULL,AS_USER},
746 /* 0x35 */ { "SMBfindnclose", reply_findnclose,NULL, AS_USER},
747 /* 0x36 */ { NULL, NULL, NULL, 0 },
748 /* 0x37 */ { NULL, NULL, NULL, 0 },
749 /* 0x38 */ { NULL, NULL, NULL, 0 },
750 /* 0x39 */ { NULL, NULL, NULL, 0 },
751 /* 0x3a */ { NULL, NULL, NULL, 0 },
752 /* 0x3b */ { NULL, NULL, NULL, 0 },
753 /* 0x3c */ { NULL, NULL, NULL, 0 },
754 /* 0x3d */ { NULL, NULL, NULL, 0 },
755 /* 0x3e */ { NULL, NULL, NULL, 0 },
756 /* 0x3f */ { NULL, NULL, NULL, 0 },
757 /* 0x40 */ { NULL, NULL, NULL, 0 },
758 /* 0x41 */ { NULL, NULL, NULL, 0 },
759 /* 0x42 */ { NULL, NULL, NULL, 0 },
760 /* 0x43 */ { NULL, NULL, NULL, 0 },
761 /* 0x44 */ { NULL, NULL, NULL, 0 },
762 /* 0x45 */ { NULL, NULL, NULL, 0 },
763 /* 0x46 */ { NULL, NULL, NULL, 0 },
764 /* 0x47 */ { NULL, NULL, NULL, 0 },
765 /* 0x48 */ { NULL, NULL, NULL, 0 },
766 /* 0x49 */ { NULL, NULL, NULL, 0 },
767 /* 0x4a */ { NULL, NULL, NULL, 0 },
768 /* 0x4b */ { NULL, NULL, NULL, 0 },
769 /* 0x4c */ { NULL, NULL, NULL, 0 },
770 /* 0x4d */ { NULL, NULL, NULL, 0 },
771 /* 0x4e */ { NULL, NULL, NULL, 0 },
772 /* 0x4f */ { NULL, NULL, NULL, 0 },
773 /* 0x50 */ { NULL, NULL, NULL, 0 },
774 /* 0x51 */ { NULL, NULL, NULL, 0 },
775 /* 0x52 */ { NULL, NULL, NULL, 0 },
776 /* 0x53 */ { NULL, NULL, NULL, 0 },
777 /* 0x54 */ { NULL, NULL, NULL, 0 },
778 /* 0x55 */ { NULL, NULL, NULL, 0 },
779 /* 0x56 */ { NULL, NULL, NULL, 0 },
780 /* 0x57 */ { NULL, NULL, NULL, 0 },
781 /* 0x58 */ { NULL, NULL, NULL, 0 },
782 /* 0x59 */ { NULL, NULL, NULL, 0 },
783 /* 0x5a */ { NULL, NULL, NULL, 0 },
784 /* 0x5b */ { NULL, NULL, NULL, 0 },
785 /* 0x5c */ { NULL, NULL, NULL, 0 },
786 /* 0x5d */ { NULL, NULL, NULL, 0 },
787 /* 0x5e */ { NULL, NULL, NULL, 0 },
788 /* 0x5f */ { NULL, NULL, NULL, 0 },
789 /* 0x60 */ { NULL, NULL, NULL, 0 },
790 /* 0x61 */ { NULL, NULL, NULL, 0 },
791 /* 0x62 */ { NULL, NULL, NULL, 0 },
792 /* 0x63 */ { NULL, NULL, NULL, 0 },
793 /* 0x64 */ { NULL, NULL, NULL, 0 },
794 /* 0x65 */ { NULL, NULL, NULL, 0 },
795 /* 0x66 */ { NULL, NULL, NULL, 0 },
796 /* 0x67 */ { NULL, NULL, NULL, 0 },
797 /* 0x68 */ { NULL, NULL, NULL, 0 },
798 /* 0x69 */ { NULL, NULL, NULL, 0 },
799 /* 0x6a */ { NULL, NULL, NULL, 0 },
800 /* 0x6b */ { NULL, NULL, NULL, 0 },
801 /* 0x6c */ { NULL, NULL, NULL, 0 },
802 /* 0x6d */ { NULL, NULL, NULL, 0 },
803 /* 0x6e */ { NULL, NULL, NULL, 0 },
804 /* 0x6f */ { NULL, NULL, NULL, 0 },
805 /* 0x70 */ { "SMBtcon",reply_tcon,NULL,0},
806 /* 0x71 */ { "SMBtdis",NULL,reply_tdis,DO_CHDIR},
807 /* 0x72 */ { "SMBnegprot",NULL,reply_negprot,0},
808 /* 0x73 */ { "SMBsesssetupX",NULL,reply_sesssetup_and_X,0},
809 /* 0x74 */ { "SMBulogoffX", NULL,reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
810 /* 0x75 */ { "SMBtconX",NULL,reply_tcon_and_X,0},
811 /* 0x76 */ { NULL, NULL, NULL, 0 },
812 /* 0x77 */ { NULL, NULL, NULL, 0 },
813 /* 0x78 */ { NULL, NULL, NULL, 0 },
814 /* 0x79 */ { NULL, NULL, NULL, 0 },
815 /* 0x7a */ { NULL, NULL, NULL, 0 },
816 /* 0x7b */ { NULL, NULL, NULL, 0 },
817 /* 0x7c */ { NULL, NULL, NULL, 0 },
818 /* 0x7d */ { NULL, NULL, NULL, 0 },
819 /* 0x7e */ { NULL, NULL, NULL, 0 },
820 /* 0x7f */ { NULL, NULL, NULL, 0 },
821 /* 0x80 */ { "SMBdskattr",NULL,reply_dskattr,AS_USER},
822 /* 0x81 */ { "SMBsearch",reply_search,NULL,AS_USER},
823 /* 0x82 */ { "SMBffirst",reply_search,NULL,AS_USER},
824 /* 0x83 */ { "SMBfunique",reply_search,NULL,AS_USER},
825 /* 0x84 */ { "SMBfclose",reply_fclose,NULL,AS_USER},
826 /* 0x85 */ { NULL, NULL, NULL, 0 },
827 /* 0x86 */ { NULL, NULL, NULL, 0 },
828 /* 0x87 */ { NULL, NULL, NULL, 0 },
829 /* 0x88 */ { NULL, NULL, NULL, 0 },
830 /* 0x89 */ { NULL, NULL, NULL, 0 },
831 /* 0x8a */ { NULL, NULL, NULL, 0 },
832 /* 0x8b */ { NULL, NULL, NULL, 0 },
833 /* 0x8c */ { NULL, NULL, NULL, 0 },
834 /* 0x8d */ { NULL, NULL, NULL, 0 },
835 /* 0x8e */ { NULL, NULL, NULL, 0 },
836 /* 0x8f */ { NULL, NULL, NULL, 0 },
837 /* 0x90 */ { NULL, NULL, NULL, 0 },
838 /* 0x91 */ { NULL, NULL, NULL, 0 },
839 /* 0x92 */ { NULL, NULL, NULL, 0 },
840 /* 0x93 */ { NULL, NULL, NULL, 0 },
841 /* 0x94 */ { NULL, NULL, NULL, 0 },
842 /* 0x95 */ { NULL, NULL, NULL, 0 },
843 /* 0x96 */ { NULL, NULL, NULL, 0 },
844 /* 0x97 */ { NULL, NULL, NULL, 0 },
845 /* 0x98 */ { NULL, NULL, NULL, 0 },
846 /* 0x99 */ { NULL, NULL, NULL, 0 },
847 /* 0x9a */ { NULL, NULL, NULL, 0 },
848 /* 0x9b */ { NULL, NULL, NULL, 0 },
849 /* 0x9c */ { NULL, NULL, NULL, 0 },
850 /* 0x9d */ { NULL, NULL, NULL, 0 },
851 /* 0x9e */ { NULL, NULL, NULL, 0 },
852 /* 0x9f */ { NULL, NULL, NULL, 0 },
853 /* 0xa0 */ { "SMBnttrans", reply_nttrans,NULL, AS_USER | CAN_IPC },
854 /* 0xa1 */ { "SMBnttranss", reply_nttranss,NULL, AS_USER | CAN_IPC },
855 /* 0xa2 */ { "SMBntcreateX", NULL,reply_ntcreate_and_X, AS_USER | CAN_IPC },
856 /* 0xa3 */ { NULL, NULL, NULL, 0 },
857 /* 0xa4 */ { "SMBntcancel", NULL,reply_ntcancel, 0 },
858 /* 0xa5 */ { "SMBntrename", reply_ntrename,NULL, AS_USER | NEED_WRITE },
859 /* 0xa6 */ { NULL, NULL, NULL, 0 },
860 /* 0xa7 */ { NULL, NULL, NULL, 0 },
861 /* 0xa8 */ { NULL, NULL, NULL, 0 },
862 /* 0xa9 */ { NULL, NULL, NULL, 0 },
863 /* 0xaa */ { NULL, NULL, NULL, 0 },
864 /* 0xab */ { NULL, NULL, NULL, 0 },
865 /* 0xac */ { NULL, NULL, NULL, 0 },
866 /* 0xad */ { NULL, NULL, NULL, 0 },
867 /* 0xae */ { NULL, NULL, NULL, 0 },
868 /* 0xaf */ { NULL, NULL, NULL, 0 },
869 /* 0xb0 */ { NULL, NULL, NULL, 0 },
870 /* 0xb1 */ { NULL, NULL, NULL, 0 },
871 /* 0xb2 */ { NULL, NULL, NULL, 0 },
872 /* 0xb3 */ { NULL, NULL, NULL, 0 },
873 /* 0xb4 */ { NULL, NULL, NULL, 0 },
874 /* 0xb5 */ { NULL, NULL, NULL, 0 },
875 /* 0xb6 */ { NULL, NULL, NULL, 0 },
876 /* 0xb7 */ { NULL, NULL, NULL, 0 },
877 /* 0xb8 */ { NULL, NULL, NULL, 0 },
878 /* 0xb9 */ { NULL, NULL, NULL, 0 },
879 /* 0xba */ { NULL, NULL, NULL, 0 },
880 /* 0xbb */ { NULL, NULL, NULL, 0 },
881 /* 0xbc */ { NULL, NULL, NULL, 0 },
882 /* 0xbd */ { NULL, NULL, NULL, 0 },
883 /* 0xbe */ { NULL, NULL, NULL, 0 },
884 /* 0xbf */ { NULL, NULL, NULL, 0 },
885 /* 0xc0 */ { "SMBsplopen",reply_printopen,NULL,AS_USER},
886 /* 0xc1 */ { "SMBsplwr",reply_printwrite,NULL,AS_USER},
887 /* 0xc2 */ { "SMBsplclose",reply_printclose,NULL,AS_USER},
888 /* 0xc3 */ { "SMBsplretq",reply_printqueue,NULL,AS_USER},
889 /* 0xc4 */ { NULL, NULL, NULL, 0 },
890 /* 0xc5 */ { NULL, NULL, NULL, 0 },
891 /* 0xc6 */ { NULL, NULL, NULL, 0 },
892 /* 0xc7 */ { NULL, NULL, NULL, 0 },
893 /* 0xc8 */ { NULL, NULL, NULL, 0 },
894 /* 0xc9 */ { NULL, NULL, NULL, 0 },
895 /* 0xca */ { NULL, NULL, NULL, 0 },
896 /* 0xcb */ { NULL, NULL, NULL, 0 },
897 /* 0xcc */ { NULL, NULL, NULL, 0 },
898 /* 0xcd */ { NULL, NULL, NULL, 0 },
899 /* 0xce */ { NULL, NULL, NULL, 0 },
900 /* 0xcf */ { NULL, NULL, NULL, 0 },
901 /* 0xd0 */ { "SMBsends",reply_sends,NULL,AS_GUEST},
902 /* 0xd1 */ { "SMBsendb",NULL, NULL,AS_GUEST},
903 /* 0xd2 */ { "SMBfwdname",NULL, NULL,AS_GUEST},
904 /* 0xd3 */ { "SMBcancelf",NULL, NULL,AS_GUEST},
905 /* 0xd4 */ { "SMBgetmac",NULL, NULL,AS_GUEST},
906 /* 0xd5 */ { "SMBsendstrt",reply_sendstrt,NULL,AS_GUEST},
907 /* 0xd6 */ { "SMBsendend",reply_sendend,NULL,AS_GUEST},
908 /* 0xd7 */ { "SMBsendtxt",reply_sendtxt,NULL,AS_GUEST},
909 /* 0xd8 */ { NULL, NULL, NULL, 0 },
910 /* 0xd9 */ { NULL, NULL, NULL, 0 },
911 /* 0xda */ { NULL, NULL, NULL, 0 },
912 /* 0xdb */ { NULL, NULL, NULL, 0 },
913 /* 0xdc */ { NULL, NULL, NULL, 0 },
914 /* 0xdd */ { NULL, NULL, NULL, 0 },
915 /* 0xde */ { NULL, NULL, NULL, 0 },
916 /* 0xdf */ { NULL, NULL, NULL, 0 },
917 /* 0xe0 */ { NULL, NULL, NULL, 0 },
918 /* 0xe1 */ { NULL, NULL, NULL, 0 },
919 /* 0xe2 */ { NULL, NULL, NULL, 0 },
920 /* 0xe3 */ { NULL, NULL, NULL, 0 },
921 /* 0xe4 */ { NULL, NULL, NULL, 0 },
922 /* 0xe5 */ { NULL, NULL, NULL, 0 },
923 /* 0xe6 */ { NULL, NULL, NULL, 0 },
924 /* 0xe7 */ { NULL, NULL, NULL, 0 },
925 /* 0xe8 */ { NULL, NULL, NULL, 0 },
926 /* 0xe9 */ { NULL, NULL, NULL, 0 },
927 /* 0xea */ { NULL, NULL, NULL, 0 },
928 /* 0xeb */ { NULL, NULL, NULL, 0 },
929 /* 0xec */ { NULL, NULL, NULL, 0 },
930 /* 0xed */ { NULL, NULL, NULL, 0 },
931 /* 0xee */ { NULL, NULL, NULL, 0 },
932 /* 0xef */ { NULL, NULL, NULL, 0 },
933 /* 0xf0 */ { NULL, NULL, NULL, 0 },
934 /* 0xf1 */ { NULL, NULL, NULL, 0 },
935 /* 0xf2 */ { NULL, NULL, NULL, 0 },
936 /* 0xf3 */ { NULL, NULL, NULL, 0 },
937 /* 0xf4 */ { NULL, NULL, NULL, 0 },
938 /* 0xf5 */ { NULL, NULL, NULL, 0 },
939 /* 0xf6 */ { NULL, NULL, NULL, 0 },
940 /* 0xf7 */ { NULL, NULL, NULL, 0 },
941 /* 0xf8 */ { NULL, NULL, NULL, 0 },
942 /* 0xf9 */ { NULL, NULL, NULL, 0 },
943 /* 0xfa */ { NULL, NULL, NULL, 0 },
944 /* 0xfb */ { NULL, NULL, NULL, 0 },
945 /* 0xfc */ { NULL, NULL, NULL, 0 },
946 /* 0xfd */ { NULL, NULL, NULL, 0 },
947 /* 0xfe */ { NULL, NULL, NULL, 0 },
948 /* 0xff */ { NULL, NULL, NULL, 0 }
949
950 };
951
952 /*******************************************************************
953  allocate and initialize a reply packet
954 ********************************************************************/
955
956 void reply_outbuf(struct smb_request *req, uint8 num_words, uint32 num_bytes)
957 {
958         /*
959          * Protect against integer wrap
960          */
961         if ((num_bytes > 0xffffff)
962             || ((num_bytes + smb_size + num_words*2) > 0xffffff)) {
963                 char *msg;
964                 asprintf(&msg, "num_bytes too large: %u",
965                          (unsigned)num_bytes);
966                 smb_panic(msg);
967         }
968
969         if (!(req->outbuf = TALLOC_ARRAY(
970                       req, uint8,
971                       smb_size + num_words*2 + num_bytes))) {
972                 smb_panic("could not allocate output buffer\n");
973         }
974
975         construct_reply_common((char *)req->inbuf, (char *)req->outbuf);
976         set_message((char *)req->inbuf, (char *)req->outbuf,
977                     num_words, num_bytes, False);
978         /*
979          * Zero out the word area, the caller has to take care of the bcc area
980          * himself
981          */
982         if (num_words != 0) {
983                 memset(req->outbuf + smb_vwv0, 0, num_words*2);
984         }
985
986         return;
987 }
988
989
990 /*******************************************************************
991  Dump a packet to a file.
992 ********************************************************************/
993
994 static void smb_dump(const char *name, int type, const char *data, ssize_t len)
995 {
996         int fd, i;
997         pstring fname;
998         if (DEBUGLEVEL < 50) return;
999
1000         if (len < 4) len = smb_len(data)+4;
1001         for (i=1;i<100;i++) {
1002                 slprintf(fname,sizeof(fname)-1, "/tmp/%s.%d.%s", name, i,
1003                                 type ? "req" : "resp");
1004                 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644);
1005                 if (fd != -1 || errno != EEXIST) break;
1006         }
1007         if (fd != -1) {
1008                 ssize_t ret = write(fd, data, len);
1009                 if (ret != len)
1010                         DEBUG(0,("smb_dump: problem: write returned %d\n", (int)ret ));
1011                 close(fd);
1012                 DEBUG(0,("created %s len %lu\n", fname, (unsigned long)len));
1013         }
1014 }
1015
1016 /****************************************************************************
1017  Prepare everything for calling the actual request function, and potentially
1018  call the request function via the "new" interface.
1019
1020  Return False if the "legacy" function needs to be called, everything is
1021  prepared.
1022
1023  Return True if we're done.
1024
1025  I know this API sucks, but it is the one with the least code change I could
1026  find.
1027 ****************************************************************************/
1028
1029 static BOOL switch_message_new(uint8 type, struct smb_request *req, int size,
1030                                connection_struct **pconn)
1031 {
1032         int flags;
1033         uint16 session_tag;
1034         connection_struct *conn;
1035
1036         static uint16 last_session_tag = UID_FIELD_INVALID;
1037
1038         errno = 0;
1039
1040         last_message = type;
1041
1042         /* Make sure this is an SMB packet. smb_size contains NetBIOS header
1043          * so subtract 4 from it. */
1044         if ((strncmp(smb_base(req->inbuf),"\377SMB",4) != 0)
1045             || (size < (smb_size - 4))) {
1046                 DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",
1047                          smb_len(req->inbuf)));
1048                 exit_server_cleanly("Non-SMB packet");
1049                 return True;
1050         }
1051
1052         if ((smb_messages[type].fn == NULL)
1053             && (smb_messages[type].fn_new == NULL)) {
1054                 DEBUG(0,("Unknown message type %d!\n",type));
1055                 smb_dump("Unknown", 1, (char *)req->inbuf, size);
1056                 reply_unknown_new(req, type);
1057                 goto done;
1058         }
1059
1060         flags = smb_messages[type].flags;
1061
1062         /* In share mode security we must ignore the vuid. */
1063         session_tag = (lp_security() == SEC_SHARE)
1064                 ? UID_FIELD_INVALID : req->vuid;
1065         conn = conn_find(req->tid);
1066
1067         DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n", smb_fn_name(type),
1068                  (int)sys_getpid(), (unsigned long)conn));
1069
1070         smb_dump(smb_fn_name(type), 1, (char *)req->inbuf, size);
1071
1072         /* Ensure this value is replaced in the incoming packet. */
1073         SSVAL(req->inbuf,smb_uid,session_tag);
1074
1075         /*
1076          * Ensure the correct username is in current_user_info.  This is a
1077          * really ugly bugfix for problems with multiple session_setup_and_X's
1078          * being done and allowing %U and %G substitutions to work correctly.
1079          * There is a reason this code is done here, don't move it unless you
1080          * know what you're doing... :-).
1081          * JRA.
1082          */
1083
1084         if (session_tag != last_session_tag) {
1085                 user_struct *vuser = NULL;
1086
1087                 last_session_tag = session_tag;
1088                 if(session_tag != UID_FIELD_INVALID) {
1089                         vuser = get_valid_user_struct(session_tag);
1090                         if (vuser) {
1091                                 set_current_user_info(&vuser->user);
1092                         }
1093                 }
1094         }
1095
1096         /* Does this call need to be run as the connected user? */
1097         if (flags & AS_USER) {
1098
1099                 /* Does this call need a valid tree connection? */
1100                 if (!conn) {
1101                         /*
1102                          * Amazingly, the error code depends on the command
1103                          * (from Samba4).
1104                          */
1105                         if (type == SMBntcreateX) {
1106                                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1107                         } else {
1108                                 reply_doserror(req, ERRSRV, ERRinvnid);
1109                         }
1110                         goto done;
1111                 }
1112
1113                 if (!change_to_user(conn,session_tag)) {
1114                         reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRbaduid));
1115                         goto done;
1116                 }
1117
1118                 /* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */
1119
1120                 /* Does it need write permission? */
1121                 if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) {
1122                         reply_nterror(req, NT_STATUS_MEDIA_WRITE_PROTECTED);
1123                         goto done;
1124                 }
1125
1126                 /* IPC services are limited */
1127                 if (IS_IPC(conn) && !(flags & CAN_IPC)) {
1128                         reply_doserror(req, ERRSRV,ERRaccess);
1129                         goto done;
1130                 }
1131         } else {
1132                 /* This call needs to be run as root */
1133                 change_to_root_user();
1134         }
1135
1136         /* load service specific parameters */
1137         if (conn) {
1138                 if (!set_current_service(conn,SVAL(req->inbuf,smb_flg),
1139                                          (flags & (AS_USER|DO_CHDIR)
1140                                           ?True:False))) {
1141                         reply_doserror(req, ERRSRV, ERRaccess);
1142                         goto done;
1143                 }
1144                 conn->num_smb_operations++;
1145         }
1146
1147         /* does this protocol need to be run as guest? */
1148         if ((flags & AS_GUEST)
1149             && (!change_to_guest() ||
1150                 !check_access(smbd_server_fd(), lp_hostsallow(-1),
1151                               lp_hostsdeny(-1)))) {
1152                 reply_doserror(req, ERRSRV, ERRaccess);
1153                 goto done;
1154         }
1155
1156         current_inbuf = (char *)req->inbuf; /* In case we need to defer this
1157                                              * message in open... */
1158
1159         if (smb_messages[type].fn_new != NULL) {
1160                 smb_messages[type].fn_new(conn, req);
1161                 goto done;
1162         }
1163
1164         /*
1165          * Indicate the upper layer that there's still work.
1166          */
1167         *pconn = conn;
1168         return False;
1169
1170  done:
1171         return True;
1172 }
1173
1174
1175 /****************************************************************************
1176  Do a switch on the message type, and return the response size
1177 ****************************************************************************/
1178
1179 static int switch_message(uint8 type, struct smb_request *req, char **outbuf,
1180                           int size, int bufsize)
1181 {
1182         int outsize = 0;
1183         connection_struct *conn = NULL;
1184
1185         if (switch_message_new(type, req, size, &conn)) {
1186                 if (req->outbuf != NULL) {
1187                         *outbuf = (char *)req->outbuf;
1188                         return smb_len(req->outbuf)+4;
1189                 }
1190                 return -1;
1191         }
1192
1193         if (InBuffer == NULL) {
1194                 DEBUG(1, ("have to alloc InBuffer for %s\n",
1195                           smb_fn_name(type)));
1196                 if (NewInBuffer(NULL) == NULL) {
1197                         smb_panic("Could not allocate InBuffer");
1198                 }
1199         }
1200
1201         if ((OutBuffer == NULL) && (NewOutBuffer(NULL) == NULL)) {
1202                 smb_panic("Could not allocate OutBuffer");
1203         }
1204
1205         clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer,
1206                        total_buffer_size);
1207
1208         memcpy(InBuffer, req->inbuf, MIN(size, total_buffer_size));
1209
1210         construct_reply_common(InBuffer, OutBuffer);
1211
1212         outsize = smb_messages[type].fn(conn, InBuffer, OutBuffer, size,
1213                                         bufsize);
1214
1215         smb_dump(smb_fn_name(type), 0, OutBuffer, outsize);
1216
1217         *outbuf = OutBuffer;
1218
1219         return(outsize);
1220 }
1221
1222 /****************************************************************************
1223  Construct a reply to the incoming packet.
1224 ****************************************************************************/
1225
1226 static void construct_reply(char *inbuf, int size)
1227 {
1228         uint8 type = CVAL(inbuf,smb_com);
1229         int outsize = 0;
1230         struct smb_request *req;
1231         char *outbuf;
1232
1233         chain_size = 0;
1234         file_chain_reset();
1235         reset_chain_p();
1236
1237         if (!(req = talloc(tmp_talloc_ctx(), struct smb_request))) {
1238                 smb_panic("could not allocate smb_request");
1239         }
1240         init_smb_request(req, (uint8 *)inbuf);
1241
1242         outsize = switch_message(type, req, &outbuf, size, max_send);
1243
1244         if (outsize > 4) {
1245                 smb_setlen(inbuf,outbuf,outsize - 4);
1246         }
1247
1248         if (outsize > 0) {
1249                 if (CVAL(outbuf,0) == 0)
1250                         show_msg(outbuf);
1251
1252                 if (outsize != smb_len(outbuf) + 4) {
1253                         DEBUG(0,("ERROR: Invalid message response size! "
1254                                  "%d %d\n", outsize, smb_len(outbuf)));
1255                 } else if (!send_smb(smbd_server_fd(),outbuf)) {
1256                         exit_server_cleanly("construct_reply: send_smb "
1257                                             "failed.");
1258                 }
1259         }
1260
1261         TALLOC_FREE(req);
1262
1263         return;
1264 }
1265
1266 /****************************************************************************
1267  Process an smb from the client
1268 ****************************************************************************/
1269
1270 static void process_smb(char *inbuf, size_t nread)
1271 {
1272         static int trans_num;
1273         int msg_type = CVAL(inbuf,0);
1274
1275         DO_PROFILE_INC(smb_count);
1276
1277         if (trans_num == 0) {
1278                 /* on the first packet, check the global hosts allow/ hosts
1279                 deny parameters before doing any parsing of the packet
1280                 passed to us by the client.  This prevents attacks on our
1281                 parsing code from hosts not in the hosts allow list */
1282                 if (!check_access(smbd_server_fd(), lp_hostsallow(-1),
1283                                   lp_hostsdeny(-1))) {
1284                         /* send a negative session response "not listening on calling name" */
1285                         static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
1286                         DEBUG( 1, ( "Connection denied from %s\n", client_addr() ) );
1287                         (void)send_smb(smbd_server_fd(),(char *)buf);
1288                         exit_server_cleanly("connection denied");
1289                 }
1290         }
1291
1292         DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type,
1293                     smb_len(inbuf) ) );
1294         DEBUG( 3, ( "Transaction %d of length %d\n", trans_num, (int)nread ) );
1295
1296         if (msg_type != 0) {
1297                 /*
1298                  * NetBIOS session request, keepalive, etc.
1299                  */
1300                 reply_special(inbuf);
1301                 return;
1302         }
1303
1304         show_msg(inbuf);
1305
1306         construct_reply(inbuf,nread);
1307       
1308         trans_num++;
1309 }
1310
1311 /****************************************************************************
1312  Return a string containing the function name of a SMB command.
1313 ****************************************************************************/
1314
1315 const char *smb_fn_name(int type)
1316 {
1317         const char *unknown_name = "SMBunknown";
1318
1319         if (smb_messages[type].name == NULL)
1320                 return(unknown_name);
1321
1322         return(smb_messages[type].name);
1323 }
1324
1325 /****************************************************************************
1326  Helper functions for contruct_reply.
1327 ****************************************************************************/
1328
1329 static uint32 common_flags2 = FLAGS2_LONG_PATH_COMPONENTS|FLAGS2_32_BIT_ERROR_CODES;
1330
1331 void add_to_common_flags2(uint32 v)
1332 {
1333         common_flags2 |= v;
1334 }
1335
1336 void remove_from_common_flags2(uint32 v)
1337 {
1338         common_flags2 &= ~v;
1339 }
1340
1341 void construct_reply_common(const char *inbuf, char *outbuf)
1342 {
1343         set_message(inbuf,outbuf,0,0,False);
1344         
1345         SCVAL(outbuf,smb_com,CVAL(inbuf,smb_com));
1346         SIVAL(outbuf,smb_rcls,0);
1347         SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES)); 
1348         SSVAL(outbuf,smb_flg2,
1349                 (SVAL(inbuf,smb_flg2) & FLAGS2_UNICODE_STRINGS) |
1350                 common_flags2);
1351         memset(outbuf+smb_pidhigh,'\0',(smb_tid-smb_pidhigh));
1352
1353         SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
1354         SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
1355         SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
1356         SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
1357 }
1358
1359 /****************************************************************************
1360  Construct a chained reply and add it to the already made reply
1361 ****************************************************************************/
1362
1363 int chain_reply(char *inbuf,char **poutbuf,int size,int bufsize)
1364 {
1365         static char *orig_inbuf;
1366         int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0);
1367         unsigned smb_off2 = SVAL(inbuf,smb_vwv1);
1368         char *inbuf2;
1369         char *outbuf2 = NULL;
1370         int outsize2;
1371         int new_size;
1372         char inbuf_saved[smb_wct];
1373         char *outbuf = *poutbuf;
1374         size_t outsize = smb_len(outbuf) + 4;
1375         size_t outsize_padded;
1376         size_t ofs, to_move;
1377
1378         struct smb_request *req;
1379         size_t caller_outputlen;
1380         char *caller_output;
1381
1382         /* Maybe its not chained, or it's an error packet. */
1383         if (smb_com2 == 0xFF || SVAL(outbuf,smb_rcls) != 0) {
1384                 SCVAL(outbuf,smb_vwv0,0xFF);
1385                 return outsize;
1386         }
1387
1388         if (chain_size == 0) {
1389                 /* this is the first part of the chain */
1390                 orig_inbuf = inbuf;
1391         }
1392
1393         /*
1394          * We need to save the output the caller added to the chain so that we
1395          * can splice it into the final output buffer later.
1396          */
1397
1398         caller_outputlen = outsize - smb_wct;
1399
1400         caller_output = (char *)memdup(outbuf + smb_wct, caller_outputlen);
1401
1402         if (caller_output == NULL) {
1403                 /* TODO: NT_STATUS_NO_MEMORY */
1404                 smb_panic("could not dup outbuf");
1405         }
1406
1407         /*
1408          * The original Win95 redirector dies on a reply to
1409          * a lockingX and read chain unless the chain reply is
1410          * 4 byte aligned. JRA.
1411          */
1412
1413         outsize_padded = (outsize + 3) & ~3;
1414
1415         /*
1416          * remember how much the caller added to the chain, only counting
1417          * stuff after the parameter words
1418          */
1419         chain_size += outsize_padded - smb_wct;
1420
1421         /*
1422          * work out pointers into the original packets. The
1423          * headers on these need to be filled in
1424          */
1425         inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct;
1426
1427         /* remember the original command type */
1428         smb_com1 = CVAL(orig_inbuf,smb_com);
1429
1430         /* save the data which will be overwritten by the new headers */
1431         memcpy(inbuf_saved,inbuf2,smb_wct);
1432
1433         /* give the new packet the same header as the last part of the SMB */
1434         memmove(inbuf2,inbuf,smb_wct);
1435
1436         /* create the in buffer */
1437         SCVAL(inbuf2,smb_com,smb_com2);
1438
1439         /* work out the new size for the in buffer. */
1440         new_size = size - (inbuf2 - inbuf);
1441         if (new_size < 0) {
1442                 DEBUG(0,("chain_reply: chain packet size incorrect "
1443                          "(orig size = %d, offset = %d)\n",
1444                          size, (int)(inbuf2 - inbuf) ));
1445                 exit_server_cleanly("Bad chained packet");
1446                 return(-1);
1447         }
1448
1449         /* And set it in the header. */
1450         smb_setlen(inbuf, inbuf2, new_size - 4);
1451
1452         DEBUG(3,("Chained message\n"));
1453         show_msg(inbuf2);
1454
1455         if (!(req = talloc(tmp_talloc_ctx(), struct smb_request))) {
1456                 smb_panic("could not allocate smb_request");
1457         }
1458         init_smb_request(req, (uint8 *)inbuf2);
1459
1460         /* process the request */
1461         outsize2 = switch_message(smb_com2, req, &outbuf2, new_size,
1462                                   bufsize-chain_size);
1463
1464         /*
1465          * We don't accept deferred operations in chained requests.
1466          */
1467         SMB_ASSERT(outsize2 >= smb_wct);
1468
1469         /*
1470          * Move away the new command output so that caller_output fits in,
1471          * copy in the caller_output saved above.
1472          */
1473
1474         SMB_ASSERT(outsize_padded >= smb_wct);
1475
1476         /*
1477          * "ofs" is the space we need for caller_output. Equal to
1478          * caller_outputlen plus the padding.
1479          */
1480
1481         ofs = outsize_padded - smb_wct;
1482
1483         /*
1484          * "to_move" is the amount of bytes the secondary routine gave us
1485          */
1486
1487         to_move = outsize2 - smb_wct;
1488
1489         if (to_move + ofs + smb_wct + chain_size > max_send) {
1490                 smb_panic("replies too large -- would have to cut");
1491         }
1492
1493         /*
1494          * In the "new" API "outbuf" is allocated via reply_outbuf, just for
1495          * the first request in the chain. So we have to re-allocate it. In
1496          * the "old" API the only outbuf ever used is the global OutBuffer
1497          * which is always large enough.
1498          */
1499
1500         if (outbuf != OutBuffer) {
1501                 outbuf = TALLOC_REALLOC_ARRAY(NULL, outbuf, char,
1502                                               to_move + ofs + smb_wct);
1503                 if (outbuf == NULL) {
1504                         smb_panic("could not realloc outbuf");
1505                 }
1506         }
1507
1508         *poutbuf = outbuf;
1509
1510         memmove(outbuf + smb_wct + ofs, outbuf2 + smb_wct, to_move);
1511         memcpy(outbuf + smb_wct, caller_output, caller_outputlen);
1512
1513         /*
1514          * copy the new reply header over the old one but preserve the smb_com
1515          * field
1516          */
1517         memmove(outbuf,outbuf2,smb_wct);
1518         SCVAL(outbuf, smb_com, smb_com1);
1519
1520         /*
1521          * We've just copied in the whole "wct" area from the secondary
1522          * function. Fix up the chaining: com2 and the offset need to be
1523          * readjusted.
1524          */
1525
1526         SCVAL(outbuf, smb_vwv0, smb_com2);
1527         SSVAL(outbuf, smb_vwv1, chain_size + smb_wct - 4);
1528
1529         if (outsize_padded > outsize) {
1530
1531                 /*
1532                  * Due to padding we have some uninitialized bytes after the
1533                  * caller's output
1534                  */
1535
1536                 memset(outbuf + outsize, 0, outsize_padded - outsize);
1537         }
1538
1539         smb_setlen(NULL, outbuf, outsize2 + chain_size - 4);
1540
1541         /*
1542          * restore the saved data, being careful not to overwrite any data
1543          * from the reply header
1544          */
1545         memcpy(inbuf2,inbuf_saved,smb_wct);
1546
1547         SAFE_FREE(caller_output);
1548         TALLOC_FREE(req);
1549
1550         return outsize2 + chain_size;
1551 }
1552
1553 void chain_reply_new(struct smb_request *req)
1554 {
1555         chain_reply(CONST_DISCARD(char *, req->inbuf),
1556                     (char **)(void *)&req->outbuf,
1557                     smb_len(req->inbuf)+4,
1558                     smb_len(req->outbuf)+4);
1559 }
1560
1561 /****************************************************************************
1562  Setup the needed select timeout in milliseconds.
1563 ****************************************************************************/
1564
1565 static int setup_select_timeout(void)
1566 {
1567         int select_timeout;
1568
1569         select_timeout = SMBD_SELECT_TIMEOUT*1000;
1570
1571         if (print_notify_messages_pending()) {
1572                 select_timeout = MIN(select_timeout, 1000);
1573         }
1574
1575         return select_timeout;
1576 }
1577
1578 /****************************************************************************
1579  Check if services need reloading.
1580 ****************************************************************************/
1581
1582 void check_reload(time_t t)
1583 {
1584         static pid_t mypid = 0;
1585         static time_t last_smb_conf_reload_time = 0;
1586         static time_t last_printer_reload_time = 0;
1587         time_t printcap_cache_time = (time_t)lp_printcap_cache_time();
1588
1589         if(last_smb_conf_reload_time == 0) {
1590                 last_smb_conf_reload_time = t;
1591                 /* Our printing subsystem might not be ready at smbd start up.
1592                    Then no printer is available till the first printers check
1593                    is performed.  A lower initial interval circumvents this. */
1594                 if ( printcap_cache_time > 60 )
1595                         last_printer_reload_time = t - printcap_cache_time + 60;
1596                 else
1597                         last_printer_reload_time = t;
1598         }
1599
1600         if (mypid != getpid()) { /* First time or fork happened meanwhile */
1601                 /* randomize over 60 second the printcap reload to avoid all
1602                  * process hitting cupsd at the same time */
1603                 int time_range = 60;
1604
1605                 last_printer_reload_time += random() % time_range;
1606                 mypid = getpid();
1607         }
1608
1609         if (reload_after_sighup || (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK)) {
1610                 reload_services(True);
1611                 reload_after_sighup = False;
1612                 last_smb_conf_reload_time = t;
1613         }
1614
1615         /* 'printcap cache time = 0' disable the feature */
1616         
1617         if ( printcap_cache_time != 0 )
1618         { 
1619                 /* see if it's time to reload or if the clock has been set back */
1620                 
1621                 if ( (t >= last_printer_reload_time+printcap_cache_time) 
1622                         || (t-last_printer_reload_time  < 0) ) 
1623                 {
1624                         DEBUG( 3,( "Printcap cache time expired.\n"));
1625                         reload_printers();
1626                         last_printer_reload_time = t;
1627                 }
1628         }
1629 }
1630
1631 /****************************************************************************
1632  Process any timeout housekeeping. Return False if the caller should exit.
1633 ****************************************************************************/
1634
1635 static BOOL timeout_processing(int *select_timeout,
1636                                time_t *last_timeout_processing_time)
1637 {
1638         time_t t;
1639
1640         if (smb_read_error == READ_EOF) {
1641                 DEBUG(3,("timeout_processing: End of file from client (client has disconnected).\n"));
1642                 return False;
1643         }
1644
1645         if (smb_read_error == READ_ERROR) {
1646                 DEBUG(3,("timeout_processing: receive_smb error (%s) Exiting\n",
1647                         strerror(errno)));
1648                 return False;
1649         }
1650
1651         if (smb_read_error == READ_BAD_SIG) {
1652                 DEBUG(3,("timeout_processing: receive_smb error bad smb signature. Exiting\n"));
1653                 return False;
1654         }
1655
1656         *last_timeout_processing_time = t = time(NULL);
1657
1658         /* become root again if waiting */
1659         change_to_root_user();
1660
1661         /* check if we need to reload services */
1662         check_reload(t);
1663
1664         if(global_machine_password_needs_changing && 
1665                         /* for ADS we need to do a regular ADS password change, not a domain
1666                                         password change */
1667                         lp_security() == SEC_DOMAIN) {
1668
1669                 unsigned char trust_passwd_hash[16];
1670                 time_t lct;
1671
1672                 /*
1673                  * We're in domain level security, and the code that
1674                  * read the machine password flagged that the machine
1675                  * password needs changing.
1676                  */
1677
1678                 /*
1679                  * First, open the machine password file with an exclusive lock.
1680                  */
1681
1682                 if (secrets_lock_trust_account_password(lp_workgroup(), True) == False) {
1683                         DEBUG(0,("process: unable to lock the machine account password for \
1684 machine %s in domain %s.\n", global_myname(), lp_workgroup() ));
1685                         return True;
1686                 }
1687
1688                 if(!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd_hash, &lct, NULL)) {
1689                         DEBUG(0,("process: unable to read the machine account password for \
1690 machine %s in domain %s.\n", global_myname(), lp_workgroup()));
1691                         secrets_lock_trust_account_password(lp_workgroup(), False);
1692                         return True;
1693                 }
1694
1695                 /*
1696                  * Make sure someone else hasn't already done this.
1697                  */
1698
1699                 if(t < lct + lp_machine_password_timeout()) {
1700                         global_machine_password_needs_changing = False;
1701                         secrets_lock_trust_account_password(lp_workgroup(), False);
1702                         return True;
1703                 }
1704
1705                 /* always just contact the PDC here */
1706     
1707                 change_trust_account_password( lp_workgroup(), NULL);
1708                 global_machine_password_needs_changing = False;
1709                 secrets_lock_trust_account_password(lp_workgroup(), False);
1710         }
1711
1712         /* update printer queue caches if necessary */
1713   
1714         update_monitored_printq_cache();
1715   
1716         /*
1717          * Now we are root, check if the log files need pruning.
1718          * Force a log file check.
1719          */
1720         force_check_log_size();
1721         check_log_size();
1722
1723         /* Send any queued printer notify message to interested smbd's. */
1724
1725         print_notify_send_messages(smbd_messaging_context(), 0);
1726
1727         /*
1728          * Modify the select timeout depending upon
1729          * what we have remaining in our queues.
1730          */
1731
1732         *select_timeout = setup_select_timeout();
1733
1734         return True;
1735 }
1736
1737 /****************************************************************************
1738  Accessor functions for InBuffer, OutBuffer.
1739 ****************************************************************************/
1740
1741 char *get_InBuffer(void)
1742 {
1743         return InBuffer;
1744 }
1745
1746 char *get_OutBuffer(void)
1747 {
1748         return OutBuffer;
1749 }
1750
1751 /****************************************************************************
1752  Allocate a new InBuffer. Returns the new and old ones.
1753 ****************************************************************************/
1754
1755 static char *NewInBuffer(char **old_inbuf)
1756 {
1757         char *new_inbuf = (char *)SMB_MALLOC(total_buffer_size);
1758         if (!new_inbuf) {
1759                 return NULL;
1760         }
1761         if (old_inbuf) {
1762                 *old_inbuf = InBuffer;
1763         }
1764         InBuffer = new_inbuf;
1765 #if defined(DEVELOPER)
1766         clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size);
1767 #endif
1768         return InBuffer;
1769 }
1770
1771 /****************************************************************************
1772  Allocate a new OutBuffer. Returns the new and old ones.
1773 ****************************************************************************/
1774
1775 static char *NewOutBuffer(char **old_outbuf)
1776 {
1777         char *new_outbuf = (char *)SMB_MALLOC(total_buffer_size);
1778         if (!new_outbuf) {
1779                 return NULL;
1780         }
1781         if (old_outbuf) {
1782                 *old_outbuf = OutBuffer;
1783         }
1784         OutBuffer = new_outbuf;
1785 #if defined(DEVELOPER)
1786         clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer, total_buffer_size);
1787 #endif
1788         return OutBuffer;
1789 }
1790
1791 /****************************************************************************
1792  Process commands from the client
1793 ****************************************************************************/
1794
1795 void smbd_process(void)
1796 {
1797         time_t last_timeout_processing_time = time(NULL);
1798         unsigned int num_smbs = 0;
1799
1800         max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
1801
1802         while (True) {
1803                 int select_timeout = setup_select_timeout();
1804                 int num_echos;
1805                 char *inbuf;
1806                 size_t inbuf_len;
1807
1808                 errno = 0;      
1809                 
1810                 /* free up temporary memory */
1811                 lp_TALLOC_FREE();
1812                 main_loop_TALLOC_FREE();
1813
1814                 /* Did someone ask for immediate checks on things like blocking locks ? */
1815                 if (select_timeout == 0) {
1816                         if(!timeout_processing(&select_timeout,
1817                                                &last_timeout_processing_time))
1818                                 return;
1819                         num_smbs = 0; /* Reset smb counter. */
1820                 }
1821
1822                 run_events(smbd_event_context(), 0, NULL, NULL);
1823
1824                 while (!receive_message_or_smb(NULL, &inbuf, &inbuf_len,
1825                                                select_timeout)) {
1826                         if(!timeout_processing(&select_timeout,
1827                                                &last_timeout_processing_time))
1828                                 return;
1829                         num_smbs = 0; /* Reset smb counter. */
1830                 }
1831
1832
1833                 /*
1834                  * Ensure we do timeout processing if the SMB we just got was
1835                  * only an echo request. This allows us to set the select
1836                  * timeout in 'receive_message_or_smb()' to any value we like
1837                  * without worrying that the client will send echo requests
1838                  * faster than the select timeout, thus starving out the
1839                  * essential processing (change notify, blocking locks) that
1840                  * the timeout code does. JRA.
1841                  */ 
1842                 num_echos = smb_echo_count;
1843
1844                 process_smb(inbuf, inbuf_len);
1845
1846                 TALLOC_FREE(inbuf);
1847
1848                 if (smb_echo_count != num_echos) {
1849                         if(!timeout_processing( &select_timeout, &last_timeout_processing_time))
1850                                 return;
1851                         num_smbs = 0; /* Reset smb counter. */
1852                 }
1853
1854                 num_smbs++;
1855
1856                 /*
1857                  * If we are getting smb requests in a constant stream
1858                  * with no echos, make sure we attempt timeout processing
1859                  * every select_timeout milliseconds - but only check for this
1860                  * every 200 smb requests.
1861                  */
1862                 
1863                 if ((num_smbs % 200) == 0) {
1864                         time_t new_check_time = time(NULL);
1865                         if(new_check_time - last_timeout_processing_time >= (select_timeout/1000)) {
1866                                 if(!timeout_processing(
1867                                            &select_timeout,
1868                                            &last_timeout_processing_time))
1869                                         return;
1870                                 num_smbs = 0; /* Reset smb counter. */
1871                                 last_timeout_processing_time = new_check_time; /* Reset time. */
1872                         }
1873                 }
1874
1875                 /* The timeout_processing function isn't run nearly
1876                    often enough to implement 'max log size' without
1877                    overrunning the size of the file by many megabytes.
1878                    This is especially true if we are running at debug
1879                    level 10.  Checking every 50 SMBs is a nice
1880                    tradeoff of performance vs log file size overrun. */
1881
1882                 if ((num_smbs % 50) == 0 && need_to_check_log_size()) {
1883                         change_to_root_user();
1884                         check_log_size();
1885                 }
1886         }
1887 }