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.
23 extern uint16 global_smbpid;
25 extern struct auth_context *negprot_global_auth_context;
26 extern int smb_echo_count;
28 struct timeval smb_last_time;
30 static char *InBuffer = NULL;
31 char *OutBuffer = NULL;
32 char *last_inbuf = NULL;
35 * Size of data we can send to client. Set
36 * by the client for all protocols above CORE.
37 * Set by us for CORE protocol.
39 int max_send = BUFFER_SIZE;
41 * Size of the data we can receive. Set by us.
42 * Can be modified by the max xmit parameter.
44 int max_recv = BUFFER_SIZE;
46 extern int last_message;
47 extern int global_oplock_break;
48 extern userdom_struct current_user_info;
49 extern int smb_read_error;
50 SIG_ATOMIC_T reload_after_sighup = 0;
51 SIG_ATOMIC_T got_sig_term = 0;
52 BOOL global_machine_password_needs_changing = False;
55 /****************************************************************************
56 Function to return the current request mid from Inbuffer.
57 ****************************************************************************/
59 uint16 get_current_mid(void)
61 return SVAL(InBuffer,smb_mid);
64 /****************************************************************************
65 structure to hold a linked list of queued messages.
67 ****************************************************************************/
69 static struct pending_message_list *smb_oplock_queue;
70 static struct pending_message_list *smb_sharing_violation_queue;
72 enum q_type { OPLOCK_QUEUE, SHARE_VIOLATION_QUEUE };
74 /****************************************************************************
76 ****************************************************************************/
78 static void free_queued_message(struct pending_message_list *msg)
80 data_blob_free(&msg->buf);
81 data_blob_free(&msg->private_data);
85 /****************************************************************************
86 Function to push a message onto the tail of a linked list of smb messages ready
88 ****************************************************************************/
90 static BOOL push_queued_message(enum q_type qt, char *buf, int msg_len, struct timeval *ptv, char *private_data, size_t private_len)
92 struct pending_message_list *tmp_msg;
93 struct pending_message_list *msg = SMB_MALLOC_P(struct pending_message_list);
96 DEBUG(0,("push_message: malloc fail (1)\n"));
100 memset(msg,'\0',sizeof(*msg));
102 msg->buf = data_blob(buf, msg_len);
103 if(msg->buf.data == NULL) {
104 DEBUG(0,("push_message: malloc fail (2)\n"));
110 msg->msg_time = *ptv;
114 msg->private_data = data_blob(private_data, private_len);
115 if (msg->private_data.data == NULL) {
116 DEBUG(0,("push_message: malloc fail (3)\n"));
117 data_blob_free(&msg->buf);
123 if (qt == OPLOCK_QUEUE) {
124 DLIST_ADD_END(smb_oplock_queue, msg, tmp_msg);
126 DLIST_ADD_END(smb_sharing_violation_queue, msg, tmp_msg);
129 DEBUG(10,("push_message: pushed message length %u on queue %s\n",
130 (unsigned int)msg_len,
131 qt == OPLOCK_QUEUE ? "smb_oplock_queue" : "smb_sharing_violation_queue" ));
136 /****************************************************************************
137 Function to push an oplock smb message onto a linked list of local smb messages ready
139 ****************************************************************************/
141 BOOL push_oplock_pending_smb_message(char *buf, int msg_len)
143 BOOL ret = push_queued_message(OPLOCK_QUEUE, buf, msg_len, NULL, NULL, 0);
145 /* Push the MID of this packet on the signing queue. */
146 srv_defer_sign_response(SVAL(buf,smb_mid));
151 /****************************************************************************
152 Function to delete a sharing violation open message by mid.
153 ****************************************************************************/
155 void remove_sharing_violation_open_smb_message(uint16 mid)
157 struct pending_message_list *pml;
159 if (!lp_defer_sharing_violations()) {
163 for (pml = smb_sharing_violation_queue; pml; pml = pml->next) {
164 if (mid == SVAL(pml->buf.data,smb_mid)) {
165 DEBUG(10,("remove_sharing_violation_open_smb_message: deleting mid %u len %u\n",
166 (unsigned int)mid, (unsigned int)pml->buf.length ));
167 DLIST_REMOVE(smb_sharing_violation_queue, pml);
168 free_queued_message(pml);
174 /****************************************************************************
175 Move a sharing violation open retry message to the front of the list and
176 schedule it for immediate processing.
177 ****************************************************************************/
179 void schedule_sharing_violation_open_smb_message(uint16 mid)
181 struct pending_message_list *pml;
184 if (!lp_defer_sharing_violations()) {
188 for (pml = smb_sharing_violation_queue; pml; pml = pml->next) {
189 uint16 msg_mid = SVAL(pml->buf.data,smb_mid);
190 DEBUG(10,("schedule_sharing_violation_open_smb_message: [%d] msg_mid = %u\n", i++,
191 (unsigned int)msg_mid ));
192 if (mid == msg_mid) {
193 DEBUG(10,("schedule_sharing_violation_open_smb_message: scheduling mid %u\n",
195 pml->msg_time.tv_sec = 0;
196 pml->msg_time.tv_usec = 0;
197 DLIST_PROMOTE(smb_sharing_violation_queue, pml);
202 DEBUG(10,("schedule_sharing_violation_open_smb_message: failed to find message mid %u\n",
206 /****************************************************************************
207 Return true if this mid is on the deferred queue.
208 ****************************************************************************/
210 BOOL open_was_deferred(uint16 mid)
212 struct pending_message_list *pml;
214 if (!lp_defer_sharing_violations()) {
218 for (pml = smb_sharing_violation_queue; pml; pml = pml->next) {
219 if (SVAL(pml->buf.data,smb_mid) == mid) {
220 set_saved_error_triple(SMB_SUCCESS, 0, NT_STATUS_OK);
227 /****************************************************************************
228 Return the message queued by this mid.
229 ****************************************************************************/
231 struct pending_message_list *get_open_deferred_message(uint16 mid)
233 struct pending_message_list *pml;
235 if (!lp_defer_sharing_violations()) {
239 for (pml = smb_sharing_violation_queue; pml; pml = pml->next) {
240 if (SVAL(pml->buf.data,smb_mid) == mid) {
247 /****************************************************************************
248 Function to push a sharing violation open smb message onto a linked list of local smb messages ready
250 ****************************************************************************/
252 BOOL push_sharing_violation_open_smb_message(struct timeval *ptv, char *private_data, size_t priv_len)
254 uint16 mid = SVAL(InBuffer,smb_mid);
258 if (!lp_defer_sharing_violations()) {
267 /* Add on the timeout. */
268 tdif += SHARING_VIOLATION_USEC_WAIT;
270 tv.tv_sec = tdif / 1000000;
271 tv.tv_usec = tdif % 1000000;
273 DEBUG(10,("push_sharing_violation_open_smb_message: pushing message len %u mid %u\
274 timeout time [%u.%06u]\n", (unsigned int) smb_len(InBuffer)+4, (unsigned int)mid,
275 (unsigned int)tv.tv_sec, (unsigned int)tv.tv_usec));
277 return push_queued_message(SHARE_VIOLATION_QUEUE, InBuffer,
278 smb_len(InBuffer)+4, &tv, private_data, priv_len);
281 /****************************************************************************
282 Do all async processing in here. This includes UDB oplock messages, kernel
283 oplock messages, change notify events etc.
284 ****************************************************************************/
286 static void async_processing(char *buffer, int buffer_len)
288 DEBUG(10,("async_processing: Doing async processing.\n"));
290 /* check for oplock messages (both UDP and kernel) */
291 if (receive_local_message(buffer, buffer_len, 1)) {
292 process_local_message(buffer, buffer_len);
296 exit_server("Caught TERM signal");
299 /* check for async change notify events */
300 process_pending_change_notify_queue(0);
302 /* check for sighup processing */
303 if (reload_after_sighup) {
304 change_to_root_user();
305 DEBUG(1,("Reloading services after SIGHUP\n"));
306 reload_services(False);
307 reload_after_sighup = 0;
311 /****************************************************************************
312 Do a select on an two fd's - with timeout.
314 If a local udp message has been pushed onto the
315 queue (this can only happen during oplock break
316 processing) call async_processing()
318 If a pending smb message has been pushed onto the
319 queue (this can only happen during oplock break
320 processing) return this next.
322 If the first smbfd is ready then read an smb from it.
323 if the second (loopback UDP) fd is ready then read a message
324 from it and setup the buffer header to identify the length
326 Returns False on timeout or error.
329 The timeout is in milliseconds
330 ****************************************************************************/
332 static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
344 to.tv_sec = timeout / 1000;
345 to.tv_usec = (timeout % 1000) * 1000;
346 pto = timeout > 0 ? &to : NULL;
349 * Note that this call must be before processing any SMB
350 * messages as we need to synchronously process any messages
351 * we may have sent to ourselves from the previous SMB.
356 * Check to see if we already have a message on the smb queue.
357 * If so - copy and return it.
359 if(smb_oplock_queue != NULL) {
360 struct pending_message_list *msg = smb_oplock_queue;
361 memcpy(buffer, msg->buf.data, MIN(buffer_len, msg->buf.length));
363 /* Free the message we just copied. */
364 DLIST_REMOVE(smb_oplock_queue, msg);
365 free_queued_message(msg);
367 DEBUG(5,("receive_message_or_smb: returning queued smb message.\n"));
372 * Check to see if we already have a message on the deferred open queue
373 * and it's time to schedule.
375 if(smb_sharing_violation_queue != NULL) {
376 BOOL pop_message = False;
377 struct pending_message_list *msg = smb_sharing_violation_queue;
379 if (msg->msg_time.tv_sec == 0 && msg->msg_time.tv_usec == 0) {
386 tdif = usec_time_diff(&msg->msg_time, &tv);
388 /* Timed out. Schedule...*/
390 DEBUG(10,("receive_message_or_smb: queued message timed out.\n"));
392 /* Make a more accurate select timeout. */
393 to.tv_sec = tdif / 1000000;
394 to.tv_usec = tdif % 1000000;
396 DEBUG(10,("receive_message_or_smb: select with timeout of [%u.%06u]\n",
397 (unsigned int)pto->tv_sec, (unsigned int)pto->tv_usec ));
402 memcpy(buffer, msg->buf.data, MIN(buffer_len, msg->buf.length));
404 /* We leave this message on the queue so the open code can
405 know this is a retry. */
406 DEBUG(5,("receive_message_or_smb: returning deferred open smb message.\n"));
412 * Setup the select read fd set.
418 * Ensure we process oplock break messages by preference.
419 * We have to do this before the select, after the select
420 * and if the select returns EINTR. This is due to the fact
421 * that the selects called from async_processing can eat an EINTR
422 * caused by a signal (we can't take the break message there).
423 * This is hideously complex - *MUST* be simplified for 3.0 ! JRA.
426 if (oplock_message_waiting(&fds)) {
427 DEBUG(10,("receive_message_or_smb: oplock_message is waiting.\n"));
428 async_processing(buffer, buffer_len);
430 * After async processing we must go and do the select again, as
431 * the state of the flag in fds for the server file descriptor is
432 * indeterminate - we may have done I/O on it in the oplock processing. JRA.
437 FD_SET(smbd_server_fd(),&fds);
438 maxfd = setup_oplock_select_set(&fds);
440 selrtn = sys_select(MAX(maxfd,smbd_server_fd())+1,&fds,NULL,NULL,pto);
442 /* if we get EINTR then maybe we have received an oplock
443 signal - treat this as select returning 1. This is ugly, but
444 is the best we can do until the oplock code knows more about
446 if (selrtn == -1 && errno == EINTR) {
447 async_processing(buffer, buffer_len);
449 * After async processing we must go and do the select again, as
450 * the state of the flag in fds for the server file descriptor is
451 * indeterminate - we may have done I/O on it in the oplock processing. JRA.
458 /* something is wrong. Maybe the socket is dead? */
459 smb_read_error = READ_ERROR;
463 /* Did we timeout ? */
465 smb_read_error = READ_TIMEOUT;
470 * Ensure we process oplock break messages by preference.
471 * This is IMPORTANT ! Otherwise we can starve other processes
472 * sending us an oplock break message. JRA.
475 if (oplock_message_waiting(&fds)) {
476 async_processing(buffer, buffer_len);
478 * After async processing we must go and do the select again, as
479 * the state of the flag in fds for the server file descriptor is
480 * indeterminate - we may have done I/O on it in the oplock processing. JRA.
485 return receive_smb(smbd_server_fd(), buffer, 0);
488 /****************************************************************************
489 Get the next SMB packet, doing the local message processing automatically.
490 ****************************************************************************/
492 BOOL receive_next_smb(char *inbuf, int bufsize, int timeout)
498 ret = receive_message_or_smb(inbuf,bufsize,timeout);
500 got_keepalive = (ret && (CVAL(inbuf,0) == SMBkeepalive));
501 } while (ret && got_keepalive);
506 /****************************************************************************
507 We're terminating and have closed all our files/connections etc.
508 If there are any pending local messages we need to respond to them
509 before termination so that other smbds don't think we just died whilst
511 ****************************************************************************/
513 void respond_to_all_remaining_local_messages(void)
518 * Assert we have no exclusive open oplocks.
521 if(get_number_of_exclusive_open_oplocks()) {
522 DEBUG(0,("respond_to_all_remaining_local_messages: PANIC : we have %d exclusive oplocks.\n",
523 get_number_of_exclusive_open_oplocks() ));
528 * Keep doing receive_local_message with a 1 ms timeout until
529 * we have no more messages.
532 while(receive_local_message(buffer, sizeof(buffer), 1)) {
533 /* Deal with oplock break requests from other smbd's. */
534 process_local_message(buffer, sizeof(buffer));
542 These flags determine some of the permissions required to do an operation
544 Note that I don't set NEED_WRITE on some write operations because they
545 are used by some brain-dead clients when printing, and I don't want to
546 force write permissions on print services.
548 #define AS_USER (1<<0)
549 #define NEED_WRITE (1<<1)
550 #define TIME_INIT (1<<2)
551 #define CAN_IPC (1<<3)
552 #define AS_GUEST (1<<5)
553 #define QUEUE_IN_OPLOCK (1<<6)
554 #define DO_CHDIR (1<<7)
557 define a list of possible SMB messages and their corresponding
558 functions. Any message that has a NULL function is unimplemented -
559 please feel free to contribute implementations!
561 static const struct smb_message_struct {
563 int (*fn)(connection_struct *conn, char *, char *, int, int);
565 } smb_messages[256] = {
567 /* 0x00 */ { "SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
568 /* 0x01 */ { "SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
569 /* 0x02 */ { "SMBopen",reply_open,AS_USER | QUEUE_IN_OPLOCK },
570 /* 0x03 */ { "SMBcreate",reply_mknew,AS_USER},
571 /* 0x04 */ { "SMBclose",reply_close,AS_USER | CAN_IPC },
572 /* 0x05 */ { "SMBflush",reply_flush,AS_USER},
573 /* 0x06 */ { "SMBunlink",reply_unlink,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK},
574 /* 0x07 */ { "SMBmv",reply_mv,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK},
575 /* 0x08 */ { "SMBgetatr",reply_getatr,AS_USER},
576 /* 0x09 */ { "SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
577 /* 0x0a */ { "SMBread",reply_read,AS_USER},
578 /* 0x0b */ { "SMBwrite",reply_write,AS_USER | CAN_IPC },
579 /* 0x0c */ { "SMBlock",reply_lock,AS_USER},
580 /* 0x0d */ { "SMBunlock",reply_unlock,AS_USER},
581 /* 0x0e */ { "SMBctemp",reply_ctemp,AS_USER | QUEUE_IN_OPLOCK },
582 /* 0x0f */ { "SMBmknew",reply_mknew,AS_USER},
583 /* 0x10 */ { "SMBchkpth",reply_chkpth,AS_USER},
584 /* 0x11 */ { "SMBexit",reply_exit,DO_CHDIR},
585 /* 0x12 */ { "SMBlseek",reply_lseek,AS_USER},
586 /* 0x13 */ { "SMBlockread",reply_lockread,AS_USER},
587 /* 0x14 */ { "SMBwriteunlock",reply_writeunlock,AS_USER},
588 /* 0x15 */ { NULL, NULL, 0 },
589 /* 0x16 */ { NULL, NULL, 0 },
590 /* 0x17 */ { NULL, NULL, 0 },
591 /* 0x18 */ { NULL, NULL, 0 },
592 /* 0x19 */ { NULL, NULL, 0 },
593 /* 0x1a */ { "SMBreadbraw",reply_readbraw,AS_USER},
594 /* 0x1b */ { "SMBreadBmpx",reply_readbmpx,AS_USER},
595 /* 0x1c */ { "SMBreadBs",NULL,0 },
596 /* 0x1d */ { "SMBwritebraw",reply_writebraw,AS_USER},
597 /* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,AS_USER},
598 /* 0x1f */ { "SMBwriteBs",reply_writebs,AS_USER},
599 /* 0x20 */ { "SMBwritec",NULL,0},
600 /* 0x21 */ { NULL, NULL, 0 },
601 /* 0x22 */ { "SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE },
602 /* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER },
603 /* 0x24 */ { "SMBlockingX",reply_lockingX,AS_USER },
604 /* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC },
605 /* 0x26 */ { "SMBtranss",NULL,AS_USER | CAN_IPC},
606 /* 0x27 */ { "SMBioctl",reply_ioctl,0},
607 /* 0x28 */ { "SMBioctls",NULL,AS_USER},
608 /* 0x29 */ { "SMBcopy",reply_copy,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK },
609 /* 0x2a */ { "SMBmove",NULL,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK },
610 /* 0x2b */ { "SMBecho",reply_echo,0},
611 /* 0x2c */ { "SMBwriteclose",reply_writeclose,AS_USER},
612 /* 0x2d */ { "SMBopenX",reply_open_and_X,AS_USER | CAN_IPC | QUEUE_IN_OPLOCK },
613 /* 0x2e */ { "SMBreadX",reply_read_and_X,AS_USER | CAN_IPC },
614 /* 0x2f */ { "SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC },
615 /* 0x30 */ { NULL, NULL, 0 },
616 /* 0x31 */ { NULL, NULL, 0 },
617 /* 0x32 */ { "SMBtrans2", reply_trans2, AS_USER | CAN_IPC },
618 /* 0x33 */ { "SMBtranss2", reply_transs2, AS_USER},
619 /* 0x34 */ { "SMBfindclose", reply_findclose,AS_USER},
620 /* 0x35 */ { "SMBfindnclose", reply_findnclose, AS_USER},
621 /* 0x36 */ { NULL, NULL, 0 },
622 /* 0x37 */ { NULL, NULL, 0 },
623 /* 0x38 */ { NULL, NULL, 0 },
624 /* 0x39 */ { NULL, NULL, 0 },
625 /* 0x3a */ { NULL, NULL, 0 },
626 /* 0x3b */ { NULL, NULL, 0 },
627 /* 0x3c */ { NULL, NULL, 0 },
628 /* 0x3d */ { NULL, NULL, 0 },
629 /* 0x3e */ { NULL, NULL, 0 },
630 /* 0x3f */ { NULL, NULL, 0 },
631 /* 0x40 */ { NULL, NULL, 0 },
632 /* 0x41 */ { NULL, NULL, 0 },
633 /* 0x42 */ { NULL, NULL, 0 },
634 /* 0x43 */ { NULL, NULL, 0 },
635 /* 0x44 */ { NULL, NULL, 0 },
636 /* 0x45 */ { NULL, NULL, 0 },
637 /* 0x46 */ { NULL, NULL, 0 },
638 /* 0x47 */ { NULL, NULL, 0 },
639 /* 0x48 */ { NULL, NULL, 0 },
640 /* 0x49 */ { NULL, NULL, 0 },
641 /* 0x4a */ { NULL, NULL, 0 },
642 /* 0x4b */ { NULL, NULL, 0 },
643 /* 0x4c */ { NULL, NULL, 0 },
644 /* 0x4d */ { NULL, NULL, 0 },
645 /* 0x4e */ { NULL, NULL, 0 },
646 /* 0x4f */ { NULL, NULL, 0 },
647 /* 0x50 */ { NULL, NULL, 0 },
648 /* 0x51 */ { NULL, NULL, 0 },
649 /* 0x52 */ { NULL, NULL, 0 },
650 /* 0x53 */ { NULL, NULL, 0 },
651 /* 0x54 */ { NULL, NULL, 0 },
652 /* 0x55 */ { NULL, NULL, 0 },
653 /* 0x56 */ { NULL, NULL, 0 },
654 /* 0x57 */ { NULL, NULL, 0 },
655 /* 0x58 */ { NULL, NULL, 0 },
656 /* 0x59 */ { NULL, NULL, 0 },
657 /* 0x5a */ { NULL, NULL, 0 },
658 /* 0x5b */ { NULL, NULL, 0 },
659 /* 0x5c */ { NULL, NULL, 0 },
660 /* 0x5d */ { NULL, NULL, 0 },
661 /* 0x5e */ { NULL, NULL, 0 },
662 /* 0x5f */ { NULL, NULL, 0 },
663 /* 0x60 */ { NULL, NULL, 0 },
664 /* 0x61 */ { NULL, NULL, 0 },
665 /* 0x62 */ { NULL, NULL, 0 },
666 /* 0x63 */ { NULL, NULL, 0 },
667 /* 0x64 */ { NULL, NULL, 0 },
668 /* 0x65 */ { NULL, NULL, 0 },
669 /* 0x66 */ { NULL, NULL, 0 },
670 /* 0x67 */ { NULL, NULL, 0 },
671 /* 0x68 */ { NULL, NULL, 0 },
672 /* 0x69 */ { NULL, NULL, 0 },
673 /* 0x6a */ { NULL, NULL, 0 },
674 /* 0x6b */ { NULL, NULL, 0 },
675 /* 0x6c */ { NULL, NULL, 0 },
676 /* 0x6d */ { NULL, NULL, 0 },
677 /* 0x6e */ { NULL, NULL, 0 },
678 /* 0x6f */ { NULL, NULL, 0 },
679 /* 0x70 */ { "SMBtcon",reply_tcon,0},
680 /* 0x71 */ { "SMBtdis",reply_tdis,DO_CHDIR},
681 /* 0x72 */ { "SMBnegprot",reply_negprot,0},
682 /* 0x73 */ { "SMBsesssetupX",reply_sesssetup_and_X,0},
683 /* 0x74 */ { "SMBulogoffX", reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
684 /* 0x75 */ { "SMBtconX",reply_tcon_and_X,0},
685 /* 0x76 */ { NULL, NULL, 0 },
686 /* 0x77 */ { NULL, NULL, 0 },
687 /* 0x78 */ { NULL, NULL, 0 },
688 /* 0x79 */ { NULL, NULL, 0 },
689 /* 0x7a */ { NULL, NULL, 0 },
690 /* 0x7b */ { NULL, NULL, 0 },
691 /* 0x7c */ { NULL, NULL, 0 },
692 /* 0x7d */ { NULL, NULL, 0 },
693 /* 0x7e */ { NULL, NULL, 0 },
694 /* 0x7f */ { NULL, NULL, 0 },
695 /* 0x80 */ { "SMBdskattr",reply_dskattr,AS_USER},
696 /* 0x81 */ { "SMBsearch",reply_search,AS_USER},
697 /* 0x82 */ { "SMBffirst",reply_search,AS_USER},
698 /* 0x83 */ { "SMBfunique",reply_search,AS_USER},
699 /* 0x84 */ { "SMBfclose",reply_fclose,AS_USER},
700 /* 0x85 */ { NULL, NULL, 0 },
701 /* 0x86 */ { NULL, NULL, 0 },
702 /* 0x87 */ { NULL, NULL, 0 },
703 /* 0x88 */ { NULL, NULL, 0 },
704 /* 0x89 */ { NULL, NULL, 0 },
705 /* 0x8a */ { NULL, NULL, 0 },
706 /* 0x8b */ { NULL, NULL, 0 },
707 /* 0x8c */ { NULL, NULL, 0 },
708 /* 0x8d */ { NULL, NULL, 0 },
709 /* 0x8e */ { NULL, NULL, 0 },
710 /* 0x8f */ { NULL, NULL, 0 },
711 /* 0x90 */ { NULL, NULL, 0 },
712 /* 0x91 */ { NULL, NULL, 0 },
713 /* 0x92 */ { NULL, NULL, 0 },
714 /* 0x93 */ { NULL, NULL, 0 },
715 /* 0x94 */ { NULL, NULL, 0 },
716 /* 0x95 */ { NULL, NULL, 0 },
717 /* 0x96 */ { NULL, NULL, 0 },
718 /* 0x97 */ { NULL, NULL, 0 },
719 /* 0x98 */ { NULL, NULL, 0 },
720 /* 0x99 */ { NULL, NULL, 0 },
721 /* 0x9a */ { NULL, NULL, 0 },
722 /* 0x9b */ { NULL, NULL, 0 },
723 /* 0x9c */ { NULL, NULL, 0 },
724 /* 0x9d */ { NULL, NULL, 0 },
725 /* 0x9e */ { NULL, NULL, 0 },
726 /* 0x9f */ { NULL, NULL, 0 },
727 /* 0xa0 */ { "SMBnttrans", reply_nttrans, AS_USER | CAN_IPC | QUEUE_IN_OPLOCK},
728 /* 0xa1 */ { "SMBnttranss", reply_nttranss, AS_USER | CAN_IPC },
729 /* 0xa2 */ { "SMBntcreateX", reply_ntcreate_and_X, AS_USER | CAN_IPC | QUEUE_IN_OPLOCK },
730 /* 0xa3 */ { NULL, NULL, 0 },
731 /* 0xa4 */ { "SMBntcancel", reply_ntcancel, 0 },
732 /* 0xa5 */ { "SMBntrename", reply_ntrename, AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK },
733 /* 0xa6 */ { NULL, NULL, 0 },
734 /* 0xa7 */ { NULL, NULL, 0 },
735 /* 0xa8 */ { NULL, NULL, 0 },
736 /* 0xa9 */ { NULL, NULL, 0 },
737 /* 0xaa */ { NULL, NULL, 0 },
738 /* 0xab */ { NULL, NULL, 0 },
739 /* 0xac */ { NULL, NULL, 0 },
740 /* 0xad */ { NULL, NULL, 0 },
741 /* 0xae */ { NULL, NULL, 0 },
742 /* 0xaf */ { NULL, NULL, 0 },
743 /* 0xb0 */ { NULL, NULL, 0 },
744 /* 0xb1 */ { NULL, NULL, 0 },
745 /* 0xb2 */ { NULL, NULL, 0 },
746 /* 0xb3 */ { NULL, NULL, 0 },
747 /* 0xb4 */ { NULL, NULL, 0 },
748 /* 0xb5 */ { NULL, NULL, 0 },
749 /* 0xb6 */ { NULL, NULL, 0 },
750 /* 0xb7 */ { NULL, NULL, 0 },
751 /* 0xb8 */ { NULL, NULL, 0 },
752 /* 0xb9 */ { NULL, NULL, 0 },
753 /* 0xba */ { NULL, NULL, 0 },
754 /* 0xbb */ { NULL, NULL, 0 },
755 /* 0xbc */ { NULL, NULL, 0 },
756 /* 0xbd */ { NULL, NULL, 0 },
757 /* 0xbe */ { NULL, NULL, 0 },
758 /* 0xbf */ { NULL, NULL, 0 },
759 /* 0xc0 */ { "SMBsplopen",reply_printopen,AS_USER | QUEUE_IN_OPLOCK },
760 /* 0xc1 */ { "SMBsplwr",reply_printwrite,AS_USER},
761 /* 0xc2 */ { "SMBsplclose",reply_printclose,AS_USER},
762 /* 0xc3 */ { "SMBsplretq",reply_printqueue,AS_USER},
763 /* 0xc4 */ { NULL, NULL, 0 },
764 /* 0xc5 */ { NULL, NULL, 0 },
765 /* 0xc6 */ { NULL, NULL, 0 },
766 /* 0xc7 */ { NULL, NULL, 0 },
767 /* 0xc8 */ { NULL, NULL, 0 },
768 /* 0xc9 */ { NULL, NULL, 0 },
769 /* 0xca */ { NULL, NULL, 0 },
770 /* 0xcb */ { NULL, NULL, 0 },
771 /* 0xcc */ { NULL, NULL, 0 },
772 /* 0xcd */ { NULL, NULL, 0 },
773 /* 0xce */ { NULL, NULL, 0 },
774 /* 0xcf */ { NULL, NULL, 0 },
775 /* 0xd0 */ { "SMBsends",reply_sends,AS_GUEST},
776 /* 0xd1 */ { "SMBsendb",NULL,AS_GUEST},
777 /* 0xd2 */ { "SMBfwdname",NULL,AS_GUEST},
778 /* 0xd3 */ { "SMBcancelf",NULL,AS_GUEST},
779 /* 0xd4 */ { "SMBgetmac",NULL,AS_GUEST},
780 /* 0xd5 */ { "SMBsendstrt",reply_sendstrt,AS_GUEST},
781 /* 0xd6 */ { "SMBsendend",reply_sendend,AS_GUEST},
782 /* 0xd7 */ { "SMBsendtxt",reply_sendtxt,AS_GUEST},
783 /* 0xd8 */ { NULL, NULL, 0 },
784 /* 0xd9 */ { NULL, NULL, 0 },
785 /* 0xda */ { NULL, NULL, 0 },
786 /* 0xdb */ { NULL, NULL, 0 },
787 /* 0xdc */ { NULL, NULL, 0 },
788 /* 0xdd */ { NULL, NULL, 0 },
789 /* 0xde */ { NULL, NULL, 0 },
790 /* 0xdf */ { NULL, NULL, 0 },
791 /* 0xe0 */ { NULL, NULL, 0 },
792 /* 0xe1 */ { NULL, NULL, 0 },
793 /* 0xe2 */ { NULL, NULL, 0 },
794 /* 0xe3 */ { NULL, NULL, 0 },
795 /* 0xe4 */ { NULL, NULL, 0 },
796 /* 0xe5 */ { NULL, NULL, 0 },
797 /* 0xe6 */ { NULL, NULL, 0 },
798 /* 0xe7 */ { NULL, NULL, 0 },
799 /* 0xe8 */ { NULL, NULL, 0 },
800 /* 0xe9 */ { NULL, NULL, 0 },
801 /* 0xea */ { NULL, NULL, 0 },
802 /* 0xeb */ { NULL, NULL, 0 },
803 /* 0xec */ { NULL, NULL, 0 },
804 /* 0xed */ { NULL, NULL, 0 },
805 /* 0xee */ { NULL, NULL, 0 },
806 /* 0xef */ { NULL, NULL, 0 },
807 /* 0xf0 */ { NULL, NULL, 0 },
808 /* 0xf1 */ { NULL, NULL, 0 },
809 /* 0xf2 */ { NULL, NULL, 0 },
810 /* 0xf3 */ { NULL, NULL, 0 },
811 /* 0xf4 */ { NULL, NULL, 0 },
812 /* 0xf5 */ { NULL, NULL, 0 },
813 /* 0xf6 */ { NULL, NULL, 0 },
814 /* 0xf7 */ { NULL, NULL, 0 },
815 /* 0xf8 */ { NULL, NULL, 0 },
816 /* 0xf9 */ { NULL, NULL, 0 },
817 /* 0xfa */ { NULL, NULL, 0 },
818 /* 0xfb */ { NULL, NULL, 0 },
819 /* 0xfc */ { NULL, NULL, 0 },
820 /* 0xfd */ { NULL, NULL, 0 },
821 /* 0xfe */ { NULL, NULL, 0 },
822 /* 0xff */ { NULL, NULL, 0 }
826 /*******************************************************************
827 Dump a packet to a file.
828 ********************************************************************/
830 static void smb_dump(const char *name, int type, char *data, ssize_t len)
834 if (DEBUGLEVEL < 50) return;
836 if (len < 4) len = smb_len(data)+4;
837 for (i=1;i<100;i++) {
838 slprintf(fname,sizeof(fname)-1, "/tmp/%s.%d.%s", name, i,
839 type ? "req" : "resp");
840 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644);
841 if (fd != -1 || errno != EEXIST) break;
844 ssize_t ret = write(fd, data, len);
846 DEBUG(0,("smb_dump: problem: write returned %d\n", (int)ret ));
848 DEBUG(0,("created %s len %lu\n", fname, (unsigned long)len));
853 /****************************************************************************
854 Do a switch on the message type, and return the response size
855 ****************************************************************************/
857 static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize)
859 static pid_t pid= (pid_t)-1;
864 if (pid == (pid_t)-1)
868 set_saved_error_triple(0, 0, NT_STATUS_OK);
872 /* Make sure this is an SMB packet. smb_size contains NetBIOS header so subtract 4 from it. */
873 if ((strncmp(smb_base(inbuf),"\377SMB",4) != 0) || (size < (smb_size - 4))) {
874 DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",smb_len(inbuf)));
875 exit_server("Non-SMB packet");
879 /* yuck! this is an interim measure before we get rid of our
880 current inbuf/outbuf system */
881 global_smbpid = SVAL(inbuf,smb_pid);
883 if (smb_messages[type].fn == NULL) {
884 DEBUG(0,("Unknown message type %d!\n",type));
885 smb_dump("Unknown", 1, inbuf, size);
886 outsize = reply_unknown(inbuf,outbuf);
888 int flags = smb_messages[type].flags;
889 static uint16 last_session_tag = UID_FIELD_INVALID;
890 /* In share mode security we must ignore the vuid. */
891 uint16 session_tag = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(inbuf,smb_uid);
892 connection_struct *conn = conn_find(SVAL(inbuf,smb_tid));
894 DEBUG(3,("switch message %s (pid %d) conn 0x%x\n",smb_fn_name(type),(int)pid,(unsigned int)conn));
896 smb_dump(smb_fn_name(type), 1, inbuf, size);
897 if(global_oplock_break) {
898 if(flags & QUEUE_IN_OPLOCK) {
900 * Queue this message as we are the process of an oplock break.
903 DEBUG( 2, ( "switch_message: queueing message due to being in " ) );
904 DEBUGADD( 2, ( "oplock break state.\n" ) );
906 push_oplock_pending_smb_message( inbuf, size );
911 /* Ensure this value is replaced in the incoming packet. */
912 SSVAL(inbuf,smb_uid,session_tag);
915 * Ensure the correct username is in current_user_info.
916 * This is a really ugly bugfix for problems with
917 * multiple session_setup_and_X's being done and
918 * allowing %U and %G substitutions to work correctly.
919 * There is a reason this code is done here, don't
920 * move it unless you know what you're doing... :-).
924 if (session_tag != last_session_tag) {
925 user_struct *vuser = NULL;
927 last_session_tag = session_tag;
928 if(session_tag != UID_FIELD_INVALID)
929 vuser = get_valid_user_struct(session_tag);
931 set_current_user_info(&vuser->user);
934 /* does this protocol need to be run as root? */
935 if (!(flags & AS_USER))
936 change_to_root_user();
938 /* does this protocol need a valid tree connection? */
939 if ((flags & AS_USER) && !conn) {
940 /* Amazingly, the error code depends on the command (from Samba4). */
941 if (type == SMBntcreateX) {
942 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
944 return ERROR_DOS(ERRSRV, ERRinvnid);
949 /* does this protocol need to be run as the connected user? */
950 if ((flags & AS_USER) && !change_to_user(conn,session_tag)) {
951 if (flags & AS_GUEST)
954 return(ERROR_FORCE_DOS(ERRSRV,ERRbaduid));
957 /* this code is to work around a bug is MS client 3 without
958 introducing a security hole - it needs to be able to do
959 print queue checks as guest if it isn't logged in properly */
963 /* does it need write permission? */
964 if ((flags & NEED_WRITE) && !CAN_WRITE(conn))
965 return(ERROR_DOS(ERRSRV,ERRaccess));
967 /* ipc services are limited */
968 if (IS_IPC(conn) && (flags & AS_USER) && !(flags & CAN_IPC))
969 return(ERROR_DOS(ERRSRV,ERRaccess));
971 /* load service specific parameters */
973 if (!set_current_service(conn,SVAL(inbuf,smb_flg),(flags & (AS_USER|DO_CHDIR)?True:False))) {
974 return(ERROR_DOS(ERRSRV,ERRaccess));
976 conn->num_smb_operations++;
979 /* does this protocol need to be run as guest? */
980 if ((flags & AS_GUEST) && (!change_to_guest() ||
981 !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1))))
982 return(ERROR_DOS(ERRSRV,ERRaccess));
986 outsize = smb_messages[type].fn(conn, inbuf,outbuf,size,bufsize);
989 smb_dump(smb_fn_name(type), 0, outbuf, outsize);
995 /****************************************************************************
996 Construct a reply to the incoming packet.
997 ****************************************************************************/
999 static int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
1001 int type = CVAL(inbuf,smb_com);
1003 int msg_type = CVAL(inbuf,0);
1005 GetTimeOfDay(&smb_last_time);
1012 return(reply_special(inbuf,outbuf));
1014 construct_reply_common(inbuf, outbuf);
1016 outsize = switch_message(type,inbuf,outbuf,size,bufsize);
1018 outsize += chain_size;
1021 smb_setlen(outbuf,outsize - 4);
1025 /****************************************************************************
1026 Keep track of the number of running smbd's. This functionality is used to
1027 'hard' limit Samba overhead on resource constrained systems.
1028 ****************************************************************************/
1030 static BOOL process_count_update_successful = False;
1032 static int32 increment_smbd_process_count(void)
1036 if (lp_max_smbd_processes()) {
1038 if (tdb_change_int32_atomic(conn_tdb_ctx(), "INFO/total_smbds", &total_smbds, 1) == -1)
1040 process_count_update_successful = True;
1041 return total_smbds + 1;
1046 void decrement_smbd_process_count(void)
1050 if (lp_max_smbd_processes() && process_count_update_successful) {
1052 tdb_change_int32_atomic(conn_tdb_ctx(), "INFO/total_smbds", &total_smbds, -1);
1056 static BOOL smbd_process_limit(void)
1060 if (lp_max_smbd_processes()) {
1062 /* Always add one to the smbd process count, as exit_server() always
1066 if (!conn_tdb_ctx()) {
1067 DEBUG(0,("smbd_process_limit: max smbd processes parameter set with status parameter not \
1068 set. Ignoring max smbd restriction.\n"));
1072 total_smbds = increment_smbd_process_count();
1073 return total_smbds > lp_max_smbd_processes();
1079 /****************************************************************************
1080 Process an smb from the client - split out from the smbd_process() code so
1081 it can be used by the oplock break code.
1082 ****************************************************************************/
1084 void process_smb(char *inbuf, char *outbuf)
1086 static int trans_num;
1087 int msg_type = CVAL(inbuf,0);
1088 int32 len = smb_len(inbuf);
1089 int nread = len + 4;
1091 DO_PROFILE_INC(smb_count);
1093 if (trans_num == 0) {
1094 /* on the first packet, check the global hosts allow/ hosts
1095 deny parameters before doing any parsing of the packet
1096 passed to us by the client. This prevents attacks on our
1097 parsing code from hosts not in the hosts allow list */
1098 if (smbd_process_limit() ||
1099 !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1))) {
1100 /* send a negative session response "not listening on calling name" */
1101 static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
1102 DEBUG( 1, ( "Connection denied from %s\n", client_addr() ) );
1103 (void)send_smb(smbd_server_fd(),(char *)buf);
1104 exit_server("connection denied");
1108 DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type, len ) );
1109 DEBUG( 3, ( "Transaction %d of length %d\n", trans_num, nread ) );
1113 else if(msg_type == SMBkeepalive)
1114 return; /* Keepalive packet. */
1116 nread = construct_reply(inbuf,outbuf,nread,max_send);
1119 if (CVAL(outbuf,0) == 0)
1122 if (nread != smb_len(outbuf) + 4) {
1123 DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
1124 nread, smb_len(outbuf)));
1125 } else if (!send_smb(smbd_server_fd(),outbuf)) {
1126 exit_server("process_smb: send_smb failed.");
1132 /****************************************************************************
1133 Return a string containing the function name of a SMB command.
1134 ****************************************************************************/
1136 const char *smb_fn_name(int type)
1138 const char *unknown_name = "SMBunknown";
1140 if (smb_messages[type].name == NULL)
1141 return(unknown_name);
1143 return(smb_messages[type].name);
1146 /****************************************************************************
1147 Helper functions for contruct_reply.
1148 ****************************************************************************/
1150 static uint32 common_flags2 = FLAGS2_LONG_PATH_COMPONENTS|FLAGS2_32_BIT_ERROR_CODES;
1152 void add_to_common_flags2(uint32 v)
1157 void remove_from_common_flags2(uint32 v)
1159 common_flags2 &= ~v;
1162 void construct_reply_common(char *inbuf,char *outbuf)
1164 memset(outbuf,'\0',smb_size);
1166 set_message(outbuf,0,0,True);
1167 SCVAL(outbuf,smb_com,CVAL(inbuf,smb_com));
1169 memcpy(outbuf+4,inbuf+4,4);
1170 SCVAL(outbuf,smb_rcls,SMB_SUCCESS);
1171 SCVAL(outbuf,smb_reh,0);
1172 SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES));
1173 SSVAL(outbuf,smb_flg2,
1174 (SVAL(inbuf,smb_flg2) & FLAGS2_UNICODE_STRINGS) |
1177 SSVAL(outbuf,smb_err,SMB_SUCCESS);
1178 SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
1179 SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
1180 SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
1181 SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
1184 /****************************************************************************
1185 Construct a chained reply and add it to the already made reply
1186 ****************************************************************************/
1188 int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
1190 static char *orig_inbuf;
1191 static char *orig_outbuf;
1192 int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0);
1193 unsigned smb_off2 = SVAL(inbuf,smb_vwv1);
1194 char *inbuf2, *outbuf2;
1196 char inbuf_saved[smb_wct];
1197 char outbuf_saved[smb_wct];
1198 int outsize = smb_len(outbuf) + 4;
1200 /* maybe its not chained */
1201 if (smb_com2 == 0xFF) {
1202 SCVAL(outbuf,smb_vwv0,0xFF);
1206 if (chain_size == 0) {
1207 /* this is the first part of the chain */
1209 orig_outbuf = outbuf;
1213 * The original Win95 redirector dies on a reply to
1214 * a lockingX and read chain unless the chain reply is
1215 * 4 byte aligned. JRA.
1218 outsize = (outsize + 3) & ~3;
1220 /* we need to tell the client where the next part of the reply will be */
1221 SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf));
1222 SCVAL(outbuf,smb_vwv0,smb_com2);
1224 /* remember how much the caller added to the chain, only counting stuff
1225 after the parameter words */
1226 chain_size += outsize - smb_wct;
1228 /* work out pointers into the original packets. The
1229 headers on these need to be filled in */
1230 inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct;
1231 outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct;
1233 /* remember the original command type */
1234 smb_com1 = CVAL(orig_inbuf,smb_com);
1236 /* save the data which will be overwritten by the new headers */
1237 memcpy(inbuf_saved,inbuf2,smb_wct);
1238 memcpy(outbuf_saved,outbuf2,smb_wct);
1240 /* give the new packet the same header as the last part of the SMB */
1241 memmove(inbuf2,inbuf,smb_wct);
1243 /* create the in buffer */
1244 SCVAL(inbuf2,smb_com,smb_com2);
1246 /* create the out buffer */
1247 construct_reply_common(inbuf2, outbuf2);
1249 DEBUG(3,("Chained message\n"));
1252 /* process the request */
1253 outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size,
1254 bufsize-chain_size);
1256 /* copy the new reply and request headers over the old ones, but
1257 preserve the smb_com field */
1258 memmove(orig_outbuf,outbuf2,smb_wct);
1259 SCVAL(orig_outbuf,smb_com,smb_com1);
1261 /* restore the saved data, being careful not to overwrite any
1262 data from the reply header */
1263 memcpy(inbuf2,inbuf_saved,smb_wct);
1266 int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf);
1267 if (ofs < 0) ofs = 0;
1268 memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs);
1274 /****************************************************************************
1275 Setup the needed select timeout.
1276 ****************************************************************************/
1278 static int setup_select_timeout(void)
1283 select_timeout = blocking_locks_timeout(SMBD_SELECT_TIMEOUT);
1284 select_timeout *= 1000;
1286 t = change_notify_timeout();
1288 select_timeout = MIN(select_timeout, t*1000);
1290 if (print_notify_messages_pending())
1291 select_timeout = MIN(select_timeout, 1000);
1293 return select_timeout;
1296 /****************************************************************************
1297 Check if services need reloading.
1298 ****************************************************************************/
1300 void check_reload(int t)
1302 static time_t last_smb_conf_reload_time = 0;
1303 static time_t last_printer_reload_time = 0;
1304 time_t printcap_cache_time = (time_t)lp_printcap_cache_time();
1306 if(last_smb_conf_reload_time == 0) {
1307 last_smb_conf_reload_time = t;
1308 /* Our printing subsystem might not be ready at smbd start up.
1309 Then no printer is available till the first printers check
1310 is performed. A lower initial interval circumvents this. */
1311 if ( printcap_cache_time > 60 )
1312 last_printer_reload_time = t - printcap_cache_time + 60;
1314 last_printer_reload_time = t;
1317 if (reload_after_sighup || (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK)) {
1318 reload_services(True);
1319 reload_after_sighup = False;
1320 last_smb_conf_reload_time = t;
1323 /* 'printcap cache time = 0' disable the feature */
1325 if ( printcap_cache_time != 0 )
1327 /* see if it's time to reload or if the clock has been set back */
1329 if ( (t >= last_printer_reload_time+printcap_cache_time)
1330 || (t-last_printer_reload_time < 0) )
1332 DEBUG( 3,( "Printcap cache time expired.\n"));
1334 last_printer_reload_time = t;
1339 /****************************************************************************
1340 Process any timeout housekeeping. Return False if the caller should exit.
1341 ****************************************************************************/
1343 static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_timeout_processing_time)
1345 static time_t last_keepalive_sent_time = 0;
1346 static time_t last_idle_closed_check = 0;
1348 BOOL allidle = True;
1350 if (smb_read_error == READ_EOF) {
1351 DEBUG(3,("timeout_processing: End of file from client (client has disconnected).\n"));
1355 if (smb_read_error == READ_ERROR) {
1356 DEBUG(3,("timeout_processing: receive_smb error (%s) Exiting\n",
1361 if (smb_read_error == READ_BAD_SIG) {
1362 DEBUG(3,("timeout_processing: receive_smb error bad smb signature. Exiting\n"));
1366 *last_timeout_processing_time = t = time(NULL);
1368 if(last_keepalive_sent_time == 0)
1369 last_keepalive_sent_time = t;
1371 if(last_idle_closed_check == 0)
1372 last_idle_closed_check = t;
1374 /* become root again if waiting */
1375 change_to_root_user();
1377 /* run all registered idle events */
1378 smb_run_idle_events(t);
1380 /* check if we need to reload services */
1383 /* automatic timeout if all connections are closed */
1384 if (conn_num_open()==0 && (t - last_idle_closed_check) >= IDLE_CLOSED_TIMEOUT) {
1385 DEBUG( 2, ( "Closing idle connection\n" ) );
1388 last_idle_closed_check = t;
1391 if (keepalive && (t - last_keepalive_sent_time)>keepalive) {
1392 if (!send_keepalive(smbd_server_fd())) {
1393 DEBUG( 2, ( "Keepalive failed - exiting.\n" ) );
1397 /* send a keepalive for a password server or the like.
1398 This is attached to the auth_info created in the
1400 if (negprot_global_auth_context && negprot_global_auth_context->challenge_set_method
1401 && negprot_global_auth_context->challenge_set_method->send_keepalive) {
1403 negprot_global_auth_context->challenge_set_method->send_keepalive
1404 (&negprot_global_auth_context->challenge_set_method->private_data);
1407 last_keepalive_sent_time = t;
1410 /* check for connection timeouts */
1411 allidle = conn_idle_all(t, deadtime);
1413 if (allidle && conn_num_open()>0) {
1414 DEBUG(2,("Closing idle connection 2.\n"));
1418 if(global_machine_password_needs_changing &&
1419 /* for ADS we need to do a regular ADS password change, not a domain
1421 lp_security() == SEC_DOMAIN) {
1423 unsigned char trust_passwd_hash[16];
1427 * We're in domain level security, and the code that
1428 * read the machine password flagged that the machine
1429 * password needs changing.
1433 * First, open the machine password file with an exclusive lock.
1436 if (secrets_lock_trust_account_password(lp_workgroup(), True) == False) {
1437 DEBUG(0,("process: unable to lock the machine account password for \
1438 machine %s in domain %s.\n", global_myname(), lp_workgroup() ));
1442 if(!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd_hash, &lct, NULL)) {
1443 DEBUG(0,("process: unable to read the machine account password for \
1444 machine %s in domain %s.\n", global_myname(), lp_workgroup()));
1445 secrets_lock_trust_account_password(lp_workgroup(), False);
1450 * Make sure someone else hasn't already done this.
1453 if(t < lct + lp_machine_password_timeout()) {
1454 global_machine_password_needs_changing = False;
1455 secrets_lock_trust_account_password(lp_workgroup(), False);
1459 /* always just contact the PDC here */
1461 change_trust_account_password( lp_workgroup(), NULL);
1462 global_machine_password_needs_changing = False;
1463 secrets_lock_trust_account_password(lp_workgroup(), False);
1467 * Check to see if we have any blocking locks
1468 * outstanding on the queue.
1470 process_blocking_lock_queue(t);
1472 /* update printer queue caches if necessary */
1474 update_monitored_printq_cache();
1477 * Check to see if we have any change notifies
1478 * outstanding on the queue.
1480 process_pending_change_notify_queue(t);
1483 * Now we are root, check if the log files need pruning.
1484 * Force a log file check.
1486 force_check_log_size();
1489 /* Send any queued printer notify message to interested smbd's. */
1491 print_notify_send_messages(0);
1494 * Modify the select timeout depending upon
1495 * what we have remaining in our queues.
1498 *select_timeout = setup_select_timeout();
1503 /****************************************************************************
1504 process commands from the client
1505 ****************************************************************************/
1507 void smbd_process(void)
1509 time_t last_timeout_processing_time = time(NULL);
1510 unsigned int num_smbs = 0;
1511 const size_t total_buffer_size = BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN;
1513 InBuffer = (char *)SMB_MALLOC(total_buffer_size);
1514 OutBuffer = (char *)SMB_MALLOC(total_buffer_size);
1515 if ((InBuffer == NULL) || (OutBuffer == NULL))
1518 #if defined(DEVELOPER)
1519 clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size);
1520 clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer, total_buffer_size);
1523 max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
1526 int deadtime = lp_deadtime()*60;
1527 int select_timeout = setup_select_timeout();
1531 deadtime = DEFAULT_SMBD_TIMEOUT;
1535 /* free up temporary memory */
1537 main_loop_talloc_free();
1539 /* run all registered idle events */
1540 smb_run_idle_events(time(NULL));
1543 /* Did someone ask for immediate checks on things like blocking locks ? */
1544 if (select_timeout == 0) {
1545 if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1547 num_smbs = 0; /* Reset smb counter. */
1550 #if defined(DEVELOPER)
1551 clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size);
1554 while (!receive_message_or_smb(InBuffer,BUFFER_SIZE+LARGE_WRITEX_HDR_SIZE,select_timeout)) {
1555 if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1557 num_smbs = 0; /* Reset smb counter. */
1561 * Ensure we do timeout processing if the SMB we just got was
1562 * only an echo request. This allows us to set the select
1563 * timeout in 'receive_message_or_smb()' to any value we like
1564 * without worrying that the client will send echo requests
1565 * faster than the select timeout, thus starving out the
1566 * essential processing (change notify, blocking locks) that
1567 * the timeout code does. JRA.
1569 num_echos = smb_echo_count;
1571 clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer, total_buffer_size);
1573 process_smb(InBuffer, OutBuffer);
1575 if (smb_echo_count != num_echos) {
1576 if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1578 num_smbs = 0; /* Reset smb counter. */
1584 * If we are getting smb requests in a constant stream
1585 * with no echos, make sure we attempt timeout processing
1586 * every select_timeout milliseconds - but only check for this
1587 * every 200 smb requests.
1590 if ((num_smbs % 200) == 0) {
1591 time_t new_check_time = time(NULL);
1592 if(new_check_time - last_timeout_processing_time >= (select_timeout/1000)) {
1593 if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1595 num_smbs = 0; /* Reset smb counter. */
1596 last_timeout_processing_time = new_check_time; /* Reset time. */
1600 /* The timeout_processing function isn't run nearly
1601 often enough to implement 'max log size' without
1602 overrunning the size of the file by many megabytes.
1603 This is especially true if we are running at debug
1604 level 10. Checking every 50 SMBs is a nice
1605 tradeoff of performance vs log file size overrun. */
1607 if ((num_smbs % 50) == 0 && need_to_check_log_size()) {
1608 change_to_root_user();