2c35eadb18a2c953c70135292f1b9120e33f8b1e
[sfrench/samba-autobuild/.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 = 0;
46 SIG_ATOMIC_T got_sig_term = 0;
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 milliseconds
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 packet to a file.
613 ********************************************************************/
614
615 static void smb_dump(const char *name, int type, char *data, ssize_t len)
616 {
617         int fd, i;
618         pstring fname;
619         if (DEBUGLEVEL < 50) return;
620
621         if (len < 4) len = smb_len(data)+4;
622         for (i=1;i<100;i++) {
623                 slprintf(fname,sizeof(fname)-1, "/tmp/%s.%d.%s", name, i,
624                                 type ? "req" : "resp");
625                 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644);
626                 if (fd != -1 || errno != EEXIST) break;
627         }
628         if (fd != -1) {
629                 ssize_t ret = write(fd, data, len);
630                 if (ret != len)
631                         DEBUG(0,("smb_dump: problem: write returned %d\n", (int)ret ));
632                 close(fd);
633                 DEBUG(0,("created %s len %d\n", fname, len));
634         }
635 }
636
637
638 /****************************************************************************
639  Do a switch on the message type, and return the response size
640 ****************************************************************************/
641
642 static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize)
643 {
644         static pid_t pid= (pid_t)-1;
645         int outsize = 0;
646         extern uint16 global_smbpid;
647
648         type &= 0xff;
649
650         if (pid == (pid_t)-1)
651                 pid = sys_getpid();
652
653         errno = 0;
654         last_message = type;
655
656         /* Make sure this is an SMB packet. smb_size contains NetBIOS header so subtract 4 from it. */
657         if ((strncmp(smb_base(inbuf),"\377SMB",4) != 0) || (size < (smb_size - 4))) {
658                 DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",smb_len(inbuf)));
659                 exit_server("Non-SMB packet");
660                 return(-1);
661         }
662
663         /* yuck! this is an interim measure before we get rid of our
664                 current inbuf/outbuf system */
665         global_smbpid = SVAL(inbuf,smb_pid);
666
667         if (smb_messages[type].fn == NULL) {
668                 DEBUG(0,("Unknown message type %d!\n",type));
669                 smb_dump("Unknown", 1, inbuf, size);
670                 outsize = reply_unknown(inbuf,outbuf);
671         } else {
672                 int flags = smb_messages[type].flags;
673                 static uint16 last_session_tag = UID_FIELD_INVALID;
674                 /* In share mode security we must ignore the vuid. */
675                 uint16 session_tag = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(inbuf,smb_uid);
676                 connection_struct *conn = conn_find(SVAL(inbuf,smb_tid));
677
678                 DEBUG(3,("switch message %s (pid %d)\n",smb_fn_name(type),(int)pid));
679
680                 smb_dump(smb_fn_name(type), 1, inbuf, size);
681                 if(global_oplock_break) {
682                         if(flags & QUEUE_IN_OPLOCK) {
683                                 /* 
684                                  * Queue this message as we are the process of an oplock break.
685                                  */
686
687                                 DEBUG( 2, ( "switch_message: queueing message due to being in " ) );
688                                 DEBUGADD( 2, ( "oplock break state.\n" ) );
689
690                                 push_oplock_pending_smb_message( inbuf, size );
691                                 return -1;
692                         }
693                 }
694
695                 /* Ensure this value is replaced in the incoming packet. */
696                 SSVAL(inbuf,smb_uid,session_tag);
697
698                 /*
699                  * Ensure the correct username is in current_user_info.
700                  * This is a really ugly bugfix for problems with
701                  * multiple session_setup_and_X's being done and
702                  * allowing %U and %G substitutions to work correctly.
703                  * There is a reason this code is done here, don't
704                  * move it unless you know what you're doing... :-).
705                  * JRA.
706                  */
707
708                 if (session_tag != last_session_tag) {
709                         user_struct *vuser = NULL;
710
711                         last_session_tag = session_tag;
712                         if(session_tag != UID_FIELD_INVALID)
713                                 vuser = get_valid_user_struct(session_tag);           
714                         if(vuser != NULL)
715                                 current_user_info = vuser->user;
716                 }
717
718                 /* does this protocol need to be run as root? */
719                 if (!(flags & AS_USER))
720                         change_to_root_user();
721
722                 /* does this protocol need a valid tree connection? */
723                 if ((flags & AS_USER) && !conn)
724                         return ERROR_DOS(ERRSRV, ERRinvnid);
725
726
727                 /* does this protocol need to be run as the connected user? */
728                 if ((flags & AS_USER) && !change_to_user(conn,session_tag)) {
729                         if (flags & AS_GUEST) 
730                                 flags &= ~AS_USER;
731                         else
732                                 return(ERROR_DOS(ERRSRV,ERRaccess));
733                 }
734
735                 /* this code is to work around a bug is MS client 3 without
736                         introducing a security hole - it needs to be able to do
737                         print queue checks as guest if it isn't logged in properly */
738                 if (flags & AS_USER)
739                         flags &= ~AS_GUEST;
740
741                 /* does it need write permission? */
742                 if ((flags & NEED_WRITE) && !CAN_WRITE(conn))
743                         return(ERROR_DOS(ERRSRV,ERRaccess));
744
745                 /* ipc services are limited */
746                 if (IS_IPC(conn) && (flags & AS_USER) && !(flags & CAN_IPC))
747                         return(ERROR_DOS(ERRSRV,ERRaccess));        
748
749                 /* load service specific parameters */
750                 if (conn && !set_current_service(conn,(flags & AS_USER)?True:False))
751                         return(ERROR_DOS(ERRSRV,ERRaccess));
752
753                 /* does this protocol need to be run as guest? */
754                 if ((flags & AS_GUEST) && (!change_to_guest() || 
755                                 !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1))))
756                         return(ERROR_DOS(ERRSRV,ERRaccess));
757
758                 last_inbuf = inbuf;
759
760                 outsize = smb_messages[type].fn(conn, inbuf,outbuf,size,bufsize);
761         }
762
763         smb_dump(smb_fn_name(type), 0, outbuf, outsize);
764
765         return(outsize);
766 }
767
768
769 /****************************************************************************
770  Construct a reply to the incoming packet.
771 ****************************************************************************/
772
773 static int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
774 {
775         int type = CVAL(inbuf,smb_com);
776         int outsize = 0;
777         int msg_type = CVAL(inbuf,0);
778
779         GetTimeOfDay(&smb_last_time);
780
781         chain_size = 0;
782         file_chain_reset();
783         reset_chain_p();
784
785         if (msg_type != 0)
786                 return(reply_special(inbuf,outbuf));  
787
788         construct_reply_common(inbuf, outbuf);
789
790         outsize = switch_message(type,inbuf,outbuf,size,bufsize);
791
792         outsize += chain_size;
793
794         if(outsize > 4)
795                 smb_setlen(outbuf,outsize - 4);
796         return(outsize);
797 }
798
799 /****************************************************************************
800  Keep track of the number of running smbd's. This functionality is used to
801  'hard' limit Samba overhead on resource constrained systems. 
802 ****************************************************************************/
803
804 static BOOL smbd_process_limit(void)
805 {
806         int32  total_smbds;
807         
808         if (lp_max_smbd_processes()) {
809
810                 /* Always add one to the smbd process count, as exit_server() always
811                  * subtracts one.
812                  */
813
814                 total_smbds = 1; /* In case we need to create the entry. */
815
816                 if (!conn_tdb_ctx()) {
817                         DEBUG(0,("smbd_process_limit: max smbd processes parameter set with status parameter not \
818 set. Ignoring max smbd restriction.\n"));
819                         return False;
820                 }
821
822                 if (tdb_change_int32_atomic(conn_tdb_ctx(), "INFO/total_smbds", &total_smbds, 1) == -1)
823                         return True;
824
825                 return total_smbds > lp_max_smbd_processes();
826         }
827         else
828                 return False;
829 }
830
831 /****************************************************************************
832   process an smb from the client - split out from the smbd_process() code so
833   it can be used by the oplock break code.
834 ****************************************************************************/
835 void process_smb(char *inbuf, char *outbuf)
836 {
837   static int trans_num;
838   int msg_type = CVAL(inbuf,0);
839   int32 len = smb_len(inbuf);
840   int nread = len + 4;
841
842   DO_PROFILE_INC(smb_count);
843
844   if (trans_num == 0) {
845           /* on the first packet, check the global hosts allow/ hosts
846              deny parameters before doing any parsing of the packet
847              passed to us by the client.  This prevents attacks on our
848              parsing code from hosts not in the hosts allow list */
849           if (smbd_process_limit() ||
850                   !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1))) {
851                   /* send a negative session response "not listening on calling
852                    name" */
853                   static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
854                   DEBUG( 1, ( "Connection denied from %s\n",
855                               client_addr() ) );
856                   (void)send_smb(smbd_server_fd(),(char *)buf);
857                   exit_server("connection denied");
858           }
859   }
860
861   DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type, len ) );
862   DEBUG( 3, ( "Transaction %d of length %d\n", trans_num, nread ) );
863
864   if (msg_type == 0)
865     show_msg(inbuf);
866   else if(msg_type == SMBkeepalive)
867     return; /* Keepalive packet. */
868
869   nread = construct_reply(inbuf,outbuf,nread,max_send);
870       
871   if(nread > 0) 
872   {
873     if (CVAL(outbuf,0) == 0)
874       show_msg(outbuf);
875         
876     if (nread != smb_len(outbuf) + 4) 
877     {
878       DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
879                  nread, smb_len(outbuf)));
880     }
881     else
882       if (!send_smb(smbd_server_fd(),outbuf))
883         exit_server("process_smb: send_smb failed.");
884   }
885   trans_num++;
886 }
887
888
889
890 /****************************************************************************
891 return a string containing the function name of a SMB command
892 ****************************************************************************/
893 const char *smb_fn_name(int type)
894 {
895         static char *unknown_name = "SMBunknown";
896
897         if (smb_messages[type].name == NULL)
898                 return(unknown_name);
899
900         return(smb_messages[type].name);
901 }
902
903
904 /****************************************************************************
905  Helper function for contruct_reply.
906 ****************************************************************************/
907
908 void construct_reply_common(char *inbuf,char *outbuf)
909 {
910         memset(outbuf,'\0',smb_size);
911
912         set_message(outbuf,0,0,True);
913         SCVAL(outbuf,smb_com,CVAL(inbuf,smb_com));
914         
915         memcpy(outbuf+4,inbuf+4,4);
916         SCVAL(outbuf,smb_rcls,SMB_SUCCESS);
917         SCVAL(outbuf,smb_reh,0);
918         SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES)); 
919         SSVAL(outbuf,smb_flg2,
920               (SVAL(inbuf,smb_flg2) & FLAGS2_UNICODE_STRINGS) |
921               FLAGS2_LONG_PATH_COMPONENTS |
922               FLAGS2_32_BIT_ERROR_CODES | FLAGS2_EXTENDED_SECURITY);
923
924         SSVAL(outbuf,smb_err,SMB_SUCCESS);
925         SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
926         SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
927         SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
928         SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
929 }
930
931 /****************************************************************************
932   construct a chained reply and add it to the already made reply
933   **************************************************************************/
934 int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
935 {
936   static char *orig_inbuf;
937   static char *orig_outbuf;
938   int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0);
939   unsigned smb_off2 = SVAL(inbuf,smb_vwv1);
940   char *inbuf2, *outbuf2;
941   int outsize2;
942   char inbuf_saved[smb_wct];
943   char outbuf_saved[smb_wct];
944   int wct = CVAL(outbuf,smb_wct);
945   int outsize = smb_size + 2*wct + SVAL(outbuf,smb_vwv0+2*wct);
946
947   /* maybe its not chained */
948   if (smb_com2 == 0xFF) {
949     SCVAL(outbuf,smb_vwv0,0xFF);
950     return outsize;
951   }
952
953   if (chain_size == 0) {
954     /* this is the first part of the chain */
955     orig_inbuf = inbuf;
956     orig_outbuf = outbuf;
957   }
958
959   /*
960    * The original Win95 redirector dies on a reply to
961    * a lockingX and read chain unless the chain reply is
962    * 4 byte aligned. JRA.
963    */
964
965   outsize = (outsize + 3) & ~3;
966
967   /* we need to tell the client where the next part of the reply will be */
968   SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf));
969   SCVAL(outbuf,smb_vwv0,smb_com2);
970
971   /* remember how much the caller added to the chain, only counting stuff
972      after the parameter words */
973   chain_size += outsize - smb_wct;
974
975   /* work out pointers into the original packets. The
976      headers on these need to be filled in */
977   inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct;
978   outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct;
979
980   /* remember the original command type */
981   smb_com1 = CVAL(orig_inbuf,smb_com);
982
983   /* save the data which will be overwritten by the new headers */
984   memcpy(inbuf_saved,inbuf2,smb_wct);
985   memcpy(outbuf_saved,outbuf2,smb_wct);
986
987   /* give the new packet the same header as the last part of the SMB */
988   memmove(inbuf2,inbuf,smb_wct);
989
990   /* create the in buffer */
991   SCVAL(inbuf2,smb_com,smb_com2);
992
993   /* create the out buffer */
994   construct_reply_common(inbuf2, outbuf2);
995
996   DEBUG(3,("Chained message\n"));
997   show_msg(inbuf2);
998
999   /* process the request */
1000   outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size,
1001                             bufsize-chain_size);
1002
1003   /* copy the new reply and request headers over the old ones, but
1004      preserve the smb_com field */
1005   memmove(orig_outbuf,outbuf2,smb_wct);
1006   SCVAL(orig_outbuf,smb_com,smb_com1);
1007
1008   /* restore the saved data, being careful not to overwrite any
1009    data from the reply header */
1010   memcpy(inbuf2,inbuf_saved,smb_wct);
1011   {
1012     int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf);
1013     if (ofs < 0) ofs = 0;
1014     memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs);
1015   }
1016
1017   return outsize2;
1018 }
1019
1020 /****************************************************************************
1021  Setup the needed select timeout.
1022 ****************************************************************************/
1023
1024 static int setup_select_timeout(void)
1025 {
1026         int select_timeout;
1027         int t;
1028
1029         select_timeout = blocking_locks_timeout(SMBD_SELECT_TIMEOUT);
1030         select_timeout *= 1000;
1031
1032         t = change_notify_timeout();
1033         if (t != -1) select_timeout = MIN(select_timeout, t*1000);
1034
1035         return select_timeout;
1036 }
1037
1038 /****************************************************************************
1039  Check if services need reloading.
1040 ****************************************************************************/
1041
1042 void check_reload(int t)
1043 {
1044   static time_t last_smb_conf_reload_time = 0;
1045
1046   if(last_smb_conf_reload_time == 0)
1047     last_smb_conf_reload_time = t;
1048
1049   if (reload_after_sighup || (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK))
1050   {
1051     reload_services(True);
1052     reload_after_sighup = False;
1053     last_smb_conf_reload_time = t;
1054   }
1055 }
1056
1057 /****************************************************************************
1058  Process any timeout housekeeping. Return False if the caller should exit.
1059 ****************************************************************************/
1060
1061 static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_timeout_processing_time)
1062 {
1063   static time_t last_keepalive_sent_time = 0;
1064   static time_t last_idle_closed_check = 0;
1065   time_t t;
1066   BOOL allidle = True;
1067   extern int keepalive;
1068
1069   if (smb_read_error == READ_EOF) 
1070   {
1071     DEBUG(3,("end of file from client\n"));
1072     return False;
1073   }
1074
1075   if (smb_read_error == READ_ERROR) 
1076   {
1077     DEBUG(3,("receive_smb error (%s) exiting\n",
1078               strerror(errno)));
1079     return False;
1080   }
1081
1082   *last_timeout_processing_time = t = time(NULL);
1083
1084   if(last_keepalive_sent_time == 0)
1085     last_keepalive_sent_time = t;
1086
1087   if(last_idle_closed_check == 0)
1088     last_idle_closed_check = t;
1089
1090   /* become root again if waiting */
1091   change_to_root_user();
1092
1093   /* check if we need to reload services */
1094   check_reload(t);
1095
1096   /* automatic timeout if all connections are closed */      
1097   if (conn_num_open()==0 && (t - last_idle_closed_check) >= IDLE_CLOSED_TIMEOUT) 
1098   {
1099     DEBUG( 2, ( "Closing idle connection\n" ) );
1100     return False;
1101   }
1102   else
1103     last_idle_closed_check = t;
1104
1105   if (keepalive && (t - last_keepalive_sent_time)>keepalive) 
1106   {
1107           extern struct auth_context *negprot_global_auth_context;
1108           if (!send_keepalive(smbd_server_fd())) {
1109                   DEBUG( 2, ( "Keepalive failed - exiting.\n" ) );
1110                   return False;
1111           }
1112           
1113           /* send a keepalive for a password server or the like.
1114              This is attached to the auth_info created in the
1115              negprot */
1116           if (negprot_global_auth_context 
1117               && negprot_global_auth_context->challenge_set_method 
1118               && negprot_global_auth_context->challenge_set_method->send_keepalive) {
1119                   negprot_global_auth_context->challenge_set_method->send_keepalive
1120                           (&negprot_global_auth_context->challenge_set_method->private_data);
1121           }
1122
1123           last_keepalive_sent_time = t;
1124   }
1125
1126   /* check for connection timeouts */
1127   allidle = conn_idle_all(t, deadtime);
1128
1129   if (allidle && conn_num_open()>0) {
1130     DEBUG(2,("Closing idle connection 2.\n"));
1131     return False;
1132   }
1133
1134   if(global_machine_password_needs_changing && 
1135      /* for ADS we need to do a regular ADS password change, not a domain
1136         password change */
1137      lp_security() == SEC_DOMAIN)
1138   {
1139     unsigned char trust_passwd_hash[16];
1140     time_t lct;
1141     pstring remote_machine_list;
1142
1143     /*
1144      * We're in domain level security, and the code that
1145      * read the machine password flagged that the machine
1146      * password needs changing.
1147      */
1148
1149     /*
1150      * First, open the machine password file with an exclusive lock.
1151      */
1152
1153     if(!secrets_fetch_trust_account_password(global_myworkgroup, trust_passwd_hash, &lct)) {
1154       DEBUG(0,("process: unable to read the machine account password for \
1155 machine %s in domain %s.\n", global_myname, global_myworkgroup ));
1156       return True;
1157     }
1158
1159     /*
1160      * Make sure someone else hasn't already done this.
1161      */
1162
1163     if(t < lct + lp_machine_password_timeout()) {
1164       global_machine_password_needs_changing = False;
1165       return True;
1166     }
1167
1168     pstrcpy(remote_machine_list, lp_passwordserver());
1169
1170     change_trust_account_password( global_myworkgroup, remote_machine_list);
1171     global_machine_password_needs_changing = False;
1172   }
1173
1174   /*
1175    * Check to see if we have any blocking locks
1176    * outstanding on the queue.
1177    */
1178   process_blocking_lock_queue(t);
1179
1180   /*
1181    * Check to see if we have any change notifies 
1182    * outstanding on the queue.
1183    */
1184   process_pending_change_notify_queue(t);
1185
1186   /*
1187    * Now we are root, check if the log files need pruning.
1188    * Force a log file check.
1189    */
1190   force_check_log_size();
1191   check_log_size();
1192
1193   /*
1194    * Modify the select timeout depending upon
1195    * what we have remaining in our queues.
1196    */
1197
1198   *select_timeout = setup_select_timeout();
1199
1200   return True;
1201 }
1202
1203 /****************************************************************************
1204   process commands from the client
1205 ****************************************************************************/
1206
1207 void smbd_process(void)
1208 {
1209         extern int smb_echo_count;
1210         time_t last_timeout_processing_time = time(NULL);
1211         unsigned int num_smbs = 0;
1212
1213         InBuffer = (char *)malloc(BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN);
1214         OutBuffer = (char *)malloc(BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN);
1215         if ((InBuffer == NULL) || (OutBuffer == NULL)) 
1216                 return;
1217
1218         max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
1219
1220         while (True) {
1221                 int deadtime = lp_deadtime()*60;
1222                 int select_timeout = setup_select_timeout();
1223                 int num_echos;
1224
1225                 if (deadtime <= 0)
1226                         deadtime = DEFAULT_SMBD_TIMEOUT;
1227
1228                 errno = 0;      
1229                 
1230                 /* free up temporary memory */
1231                 lp_talloc_free();
1232                 main_loop_talloc_free();
1233
1234                 while (!receive_message_or_smb(InBuffer,BUFFER_SIZE+LARGE_WRITEX_HDR_SIZE,select_timeout)) {
1235                         if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1236                                 return;
1237                         num_smbs = 0; /* Reset smb counter. */
1238                 }
1239
1240                 /*
1241                  * Ensure we do timeout processing if the SMB we just got was
1242                  * only an echo request. This allows us to set the select
1243                  * timeout in 'receive_message_or_smb()' to any value we like
1244                  * without worrying that the client will send echo requests
1245                  * faster than the select timeout, thus starving out the
1246                  * essential processing (change notify, blocking locks) that
1247                  * the timeout code does. JRA.
1248                  */ 
1249                 num_echos = smb_echo_count;
1250
1251                 process_smb(InBuffer, OutBuffer);
1252
1253                 if (smb_echo_count != num_echos) {
1254                         if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1255                                 return;
1256                         num_smbs = 0; /* Reset smb counter. */
1257                 }
1258
1259                 num_smbs++;
1260
1261                 /*
1262                  * If we are getting smb requests in a constant stream
1263                  * with no echos, make sure we attempt timeout processing
1264                  * every select_timeout milliseconds - but only check for this
1265                  * every 200 smb requests.
1266                  */
1267                 
1268                 if ((num_smbs % 200) == 0) {
1269                         time_t new_check_time = time(NULL);
1270                         if(new_check_time - last_timeout_processing_time >= (select_timeout/1000)) {
1271                                 if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1272                                         return;
1273                                 num_smbs = 0; /* Reset smb counter. */
1274                                 last_timeout_processing_time = new_check_time; /* Reset time. */
1275                         }
1276                 }
1277         }
1278 }