2 Unix SMB/CIFS implementation.
3 process incoming packets - main loop
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Volker Lendecke 2005
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 extern uint16 global_smbpid;
26 extern struct auth_context *negprot_global_auth_context;
27 extern int smb_echo_count;
29 struct timeval smb_last_time;
31 static char *InBuffer = NULL;
32 static char *OutBuffer = NULL;
33 static char *current_inbuf = NULL;
36 * Size of data we can send to client. Set
37 * by the client for all protocols above CORE.
38 * Set by us for CORE protocol.
40 int max_send = BUFFER_SIZE;
42 * Size of the data we can receive. Set by us.
43 * Can be modified by the max xmit parameter.
45 int max_recv = BUFFER_SIZE;
47 extern int last_message;
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 extern BOOL global_machine_password_needs_changing;
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 *deferred_open_queue;
71 /****************************************************************************
72 Function to push a message onto the tail of a linked list of smb messages ready
74 ****************************************************************************/
76 static BOOL push_queued_message(char *buf, int msg_len,
77 struct timeval request_time,
78 struct timeval end_time,
79 char *private_data, size_t private_len)
81 struct pending_message_list *tmp_msg;
82 struct pending_message_list *msg;
84 msg = TALLOC_ZERO_P(NULL, struct pending_message_list);
87 DEBUG(0,("push_message: malloc fail (1)\n"));
91 msg->buf = data_blob_talloc(msg, buf, msg_len);
92 if(msg->buf.data == NULL) {
93 DEBUG(0,("push_message: malloc fail (2)\n"));
98 msg->request_time = request_time;
99 msg->end_time = end_time;
102 msg->private_data = data_blob_talloc(msg, private_data,
104 if (msg->private_data.data == NULL) {
105 DEBUG(0,("push_message: malloc fail (3)\n"));
111 DLIST_ADD_END(deferred_open_queue, msg, tmp_msg);
113 DEBUG(10,("push_message: pushed message length %u on "
114 "deferred_open_queue\n", (unsigned int)msg_len));
119 /****************************************************************************
120 Function to delete a sharing violation open message by mid.
121 ****************************************************************************/
123 void remove_deferred_open_smb_message(uint16 mid)
125 struct pending_message_list *pml;
127 for (pml = deferred_open_queue; pml; pml = pml->next) {
128 if (mid == SVAL(pml->buf.data,smb_mid)) {
129 DEBUG(10,("remove_sharing_violation_open_smb_message: "
130 "deleting mid %u len %u\n",
132 (unsigned int)pml->buf.length ));
133 DLIST_REMOVE(deferred_open_queue, pml);
140 /****************************************************************************
141 Move a sharing violation open retry message to the front of the list and
142 schedule it for immediate processing.
143 ****************************************************************************/
145 void schedule_deferred_open_smb_message(uint16 mid)
147 struct pending_message_list *pml;
150 for (pml = deferred_open_queue; pml; pml = pml->next) {
151 uint16 msg_mid = SVAL(pml->buf.data,smb_mid);
152 DEBUG(10,("schedule_deferred_open_smb_message: [%d] msg_mid = %u\n", i++,
153 (unsigned int)msg_mid ));
154 if (mid == msg_mid) {
155 DEBUG(10,("schedule_deferred_open_smb_message: scheduling mid %u\n",
157 pml->end_time.tv_sec = 0;
158 pml->end_time.tv_usec = 0;
159 DLIST_PROMOTE(deferred_open_queue, pml);
164 DEBUG(10,("schedule_deferred_open_smb_message: failed to find message mid %u\n",
168 /****************************************************************************
169 Return true if this mid is on the deferred queue.
170 ****************************************************************************/
172 BOOL open_was_deferred(uint16 mid)
174 struct pending_message_list *pml;
176 for (pml = deferred_open_queue; pml; pml = pml->next) {
177 if (SVAL(pml->buf.data,smb_mid) == mid) {
178 set_saved_ntstatus(NT_STATUS_OK);
185 /****************************************************************************
186 Return the message queued by this mid.
187 ****************************************************************************/
189 struct pending_message_list *get_open_deferred_message(uint16 mid)
191 struct pending_message_list *pml;
193 for (pml = deferred_open_queue; pml; pml = pml->next) {
194 if (SVAL(pml->buf.data,smb_mid) == mid) {
201 /****************************************************************************
202 Function to push a deferred open smb message onto a linked list of local smb
203 messages ready for processing.
204 ****************************************************************************/
206 BOOL push_deferred_smb_message(uint16 mid,
207 struct timeval request_time,
208 struct timeval timeout,
209 char *private_data, size_t priv_len)
211 struct timeval end_time;
213 end_time = timeval_sum(&request_time, &timeout);
215 DEBUG(10,("push_deferred_open_smb_message: pushing message len %u mid %u "
216 "timeout time [%u.%06u]\n",
217 (unsigned int) smb_len(current_inbuf)+4, (unsigned int)mid,
218 (unsigned int)end_time.tv_sec,
219 (unsigned int)end_time.tv_usec));
221 return push_queued_message(current_inbuf, smb_len(current_inbuf)+4,
222 request_time, end_time,
223 private_data, priv_len);
227 struct timed_event *te;
228 struct timeval interval;
229 BOOL (*handler)(const struct timeval *now, void *private_data);
233 static void idle_event_handler(struct timed_event *te,
234 const struct timeval *now,
237 struct idle_event *event =
238 talloc_get_type_abort(private_data, struct idle_event);
240 talloc_free(event->te);
242 if (!event->handler(now, event->private_data)) {
243 /* Don't repeat, delete ourselves */
248 event->te = add_timed_event(event, timeval_sum(now, &event->interval),
249 "idle_event_handler",
250 idle_event_handler, event);
252 /* We can't do much but fail here. */
253 SMB_ASSERT(event->te != NULL);
256 struct idle_event *add_idle_event(TALLOC_CTX *mem_ctx,
257 struct timeval interval,
258 BOOL (*handler)(const struct timeval *now,
262 struct idle_event *result;
263 struct timeval now = timeval_current();
265 result = TALLOC_P(mem_ctx, struct idle_event);
266 if (result == NULL) {
267 DEBUG(0, ("talloc failed\n"));
271 result->interval = interval;
272 result->handler = handler;
273 result->private_data = private_data;
275 result->te = add_timed_event(result, timeval_sum(&now, &interval),
276 "idle_event_handler",
277 idle_event_handler, result);
278 if (result->te == NULL) {
279 DEBUG(0, ("add_timed_event failed\n"));
287 /****************************************************************************
288 Do all async processing in here. This includes kernel oplock messages, change
290 ****************************************************************************/
292 static void async_processing(void)
294 DEBUG(10,("async_processing: Doing async processing.\n"));
298 process_kernel_oplocks();
300 /* Do the aio check again after receive_local_message as it does a
301 select and may have eaten our signal. */
302 /* Is this till true? -- vl */
306 exit_server("Caught TERM signal");
309 /* check for async change notify events */
310 process_pending_change_notify_queue(0);
312 /* check for sighup processing */
313 if (reload_after_sighup) {
314 change_to_root_user();
315 DEBUG(1,("Reloading services after SIGHUP\n"));
316 reload_services(False);
317 reload_after_sighup = 0;
321 /****************************************************************************
322 Do a select on an two fd's - with timeout.
324 If a local udp message has been pushed onto the
325 queue (this can only happen during oplock break
326 processing) call async_processing()
328 If a pending smb message has been pushed onto the
329 queue (this can only happen during oplock break
330 processing) return this next.
332 If the first smbfd is ready then read an smb from it.
333 if the second (loopback UDP) fd is ready then read a message
334 from it and setup the buffer header to identify the length
336 Returns False on timeout or error.
339 The timeout is in milliseconds
340 ****************************************************************************/
342 static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
346 struct timeval to = timeval_set(SMBD_SELECT_TIMEOUT, 0);
354 to.tv_sec = timeout / 1000;
355 to.tv_usec = (timeout % 1000) * 1000;
359 * Note that this call must be before processing any SMB
360 * messages as we need to synchronously process any messages
361 * we may have sent to ourselves from the previous SMB.
366 * Check to see if we already have a message on the deferred open queue
367 * and it's time to schedule.
369 if(deferred_open_queue != NULL) {
370 BOOL pop_message = False;
371 struct pending_message_list *msg = deferred_open_queue;
373 if (timeval_is_zero(&msg->end_time)) {
380 tdif = usec_time_diff(&msg->end_time, &tv);
382 /* Timed out. Schedule...*/
384 DEBUG(10,("receive_message_or_smb: queued message timed out.\n"));
386 /* Make a more accurate select timeout. */
387 to.tv_sec = tdif / 1000000;
388 to.tv_usec = tdif % 1000000;
389 DEBUG(10,("receive_message_or_smb: select with timeout of [%u.%06u]\n",
390 (unsigned int)to.tv_sec, (unsigned int)to.tv_usec ));
395 memcpy(buffer, msg->buf.data, MIN(buffer_len, msg->buf.length));
397 /* We leave this message on the queue so the open code can
398 know this is a retry. */
399 DEBUG(5,("receive_message_or_smb: returning deferred open smb message.\n"));
405 * Setup the select read fd set.
411 * Ensure we process oplock break messages by preference.
412 * We have to do this before the select, after the select
413 * and if the select returns EINTR. This is due to the fact
414 * that the selects called from async_processing can eat an EINTR
415 * caused by a signal (we can't take the break message there).
416 * This is hideously complex - *MUST* be simplified for 3.0 ! JRA.
419 if (oplock_message_waiting(&fds)) {
420 DEBUG(10,("receive_message_or_smb: oplock_message is waiting.\n"));
423 * After async processing we must go and do the select again, as
424 * the state of the flag in fds for the server file descriptor is
425 * indeterminate - we may have done I/O on it in the oplock processing. JRA.
432 struct timeval *tp = get_timed_events_timeout(&tmp,SMBD_SELECT_TIMEOUT);
434 to = timeval_min(&to, tp);
435 if (timeval_is_zero(&to)) {
440 FD_SET(smbd_server_fd(),&fds);
441 maxfd = setup_oplock_select_set(&fds);
443 selrtn = sys_select(MAX(maxfd,smbd_server_fd())+1,&fds,NULL,NULL,&to);
445 /* if we get EINTR then maybe we have received an oplock
446 signal - treat this as select returning 1. This is ugly, but
447 is the best we can do until the oplock code knows more about
449 if (selrtn == -1 && errno == EINTR) {
452 * After async processing we must go and do the select again, as
453 * the state of the flag in fds for the server file descriptor is
454 * indeterminate - we may have done I/O on it in the oplock processing. JRA.
461 /* something is wrong. Maybe the socket is dead? */
462 smb_read_error = READ_ERROR;
466 /* Did we timeout ? */
468 smb_read_error = READ_TIMEOUT;
473 * Ensure we process oplock break messages by preference.
474 * This is IMPORTANT ! Otherwise we can starve other processes
475 * sending us an oplock break message. JRA.
478 if (oplock_message_waiting(&fds)) {
481 * After async processing we must go and do the select again, as
482 * the state of the flag in fds for the server file descriptor is
483 * indeterminate - we may have done I/O on it in the oplock processing. JRA.
488 return receive_smb(smbd_server_fd(), buffer, 0);
491 /****************************************************************************
492 Get the next SMB packet, doing the local message processing automatically.
493 ****************************************************************************/
495 BOOL receive_next_smb(char *inbuf, int bufsize, int timeout)
501 ret = receive_message_or_smb(inbuf,bufsize,timeout);
503 got_keepalive = (ret && (CVAL(inbuf,0) == SMBkeepalive));
504 } while (ret && got_keepalive);
509 /****************************************************************************
510 We're terminating and have closed all our files/connections etc.
511 If there are any pending local messages we need to respond to them
512 before termination so that other smbds don't think we just died whilst
514 ****************************************************************************/
516 void respond_to_all_remaining_local_messages(void)
519 * Assert we have no exclusive open oplocks.
522 if(get_number_of_exclusive_open_oplocks()) {
523 DEBUG(0,("respond_to_all_remaining_local_messages: PANIC : we have %d exclusive oplocks.\n",
524 get_number_of_exclusive_open_oplocks() ));
528 process_kernel_oplocks();
535 These flags determine some of the permissions required to do an operation
537 Note that I don't set NEED_WRITE on some write operations because they
538 are used by some brain-dead clients when printing, and I don't want to
539 force write permissions on print services.
541 #define AS_USER (1<<0)
542 #define NEED_WRITE (1<<1)
543 #define TIME_INIT (1<<2)
544 #define CAN_IPC (1<<3)
545 #define AS_GUEST (1<<5)
546 #define DO_CHDIR (1<<6)
549 define a list of possible SMB messages and their corresponding
550 functions. Any message that has a NULL function is unimplemented -
551 please feel free to contribute implementations!
553 static const struct smb_message_struct {
555 int (*fn)(connection_struct *conn, char *, char *, int, int);
557 } smb_messages[256] = {
559 /* 0x00 */ { "SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
560 /* 0x01 */ { "SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
561 /* 0x02 */ { "SMBopen",reply_open,AS_USER },
562 /* 0x03 */ { "SMBcreate",reply_mknew,AS_USER},
563 /* 0x04 */ { "SMBclose",reply_close,AS_USER | CAN_IPC },
564 /* 0x05 */ { "SMBflush",reply_flush,AS_USER},
565 /* 0x06 */ { "SMBunlink",reply_unlink,AS_USER | NEED_WRITE },
566 /* 0x07 */ { "SMBmv",reply_mv,AS_USER | NEED_WRITE },
567 /* 0x08 */ { "SMBgetatr",reply_getatr,AS_USER},
568 /* 0x09 */ { "SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
569 /* 0x0a */ { "SMBread",reply_read,AS_USER},
570 /* 0x0b */ { "SMBwrite",reply_write,AS_USER | CAN_IPC },
571 /* 0x0c */ { "SMBlock",reply_lock,AS_USER},
572 /* 0x0d */ { "SMBunlock",reply_unlock,AS_USER},
573 /* 0x0e */ { "SMBctemp",reply_ctemp,AS_USER },
574 /* 0x0f */ { "SMBmknew",reply_mknew,AS_USER},
575 /* 0x10 */ { "SMBchkpth",reply_chkpth,AS_USER},
576 /* 0x11 */ { "SMBexit",reply_exit,DO_CHDIR},
577 /* 0x12 */ { "SMBlseek",reply_lseek,AS_USER},
578 /* 0x13 */ { "SMBlockread",reply_lockread,AS_USER},
579 /* 0x14 */ { "SMBwriteunlock",reply_writeunlock,AS_USER},
580 /* 0x15 */ { NULL, NULL, 0 },
581 /* 0x16 */ { NULL, NULL, 0 },
582 /* 0x17 */ { NULL, NULL, 0 },
583 /* 0x18 */ { NULL, NULL, 0 },
584 /* 0x19 */ { NULL, NULL, 0 },
585 /* 0x1a */ { "SMBreadbraw",reply_readbraw,AS_USER},
586 /* 0x1b */ { "SMBreadBmpx",reply_readbmpx,AS_USER},
587 /* 0x1c */ { "SMBreadBs",NULL,0 },
588 /* 0x1d */ { "SMBwritebraw",reply_writebraw,AS_USER},
589 /* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,AS_USER},
590 /* 0x1f */ { "SMBwriteBs",reply_writebs,AS_USER},
591 /* 0x20 */ { "SMBwritec",NULL,0},
592 /* 0x21 */ { NULL, NULL, 0 },
593 /* 0x22 */ { "SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE },
594 /* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER },
595 /* 0x24 */ { "SMBlockingX",reply_lockingX,AS_USER },
596 /* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC },
597 /* 0x26 */ { "SMBtranss",NULL,AS_USER | CAN_IPC},
598 /* 0x27 */ { "SMBioctl",reply_ioctl,0},
599 /* 0x28 */ { "SMBioctls",NULL,AS_USER},
600 /* 0x29 */ { "SMBcopy",reply_copy,AS_USER | NEED_WRITE },
601 /* 0x2a */ { "SMBmove",NULL,AS_USER | NEED_WRITE },
602 /* 0x2b */ { "SMBecho",reply_echo,0},
603 /* 0x2c */ { "SMBwriteclose",reply_writeclose,AS_USER},
604 /* 0x2d */ { "SMBopenX",reply_open_and_X,AS_USER | CAN_IPC },
605 /* 0x2e */ { "SMBreadX",reply_read_and_X,AS_USER | CAN_IPC },
606 /* 0x2f */ { "SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC },
607 /* 0x30 */ { NULL, NULL, 0 },
608 /* 0x31 */ { NULL, NULL, 0 },
609 /* 0x32 */ { "SMBtrans2", reply_trans2, AS_USER | CAN_IPC },
610 /* 0x33 */ { "SMBtranss2", reply_transs2, AS_USER},
611 /* 0x34 */ { "SMBfindclose", reply_findclose,AS_USER},
612 /* 0x35 */ { "SMBfindnclose", reply_findnclose, AS_USER},
613 /* 0x36 */ { NULL, NULL, 0 },
614 /* 0x37 */ { NULL, NULL, 0 },
615 /* 0x38 */ { NULL, NULL, 0 },
616 /* 0x39 */ { NULL, NULL, 0 },
617 /* 0x3a */ { NULL, NULL, 0 },
618 /* 0x3b */ { NULL, NULL, 0 },
619 /* 0x3c */ { NULL, NULL, 0 },
620 /* 0x3d */ { NULL, NULL, 0 },
621 /* 0x3e */ { NULL, NULL, 0 },
622 /* 0x3f */ { NULL, NULL, 0 },
623 /* 0x40 */ { NULL, NULL, 0 },
624 /* 0x41 */ { NULL, NULL, 0 },
625 /* 0x42 */ { NULL, NULL, 0 },
626 /* 0x43 */ { NULL, NULL, 0 },
627 /* 0x44 */ { NULL, NULL, 0 },
628 /* 0x45 */ { NULL, NULL, 0 },
629 /* 0x46 */ { NULL, NULL, 0 },
630 /* 0x47 */ { NULL, NULL, 0 },
631 /* 0x48 */ { NULL, NULL, 0 },
632 /* 0x49 */ { NULL, NULL, 0 },
633 /* 0x4a */ { NULL, NULL, 0 },
634 /* 0x4b */ { NULL, NULL, 0 },
635 /* 0x4c */ { NULL, NULL, 0 },
636 /* 0x4d */ { NULL, NULL, 0 },
637 /* 0x4e */ { NULL, NULL, 0 },
638 /* 0x4f */ { NULL, NULL, 0 },
639 /* 0x50 */ { NULL, NULL, 0 },
640 /* 0x51 */ { NULL, NULL, 0 },
641 /* 0x52 */ { NULL, NULL, 0 },
642 /* 0x53 */ { NULL, NULL, 0 },
643 /* 0x54 */ { NULL, NULL, 0 },
644 /* 0x55 */ { NULL, NULL, 0 },
645 /* 0x56 */ { NULL, NULL, 0 },
646 /* 0x57 */ { NULL, NULL, 0 },
647 /* 0x58 */ { NULL, NULL, 0 },
648 /* 0x59 */ { NULL, NULL, 0 },
649 /* 0x5a */ { NULL, NULL, 0 },
650 /* 0x5b */ { NULL, NULL, 0 },
651 /* 0x5c */ { NULL, NULL, 0 },
652 /* 0x5d */ { NULL, NULL, 0 },
653 /* 0x5e */ { NULL, NULL, 0 },
654 /* 0x5f */ { NULL, NULL, 0 },
655 /* 0x60 */ { NULL, NULL, 0 },
656 /* 0x61 */ { NULL, NULL, 0 },
657 /* 0x62 */ { NULL, NULL, 0 },
658 /* 0x63 */ { NULL, NULL, 0 },
659 /* 0x64 */ { NULL, NULL, 0 },
660 /* 0x65 */ { NULL, NULL, 0 },
661 /* 0x66 */ { NULL, NULL, 0 },
662 /* 0x67 */ { NULL, NULL, 0 },
663 /* 0x68 */ { NULL, NULL, 0 },
664 /* 0x69 */ { NULL, NULL, 0 },
665 /* 0x6a */ { NULL, NULL, 0 },
666 /* 0x6b */ { NULL, NULL, 0 },
667 /* 0x6c */ { NULL, NULL, 0 },
668 /* 0x6d */ { NULL, NULL, 0 },
669 /* 0x6e */ { NULL, NULL, 0 },
670 /* 0x6f */ { NULL, NULL, 0 },
671 /* 0x70 */ { "SMBtcon",reply_tcon,0},
672 /* 0x71 */ { "SMBtdis",reply_tdis,DO_CHDIR},
673 /* 0x72 */ { "SMBnegprot",reply_negprot,0},
674 /* 0x73 */ { "SMBsesssetupX",reply_sesssetup_and_X,0},
675 /* 0x74 */ { "SMBulogoffX", reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
676 /* 0x75 */ { "SMBtconX",reply_tcon_and_X,0},
677 /* 0x76 */ { NULL, NULL, 0 },
678 /* 0x77 */ { NULL, NULL, 0 },
679 /* 0x78 */ { NULL, NULL, 0 },
680 /* 0x79 */ { NULL, NULL, 0 },
681 /* 0x7a */ { NULL, NULL, 0 },
682 /* 0x7b */ { NULL, NULL, 0 },
683 /* 0x7c */ { NULL, NULL, 0 },
684 /* 0x7d */ { NULL, NULL, 0 },
685 /* 0x7e */ { NULL, NULL, 0 },
686 /* 0x7f */ { NULL, NULL, 0 },
687 /* 0x80 */ { "SMBdskattr",reply_dskattr,AS_USER},
688 /* 0x81 */ { "SMBsearch",reply_search,AS_USER},
689 /* 0x82 */ { "SMBffirst",reply_search,AS_USER},
690 /* 0x83 */ { "SMBfunique",reply_search,AS_USER},
691 /* 0x84 */ { "SMBfclose",reply_fclose,AS_USER},
692 /* 0x85 */ { NULL, NULL, 0 },
693 /* 0x86 */ { NULL, NULL, 0 },
694 /* 0x87 */ { NULL, NULL, 0 },
695 /* 0x88 */ { NULL, NULL, 0 },
696 /* 0x89 */ { NULL, NULL, 0 },
697 /* 0x8a */ { NULL, NULL, 0 },
698 /* 0x8b */ { NULL, NULL, 0 },
699 /* 0x8c */ { NULL, NULL, 0 },
700 /* 0x8d */ { NULL, NULL, 0 },
701 /* 0x8e */ { NULL, NULL, 0 },
702 /* 0x8f */ { NULL, NULL, 0 },
703 /* 0x90 */ { NULL, NULL, 0 },
704 /* 0x91 */ { NULL, NULL, 0 },
705 /* 0x92 */ { NULL, NULL, 0 },
706 /* 0x93 */ { NULL, NULL, 0 },
707 /* 0x94 */ { NULL, NULL, 0 },
708 /* 0x95 */ { NULL, NULL, 0 },
709 /* 0x96 */ { NULL, NULL, 0 },
710 /* 0x97 */ { NULL, NULL, 0 },
711 /* 0x98 */ { NULL, NULL, 0 },
712 /* 0x99 */ { NULL, NULL, 0 },
713 /* 0x9a */ { NULL, NULL, 0 },
714 /* 0x9b */ { NULL, NULL, 0 },
715 /* 0x9c */ { NULL, NULL, 0 },
716 /* 0x9d */ { NULL, NULL, 0 },
717 /* 0x9e */ { NULL, NULL, 0 },
718 /* 0x9f */ { NULL, NULL, 0 },
719 /* 0xa0 */ { "SMBnttrans", reply_nttrans, AS_USER | CAN_IPC },
720 /* 0xa1 */ { "SMBnttranss", reply_nttranss, AS_USER | CAN_IPC },
721 /* 0xa2 */ { "SMBntcreateX", reply_ntcreate_and_X, AS_USER | CAN_IPC },
722 /* 0xa3 */ { NULL, NULL, 0 },
723 /* 0xa4 */ { "SMBntcancel", reply_ntcancel, 0 },
724 /* 0xa5 */ { "SMBntrename", reply_ntrename, AS_USER | NEED_WRITE },
725 /* 0xa6 */ { NULL, NULL, 0 },
726 /* 0xa7 */ { NULL, NULL, 0 },
727 /* 0xa8 */ { NULL, NULL, 0 },
728 /* 0xa9 */ { NULL, NULL, 0 },
729 /* 0xaa */ { NULL, NULL, 0 },
730 /* 0xab */ { NULL, NULL, 0 },
731 /* 0xac */ { NULL, NULL, 0 },
732 /* 0xad */ { NULL, NULL, 0 },
733 /* 0xae */ { NULL, NULL, 0 },
734 /* 0xaf */ { NULL, NULL, 0 },
735 /* 0xb0 */ { NULL, NULL, 0 },
736 /* 0xb1 */ { NULL, NULL, 0 },
737 /* 0xb2 */ { NULL, NULL, 0 },
738 /* 0xb3 */ { NULL, NULL, 0 },
739 /* 0xb4 */ { NULL, NULL, 0 },
740 /* 0xb5 */ { NULL, NULL, 0 },
741 /* 0xb6 */ { NULL, NULL, 0 },
742 /* 0xb7 */ { NULL, NULL, 0 },
743 /* 0xb8 */ { NULL, NULL, 0 },
744 /* 0xb9 */ { NULL, NULL, 0 },
745 /* 0xba */ { NULL, NULL, 0 },
746 /* 0xbb */ { NULL, NULL, 0 },
747 /* 0xbc */ { NULL, NULL, 0 },
748 /* 0xbd */ { NULL, NULL, 0 },
749 /* 0xbe */ { NULL, NULL, 0 },
750 /* 0xbf */ { NULL, NULL, 0 },
751 /* 0xc0 */ { "SMBsplopen",reply_printopen,AS_USER},
752 /* 0xc1 */ { "SMBsplwr",reply_printwrite,AS_USER},
753 /* 0xc2 */ { "SMBsplclose",reply_printclose,AS_USER},
754 /* 0xc3 */ { "SMBsplretq",reply_printqueue,AS_USER},
755 /* 0xc4 */ { NULL, NULL, 0 },
756 /* 0xc5 */ { NULL, NULL, 0 },
757 /* 0xc6 */ { NULL, NULL, 0 },
758 /* 0xc7 */ { NULL, NULL, 0 },
759 /* 0xc8 */ { NULL, NULL, 0 },
760 /* 0xc9 */ { NULL, NULL, 0 },
761 /* 0xca */ { NULL, NULL, 0 },
762 /* 0xcb */ { NULL, NULL, 0 },
763 /* 0xcc */ { NULL, NULL, 0 },
764 /* 0xcd */ { NULL, NULL, 0 },
765 /* 0xce */ { NULL, NULL, 0 },
766 /* 0xcf */ { NULL, NULL, 0 },
767 /* 0xd0 */ { "SMBsends",reply_sends,AS_GUEST},
768 /* 0xd1 */ { "SMBsendb",NULL,AS_GUEST},
769 /* 0xd2 */ { "SMBfwdname",NULL,AS_GUEST},
770 /* 0xd3 */ { "SMBcancelf",NULL,AS_GUEST},
771 /* 0xd4 */ { "SMBgetmac",NULL,AS_GUEST},
772 /* 0xd5 */ { "SMBsendstrt",reply_sendstrt,AS_GUEST},
773 /* 0xd6 */ { "SMBsendend",reply_sendend,AS_GUEST},
774 /* 0xd7 */ { "SMBsendtxt",reply_sendtxt,AS_GUEST},
775 /* 0xd8 */ { NULL, NULL, 0 },
776 /* 0xd9 */ { NULL, NULL, 0 },
777 /* 0xda */ { NULL, NULL, 0 },
778 /* 0xdb */ { NULL, NULL, 0 },
779 /* 0xdc */ { NULL, NULL, 0 },
780 /* 0xdd */ { NULL, NULL, 0 },
781 /* 0xde */ { NULL, NULL, 0 },
782 /* 0xdf */ { NULL, NULL, 0 },
783 /* 0xe0 */ { NULL, NULL, 0 },
784 /* 0xe1 */ { NULL, NULL, 0 },
785 /* 0xe2 */ { NULL, NULL, 0 },
786 /* 0xe3 */ { NULL, NULL, 0 },
787 /* 0xe4 */ { NULL, NULL, 0 },
788 /* 0xe5 */ { NULL, NULL, 0 },
789 /* 0xe6 */ { NULL, NULL, 0 },
790 /* 0xe7 */ { NULL, NULL, 0 },
791 /* 0xe8 */ { NULL, NULL, 0 },
792 /* 0xe9 */ { NULL, NULL, 0 },
793 /* 0xea */ { NULL, NULL, 0 },
794 /* 0xeb */ { NULL, NULL, 0 },
795 /* 0xec */ { NULL, NULL, 0 },
796 /* 0xed */ { NULL, NULL, 0 },
797 /* 0xee */ { NULL, NULL, 0 },
798 /* 0xef */ { NULL, NULL, 0 },
799 /* 0xf0 */ { NULL, NULL, 0 },
800 /* 0xf1 */ { NULL, NULL, 0 },
801 /* 0xf2 */ { NULL, NULL, 0 },
802 /* 0xf3 */ { NULL, NULL, 0 },
803 /* 0xf4 */ { NULL, NULL, 0 },
804 /* 0xf5 */ { NULL, NULL, 0 },
805 /* 0xf6 */ { NULL, NULL, 0 },
806 /* 0xf7 */ { NULL, NULL, 0 },
807 /* 0xf8 */ { NULL, NULL, 0 },
808 /* 0xf9 */ { NULL, NULL, 0 },
809 /* 0xfa */ { NULL, NULL, 0 },
810 /* 0xfb */ { NULL, NULL, 0 },
811 /* 0xfc */ { NULL, NULL, 0 },
812 /* 0xfd */ { NULL, NULL, 0 },
813 /* 0xfe */ { NULL, NULL, 0 },
814 /* 0xff */ { NULL, NULL, 0 }
818 /*******************************************************************
819 Dump a packet to a file.
820 ********************************************************************/
822 static void smb_dump(const char *name, int type, char *data, ssize_t len)
826 if (DEBUGLEVEL < 50) return;
828 if (len < 4) len = smb_len(data)+4;
829 for (i=1;i<100;i++) {
830 slprintf(fname,sizeof(fname)-1, "/tmp/%s.%d.%s", name, i,
831 type ? "req" : "resp");
832 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644);
833 if (fd != -1 || errno != EEXIST) break;
836 ssize_t ret = write(fd, data, len);
838 DEBUG(0,("smb_dump: problem: write returned %d\n", (int)ret ));
840 DEBUG(0,("created %s len %lu\n", fname, (unsigned long)len));
845 /****************************************************************************
846 Do a switch on the message type, and return the response size
847 ****************************************************************************/
849 static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize)
851 static pid_t pid= (pid_t)-1;
856 if (pid == (pid_t)-1)
860 set_saved_ntstatus(NT_STATUS_OK);
864 /* Make sure this is an SMB packet. smb_size contains NetBIOS header so subtract 4 from it. */
865 if ((strncmp(smb_base(inbuf),"\377SMB",4) != 0) || (size < (smb_size - 4))) {
866 DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",smb_len(inbuf)));
867 exit_server("Non-SMB packet");
871 /* yuck! this is an interim measure before we get rid of our
872 current inbuf/outbuf system */
873 global_smbpid = SVAL(inbuf,smb_pid);
875 if (smb_messages[type].fn == NULL) {
876 DEBUG(0,("Unknown message type %d!\n",type));
877 smb_dump("Unknown", 1, inbuf, size);
878 outsize = reply_unknown(inbuf,outbuf);
880 int flags = smb_messages[type].flags;
881 static uint16 last_session_tag = UID_FIELD_INVALID;
882 /* In share mode security we must ignore the vuid. */
883 uint16 session_tag = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(inbuf,smb_uid);
884 connection_struct *conn = conn_find(SVAL(inbuf,smb_tid));
886 DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n",smb_fn_name(type),(int)pid,(unsigned long)conn));
888 smb_dump(smb_fn_name(type), 1, inbuf, size);
890 /* Ensure this value is replaced in the incoming packet. */
891 SSVAL(inbuf,smb_uid,session_tag);
894 * Ensure the correct username is in current_user_info.
895 * This is a really ugly bugfix for problems with
896 * multiple session_setup_and_X's being done and
897 * allowing %U and %G substitutions to work correctly.
898 * There is a reason this code is done here, don't
899 * move it unless you know what you're doing... :-).
903 if (session_tag != last_session_tag) {
904 user_struct *vuser = NULL;
906 last_session_tag = session_tag;
907 if(session_tag != UID_FIELD_INVALID)
908 vuser = get_valid_user_struct(session_tag);
910 set_current_user_info(&vuser->user);
913 /* does this protocol need to be run as root? */
914 if (!(flags & AS_USER))
915 change_to_root_user();
917 /* does this protocol need a valid tree connection? */
918 if ((flags & AS_USER) && !conn) {
919 /* Amazingly, the error code depends on the command (from Samba4). */
920 if (type == SMBntcreateX) {
921 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
923 return ERROR_DOS(ERRSRV, ERRinvnid);
928 /* does this protocol need to be run as the connected user? */
929 if ((flags & AS_USER) && !change_to_user(conn,session_tag)) {
930 if (flags & AS_GUEST)
933 return(ERROR_FORCE_DOS(ERRSRV,ERRbaduid));
936 /* this code is to work around a bug is MS client 3 without
937 introducing a security hole - it needs to be able to do
938 print queue checks as guest if it isn't logged in properly */
942 /* does it need write permission? */
943 if ((flags & NEED_WRITE) && !CAN_WRITE(conn))
944 return(ERROR_DOS(ERRSRV,ERRaccess));
946 /* ipc services are limited */
947 if (IS_IPC(conn) && (flags & AS_USER) && !(flags & CAN_IPC))
948 return(ERROR_DOS(ERRSRV,ERRaccess));
950 /* load service specific parameters */
952 if (!set_current_service(conn,SVAL(inbuf,smb_flg),(flags & (AS_USER|DO_CHDIR)?True:False))) {
953 return(ERROR_DOS(ERRSRV,ERRaccess));
955 conn->num_smb_operations++;
958 /* does this protocol need to be run as guest? */
959 if ((flags & AS_GUEST) && (!change_to_guest() ||
960 !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1))))
961 return(ERROR_DOS(ERRSRV,ERRaccess));
963 current_inbuf = inbuf; /* In case we need to defer this message in open... */
964 outsize = smb_messages[type].fn(conn, inbuf,outbuf,size,bufsize);
967 smb_dump(smb_fn_name(type), 0, outbuf, outsize);
973 /****************************************************************************
974 Construct a reply to the incoming packet.
975 ****************************************************************************/
977 static int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
979 int type = CVAL(inbuf,smb_com);
981 int msg_type = CVAL(inbuf,0);
983 GetTimeOfDay(&smb_last_time);
990 return(reply_special(inbuf,outbuf));
992 construct_reply_common(inbuf, outbuf);
994 outsize = switch_message(type,inbuf,outbuf,size,bufsize);
996 outsize += chain_size;
999 smb_setlen(outbuf,outsize - 4);
1003 /****************************************************************************
1004 Keep track of the number of running smbd's. This functionality is used to
1005 'hard' limit Samba overhead on resource constrained systems.
1006 ****************************************************************************/
1008 static BOOL process_count_update_successful = False;
1010 static int32 increment_smbd_process_count(void)
1014 if (lp_max_smbd_processes()) {
1016 if (tdb_change_int32_atomic(conn_tdb_ctx(), "INFO/total_smbds", &total_smbds, 1) == -1)
1018 process_count_update_successful = True;
1019 return total_smbds + 1;
1024 void decrement_smbd_process_count(void)
1028 if (lp_max_smbd_processes() && process_count_update_successful) {
1030 tdb_change_int32_atomic(conn_tdb_ctx(), "INFO/total_smbds", &total_smbds, -1);
1034 static BOOL smbd_process_limit(void)
1038 if (lp_max_smbd_processes()) {
1040 /* Always add one to the smbd process count, as exit_server() always
1044 if (!conn_tdb_ctx()) {
1045 DEBUG(0,("smbd_process_limit: max smbd processes parameter set with status parameter not \
1046 set. Ignoring max smbd restriction.\n"));
1050 total_smbds = increment_smbd_process_count();
1051 return total_smbds > lp_max_smbd_processes();
1057 /****************************************************************************
1058 Process an smb from the client - split out from the smbd_process() code so
1059 it can be used by the oplock break code.
1060 ****************************************************************************/
1062 void process_smb(char *inbuf, char *outbuf)
1064 static int trans_num;
1065 int msg_type = CVAL(inbuf,0);
1066 int32 len = smb_len(inbuf);
1067 int nread = len + 4;
1069 DO_PROFILE_INC(smb_count);
1071 if (trans_num == 0) {
1072 /* on the first packet, check the global hosts allow/ hosts
1073 deny parameters before doing any parsing of the packet
1074 passed to us by the client. This prevents attacks on our
1075 parsing code from hosts not in the hosts allow list */
1076 if (smbd_process_limit() ||
1077 !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1))) {
1078 /* send a negative session response "not listening on calling name" */
1079 static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
1080 DEBUG( 1, ( "Connection denied from %s\n", client_addr() ) );
1081 (void)send_smb(smbd_server_fd(),(char *)buf);
1082 exit_server("connection denied");
1086 DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type, len ) );
1087 DEBUG( 3, ( "Transaction %d of length %d\n", trans_num, nread ) );
1091 else if(msg_type == SMBkeepalive)
1092 return; /* Keepalive packet. */
1094 nread = construct_reply(inbuf,outbuf,nread,max_send);
1097 if (CVAL(outbuf,0) == 0)
1100 if (nread != smb_len(outbuf) + 4) {
1101 DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
1102 nread, smb_len(outbuf)));
1103 } else if (!send_smb(smbd_server_fd(),outbuf)) {
1104 exit_server("process_smb: send_smb failed.");
1110 /****************************************************************************
1111 Return a string containing the function name of a SMB command.
1112 ****************************************************************************/
1114 const char *smb_fn_name(int type)
1116 const char *unknown_name = "SMBunknown";
1118 if (smb_messages[type].name == NULL)
1119 return(unknown_name);
1121 return(smb_messages[type].name);
1124 /****************************************************************************
1125 Helper functions for contruct_reply.
1126 ****************************************************************************/
1128 static uint32 common_flags2 = FLAGS2_LONG_PATH_COMPONENTS|FLAGS2_32_BIT_ERROR_CODES;
1130 void add_to_common_flags2(uint32 v)
1135 void remove_from_common_flags2(uint32 v)
1137 common_flags2 &= ~v;
1140 void construct_reply_common(char *inbuf,char *outbuf)
1142 memset(outbuf,'\0',smb_size);
1144 set_message(outbuf,0,0,True);
1145 SCVAL(outbuf,smb_com,CVAL(inbuf,smb_com));
1147 memcpy(outbuf+4,inbuf+4,4);
1148 SCVAL(outbuf,smb_rcls,SMB_SUCCESS);
1149 SCVAL(outbuf,smb_reh,0);
1150 SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES));
1151 SSVAL(outbuf,smb_flg2,
1152 (SVAL(inbuf,smb_flg2) & FLAGS2_UNICODE_STRINGS) |
1155 SSVAL(outbuf,smb_err,SMB_SUCCESS);
1156 SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
1157 SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
1158 SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
1159 SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
1162 /****************************************************************************
1163 Construct a chained reply and add it to the already made reply
1164 ****************************************************************************/
1166 int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
1168 static char *orig_inbuf;
1169 static char *orig_outbuf;
1170 int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0);
1171 unsigned smb_off2 = SVAL(inbuf,smb_vwv1);
1172 char *inbuf2, *outbuf2;
1174 char inbuf_saved[smb_wct];
1175 char outbuf_saved[smb_wct];
1176 int outsize = smb_len(outbuf) + 4;
1178 /* maybe its not chained */
1179 if (smb_com2 == 0xFF) {
1180 SCVAL(outbuf,smb_vwv0,0xFF);
1184 if (chain_size == 0) {
1185 /* this is the first part of the chain */
1187 orig_outbuf = outbuf;
1191 * The original Win95 redirector dies on a reply to
1192 * a lockingX and read chain unless the chain reply is
1193 * 4 byte aligned. JRA.
1196 outsize = (outsize + 3) & ~3;
1198 /* we need to tell the client where the next part of the reply will be */
1199 SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf));
1200 SCVAL(outbuf,smb_vwv0,smb_com2);
1202 /* remember how much the caller added to the chain, only counting stuff
1203 after the parameter words */
1204 chain_size += outsize - smb_wct;
1206 /* work out pointers into the original packets. The
1207 headers on these need to be filled in */
1208 inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct;
1209 outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct;
1211 /* remember the original command type */
1212 smb_com1 = CVAL(orig_inbuf,smb_com);
1214 /* save the data which will be overwritten by the new headers */
1215 memcpy(inbuf_saved,inbuf2,smb_wct);
1216 memcpy(outbuf_saved,outbuf2,smb_wct);
1218 /* give the new packet the same header as the last part of the SMB */
1219 memmove(inbuf2,inbuf,smb_wct);
1221 /* create the in buffer */
1222 SCVAL(inbuf2,smb_com,smb_com2);
1224 /* create the out buffer */
1225 construct_reply_common(inbuf2, outbuf2);
1227 DEBUG(3,("Chained message\n"));
1230 /* process the request */
1231 outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size,
1232 bufsize-chain_size);
1234 /* copy the new reply and request headers over the old ones, but
1235 preserve the smb_com field */
1236 memmove(orig_outbuf,outbuf2,smb_wct);
1237 SCVAL(orig_outbuf,smb_com,smb_com1);
1239 /* restore the saved data, being careful not to overwrite any
1240 data from the reply header */
1241 memcpy(inbuf2,inbuf_saved,smb_wct);
1244 int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf);
1245 if (ofs < 0) ofs = 0;
1246 memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs);
1252 /****************************************************************************
1253 Setup the needed select timeout.
1254 ****************************************************************************/
1256 static int setup_select_timeout(void)
1261 select_timeout = blocking_locks_timeout(SMBD_SELECT_TIMEOUT);
1262 select_timeout *= 1000;
1264 t = change_notify_timeout();
1265 DEBUG(10, ("change_notify_timeout: %d\n", t));
1267 select_timeout = MIN(select_timeout, t*1000);
1269 if (print_notify_messages_pending())
1270 select_timeout = MIN(select_timeout, 1000);
1272 return select_timeout;
1275 /****************************************************************************
1276 Check if services need reloading.
1277 ****************************************************************************/
1279 void check_reload(time_t t)
1281 static pid_t mypid = 0;
1282 static time_t last_smb_conf_reload_time = 0;
1283 static time_t last_printer_reload_time = 0;
1284 time_t printcap_cache_time = (time_t)lp_printcap_cache_time();
1286 if(last_smb_conf_reload_time == 0) {
1287 last_smb_conf_reload_time = t;
1288 /* Our printing subsystem might not be ready at smbd start up.
1289 Then no printer is available till the first printers check
1290 is performed. A lower initial interval circumvents this. */
1291 if ( printcap_cache_time > 60 )
1292 last_printer_reload_time = t - printcap_cache_time + 60;
1294 last_printer_reload_time = t;
1297 if (mypid != getpid()) { /* First time or fork happened meanwhile */
1298 /* randomize over 60 second the printcap reload to avoid all
1299 * process hitting cupsd at the same time */
1300 int time_range = 60;
1302 last_printer_reload_time += random() % time_range;
1306 if (reload_after_sighup || (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK)) {
1307 reload_services(True);
1308 reload_after_sighup = False;
1309 last_smb_conf_reload_time = t;
1312 /* 'printcap cache time = 0' disable the feature */
1314 if ( printcap_cache_time != 0 )
1316 /* see if it's time to reload or if the clock has been set back */
1318 if ( (t >= last_printer_reload_time+printcap_cache_time)
1319 || (t-last_printer_reload_time < 0) )
1321 DEBUG( 3,( "Printcap cache time expired.\n"));
1323 last_printer_reload_time = t;
1328 /****************************************************************************
1329 Process any timeout housekeeping. Return False if the caller should exit.
1330 ****************************************************************************/
1332 static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_timeout_processing_time)
1334 static time_t last_keepalive_sent_time = 0;
1335 static time_t last_idle_closed_check = 0;
1337 BOOL allidle = True;
1339 if (smb_read_error == READ_EOF) {
1340 DEBUG(3,("timeout_processing: End of file from client (client has disconnected).\n"));
1344 if (smb_read_error == READ_ERROR) {
1345 DEBUG(3,("timeout_processing: receive_smb error (%s) Exiting\n",
1350 if (smb_read_error == READ_BAD_SIG) {
1351 DEBUG(3,("timeout_processing: receive_smb error bad smb signature. Exiting\n"));
1355 *last_timeout_processing_time = t = time(NULL);
1357 if(last_keepalive_sent_time == 0)
1358 last_keepalive_sent_time = t;
1360 if(last_idle_closed_check == 0)
1361 last_idle_closed_check = t;
1363 /* become root again if waiting */
1364 change_to_root_user();
1366 /* run all registered idle events */
1367 smb_run_idle_events(t);
1369 /* check if we need to reload services */
1372 /* automatic timeout if all connections are closed */
1373 if (conn_num_open()==0 && (t - last_idle_closed_check) >= IDLE_CLOSED_TIMEOUT) {
1374 DEBUG( 2, ( "Closing idle connection\n" ) );
1377 last_idle_closed_check = t;
1380 if (keepalive && (t - last_keepalive_sent_time)>keepalive) {
1381 if (!send_keepalive(smbd_server_fd())) {
1382 DEBUG( 2, ( "Keepalive failed - exiting.\n" ) );
1386 /* send a keepalive for a password server or the like.
1387 This is attached to the auth_info created in the
1389 if (negprot_global_auth_context && negprot_global_auth_context->challenge_set_method
1390 && negprot_global_auth_context->challenge_set_method->send_keepalive) {
1392 negprot_global_auth_context->challenge_set_method->send_keepalive
1393 (&negprot_global_auth_context->challenge_set_method->private_data);
1396 last_keepalive_sent_time = t;
1399 /* check for connection timeouts */
1400 allidle = conn_idle_all(t, deadtime);
1402 if (allidle && conn_num_open()>0) {
1403 DEBUG(2,("Closing idle connection 2.\n"));
1407 if(global_machine_password_needs_changing &&
1408 /* for ADS we need to do a regular ADS password change, not a domain
1410 lp_security() == SEC_DOMAIN) {
1412 unsigned char trust_passwd_hash[16];
1416 * We're in domain level security, and the code that
1417 * read the machine password flagged that the machine
1418 * password needs changing.
1422 * First, open the machine password file with an exclusive lock.
1425 if (secrets_lock_trust_account_password(lp_workgroup(), True) == False) {
1426 DEBUG(0,("process: unable to lock the machine account password for \
1427 machine %s in domain %s.\n", global_myname(), lp_workgroup() ));
1431 if(!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd_hash, &lct, NULL)) {
1432 DEBUG(0,("process: unable to read the machine account password for \
1433 machine %s in domain %s.\n", global_myname(), lp_workgroup()));
1434 secrets_lock_trust_account_password(lp_workgroup(), False);
1439 * Make sure someone else hasn't already done this.
1442 if(t < lct + lp_machine_password_timeout()) {
1443 global_machine_password_needs_changing = False;
1444 secrets_lock_trust_account_password(lp_workgroup(), False);
1448 /* always just contact the PDC here */
1450 change_trust_account_password( lp_workgroup(), NULL);
1451 global_machine_password_needs_changing = False;
1452 secrets_lock_trust_account_password(lp_workgroup(), False);
1456 * Check to see if we have any blocking locks
1457 * outstanding on the queue.
1459 process_blocking_lock_queue(t);
1461 /* update printer queue caches if necessary */
1463 update_monitored_printq_cache();
1466 * Check to see if we have any change notifies
1467 * outstanding on the queue.
1469 process_pending_change_notify_queue(t);
1472 * Now we are root, check if the log files need pruning.
1473 * Force a log file check.
1475 force_check_log_size();
1478 /* Send any queued printer notify message to interested smbd's. */
1480 print_notify_send_messages(0);
1483 * Modify the select timeout depending upon
1484 * what we have remaining in our queues.
1487 *select_timeout = setup_select_timeout();
1492 /****************************************************************************
1493 Accessor functions for InBuffer, OutBuffer.
1494 ****************************************************************************/
1496 char *get_InBuffer(void)
1501 void set_InBuffer(char *new_inbuf)
1503 InBuffer = new_inbuf;
1504 current_inbuf = InBuffer;
1507 char *get_OutBuffer(void)
1512 void set_OutBuffer(char *new_outbuf)
1514 OutBuffer = new_outbuf;
1517 /****************************************************************************
1518 Free an InBuffer. Checks if not in use by aio system.
1519 Must have been allocated by NewInBuffer.
1520 ****************************************************************************/
1522 void free_InBuffer(char *inbuf)
1524 if (!aio_inbuffer_in_use(inbuf)) {
1525 if (current_inbuf == inbuf) {
1526 current_inbuf = NULL;
1532 /****************************************************************************
1533 Free an OutBuffer. No outbuffers currently stolen by aio system.
1534 Must have been allocated by NewInBuffer.
1535 ****************************************************************************/
1537 void free_OutBuffer(char *outbuf)
1542 const int total_buffer_size = (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN);
1544 /****************************************************************************
1545 Allocate a new InBuffer. Returns the new and old ones.
1546 ****************************************************************************/
1548 char *NewInBuffer(char **old_inbuf)
1550 char *new_inbuf = (char *)SMB_MALLOC(total_buffer_size);
1555 *old_inbuf = InBuffer;
1557 InBuffer = new_inbuf;
1558 #if defined(DEVELOPER)
1559 clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size);
1564 /****************************************************************************
1565 Allocate a new OutBuffer. Returns the new and old ones.
1566 ****************************************************************************/
1568 char *NewOutBuffer(char **old_outbuf)
1570 char *new_outbuf = (char *)SMB_MALLOC(total_buffer_size);
1575 *old_outbuf = OutBuffer;
1577 OutBuffer = new_outbuf;
1578 #if defined(DEVELOPER)
1579 clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer, total_buffer_size);
1584 /****************************************************************************
1585 Process commands from the client
1586 ****************************************************************************/
1588 void smbd_process(void)
1590 time_t last_timeout_processing_time = time(NULL);
1591 unsigned int num_smbs = 0;
1593 /* Allocate the primary Inbut/Output buffers. */
1595 if ((NewInBuffer(NULL) == NULL) || (NewOutBuffer(NULL) == NULL))
1598 max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
1601 int deadtime = lp_deadtime()*60;
1602 int select_timeout = setup_select_timeout();
1606 deadtime = DEFAULT_SMBD_TIMEOUT;
1610 /* free up temporary memory */
1612 main_loop_talloc_free();
1614 /* Did someone ask for immediate checks on things like blocking locks ? */
1615 if (select_timeout == 0) {
1616 if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1618 num_smbs = 0; /* Reset smb counter. */
1623 #if defined(DEVELOPER)
1624 clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size);
1627 while (!receive_message_or_smb(InBuffer,BUFFER_SIZE+LARGE_WRITEX_HDR_SIZE,select_timeout)) {
1628 if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1630 num_smbs = 0; /* Reset smb counter. */
1634 * Ensure we do timeout processing if the SMB we just got was
1635 * only an echo request. This allows us to set the select
1636 * timeout in 'receive_message_or_smb()' to any value we like
1637 * without worrying that the client will send echo requests
1638 * faster than the select timeout, thus starving out the
1639 * essential processing (change notify, blocking locks) that
1640 * the timeout code does. JRA.
1642 num_echos = smb_echo_count;
1644 clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer, total_buffer_size);
1646 process_smb(InBuffer, OutBuffer);
1648 if (smb_echo_count != num_echos) {
1649 if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1651 num_smbs = 0; /* Reset smb counter. */
1657 * If we are getting smb requests in a constant stream
1658 * with no echos, make sure we attempt timeout processing
1659 * every select_timeout milliseconds - but only check for this
1660 * every 200 smb requests.
1663 if ((num_smbs % 200) == 0) {
1664 time_t new_check_time = time(NULL);
1665 if(new_check_time - last_timeout_processing_time >= (select_timeout/1000)) {
1666 if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1668 num_smbs = 0; /* Reset smb counter. */
1669 last_timeout_processing_time = new_check_time; /* Reset time. */
1673 /* The timeout_processing function isn't run nearly
1674 often enough to implement 'max log size' without
1675 overrunning the size of the file by many megabytes.
1676 This is especially true if we are running at debug
1677 level 10. Checking every 50 SMBs is a nice
1678 tradeoff of performance vs log file size overrun. */
1680 if ((num_smbs % 50) == 0 && need_to_check_log_size()) {
1681 change_to_root_user();