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