r996: Fix error in change to queuing code (dlink).
[Samba/gebeck_regimport.git] / source3 / smbd / process.c
blob72df91a21d5db359fae945ab0abe11fb44642ca3
1 /*
2 Unix SMB/CIFS implementation.
3 process incoming packets - main loop
4 Copyright (C) Andrew Tridgell 1992-1998
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.
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.
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.
21 #include "includes.h"
23 struct timeval smb_last_time;
25 static char *InBuffer = NULL;
26 char *OutBuffer = NULL;
27 char *last_inbuf = NULL;
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.
34 int max_send = BUFFER_SIZE;
36 * Size of the data we can receive. Set by us.
37 * Can be modified by the max xmit parameter.
39 int max_recv = BUFFER_SIZE;
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;
50 /****************************************************************************
51 Function to return the current request mid from Inbuffer.
52 ****************************************************************************/
54 uint16 get_current_mid(void)
56 return SVAL(InBuffer,smb_mid);
59 /****************************************************************************
60 structure to hold a linked list of queued messages.
61 for processing.
62 ****************************************************************************/
64 struct pending_message_list {
65 struct pending_message_list *next, *prev;
66 char *msg_buf;
67 int msg_len;
70 static struct pending_message_list *smb_oplock_queue;
72 /****************************************************************************
73 Function to push a message onto the tail of a linked list of smb messages ready
74 for processing.
75 ****************************************************************************/
77 static BOOL push_message(struct pending_message_list **pplist_head, char *buf, int msg_len)
79 struct pending_message_list *tmp_msg;
80 struct pending_message_list *msg = (struct pending_message_list *)
81 malloc(sizeof(struct pending_message_list));
83 if(msg == NULL) {
84 DEBUG(0,("push_message: malloc fail (1)\n"));
85 return False;
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;
95 memcpy(msg->msg_buf, buf, msg_len);
96 msg->msg_len = msg_len;
98 DLIST_ADD_END(*pplist_head, msg, tmp_msg);
100 /* Push the MID of this packet on the signing queue. */
101 srv_defer_sign_response(SVAL(buf,smb_mid));
103 return True;
106 /****************************************************************************
107 Function to push a smb message onto a linked list of local smb messages ready
108 for processing.
109 ****************************************************************************/
111 BOOL push_oplock_pending_smb_message(char *buf, int msg_len)
113 return push_message(&smb_oplock_queue, buf, msg_len);
116 /****************************************************************************
117 Do all async processing in here. This includes UDB oplock messages, kernel
118 oplock messages, change notify events etc.
119 ****************************************************************************/
121 static void async_processing(char *buffer, int buffer_len)
123 DEBUG(10,("async_processing: Doing async processing.\n"));
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);
130 if (got_sig_term) {
131 exit_server("Caught TERM signal");
134 /* check for async change notify events */
135 process_pending_change_notify_queue(0);
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;
146 /****************************************************************************
147 Do a select on an two fd's - with timeout.
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()
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.
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.
164 The timeout is in milliseconds
165 ****************************************************************************/
167 static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
169 fd_set fds;
170 int selrtn;
171 struct timeval to;
172 int maxfd;
174 smb_read_error = 0;
176 again:
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.
183 message_dispatch();
186 * Check to see if we already have a message on the smb queue.
187 * If so - copy and return it.
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));
193 /* Free the message we just copied. */
194 DLIST_REMOVE(smb_oplock_queue, msg);
195 SAFE_FREE(msg->msg_buf);
196 SAFE_FREE(msg);
198 DEBUG(5,("receive_message_or_smb: returning queued smb message.\n"));
199 return True;
204 * Setup the select read fd set.
207 FD_ZERO(&fds);
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.
218 if (oplock_message_waiting(&fds)) {
219 DEBUG(10,("receive_message_or_smb: oplock_message is waiting.\n"));
220 async_processing(buffer, buffer_len);
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.
226 goto again;
229 FD_SET(smbd_server_fd(),&fds);
230 maxfd = setup_oplock_select_set(&fds);
232 to.tv_sec = timeout / 1000;
233 to.tv_usec = (timeout % 1000) * 1000;
235 selrtn = sys_select(MAX(maxfd,smbd_server_fd())+1,&fds,NULL,NULL,timeout>0?&to:NULL);
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);
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.
248 goto again;
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;
258 /* Did we timeout ? */
259 if (selrtn == 0) {
260 smb_read_error = READ_TIMEOUT;
261 return False;
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.
270 if (oplock_message_waiting(&fds)) {
271 async_processing(buffer, buffer_len);
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.
277 goto again;
280 return receive_smb(smbd_server_fd(), buffer, 0);
283 /****************************************************************************
284 Get the next SMB packet, doing the local message processing automatically.
285 ****************************************************************************/
287 BOOL receive_next_smb(char *inbuf, int bufsize, int timeout)
289 BOOL got_keepalive;
290 BOOL ret;
292 do {
293 ret = receive_message_or_smb(inbuf,bufsize,timeout);
295 got_keepalive = (ret && (CVAL(inbuf,0) == SMBkeepalive));
296 } while (ret && got_keepalive);
298 return ret;
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 ****************************************************************************/
308 void respond_to_all_remaining_local_messages(void)
310 char buffer[1024];
313 * Assert we have no exclusive open oplocks.
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;
323 * Keep doing receive_local_message with a 1 ms timeout until
324 * we have no more messages.
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));
332 return;
337 These flags determine some of the permissions required to do an operation
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.
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)
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!
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] = {
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 }
621 /*******************************************************************
622 Dump a packet to a file.
623 ********************************************************************/
625 static void smb_dump(const char *name, int type, char *data, ssize_t len)
627 int fd, i;
628 pstring fname;
629 if (DEBUGLEVEL < 50) return;
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;
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));
648 /****************************************************************************
649 Do a switch on the message type, and return the response size
650 ****************************************************************************/
652 static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize)
654 static pid_t pid= (pid_t)-1;
655 int outsize = 0;
656 extern uint16 global_smbpid;
658 type &= 0xff;
660 if (pid == (pid_t)-1)
661 pid = sys_getpid();
663 errno = 0;
664 last_message = type;
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);
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);
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));
688 DEBUG(3,("switch message %s (pid %d) conn 0x%x\n",smb_fn_name(type),(int)pid,(unsigned int)conn));
690 smb_dump(smb_fn_name(type), 1, inbuf, size);
691 if(global_oplock_break) {
692 if(flags & QUEUE_IN_OPLOCK) {
694 * Queue this message as we are the process of an oplock break.
697 DEBUG( 2, ( "switch_message: queueing message due to being in " ) );
698 DEBUGADD( 2, ( "oplock break state.\n" ) );
700 push_oplock_pending_smb_message( inbuf, size );
701 return -1;
705 /* Ensure this value is replaced in the incoming packet. */
706 SSVAL(inbuf,smb_uid,session_tag);
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.
718 if (session_tag != last_session_tag) {
719 user_struct *vuser = NULL;
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);
728 /* does this protocol need to be run as root? */
729 if (!(flags & AS_USER))
730 change_to_root_user();
732 /* does this protocol need a valid tree connection? */
733 if ((flags & AS_USER) && !conn)
734 return ERROR_DOS(ERRSRV, ERRinvnid);
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));
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;
751 /* does it need write permission? */
752 if ((flags & NEED_WRITE) && !CAN_WRITE(conn))
753 return(ERROR_DOS(ERRSRV,ERRaccess));
755 /* ipc services are limited */
756 if (IS_IPC(conn) && (flags & AS_USER) && !(flags & CAN_IPC))
757 return(ERROR_DOS(ERRSRV,ERRaccess));
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));
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));
768 last_inbuf = inbuf;
770 outsize = smb_messages[type].fn(conn, inbuf,outbuf,size,bufsize);
773 smb_dump(smb_fn_name(type), 0, outbuf, outsize);
775 return(outsize);
779 /****************************************************************************
780 Construct a reply to the incoming packet.
781 ****************************************************************************/
783 static int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
785 int type = CVAL(inbuf,smb_com);
786 int outsize = 0;
787 int msg_type = CVAL(inbuf,0);
789 GetTimeOfDay(&smb_last_time);
791 chain_size = 0;
792 file_chain_reset();
793 reset_chain_p();
795 if (msg_type != 0)
796 return(reply_special(inbuf,outbuf));
798 construct_reply_common(inbuf, outbuf);
800 outsize = switch_message(type,inbuf,outbuf,size,bufsize);
802 outsize += chain_size;
804 if(outsize > 4)
805 smb_setlen(outbuf,outsize - 4);
806 return(outsize);
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 ****************************************************************************/
814 static BOOL process_count_update_successful = False;
816 static int32 increment_smbd_process_count(void)
818 int32 total_smbds;
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;
827 return 1;
830 void decrement_smbd_process_count(void)
832 int32 total_smbds;
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);
840 static BOOL smbd_process_limit(void)
842 int32 total_smbds;
844 if (lp_max_smbd_processes()) {
846 /* Always add one to the smbd process count, as exit_server() always
847 * subtracts one.
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;
856 total_smbds = increment_smbd_process_count();
857 return total_smbds > lp_max_smbd_processes();
859 else
860 return False;
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 ****************************************************************************/
868 void process_smb(char *inbuf, char *outbuf)
870 static int trans_num;
871 int msg_type = CVAL(inbuf,0);
872 int32 len = smb_len(inbuf);
873 int nread = len + 4;
875 DO_PROFILE_INC(smb_count);
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");
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 ) );
895 if (msg_type == 0)
896 show_msg(inbuf);
897 else if(msg_type == SMBkeepalive)
898 return; /* Keepalive packet. */
900 nread = construct_reply(inbuf,outbuf,nread,max_send);
902 if(nread > 0) {
903 if (CVAL(outbuf,0) == 0)
904 show_msg(outbuf);
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.");
913 trans_num++;
916 /****************************************************************************
917 Return a string containing the function name of a SMB command.
918 ****************************************************************************/
920 const char *smb_fn_name(int type)
922 const char *unknown_name = "SMBunknown";
924 if (smb_messages[type].name == NULL)
925 return(unknown_name);
927 return(smb_messages[type].name);
930 /****************************************************************************
931 Helper functions for contruct_reply.
932 ****************************************************************************/
934 static uint32 common_flags2 = FLAGS2_LONG_PATH_COMPONENTS|FLAGS2_EXTENDED_SECURITY|FLAGS2_32_BIT_ERROR_CODES;
936 void remove_from_common_flags2(uint32 v)
938 common_flags2 &= ~v;
941 void construct_reply_common(char *inbuf,char *outbuf)
943 memset(outbuf,'\0',smb_size);
945 set_message(outbuf,0,0,True);
946 SCVAL(outbuf,smb_com,CVAL(inbuf,smb_com));
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);
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));
963 /****************************************************************************
964 Construct a chained reply and add it to the already made reply
965 ****************************************************************************/
967 int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
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);
980 /* maybe its not chained */
981 if (smb_com2 == 0xFF) {
982 SCVAL(outbuf,smb_vwv0,0xFF);
983 return outsize;
986 if (chain_size == 0) {
987 /* this is the first part of the chain */
988 orig_inbuf = inbuf;
989 orig_outbuf = outbuf;
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.
998 outsize = (outsize + 3) & ~3;
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);
1004 /* remember how much the caller added to the chain, only counting stuff
1005 after the parameter words */
1006 chain_size += outsize - smb_wct;
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;
1013 /* remember the original command type */
1014 smb_com1 = CVAL(orig_inbuf,smb_com);
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);
1020 /* give the new packet the same header as the last part of the SMB */
1021 memmove(inbuf2,inbuf,smb_wct);
1023 /* create the in buffer */
1024 SCVAL(inbuf2,smb_com,smb_com2);
1026 /* create the out buffer */
1027 construct_reply_common(inbuf2, outbuf2);
1029 DEBUG(3,("Chained message\n"));
1030 show_msg(inbuf2);
1032 /* process the request */
1033 outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size,
1034 bufsize-chain_size);
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);
1041 /* restore the saved data, being careful not to overwrite any
1042 data from the reply header */
1043 memcpy(inbuf2,inbuf_saved,smb_wct);
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);
1051 return outsize2;
1054 /****************************************************************************
1055 Setup the needed select timeout.
1056 ****************************************************************************/
1058 static int setup_select_timeout(void)
1060 int select_timeout;
1061 int t;
1063 select_timeout = blocking_locks_timeout(SMBD_SELECT_TIMEOUT);
1064 select_timeout *= 1000;
1066 t = change_notify_timeout();
1067 if (t != -1)
1068 select_timeout = MIN(select_timeout, t*1000);
1070 if (print_notify_messages_pending())
1071 select_timeout = MIN(select_timeout, 1000);
1073 return select_timeout;
1076 /****************************************************************************
1077 Check if services need reloading.
1078 ****************************************************************************/
1080 void check_reload(int t)
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();
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;
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;
1103 /* 'printcap cache time = 0' disable the feature */
1105 if ( printcap_cache_time != 0 )
1107 /* see if it's time to reload or if the clock has been set back */
1109 if ( (t >= last_load_printers_reload_time+printcap_cache_time)
1110 || (t-last_load_printers_reload_time < 0) )
1112 DEBUG( 3,( "Printcap cache time expired.\n"));
1113 remove_stale_printers();
1114 load_printers();
1115 last_load_printers_reload_time = t;
1120 /****************************************************************************
1121 Process any timeout housekeeping. Return False if the caller should exit.
1122 ****************************************************************************/
1124 static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_timeout_processing_time)
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;
1132 if (smb_read_error == READ_EOF) {
1133 DEBUG(3,("timeout_processing: End of file from client (client has disconnected).\n"));
1134 return False;
1137 if (smb_read_error == READ_ERROR) {
1138 DEBUG(3,("timeout_processing: receive_smb error (%s) Exiting\n",
1139 strerror(errno)));
1140 return False;
1143 if (smb_read_error == READ_BAD_SIG) {
1144 DEBUG(3,("timeout_processing: receive_smb error bad smb signature. Exiting\n"));
1145 return False;
1148 *last_timeout_processing_time = t = time(NULL);
1150 if(last_keepalive_sent_time == 0)
1151 last_keepalive_sent_time = t;
1153 if(last_idle_closed_check == 0)
1154 last_idle_closed_check = t;
1156 /* become root again if waiting */
1157 change_to_root_user();
1159 /* run all registered idle events */
1160 smb_run_idle_events(t);
1162 /* check if we need to reload services */
1163 check_reload(t);
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;
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;
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) {
1186 negprot_global_auth_context->challenge_set_method->send_keepalive
1187 (&negprot_global_auth_context->challenge_set_method->private_data);
1190 last_keepalive_sent_time = t;
1193 /* check for connection timeouts */
1194 allidle = conn_idle_all(t, deadtime);
1196 if (allidle && conn_num_open()>0) {
1197 DEBUG(2,("Closing idle connection 2.\n"));
1198 return False;
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) {
1206 unsigned char trust_passwd_hash[16];
1207 time_t lct;
1210 * We're in domain level security, and the code that
1211 * read the machine password flagged that the machine
1212 * password needs changing.
1216 * First, open the machine password file with an exclusive lock.
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;
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;
1233 * Make sure someone else hasn't already done this.
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;
1242 /* always just contact the PDC here */
1244 change_trust_account_password( lp_workgroup(), NULL);
1245 global_machine_password_needs_changing = False;
1246 secrets_lock_trust_account_password(lp_workgroup(), False);
1250 * Check to see if we have any blocking locks
1251 * outstanding on the queue.
1253 process_blocking_lock_queue(t);
1255 /* update printer queue caches if necessary */
1257 update_monitored_printq_cache();
1260 * Check to see if we have any change notifies
1261 * outstanding on the queue.
1263 process_pending_change_notify_queue(t);
1266 * Now we are root, check if the log files need pruning.
1267 * Force a log file check.
1269 force_check_log_size();
1270 check_log_size();
1272 /* Send any queued printer notify message to interested smbd's. */
1274 print_notify_send_messages(0);
1277 * Modify the select timeout depending upon
1278 * what we have remaining in our queues.
1281 *select_timeout = setup_select_timeout();
1283 return True;
1286 /****************************************************************************
1287 process commands from the client
1288 ****************************************************************************/
1290 void smbd_process(void)
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;
1297 InBuffer = (char *)malloc(total_buffer_size);
1298 OutBuffer = (char *)malloc(total_buffer_size);
1299 if ((InBuffer == NULL) || (OutBuffer == NULL))
1300 return;
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
1307 max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
1309 while (True) {
1310 int deadtime = lp_deadtime()*60;
1311 int select_timeout = setup_select_timeout();
1312 int num_echos;
1314 if (deadtime <= 0)
1315 deadtime = DEFAULT_SMBD_TIMEOUT;
1317 errno = 0;
1319 /* free up temporary memory */
1320 lp_talloc_free();
1321 main_loop_talloc_free();
1323 /* run all registered idle events */
1324 smb_run_idle_events(time(NULL));
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. */
1334 #if defined(DEVELOPER)
1335 clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size);
1336 #endif
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. */
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.
1353 num_echos = smb_echo_count;
1355 clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer, total_buffer_size);
1357 process_smb(InBuffer, OutBuffer);
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. */
1365 num_smbs++;
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.
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. */
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. */
1391 if ((num_smbs % 50) == 0 && need_to_check_log_size()) {
1392 change_to_root_user();
1393 check_log_size();