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