sync'ing up for 3.0alpha20 release
[abartlet/samba.git/.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)
1034                 select_timeout = MIN(select_timeout, t*1000);
1035
1036         if (print_notify_messages_pending())
1037                 select_timeout = MIN(select_timeout, 1000);
1038
1039         return select_timeout;
1040 }
1041
1042 /****************************************************************************
1043  Check if services need reloading.
1044 ****************************************************************************/
1045
1046 void check_reload(int t)
1047 {
1048   static time_t last_smb_conf_reload_time = 0;
1049
1050   if(last_smb_conf_reload_time == 0)
1051     last_smb_conf_reload_time = t;
1052
1053   if (reload_after_sighup || (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK))
1054   {
1055     reload_services(True);
1056     reload_after_sighup = False;
1057     last_smb_conf_reload_time = t;
1058   }
1059 }
1060
1061 /****************************************************************************
1062  Process any timeout housekeeping. Return False if the caller should exit.
1063 ****************************************************************************/
1064
1065 static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_timeout_processing_time)
1066 {
1067   static time_t last_keepalive_sent_time = 0;
1068   static time_t last_idle_closed_check = 0;
1069   time_t t;
1070   BOOL allidle = True;
1071   extern int keepalive;
1072
1073   if (smb_read_error == READ_EOF) 
1074   {
1075     DEBUG(3,("end of file from client\n"));
1076     return False;
1077   }
1078
1079   if (smb_read_error == READ_ERROR) 
1080   {
1081     DEBUG(3,("receive_smb error (%s) exiting\n",
1082               strerror(errno)));
1083     return False;
1084   }
1085
1086   *last_timeout_processing_time = t = time(NULL);
1087
1088   if(last_keepalive_sent_time == 0)
1089     last_keepalive_sent_time = t;
1090
1091   if(last_idle_closed_check == 0)
1092     last_idle_closed_check = t;
1093
1094   /* become root again if waiting */
1095   change_to_root_user();
1096
1097   /* check if we need to reload services */
1098   check_reload(t);
1099
1100   /* automatic timeout if all connections are closed */      
1101   if (conn_num_open()==0 && (t - last_idle_closed_check) >= IDLE_CLOSED_TIMEOUT) 
1102   {
1103     DEBUG( 2, ( "Closing idle connection\n" ) );
1104     return False;
1105   }
1106   else
1107     last_idle_closed_check = t;
1108
1109   if (keepalive && (t - last_keepalive_sent_time)>keepalive) 
1110   {
1111           extern struct auth_context *negprot_global_auth_context;
1112           if (!send_keepalive(smbd_server_fd())) {
1113                   DEBUG( 2, ( "Keepalive failed - exiting.\n" ) );
1114                   return False;
1115           }
1116           
1117           /* send a keepalive for a password server or the like.
1118              This is attached to the auth_info created in the
1119              negprot */
1120           if (negprot_global_auth_context 
1121               && negprot_global_auth_context->challenge_set_method 
1122               && negprot_global_auth_context->challenge_set_method->send_keepalive) {
1123                   negprot_global_auth_context->challenge_set_method->send_keepalive
1124                           (&negprot_global_auth_context->challenge_set_method->private_data);
1125           }
1126
1127           last_keepalive_sent_time = t;
1128   }
1129
1130   /* check for connection timeouts */
1131   allidle = conn_idle_all(t, deadtime);
1132
1133   if (allidle && conn_num_open()>0) {
1134     DEBUG(2,("Closing idle connection 2.\n"));
1135     return False;
1136   }
1137
1138   if(global_machine_password_needs_changing && 
1139      /* for ADS we need to do a regular ADS password change, not a domain
1140         password change */
1141      lp_security() == SEC_DOMAIN)
1142   {
1143     unsigned char trust_passwd_hash[16];
1144     time_t lct;
1145     pstring remote_machine_list;
1146
1147     /*
1148      * We're in domain level security, and the code that
1149      * read the machine password flagged that the machine
1150      * password needs changing.
1151      */
1152
1153     /*
1154      * First, open the machine password file with an exclusive lock.
1155      */
1156
1157     if (secrets_lock_trust_account_password(global_myworkgroup, True) == False) {
1158       DEBUG(0,("process: unable to lock the machine account password for \
1159 machine %s in domain %s.\n", global_myname, global_myworkgroup ));
1160       return True;
1161     }
1162
1163     if(!secrets_fetch_trust_account_password(global_myworkgroup, trust_passwd_hash, &lct)) {
1164       DEBUG(0,("process: unable to read the machine account password for \
1165 machine %s in domain %s.\n", global_myname, global_myworkgroup ));
1166       secrets_lock_trust_account_password(global_myworkgroup, False);
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       secrets_lock_trust_account_password(global_myworkgroup, False);
1177       return True;
1178     }
1179
1180     pstrcpy(remote_machine_list, lp_passwordserver());
1181
1182     change_trust_account_password( global_myworkgroup, remote_machine_list);
1183     global_machine_password_needs_changing = False;
1184     secrets_lock_trust_account_password(global_myworkgroup, False);
1185   }
1186
1187   /*
1188    * Check to see if we have any blocking locks
1189    * outstanding on the queue.
1190    */
1191   process_blocking_lock_queue(t);
1192
1193   /*
1194    * Check to see if we have any change notifies 
1195    * outstanding on the queue.
1196    */
1197   process_pending_change_notify_queue(t);
1198
1199   /*
1200    * Now we are root, check if the log files need pruning.
1201    * Force a log file check.
1202    */
1203   force_check_log_size();
1204   check_log_size();
1205
1206   /* Send any queued printer notify message to interested smbd's. */
1207
1208   print_notify_send_messages();
1209
1210   /*
1211    * Modify the select timeout depending upon
1212    * what we have remaining in our queues.
1213    */
1214
1215   *select_timeout = setup_select_timeout();
1216
1217   return True;
1218 }
1219
1220 /****************************************************************************
1221   process commands from the client
1222 ****************************************************************************/
1223
1224 void smbd_process(void)
1225 {
1226         extern int smb_echo_count;
1227         time_t last_timeout_processing_time = time(NULL);
1228         unsigned int num_smbs = 0;
1229
1230         InBuffer = (char *)malloc(BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN);
1231         OutBuffer = (char *)malloc(BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN);
1232         if ((InBuffer == NULL) || (OutBuffer == NULL)) 
1233                 return;
1234
1235         max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
1236
1237         while (True) {
1238                 int deadtime = lp_deadtime()*60;
1239                 int select_timeout = setup_select_timeout();
1240                 int num_echos;
1241
1242                 if (deadtime <= 0)
1243                         deadtime = DEFAULT_SMBD_TIMEOUT;
1244
1245                 errno = 0;      
1246                 
1247                 /* free up temporary memory */
1248                 lp_talloc_free();
1249                 main_loop_talloc_free();
1250
1251                 while (!receive_message_or_smb(InBuffer,BUFFER_SIZE+LARGE_WRITEX_HDR_SIZE,select_timeout)) {
1252                         if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1253                                 return;
1254                         num_smbs = 0; /* Reset smb counter. */
1255                 }
1256
1257                 /*
1258                  * Ensure we do timeout processing if the SMB we just got was
1259                  * only an echo request. This allows us to set the select
1260                  * timeout in 'receive_message_or_smb()' to any value we like
1261                  * without worrying that the client will send echo requests
1262                  * faster than the select timeout, thus starving out the
1263                  * essential processing (change notify, blocking locks) that
1264                  * the timeout code does. JRA.
1265                  */ 
1266                 num_echos = smb_echo_count;
1267
1268                 process_smb(InBuffer, OutBuffer);
1269
1270                 if (smb_echo_count != num_echos) {
1271                         if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1272                                 return;
1273                         num_smbs = 0; /* Reset smb counter. */
1274                 }
1275
1276                 num_smbs++;
1277
1278                 /*
1279                  * If we are getting smb requests in a constant stream
1280                  * with no echos, make sure we attempt timeout processing
1281                  * every select_timeout milliseconds - but only check for this
1282                  * every 200 smb requests.
1283                  */
1284                 
1285                 if ((num_smbs % 200) == 0) {
1286                         time_t new_check_time = time(NULL);
1287                         if(new_check_time - last_timeout_processing_time >= (select_timeout/1000)) {
1288                                 if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1289                                         return;
1290                                 num_smbs = 0; /* Reset smb counter. */
1291                                 last_timeout_processing_time = new_check_time; /* Reset time. */
1292                         }
1293                 }
1294         }
1295 }