force checking of log size after 200 smbd in a row or after 30 sec with no
[tprouty/samba.git] / source / smbd / process.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    process incoming packets - main loop
5    Copyright (C) Andrew Tridgell 1992-1998
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 2 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, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23
24 extern int DEBUGLEVEL;
25
26 struct timeval smb_last_time;
27
28 static char *InBuffer = NULL;
29 char *OutBuffer = NULL;
30 char *last_inbuf = NULL;
31
32 /* 
33  * Size of data we can send to client. Set
34  *  by the client for all protocols above CORE.
35  *  Set by us for CORE protocol.
36  */
37 int max_send = BUFFER_SIZE;
38 /*
39  * Size of the data we can receive. Set by us.
40  * Can be modified by the max xmit parameter.
41  */
42 int max_recv = BUFFER_SIZE;
43
44 extern int last_message;
45 extern int global_oplock_break;
46 extern userdom_struct current_user_info;
47 extern char *last_inbuf;
48 extern char *InBuffer;
49 extern char *OutBuffer;
50 extern int smb_read_error;
51 extern VOLATILE sig_atomic_t reload_after_sighup;
52 extern BOOL global_machine_password_needs_changing;
53 extern fstring global_myworkgroup;
54 extern pstring global_myname;
55 extern int max_send;
56
57 /****************************************************************************
58  structure to hold a linked list of queued messages.
59  for processing.
60 ****************************************************************************/
61
62 typedef struct {
63    ubi_slNode msg_next;
64    char *msg_buf;
65    int msg_len;
66 } pending_message_list;
67
68 static ubi_slList smb_oplock_queue = { NULL, (ubi_slNodePtr)&smb_oplock_queue, 0};
69
70 /****************************************************************************
71  Function to push a message onto the tail of a linked list of smb messages ready
72  for processing.
73 ****************************************************************************/
74
75 static BOOL push_message(ubi_slList *list_head, char *buf, int msg_len)
76 {
77   pending_message_list *msg = (pending_message_list *)
78                                malloc(sizeof(pending_message_list));
79
80   if(msg == NULL)
81   {
82     DEBUG(0,("push_message: malloc fail (1)\n"));
83     return False;
84   }
85
86   msg->msg_buf = (char *)malloc(msg_len);
87   if(msg->msg_buf == NULL)
88   {
89     DEBUG(0,("push_message: malloc fail (2)\n"));
90     free((char *)msg);
91     return False;
92   }
93
94   memcpy(msg->msg_buf, buf, msg_len);
95   msg->msg_len = msg_len;
96
97   ubi_slAddTail( list_head, msg);
98
99   return True;
100 }
101
102 /****************************************************************************
103  Function to push a smb message onto a linked list of local smb messages ready
104  for processing.
105 ****************************************************************************/
106
107 BOOL push_oplock_pending_smb_message(char *buf, int msg_len)
108 {
109         return push_message(&smb_oplock_queue, buf, msg_len);
110 }
111
112 /****************************************************************************
113 do all async processing in here. This includes UDB oplock messages, kernel
114 oplock messages, change notify events etc.
115 ****************************************************************************/
116 static void async_processing(fd_set *fds, char *buffer, int buffer_len)
117 {
118         /* check for oplock messages (both UDP and kernel) */
119         if (receive_local_message(fds, buffer, buffer_len, 0)) {
120                 process_local_message(buffer, buffer_len);
121         }
122
123         /* check for async change notify events */
124         process_pending_change_notify_queue(0);
125
126         /* check for sighup processing */
127         if (reload_after_sighup) {
128                 unbecome_user();
129                 DEBUG(1,("Reloading services after SIGHUP\n"));
130                 reload_services(False);
131                 reload_after_sighup = False;
132         }
133 }
134
135 /****************************************************************************
136   Do a select on an two fd's - with timeout. 
137
138   If a local udp message has been pushed onto the
139   queue (this can only happen during oplock break
140   processing) call async_processing()
141
142   If a pending smb message has been pushed onto the
143   queue (this can only happen during oplock break
144   processing) return this next.
145
146   If the first smbfd is ready then read an smb from it.
147   if the second (loopback UDP) fd is ready then read a message
148   from it and setup the buffer header to identify the length
149   and from address.
150   Returns False on timeout or error.
151   Else returns True.
152
153 The timeout is in milli seconds
154 ****************************************************************************/
155
156 static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
157 {
158         fd_set fds;
159         int selrtn;
160         struct timeval to;
161         int maxfd;
162
163         smb_read_error = 0;
164
165  again:
166
167         /*
168          * Note that this call must be before processing any SMB
169          * messages as we need to synchronously process any messages
170          * we may have sent to ourselves from the previous SMB.
171          */
172         message_dispatch();
173
174         /*
175          * Check to see if we already have a message on the smb queue.
176          * If so - copy and return it.
177          */
178         if(ubi_slCount(&smb_oplock_queue) != 0) {
179                 pending_message_list *msg = (pending_message_list *)ubi_slRemHead(&smb_oplock_queue);
180                 memcpy(buffer, msg->msg_buf, MIN(buffer_len, msg->msg_len));
181   
182                 /* Free the message we just copied. */
183                 free((char *)msg->msg_buf);
184                 free((char *)msg);
185                 
186                 DEBUG(5,("receive_message_or_smb: returning queued smb message.\n"));
187                 return True;
188         }
189
190
191         /*
192          * Setup the select read fd set.
193          */
194
195         FD_ZERO(&fds);
196         FD_SET(smbd_server_fd(),&fds);
197         maxfd = setup_oplock_select_set(&fds);
198
199         to.tv_sec = timeout / 1000;
200         to.tv_usec = (timeout % 1000) * 1000;
201
202         selrtn = sys_select(MAX(maxfd,smbd_server_fd())+1,&fds,timeout>0?&to:NULL);
203
204         /* if we get EINTR then maybe we have received an oplock
205            signal - treat this as select returning 1. This is ugly, but
206            is the best we can do until the oplock code knows more about
207            signals */
208         if (selrtn == -1 && errno == EINTR) {
209                 async_processing(&fds, buffer, buffer_len);
210                 goto again;
211         }
212
213         /* Check if error */
214         if (selrtn == -1) {
215                 /* something is wrong. Maybe the socket is dead? */
216                 smb_read_error = READ_ERROR;
217                 return False;
218         } 
219     
220         /* Did we timeout ? */
221         if (selrtn == 0) {
222                 smb_read_error = READ_TIMEOUT;
223                 return False;
224         }
225
226         if (!FD_ISSET(smbd_server_fd(),&fds) || selrtn > 1) {
227                 async_processing(&fds, buffer, buffer_len);
228                 if (!FD_ISSET(smbd_server_fd(),&fds)) goto again;
229         }
230         
231         return receive_smb(smbd_server_fd(), buffer, 0);
232 }
233
234 /****************************************************************************
235 Get the next SMB packet, doing the local message processing automatically.
236 ****************************************************************************/
237
238 BOOL receive_next_smb(char *inbuf, int bufsize, int timeout)
239 {
240         BOOL got_keepalive;
241         BOOL ret;
242
243         do {
244                 ret = receive_message_or_smb(inbuf,bufsize,timeout);
245                 
246                 got_keepalive = (ret && (CVAL(inbuf,0) == 0x85));
247         } while (ret && got_keepalive);
248
249         return ret;
250 }
251
252 /****************************************************************************
253  We're terminating and have closed all our files/connections etc.
254  If there are any pending local messages we need to respond to them
255  before termination so that other smbds don't think we just died whilst
256  holding oplocks.
257 ****************************************************************************/
258
259 void respond_to_all_remaining_local_messages(void)
260 {
261   char buffer[1024];
262   fd_set fds;
263
264   /*
265    * Assert we have no exclusive open oplocks.
266    */
267
268   if(get_number_of_exclusive_open_oplocks()) {
269     DEBUG(0,("respond_to_all_remaining_local_messages: PANIC : we have %d exclusive oplocks.\n",
270           get_number_of_exclusive_open_oplocks() ));
271     return;
272   }
273
274   /*
275    * Setup the select read fd set.
276    */
277
278   FD_ZERO(&fds);
279   if(!setup_oplock_select_set(&fds))
280     return;
281
282   /*
283    * Keep doing receive_local_message with a 1 ms timeout until
284    * we have no more messages.
285    */
286   while(receive_local_message(&fds, buffer, sizeof(buffer), 1)) {
287           /* Deal with oplock break requests from other smbd's. */
288           process_local_message(buffer, sizeof(buffer));
289
290           FD_ZERO(&fds);
291           (void)setup_oplock_select_set(&fds);
292   }
293
294   return;
295 }
296
297
298 /*
299 These flags determine some of the permissions required to do an operation 
300
301 Note that I don't set NEED_WRITE on some write operations because they
302 are used by some brain-dead clients when printing, and I don't want to
303 force write permissions on print services.
304 */
305 #define AS_USER (1<<0)
306 #define NEED_WRITE (1<<1)
307 #define TIME_INIT (1<<2)
308 #define CAN_IPC (1<<3)
309 #define AS_GUEST (1<<5)
310 #define QUEUE_IN_OPLOCK (1<<6)
311
312 /* 
313    define a list of possible SMB messages and their corresponding
314    functions. Any message that has a NULL function is unimplemented -
315    please feel free to contribute implementations!
316 */
317 struct smb_message_struct
318 {
319   char *name;
320   int (*fn)(connection_struct *conn, char *, char *, int, int);
321   int flags;
322 }
323  smb_messages[256] = {
324
325 /* 0x00 */ { "SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
326 /* 0x01 */ { "SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
327 /* 0x02 */ { "SMBopen",reply_open,AS_USER | QUEUE_IN_OPLOCK },
328 /* 0x03 */ { "SMBcreate",reply_mknew,AS_USER},
329 /* 0x04 */ { "SMBclose",reply_close,AS_USER | CAN_IPC },
330 /* 0x05 */ { "SMBflush",reply_flush,AS_USER},
331 /* 0x06 */ { "SMBunlink",reply_unlink,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK},
332 /* 0x07 */ { "SMBmv",reply_mv,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK},
333 /* 0x08 */ { "SMBgetatr",reply_getatr,AS_USER},
334 /* 0x09 */ { "SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
335 /* 0x0a */ { "SMBread",reply_read,AS_USER},
336 /* 0x0b */ { "SMBwrite",reply_write,AS_USER | CAN_IPC },
337 /* 0x0c */ { "SMBlock",reply_lock,AS_USER},
338 /* 0x0d */ { "SMBunlock",reply_unlock,AS_USER},
339 /* 0x0e */ { "SMBctemp",reply_ctemp,AS_USER | QUEUE_IN_OPLOCK },
340 /* 0x0f */ { "SMBmknew",reply_mknew,AS_USER}, 
341 /* 0x10 */ { "SMBchkpth",reply_chkpth,AS_USER},
342 /* 0x11 */ { "SMBexit",reply_exit,0},
343 /* 0x12 */ { "SMBlseek",reply_lseek,AS_USER},
344 /* 0x13 */ { "SMBlockread",reply_lockread,AS_USER},
345 /* 0x14 */ { "SMBwriteunlock",reply_writeunlock,AS_USER},
346 /* 0x15 */ { NULL, NULL, 0 },
347 /* 0x16 */ { NULL, NULL, 0 },
348 /* 0x17 */ { NULL, NULL, 0 },
349 /* 0x18 */ { NULL, NULL, 0 },
350 /* 0x19 */ { NULL, NULL, 0 },
351 /* 0x1a */ { "SMBreadbraw",reply_readbraw,AS_USER},
352 /* 0x1b */ { "SMBreadBmpx",reply_readbmpx,AS_USER},
353 /* 0x1c */ { "SMBreadBs",NULL,AS_USER},
354 /* 0x1d */ { "SMBwritebraw",reply_writebraw,AS_USER},
355 /* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,AS_USER},
356 /* 0x1f */ { "SMBwriteBs",reply_writebs,AS_USER},
357 /* 0x20 */ { "SMBwritec",NULL,AS_USER},
358 /* 0x21 */ { NULL, NULL, 0 },
359 /* 0x22 */ { "SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE },
360 /* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER },
361 /* 0x24 */ { "SMBlockingX",reply_lockingX,AS_USER },
362 /* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC | QUEUE_IN_OPLOCK},
363 /* 0x26 */ { "SMBtranss",NULL,AS_USER | CAN_IPC},
364 /* 0x27 */ { "SMBioctl",reply_ioctl,0},
365 /* 0x28 */ { "SMBioctls",NULL,AS_USER},
366 /* 0x29 */ { "SMBcopy",reply_copy,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK },
367 /* 0x2a */ { "SMBmove",NULL,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK },
368 /* 0x2b */ { "SMBecho",reply_echo,0},
369 /* 0x2c */ { "SMBwriteclose",reply_writeclose,AS_USER},
370 /* 0x2d */ { "SMBopenX",reply_open_and_X,AS_USER | CAN_IPC | QUEUE_IN_OPLOCK },
371 /* 0x2e */ { "SMBreadX",reply_read_and_X,AS_USER | CAN_IPC },
372 /* 0x2f */ { "SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC },
373 /* 0x30 */ { NULL, NULL, 0 },
374 /* 0x31 */ { NULL, NULL, 0 },
375 /* 0x32 */ { "SMBtrans2", reply_trans2, AS_USER | QUEUE_IN_OPLOCK | CAN_IPC },
376 /* 0x33 */ { "SMBtranss2", reply_transs2, AS_USER},
377 /* 0x34 */ { "SMBfindclose", reply_findclose,AS_USER},
378 /* 0x35 */ { "SMBfindnclose", reply_findnclose, AS_USER},
379 /* 0x36 */ { NULL, NULL, 0 },
380 /* 0x37 */ { NULL, NULL, 0 },
381 /* 0x38 */ { NULL, NULL, 0 },
382 /* 0x39 */ { NULL, NULL, 0 },
383 /* 0x3a */ { NULL, NULL, 0 },
384 /* 0x3b */ { NULL, NULL, 0 },
385 /* 0x3c */ { NULL, NULL, 0 },
386 /* 0x3d */ { NULL, NULL, 0 },
387 /* 0x3e */ { NULL, NULL, 0 },
388 /* 0x3f */ { NULL, NULL, 0 },
389 /* 0x40 */ { NULL, NULL, 0 },
390 /* 0x41 */ { NULL, NULL, 0 },
391 /* 0x42 */ { NULL, NULL, 0 },
392 /* 0x43 */ { NULL, NULL, 0 },
393 /* 0x44 */ { NULL, NULL, 0 },
394 /* 0x45 */ { NULL, NULL, 0 },
395 /* 0x46 */ { NULL, NULL, 0 },
396 /* 0x47 */ { NULL, NULL, 0 },
397 /* 0x48 */ { NULL, NULL, 0 },
398 /* 0x49 */ { NULL, NULL, 0 },
399 /* 0x4a */ { NULL, NULL, 0 },
400 /* 0x4b */ { NULL, NULL, 0 },
401 /* 0x4c */ { NULL, NULL, 0 },
402 /* 0x4d */ { NULL, NULL, 0 },
403 /* 0x4e */ { NULL, NULL, 0 },
404 /* 0x4f */ { NULL, NULL, 0 },
405 /* 0x50 */ { NULL, NULL, 0 },
406 /* 0x51 */ { NULL, NULL, 0 },
407 /* 0x52 */ { NULL, NULL, 0 },
408 /* 0x53 */ { NULL, NULL, 0 },
409 /* 0x54 */ { NULL, NULL, 0 },
410 /* 0x55 */ { NULL, NULL, 0 },
411 /* 0x56 */ { NULL, NULL, 0 },
412 /* 0x57 */ { NULL, NULL, 0 },
413 /* 0x58 */ { NULL, NULL, 0 },
414 /* 0x59 */ { NULL, NULL, 0 },
415 /* 0x5a */ { NULL, NULL, 0 },
416 /* 0x5b */ { NULL, NULL, 0 },
417 /* 0x5c */ { NULL, NULL, 0 },
418 /* 0x5d */ { NULL, NULL, 0 },
419 /* 0x5e */ { NULL, NULL, 0 },
420 /* 0x5f */ { NULL, NULL, 0 },
421 /* 0x60 */ { NULL, NULL, 0 },
422 /* 0x61 */ { NULL, NULL, 0 },
423 /* 0x62 */ { NULL, NULL, 0 },
424 /* 0x63 */ { NULL, NULL, 0 },
425 /* 0x64 */ { NULL, NULL, 0 },
426 /* 0x65 */ { NULL, NULL, 0 },
427 /* 0x66 */ { NULL, NULL, 0 },
428 /* 0x67 */ { NULL, NULL, 0 },
429 /* 0x68 */ { NULL, NULL, 0 },
430 /* 0x69 */ { NULL, NULL, 0 },
431 /* 0x6a */ { NULL, NULL, 0 },
432 /* 0x6b */ { NULL, NULL, 0 },
433 /* 0x6c */ { NULL, NULL, 0 },
434 /* 0x6d */ { NULL, NULL, 0 },
435 /* 0x6e */ { NULL, NULL, 0 },
436 /* 0x6f */ { NULL, NULL, 0 },
437 /* 0x70 */ { "SMBtcon",reply_tcon,0},
438 /* 0x71 */ { "SMBtdis",reply_tdis,0},
439 /* 0x72 */ { "SMBnegprot",reply_negprot,0},
440 /* 0x73 */ { "SMBsesssetupX",reply_sesssetup_and_X,0},
441 /* 0x74 */ { "SMBulogoffX", reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
442 /* 0x75 */ { "SMBtconX",reply_tcon_and_X,0},
443 /* 0x76 */ { NULL, NULL, 0 },
444 /* 0x77 */ { NULL, NULL, 0 },
445 /* 0x78 */ { NULL, NULL, 0 },
446 /* 0x79 */ { NULL, NULL, 0 },
447 /* 0x7a */ { NULL, NULL, 0 },
448 /* 0x7b */ { NULL, NULL, 0 },
449 /* 0x7c */ { NULL, NULL, 0 },
450 /* 0x7d */ { NULL, NULL, 0 },
451 /* 0x7e */ { NULL, NULL, 0 },
452 /* 0x7f */ { NULL, NULL, 0 },
453 /* 0x80 */ { "SMBdskattr",reply_dskattr,AS_USER},
454 /* 0x81 */ { "SMBsearch",reply_search,AS_USER},
455 /* 0x82 */ { "SMBffirst",reply_search,AS_USER},
456 /* 0x83 */ { "SMBfunique",reply_search,AS_USER},
457 /* 0x84 */ { "SMBfclose",reply_fclose,AS_USER},
458 /* 0x85 */ { NULL, NULL, 0 },
459 /* 0x86 */ { NULL, NULL, 0 },
460 /* 0x87 */ { NULL, NULL, 0 },
461 /* 0x88 */ { NULL, NULL, 0 },
462 /* 0x89 */ { NULL, NULL, 0 },
463 /* 0x8a */ { NULL, NULL, 0 },
464 /* 0x8b */ { NULL, NULL, 0 },
465 /* 0x8c */ { NULL, NULL, 0 },
466 /* 0x8d */ { NULL, NULL, 0 },
467 /* 0x8e */ { NULL, NULL, 0 },
468 /* 0x8f */ { NULL, NULL, 0 },
469 /* 0x90 */ { NULL, NULL, 0 },
470 /* 0x91 */ { NULL, NULL, 0 },
471 /* 0x92 */ { NULL, NULL, 0 },
472 /* 0x93 */ { NULL, NULL, 0 },
473 /* 0x94 */ { NULL, NULL, 0 },
474 /* 0x95 */ { NULL, NULL, 0 },
475 /* 0x96 */ { NULL, NULL, 0 },
476 /* 0x97 */ { NULL, NULL, 0 },
477 /* 0x98 */ { NULL, NULL, 0 },
478 /* 0x99 */ { NULL, NULL, 0 },
479 /* 0x9a */ { NULL, NULL, 0 },
480 /* 0x9b */ { NULL, NULL, 0 },
481 /* 0x9c */ { NULL, NULL, 0 },
482 /* 0x9d */ { NULL, NULL, 0 },
483 /* 0x9e */ { NULL, NULL, 0 },
484 /* 0x9f */ { NULL, NULL, 0 },
485 /* 0xa0 */ { "SMBnttrans", reply_nttrans, AS_USER | CAN_IPC | QUEUE_IN_OPLOCK},
486 /* 0xa1 */ { "SMBnttranss", reply_nttranss, AS_USER | CAN_IPC },
487 /* 0xa2 */ { "SMBntcreateX", reply_ntcreate_and_X, AS_USER | CAN_IPC | QUEUE_IN_OPLOCK },
488 /* 0xa3 */ { NULL, NULL, 0 },
489 /* 0xa4 */ { "SMBntcancel", reply_ntcancel, 0 },
490 /* 0xa5 */ { NULL, NULL, 0 },
491 /* 0xa6 */ { NULL, NULL, 0 },
492 /* 0xa7 */ { NULL, NULL, 0 },
493 /* 0xa8 */ { NULL, NULL, 0 },
494 /* 0xa9 */ { NULL, NULL, 0 },
495 /* 0xaa */ { NULL, NULL, 0 },
496 /* 0xab */ { NULL, NULL, 0 },
497 /* 0xac */ { NULL, NULL, 0 },
498 /* 0xad */ { NULL, NULL, 0 },
499 /* 0xae */ { NULL, NULL, 0 },
500 /* 0xaf */ { NULL, NULL, 0 },
501 /* 0xb0 */ { NULL, NULL, 0 },
502 /* 0xb1 */ { NULL, NULL, 0 },
503 /* 0xb2 */ { NULL, NULL, 0 },
504 /* 0xb3 */ { NULL, NULL, 0 },
505 /* 0xb4 */ { NULL, NULL, 0 },
506 /* 0xb5 */ { NULL, NULL, 0 },
507 /* 0xb6 */ { NULL, NULL, 0 },
508 /* 0xb7 */ { NULL, NULL, 0 },
509 /* 0xb8 */ { NULL, NULL, 0 },
510 /* 0xb9 */ { NULL, NULL, 0 },
511 /* 0xba */ { NULL, NULL, 0 },
512 /* 0xbb */ { NULL, NULL, 0 },
513 /* 0xbc */ { NULL, NULL, 0 },
514 /* 0xbd */ { NULL, NULL, 0 },
515 /* 0xbe */ { NULL, NULL, 0 },
516 /* 0xbf */ { NULL, NULL, 0 },
517 /* 0xc0 */ { "SMBsplopen",reply_printopen,AS_USER | QUEUE_IN_OPLOCK },
518 /* 0xc1 */ { "SMBsplwr",reply_printwrite,AS_USER},
519 /* 0xc2 */ { "SMBsplclose",reply_printclose,AS_USER},
520 /* 0xc3 */ { "SMBsplretq",reply_printqueue,AS_USER},
521 /* 0xc4 */ { NULL, NULL, 0 },
522 /* 0xc5 */ { NULL, NULL, 0 },
523 /* 0xc6 */ { NULL, NULL, 0 },
524 /* 0xc7 */ { NULL, NULL, 0 },
525 /* 0xc8 */ { NULL, NULL, 0 },
526 /* 0xc9 */ { NULL, NULL, 0 },
527 /* 0xca */ { NULL, NULL, 0 },
528 /* 0xcb */ { NULL, NULL, 0 },
529 /* 0xcc */ { NULL, NULL, 0 },
530 /* 0xcd */ { NULL, NULL, 0 },
531 /* 0xce */ { NULL, NULL, 0 },
532 /* 0xcf */ { NULL, NULL, 0 },
533 /* 0xd0 */ { "SMBsends",reply_sends,AS_GUEST},
534 /* 0xd1 */ { "SMBsendb",NULL,AS_GUEST},
535 /* 0xd2 */ { "SMBfwdname",NULL,AS_GUEST},
536 /* 0xd3 */ { "SMBcancelf",NULL,AS_GUEST},
537 /* 0xd4 */ { "SMBgetmac",NULL,AS_GUEST},
538 /* 0xd5 */ { "SMBsendstrt",reply_sendstrt,AS_GUEST},
539 /* 0xd6 */ { "SMBsendend",reply_sendend,AS_GUEST},
540 /* 0xd7 */ { "SMBsendtxt",reply_sendtxt,AS_GUEST},
541 /* 0xd8 */ { NULL, NULL, 0 },
542 /* 0xd9 */ { NULL, NULL, 0 },
543 /* 0xda */ { NULL, NULL, 0 },
544 /* 0xdb */ { NULL, NULL, 0 },
545 /* 0xdc */ { NULL, NULL, 0 },
546 /* 0xdd */ { NULL, NULL, 0 },
547 /* 0xde */ { NULL, NULL, 0 },
548 /* 0xdf */ { NULL, NULL, 0 },
549 /* 0xe0 */ { NULL, NULL, 0 },
550 /* 0xe1 */ { NULL, NULL, 0 },
551 /* 0xe2 */ { NULL, NULL, 0 },
552 /* 0xe3 */ { NULL, NULL, 0 },
553 /* 0xe4 */ { NULL, NULL, 0 },
554 /* 0xe5 */ { NULL, NULL, 0 },
555 /* 0xe6 */ { NULL, NULL, 0 },
556 /* 0xe7 */ { NULL, NULL, 0 },
557 /* 0xe8 */ { NULL, NULL, 0 },
558 /* 0xe9 */ { NULL, NULL, 0 },
559 /* 0xea */ { NULL, NULL, 0 },
560 /* 0xeb */ { NULL, NULL, 0 },
561 /* 0xec */ { NULL, NULL, 0 },
562 /* 0xed */ { NULL, NULL, 0 },
563 /* 0xee */ { NULL, NULL, 0 },
564 /* 0xef */ { NULL, NULL, 0 },
565 /* 0xf0 */ { NULL, NULL, 0 },
566 /* 0xf1 */ { NULL, NULL, 0 },
567 /* 0xf2 */ { NULL, NULL, 0 },
568 /* 0xf3 */ { NULL, NULL, 0 },
569 /* 0xf4 */ { NULL, NULL, 0 },
570 /* 0xf5 */ { NULL, NULL, 0 },
571 /* 0xf6 */ { NULL, NULL, 0 },
572 /* 0xf7 */ { NULL, NULL, 0 },
573 /* 0xf8 */ { NULL, NULL, 0 },
574 /* 0xf9 */ { NULL, NULL, 0 },
575 /* 0xfa */ { NULL, NULL, 0 },
576 /* 0xfb */ { NULL, NULL, 0 },
577 /* 0xfc */ { NULL, NULL, 0 },
578 /* 0xfd */ { NULL, NULL, 0 },
579 /* 0xfe */ { NULL, NULL, 0 },
580 /* 0xff */ { NULL, NULL, 0 }
581
582 };
583
584 /*******************************************************************
585 dump a prs to a file
586  ********************************************************************/
587 static void smb_dump(char *name, int type, char *data, ssize_t len)
588 {
589         int fd, i;
590         pstring fname;
591         if (DEBUGLEVEL < 50) return;
592
593         if (len < 4) len = smb_len(data)+4;
594         for (i=1;i<100;i++) {
595                 slprintf(fname,sizeof(fname)-1, "/tmp/%s.%d.%s", name, i,
596                                 type ? "req" : "resp");
597                 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644);
598                 if (fd != -1 || errno != EEXIST) break;
599         }
600         if (fd != -1) {
601                 write(fd, data, len);
602                 close(fd);
603                 DEBUG(0,("created %s len %d\n", fname, len));
604         }
605 }
606
607
608 /****************************************************************************
609 do a switch on the message type, and return the response size
610 ****************************************************************************/
611 static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize)
612 {
613   static pid_t pid= (pid_t)-1;
614   int outsize = 0;
615   extern uint16 global_smbpid;
616
617   type &= 0xff;
618
619   if (pid == (pid_t)-1)
620     pid = sys_getpid();
621
622   errno = 0;
623   last_message = type;
624
625   /* make sure this is an SMB packet */
626   if (strncmp(smb_base(inbuf),"\377SMB",4) != 0)
627   {
628     DEBUG(2,("Non-SMB packet of length %d\n",smb_len(inbuf)));
629     return(-1);
630   }
631
632   /* yuck! this is an interim measure before we get rid of our
633      current inbuf/outbuf system */
634   global_smbpid = SVAL(inbuf,smb_pid);
635
636   if (smb_messages[type].fn == NULL)
637   {
638     DEBUG(0,("Unknown message type %d!\n",type));
639     smb_dump("Unknown", 1, inbuf, size);
640     outsize = reply_unknown(inbuf,outbuf);
641   }
642   else
643   {
644     int flags = smb_messages[type].flags;
645     static uint16 last_session_tag = UID_FIELD_INVALID;
646     /* In share mode security we must ignore the vuid. */
647     uint16 session_tag = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(inbuf,smb_uid);
648     connection_struct *conn = conn_find(SVAL(inbuf,smb_tid));
649
650     DEBUG(3,("switch message %s (pid %d)\n",smb_fn_name(type),(int)pid));
651
652     smb_dump(smb_fn_name(type), 1, inbuf, size);
653     if(global_oplock_break)
654     {
655       if(flags & QUEUE_IN_OPLOCK)
656       {
657         /* 
658          * Queue this message as we are the process of an oplock break.
659          */
660
661         DEBUG( 2, ( "switch_message: queueing message due to being in " ) );
662         DEBUGADD( 2, ( "oplock break state.\n" ) );
663
664         push_oplock_pending_smb_message( inbuf, size );
665         return -1;
666       }          
667     }
668
669     /* Ensure this value is replaced in the incoming packet. */
670     SSVAL(inbuf,smb_uid,session_tag);
671
672     /*
673      * Ensure the correct username is in current_user_info.
674      * This is a really ugly bugfix for problems with
675      * multiple session_setup_and_X's being done and
676      * allowing %U and %G substitutions to work correctly.
677      * There is a reason this code is done here, don't
678      * move it unless you know what you're doing... :-).
679      * JRA.
680      */
681
682     if (session_tag != last_session_tag) {
683       user_struct *vuser = NULL;
684
685       last_session_tag = session_tag;
686       if(session_tag != UID_FIELD_INVALID)
687         vuser = get_valid_user_struct(session_tag);           
688       if(vuser != NULL)
689         current_user_info = vuser->user;
690     }
691
692     /* does this protocol need to be run as root? */
693     if (!(flags & AS_USER))
694       unbecome_user();
695
696     /* does this protocol need a valid tree connection? */
697     if ((flags & AS_USER) && !conn) {
698             return ERROR(ERRSRV, ERRinvnid);
699     }
700
701
702     /* does this protocol need to be run as the connected user? */
703     if ((flags & AS_USER) && !become_user(conn,session_tag)) {
704       if (flags & AS_GUEST) 
705         flags &= ~AS_USER;
706       else
707         return(ERROR(ERRSRV,ERRaccess));
708     }
709
710     /* this code is to work around a bug is MS client 3 without
711        introducing a security hole - it needs to be able to do
712        print queue checks as guest if it isn't logged in properly */
713     if (flags & AS_USER)
714       flags &= ~AS_GUEST;
715
716     /* does it need write permission? */
717     if ((flags & NEED_WRITE) && !CAN_WRITE(conn))
718       return(ERROR(ERRSRV,ERRaccess));
719
720     /* ipc services are limited */
721     if (IS_IPC(conn) && (flags & AS_USER) && !(flags & CAN_IPC)) {
722       return(ERROR(ERRSRV,ERRaccess));      
723     }
724
725     /* load service specific parameters */
726     if (conn && !become_service(conn,(flags & AS_USER)?True:False)) {
727       return(ERROR(ERRSRV,ERRaccess));
728     }
729
730     /* does this protocol need to be run as guest? */
731     if ((flags & AS_GUEST) && 
732                  (!become_guest() || 
733                 !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1)))) {
734       return(ERROR(ERRSRV,ERRaccess));
735     }
736
737     last_inbuf = inbuf;
738
739     outsize = smb_messages[type].fn(conn, inbuf,outbuf,size,bufsize);
740   }
741
742   smb_dump(smb_fn_name(type), 0, outbuf, outsize);
743
744   return(outsize);
745 }
746
747
748 /****************************************************************************
749   construct a reply to the incoming packet
750 ****************************************************************************/
751 static int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
752 {
753   int type = CVAL(inbuf,smb_com);
754   int outsize = 0;
755   int msg_type = CVAL(inbuf,0);
756
757   GetTimeOfDay(&smb_last_time);
758
759   chain_size = 0;
760   file_chain_reset();
761   reset_chain_p();
762
763   if (msg_type != 0)
764     return(reply_special(inbuf,outbuf));  
765
766   construct_reply_common(inbuf, outbuf);
767
768   outsize = switch_message(type,inbuf,outbuf,size,bufsize);
769
770   outsize += chain_size;
771
772   if(outsize > 4)
773     smb_setlen(outbuf,outsize - 4);
774   return(outsize);
775 }
776
777 /****************************************************************************
778   Keep track of the number of running smbd's. This functionality is used to
779   'hard' limit Samba overhead on resource constrained systems. 
780 ****************************************************************************/
781 static BOOL smbd_process_limit(void)
782 {
783         int  total_smbds;
784         
785         if (lp_max_smbd_processes()) {
786
787                 /* Always add one to the smbd process count, as exit_server() always
788                  * subtracts one.
789                  */
790
791                 total_smbds = 1; /* In case we need to create the entry. */
792
793                 if (tdb_change_int_atomic(conn_tdb_ctx(), "INFO/total_smbds", &total_smbds, 1) == -1)
794                         return True;
795
796                 return total_smbds > lp_max_smbd_processes();
797         }
798         else
799                 return False;
800 }
801
802 /****************************************************************************
803   process an smb from the client - split out from the process() code so
804   it can be used by the oplock break code.
805 ****************************************************************************/
806 void process_smb(char *inbuf, char *outbuf)
807 {
808 #ifdef WITH_SSL
809   extern BOOL sslEnabled;     /* don't use function for performance reasons */
810   static int sslConnected = 0;
811 #endif /* WITH_SSL */
812   static int trans_num;
813   int msg_type = CVAL(inbuf,0);
814   int32 len = smb_len(inbuf);
815   int nread = len + 4;
816
817   DO_PROFILE_INC(smb_count);
818
819   if (trans_num == 0) {
820           /* on the first packet, check the global hosts allow/ hosts
821              deny parameters before doing any parsing of the packet
822              passed to us by the client.  This prevents attacks on our
823              parsing code from hosts not in the hosts allow list */
824           if (smbd_process_limit() ||
825                   !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1))) {
826                   /* send a negative session response "not listening on calling
827                    name" */
828                   static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
829                   DEBUG( 1, ( "Connection denied from %s\n",
830                               client_addr() ) );
831                   (void)send_smb(smbd_server_fd(),(char *)buf);
832                   exit_server("connection denied");
833           }
834   }
835
836   DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type, len ) );
837   DEBUG( 3, ( "Transaction %d of length %d\n", trans_num, nread ) );
838
839 #ifdef WITH_SSL
840     if(sslEnabled && !sslConnected){
841         sslConnected = sslutil_negotiate_ssl(smbd_server_fd(), msg_type);
842         if(sslConnected < 0){   /* an error occured */
843             exit_server("SSL negotiation failed");
844         }else if(sslConnected){
845             trans_num++;
846             return;
847         }
848     }
849 #endif  /* WITH_SSL */
850
851   if (msg_type == 0)
852     show_msg(inbuf);
853   else if(msg_type == 0x85)
854     return; /* Keepalive packet. */
855
856   nread = construct_reply(inbuf,outbuf,nread,max_send);
857       
858   if(nread > 0) 
859   {
860     if (CVAL(outbuf,0) == 0)
861       show_msg(outbuf);
862         
863     if (nread != smb_len(outbuf) + 4) 
864     {
865       DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
866                  nread, smb_len(outbuf)));
867     }
868     else
869       if (!send_smb(smbd_server_fd(),outbuf))
870         exit_server("process_smb: send_smb failed.\n");
871   }
872   trans_num++;
873 }
874
875
876
877 /****************************************************************************
878 return a string containing the function name of a SMB command
879 ****************************************************************************/
880 char *smb_fn_name(int type)
881 {
882         static char *unknown_name = "SMBunknown";
883
884         if (smb_messages[type].name == NULL)
885                 return(unknown_name);
886
887         return(smb_messages[type].name);
888 }
889
890
891 /****************************************************************************
892  Helper function for contruct_reply.
893 ****************************************************************************/
894
895 void construct_reply_common(char *inbuf,char *outbuf)
896 {
897   memset(outbuf,'\0',smb_size);
898
899   set_message(outbuf,0,0,True);
900   CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com);
901
902   memcpy(outbuf+4,inbuf+4,4);
903   CVAL(outbuf,smb_rcls) = SMB_SUCCESS;
904   CVAL(outbuf,smb_reh) = 0;
905   SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES)); /* bit 7 set
906                                  means a reply */
907   SSVAL(outbuf,smb_flg2,
908         (SVAL(inbuf,smb_flg2)&FLAGS2_UNICODE_STRINGS) | FLAGS2_LONG_PATH_COMPONENTS);
909         /* say we support long filenames */
910
911   SSVAL(outbuf,smb_err,SMB_SUCCESS);
912   SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
913   SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
914   SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
915   SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
916 }
917
918 /****************************************************************************
919   construct a chained reply and add it to the already made reply
920   **************************************************************************/
921 int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
922 {
923   static char *orig_inbuf;
924   static char *orig_outbuf;
925   int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0);
926   unsigned smb_off2 = SVAL(inbuf,smb_vwv1);
927   char *inbuf2, *outbuf2;
928   int outsize2;
929   char inbuf_saved[smb_wct];
930   char outbuf_saved[smb_wct];
931   int wct = CVAL(outbuf,smb_wct);
932   int outsize = smb_size + 2*wct + SVAL(outbuf,smb_vwv0+2*wct);
933
934   /* maybe its not chained */
935   if (smb_com2 == 0xFF) {
936     CVAL(outbuf,smb_vwv0) = 0xFF;
937     return outsize;
938   }
939
940   if (chain_size == 0) {
941     /* this is the first part of the chain */
942     orig_inbuf = inbuf;
943     orig_outbuf = outbuf;
944   }
945
946   /*
947    * The original Win95 redirector dies on a reply to
948    * a lockingX and read chain unless the chain reply is
949    * 4 byte aligned. JRA.
950    */
951
952   outsize = (outsize + 3) & ~3;
953
954   /* we need to tell the client where the next part of the reply will be */
955   SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf));
956   CVAL(outbuf,smb_vwv0) = smb_com2;
957
958   /* remember how much the caller added to the chain, only counting stuff
959      after the parameter words */
960   chain_size += outsize - smb_wct;
961
962   /* work out pointers into the original packets. The
963      headers on these need to be filled in */
964   inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct;
965   outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct;
966
967   /* remember the original command type */
968   smb_com1 = CVAL(orig_inbuf,smb_com);
969
970   /* save the data which will be overwritten by the new headers */
971   memcpy(inbuf_saved,inbuf2,smb_wct);
972   memcpy(outbuf_saved,outbuf2,smb_wct);
973
974   /* give the new packet the same header as the last part of the SMB */
975   memmove(inbuf2,inbuf,smb_wct);
976
977   /* create the in buffer */
978   CVAL(inbuf2,smb_com) = smb_com2;
979
980   /* create the out buffer */
981   construct_reply_common(inbuf2, outbuf2);
982
983   DEBUG(3,("Chained message\n"));
984   show_msg(inbuf2);
985
986   /* process the request */
987   outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size,
988                             bufsize-chain_size);
989
990   /* copy the new reply and request headers over the old ones, but
991      preserve the smb_com field */
992   memmove(orig_outbuf,outbuf2,smb_wct);
993   CVAL(orig_outbuf,smb_com) = smb_com1;
994
995   /* restore the saved data, being careful not to overwrite any
996    data from the reply header */
997   memcpy(inbuf2,inbuf_saved,smb_wct);
998   {
999     int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf);
1000     if (ofs < 0) ofs = 0;
1001     memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs);
1002   }
1003
1004   return outsize2;
1005 }
1006
1007 /****************************************************************************
1008  Setup the needed select timeout.
1009 ****************************************************************************/
1010
1011 static int setup_select_timeout(void)
1012 {
1013         int select_timeout;
1014         int t;
1015
1016         /*
1017          * Increase the select timeout back to SMBD_SELECT_TIMEOUT if we
1018          * have removed any blocking locks. JRA.
1019          */
1020
1021         select_timeout = blocking_locks_pending() ? SMBD_SELECT_TIMEOUT_WITH_PENDING_LOCKS*1000 :
1022                 SMBD_SELECT_TIMEOUT*1000;
1023
1024         t = change_notify_timeout();
1025         if (t != -1) select_timeout = MIN(select_timeout, t*1000);
1026
1027         return select_timeout;
1028 }
1029
1030 /****************************************************************************
1031  Check if services need reloading.
1032 ****************************************************************************/
1033
1034 void check_reload(int t)
1035 {
1036   static time_t last_smb_conf_reload_time = 0;
1037
1038   if(last_smb_conf_reload_time == 0)
1039     last_smb_conf_reload_time = t;
1040
1041   if (reload_after_sighup || (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK))
1042   {
1043     reload_services(True);
1044     reload_after_sighup = False;
1045     last_smb_conf_reload_time = t;
1046   }
1047 }
1048
1049 /****************************************************************************
1050  Process any timeout housekeeping. Return False if the caller should exit.
1051 ****************************************************************************/
1052
1053 static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_timeout_processing_time)
1054 {
1055   static time_t last_keepalive_sent_time = 0;
1056   static time_t last_idle_closed_check = 0;
1057   time_t t;
1058   BOOL allidle = True;
1059   extern int keepalive;
1060
1061   if (smb_read_error == READ_EOF) 
1062   {
1063     DEBUG(3,("end of file from client\n"));
1064     return False;
1065   }
1066
1067   if (smb_read_error == READ_ERROR) 
1068   {
1069     DEBUG(3,("receive_smb error (%s) exiting\n",
1070               strerror(errno)));
1071     return False;
1072   }
1073
1074   *last_timeout_processing_time = t = time(NULL);
1075
1076   if(last_keepalive_sent_time == 0)
1077     last_keepalive_sent_time = t;
1078
1079   if(last_idle_closed_check == 0)
1080     last_idle_closed_check = t;
1081
1082   /* become root again if waiting */
1083   unbecome_user();
1084
1085   /* check if we need to reload services */
1086   check_reload(t);
1087
1088   /* automatic timeout if all connections are closed */      
1089   if (conn_num_open()==0 && (t - last_idle_closed_check) >= IDLE_CLOSED_TIMEOUT) 
1090   {
1091     DEBUG( 2, ( "Closing idle connection\n" ) );
1092     return False;
1093   }
1094   else
1095     last_idle_closed_check = t;
1096
1097   if (keepalive && (t - last_keepalive_sent_time)>keepalive) 
1098   {
1099     struct cli_state *cli = server_client();
1100     if (!send_keepalive(smbd_server_fd())) {
1101       DEBUG( 2, ( "Keepalive failed - exiting.\n" ) );
1102       return False;
1103     }       
1104     /* also send a keepalive to the password server if its still
1105        connected */
1106     if (cli && cli->initialised)
1107       if (!send_keepalive(cli->fd)) {
1108         DEBUG( 2, ( "password server keepalive failed.\n"));
1109         cli_shutdown(cli);
1110       }
1111     last_keepalive_sent_time = t;
1112   }
1113
1114   /* check for connection timeouts */
1115   allidle = conn_idle_all(t, deadtime);
1116
1117   if (allidle && conn_num_open()>0) {
1118     DEBUG(2,("Closing idle connection 2.\n"));
1119     return False;
1120   }
1121
1122   if(global_machine_password_needs_changing)
1123   {
1124     unsigned char trust_passwd_hash[16];
1125     time_t lct;
1126     pstring remote_machine_list;
1127
1128     /*
1129      * We're in domain level security, and the code that
1130      * read the machine password flagged that the machine
1131      * password needs changing.
1132      */
1133
1134     /*
1135      * First, open the machine password file with an exclusive lock.
1136      */
1137
1138     if(!secrets_fetch_trust_account_password(global_myworkgroup, trust_passwd_hash, &lct)) {
1139       DEBUG(0,("process: unable to read the machine account password for \
1140 machine %s in domain %s.\n", global_myname, global_myworkgroup ));
1141       return True;
1142     }
1143
1144     /*
1145      * Make sure someone else hasn't already done this.
1146      */
1147
1148     if(t < lct + lp_machine_password_timeout()) {
1149       global_machine_password_needs_changing = False;
1150       return True;
1151     }
1152
1153     pstrcpy(remote_machine_list, lp_passwordserver());
1154
1155     change_trust_account_password( global_myworkgroup, remote_machine_list);
1156     global_machine_password_needs_changing = False;
1157   }
1158
1159   /*
1160    * Check to see if we have any blocking locks
1161    * outstanding on the queue.
1162    */
1163   process_blocking_lock_queue(t);
1164
1165   /*
1166    * Check to see if we have any change notifies 
1167    * outstanding on the queue.
1168    */
1169   process_pending_change_notify_queue(t);
1170
1171   /*
1172    * Now we are root, check if the log files need pruning.
1173    * Force a log file check.
1174    */
1175   force_check_log_size();
1176   check_log_size();
1177
1178   /*
1179    * Modify the select timeout depending upon
1180    * what we have remaining in our queues.
1181    */
1182
1183   *select_timeout = setup_select_timeout();
1184
1185   return True;
1186 }
1187
1188 /****************************************************************************
1189   process commands from the client
1190 ****************************************************************************/
1191
1192 void smbd_process(void)
1193 {
1194         extern int smb_echo_count;
1195         time_t last_timeout_processing_time = time(NULL);
1196         unsigned int num_smbs = 0;
1197
1198         InBuffer = (char *)malloc(BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN);
1199         OutBuffer = (char *)malloc(BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN);
1200         if ((InBuffer == NULL) || (OutBuffer == NULL)) 
1201                 return;
1202
1203         max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
1204
1205         /* re-initialise the timezone */
1206         TimeInit();
1207
1208         /* register our message handlers */
1209         message_register(MSG_SMB_FORCE_TDIS, msg_force_tdis);
1210
1211         while (True) {
1212                 int deadtime = lp_deadtime()*60;
1213                 int select_timeout = setup_select_timeout();
1214                 int num_echos;
1215
1216                 if (deadtime <= 0)
1217                         deadtime = DEFAULT_SMBD_TIMEOUT;
1218
1219                 errno = 0;      
1220                 
1221                 /* free up temporary memory */
1222                 lp_talloc_free();
1223                 main_loop_talloc_free();
1224
1225                 while (!receive_message_or_smb(InBuffer,BUFFER_SIZE+LARGE_WRITEX_HDR_SIZE,select_timeout)) {
1226                         if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1227                                 return;
1228                         num_smbs = 0; /* Reset smb counter. */
1229                 }
1230
1231                 /*
1232                  * Ensure we do timeout processing if the SMB we just got was
1233                  * only an echo request. This allows us to set the select
1234                  * timeout in 'receive_message_or_smb()' to any value we like
1235                  * without worrying that the client will send echo requests
1236                  * faster than the select timeout, thus starving out the
1237                  * essential processing (change notify, blocking locks) that
1238                  * the timeout code does. JRA.
1239                  */ 
1240                 num_echos = smb_echo_count;
1241
1242                 process_smb(InBuffer, OutBuffer);
1243
1244                 if (smb_echo_count != num_echos) {
1245                         if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1246                                 return;
1247                         num_smbs = 0; /* Reset smb counter. */
1248                 }
1249
1250                 num_smbs++;
1251
1252                 /*
1253                  * If we are getting smb requests in a constant stream
1254                  * with no echos, make sure we attempt timeout processing
1255                  * every select_timeout milliseconds - but only check for this
1256                  * every 200 smb requests.
1257                  */
1258                 
1259                 if ((num_smbs % 200) == 0) {
1260                         time_t new_check_time = time(NULL);
1261                         if(new_check_time - last_timeout_processing_time >= (select_timeout/1000)) {
1262                                 if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1263                                         return;
1264                                 num_smbs = 0; /* Reset smb counter. */
1265                                 last_timeout_processing_time = new_check_time; /* Reset time. */
1266                         }
1267                 }
1268         }
1269 }