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 3 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, see <http://www.gnu.org/licenses/>.
24 extern struct auth_context *negprot_global_auth_context;
25 extern int smb_echo_count;
27 static char *InBuffer = NULL;
28 static char *OutBuffer = NULL;
29 static char *current_inbuf = NULL;
32 * Size of data we can send to client. Set
33 * by the client for all protocols above CORE.
34 * Set by us for CORE protocol.
36 int max_send = BUFFER_SIZE;
38 * Size of the data we can receive. Set by us.
39 * Can be modified by the max xmit parameter.
41 int max_recv = BUFFER_SIZE;
43 extern int last_message;
44 extern int smb_read_error;
45 SIG_ATOMIC_T reload_after_sighup = 0;
46 SIG_ATOMIC_T got_sig_term = 0;
47 extern BOOL global_machine_password_needs_changing;
51 * Initialize a struct smb_request from an inbuf
54 void init_smb_request(struct smb_request *req, const uint8 *inbuf)
56 req->flags2 = SVAL(inbuf, smb_flg2);
57 req->smbpid = SVAL(inbuf, smb_pid);
58 req->mid = SVAL(inbuf, smb_mid);
59 req->vuid = SVAL(inbuf, smb_uid);
62 /****************************************************************************
63 structure to hold a linked list of queued messages.
65 ****************************************************************************/
67 static struct pending_message_list *deferred_open_queue;
69 /****************************************************************************
70 Function to push a message onto the tail of a linked list of smb messages
72 ****************************************************************************/
74 static BOOL push_queued_message(char *buf, int msg_len,
75 struct timeval request_time,
76 struct timeval end_time,
77 char *private_data, size_t private_len)
79 struct pending_message_list *msg;
81 msg = TALLOC_ZERO_P(NULL, struct pending_message_list);
84 DEBUG(0,("push_message: malloc fail (1)\n"));
88 msg->buf = data_blob_talloc(msg, buf, msg_len);
89 if(msg->buf.data == NULL) {
90 DEBUG(0,("push_message: malloc fail (2)\n"));
95 msg->request_time = request_time;
96 msg->end_time = end_time;
99 msg->private_data = data_blob_talloc(msg, private_data,
101 if (msg->private_data.data == NULL) {
102 DEBUG(0,("push_message: malloc fail (3)\n"));
108 DLIST_ADD_END(deferred_open_queue, msg, struct pending_message_list *);
110 DEBUG(10,("push_message: pushed message length %u on "
111 "deferred_open_queue\n", (unsigned int)msg_len));
116 /****************************************************************************
117 Function to delete a sharing violation open message by mid.
118 ****************************************************************************/
120 void remove_deferred_open_smb_message(uint16 mid)
122 struct pending_message_list *pml;
124 for (pml = deferred_open_queue; pml; pml = pml->next) {
125 if (mid == SVAL(pml->buf.data,smb_mid)) {
126 DEBUG(10,("remove_deferred_open_smb_message: "
127 "deleting mid %u len %u\n",
129 (unsigned int)pml->buf.length ));
130 DLIST_REMOVE(deferred_open_queue, pml);
137 /****************************************************************************
138 Move a sharing violation open retry message to the front of the list and
139 schedule it for immediate processing.
140 ****************************************************************************/
142 void schedule_deferred_open_smb_message(uint16 mid)
144 struct pending_message_list *pml;
147 for (pml = deferred_open_queue; pml; pml = pml->next) {
148 uint16 msg_mid = SVAL(pml->buf.data,smb_mid);
149 DEBUG(10, ("schedule_deferred_open_smb_message: [%d] "
150 "msg_mid = %u\n", i++, (unsigned int)msg_mid ));
151 if (mid == msg_mid) {
152 DEBUG(10, ("schedule_deferred_open_smb_message: "
153 "scheduling mid %u\n", mid));
154 pml->end_time.tv_sec = 0;
155 pml->end_time.tv_usec = 0;
156 DLIST_PROMOTE(deferred_open_queue, pml);
161 DEBUG(10, ("schedule_deferred_open_smb_message: failed to find "
162 "message mid %u\n", mid ));
165 /****************************************************************************
166 Return true if this mid is on the deferred queue.
167 ****************************************************************************/
169 BOOL open_was_deferred(uint16 mid)
171 struct pending_message_list *pml;
173 for (pml = deferred_open_queue; pml; pml = pml->next) {
174 if (SVAL(pml->buf.data,smb_mid) == mid) {
181 /****************************************************************************
182 Return the message queued by this mid.
183 ****************************************************************************/
185 struct pending_message_list *get_open_deferred_message(uint16 mid)
187 struct pending_message_list *pml;
189 for (pml = deferred_open_queue; pml; pml = pml->next) {
190 if (SVAL(pml->buf.data,smb_mid) == mid) {
197 /****************************************************************************
198 Function to push a deferred open smb message onto a linked list of local smb
199 messages ready for processing.
200 ****************************************************************************/
202 BOOL push_deferred_smb_message(uint16 mid,
203 struct timeval request_time,
204 struct timeval timeout,
205 char *private_data, size_t priv_len)
207 struct timeval end_time;
209 end_time = timeval_sum(&request_time, &timeout);
211 DEBUG(10,("push_deferred_open_smb_message: pushing message len %u mid %u "
212 "timeout time [%u.%06u]\n",
213 (unsigned int) smb_len(current_inbuf)+4, (unsigned int)mid,
214 (unsigned int)end_time.tv_sec,
215 (unsigned int)end_time.tv_usec));
217 return push_queued_message(current_inbuf, smb_len(current_inbuf)+4,
218 request_time, end_time,
219 private_data, priv_len);
223 struct timed_event *te;
224 struct timeval interval;
226 BOOL (*handler)(const struct timeval *now, void *private_data);
230 static void idle_event_handler(struct event_context *ctx,
231 struct timed_event *te,
232 const struct timeval *now,
235 struct idle_event *event =
236 talloc_get_type_abort(private_data, struct idle_event);
238 TALLOC_FREE(event->te);
240 if (!event->handler(now, event->private_data)) {
241 /* Don't repeat, delete ourselves */
246 event->te = event_add_timed(ctx, event,
247 timeval_sum(now, &event->interval),
249 idle_event_handler, event);
251 /* We can't do much but fail here. */
252 SMB_ASSERT(event->te != NULL);
255 struct idle_event *event_add_idle(struct event_context *event_ctx,
257 struct timeval interval,
259 BOOL (*handler)(const struct timeval *now,
263 struct idle_event *result;
264 struct timeval now = timeval_current();
266 result = TALLOC_P(mem_ctx, struct idle_event);
267 if (result == NULL) {
268 DEBUG(0, ("talloc failed\n"));
272 result->interval = interval;
273 result->handler = handler;
274 result->private_data = private_data;
276 if (!(result->name = talloc_asprintf(result, "idle_evt(%s)", name))) {
277 DEBUG(0, ("talloc failed\n"));
282 result->te = event_add_timed(event_ctx, result,
283 timeval_sum(&now, &interval),
285 idle_event_handler, result);
286 if (result->te == NULL) {
287 DEBUG(0, ("event_add_timed failed\n"));
295 /****************************************************************************
296 Do all async processing in here. This includes kernel oplock messages, change
298 ****************************************************************************/
300 static void async_processing(fd_set *pfds)
302 DEBUG(10,("async_processing: Doing async processing.\n"));
306 process_kernel_oplocks(smbd_messaging_context(), pfds);
308 /* Do the aio check again after receive_local_message as it does a
309 select and may have eaten our signal. */
310 /* Is this till true? -- vl */
314 exit_server_cleanly("termination signal");
317 /* check for sighup processing */
318 if (reload_after_sighup) {
319 change_to_root_user();
320 DEBUG(1,("Reloading services after SIGHUP\n"));
321 reload_services(False);
322 reload_after_sighup = 0;
326 /****************************************************************************
327 Add a fd to the set we will be select(2)ing on.
328 ****************************************************************************/
330 static int select_on_fd(int fd, int maxfd, fd_set *fds)
334 maxfd = MAX(maxfd, fd);
340 /****************************************************************************
341 Do a select on an two fd's - with timeout.
343 If a local udp message has been pushed onto the
344 queue (this can only happen during oplock break
345 processing) call async_processing()
347 If a pending smb message has been pushed onto the
348 queue (this can only happen during oplock break
349 processing) return this next.
351 If the first smbfd is ready then read an smb from it.
352 if the second (loopback UDP) fd is ready then read a message
353 from it and setup the buffer header to identify the length
355 Returns False on timeout or error.
358 The timeout is in milliseconds
359 ****************************************************************************/
361 static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
373 to.tv_sec = timeout / 1000;
374 to.tv_usec = (timeout % 1000) * 1000;
376 to.tv_sec = SMBD_SELECT_TIMEOUT;
381 * Note that this call must be before processing any SMB
382 * messages as we need to synchronously process any messages
383 * we may have sent to ourselves from the previous SMB.
385 message_dispatch(smbd_messaging_context());
388 * Check to see if we already have a message on the deferred open queue
389 * and it's time to schedule.
391 if(deferred_open_queue != NULL) {
392 BOOL pop_message = False;
393 struct pending_message_list *msg = deferred_open_queue;
395 if (timeval_is_zero(&msg->end_time)) {
402 tdif = usec_time_diff(&msg->end_time, &tv);
404 /* Timed out. Schedule...*/
406 DEBUG(10,("receive_message_or_smb: queued message timed out.\n"));
408 /* Make a more accurate select timeout. */
409 to.tv_sec = tdif / 1000000;
410 to.tv_usec = tdif % 1000000;
411 DEBUG(10,("receive_message_or_smb: select with timeout of [%u.%06u]\n",
412 (unsigned int)to.tv_sec, (unsigned int)to.tv_usec ));
417 memcpy(buffer, msg->buf.data, MIN(buffer_len, msg->buf.length));
419 /* We leave this message on the queue so the open code can
420 know this is a retry. */
421 DEBUG(5,("receive_message_or_smb: returning deferred open smb message.\n"));
427 * Setup the select fd sets.
434 * Ensure we process oplock break messages by preference.
435 * We have to do this before the select, after the select
436 * and if the select returns EINTR. This is due to the fact
437 * that the selects called from async_processing can eat an EINTR
438 * caused by a signal (we can't take the break message there).
439 * This is hideously complex - *MUST* be simplified for 3.0 ! JRA.
442 if (oplock_message_waiting(&r_fds)) {
443 DEBUG(10,("receive_message_or_smb: oplock_message is waiting.\n"));
444 async_processing(&r_fds);
446 * After async processing we must go and do the select again, as
447 * the state of the flag in fds for the server file descriptor is
448 * indeterminate - we may have done I/O on it in the oplock processing. JRA.
454 * Are there any timed events waiting ? If so, ensure we don't
455 * select for longer than it would take to wait for them.
462 event_add_to_select_args(smbd_event_context(), &now,
463 &r_fds, &w_fds, &to, &maxfd);
466 if (timeval_is_zero(&to)) {
467 /* Process a timed event now... */
468 if (run_events(smbd_event_context(), 0, NULL, NULL)) {
475 START_PROFILE(smbd_idle);
477 maxfd = select_on_fd(smbd_server_fd(), maxfd, &r_fds);
478 maxfd = select_on_fd(oplock_notify_fd(), maxfd, &r_fds);
480 selrtn = sys_select(maxfd+1,&r_fds,&w_fds,NULL,&to);
483 END_PROFILE(smbd_idle);
487 if (run_events(smbd_event_context(), selrtn, &r_fds, &w_fds)) {
491 /* if we get EINTR then maybe we have received an oplock
492 signal - treat this as select returning 1. This is ugly, but
493 is the best we can do until the oplock code knows more about
495 if (selrtn == -1 && errno == EINTR) {
496 async_processing(&r_fds);
498 * After async processing we must go and do the select again, as
499 * the state of the flag in fds for the server file descriptor is
500 * indeterminate - we may have done I/O on it in the oplock processing. JRA.
507 /* something is wrong. Maybe the socket is dead? */
508 smb_read_error = READ_ERROR;
512 /* Did we timeout ? */
514 smb_read_error = READ_TIMEOUT;
519 * Ensure we process oplock break messages by preference.
520 * This is IMPORTANT ! Otherwise we can starve other processes
521 * sending us an oplock break message. JRA.
524 if (oplock_message_waiting(&r_fds)) {
525 async_processing(&r_fds);
527 * After async processing we must go and do the select again, as
528 * the state of the flag in fds for the server file descriptor is
529 * indeterminate - we may have done I/O on it in the oplock processing. JRA.
534 return receive_smb(smbd_server_fd(), buffer, 0);
538 * Only allow 5 outstanding trans requests. We're allocating memory, so
542 NTSTATUS allow_new_trans(struct trans_state *list, int mid)
545 for (; list != NULL; list = list->next) {
547 if (list->mid == mid) {
548 return NT_STATUS_INVALID_PARAMETER;
554 return NT_STATUS_INSUFFICIENT_RESOURCES;
560 /****************************************************************************
561 We're terminating and have closed all our files/connections etc.
562 If there are any pending local messages we need to respond to them
563 before termination so that other smbds don't think we just died whilst
565 ****************************************************************************/
567 void respond_to_all_remaining_local_messages(void)
570 * Assert we have no exclusive open oplocks.
573 if(get_number_of_exclusive_open_oplocks()) {
574 DEBUG(0,("respond_to_all_remaining_local_messages: PANIC : we have %d exclusive oplocks.\n",
575 get_number_of_exclusive_open_oplocks() ));
579 process_kernel_oplocks(smbd_messaging_context(), NULL);
586 These flags determine some of the permissions required to do an operation
588 Note that I don't set NEED_WRITE on some write operations because they
589 are used by some brain-dead clients when printing, and I don't want to
590 force write permissions on print services.
592 #define AS_USER (1<<0)
593 #define NEED_WRITE (1<<1) /* Must be paired with AS_USER */
594 #define TIME_INIT (1<<2)
595 #define CAN_IPC (1<<3) /* Must be paired with AS_USER */
596 #define AS_GUEST (1<<5) /* Must *NOT* be paired with AS_USER */
597 #define DO_CHDIR (1<<6)
600 define a list of possible SMB messages and their corresponding
601 functions. Any message that has a NULL function is unimplemented -
602 please feel free to contribute implementations!
604 static const struct smb_message_struct {
606 int (*fn)(connection_struct *conn, char *, char *, int, int);
608 } smb_messages[256] = {
610 /* 0x00 */ { "SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
611 /* 0x01 */ { "SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
612 /* 0x02 */ { "SMBopen",reply_open,AS_USER },
613 /* 0x03 */ { "SMBcreate",reply_mknew,AS_USER},
614 /* 0x04 */ { "SMBclose",reply_close,AS_USER | CAN_IPC },
615 /* 0x05 */ { "SMBflush",reply_flush,AS_USER},
616 /* 0x06 */ { "SMBunlink",reply_unlink,AS_USER | NEED_WRITE },
617 /* 0x07 */ { "SMBmv",reply_mv,AS_USER | NEED_WRITE },
618 /* 0x08 */ { "SMBgetatr",reply_getatr,AS_USER},
619 /* 0x09 */ { "SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
620 /* 0x0a */ { "SMBread",reply_read,AS_USER},
621 /* 0x0b */ { "SMBwrite",reply_write,AS_USER | CAN_IPC },
622 /* 0x0c */ { "SMBlock",reply_lock,AS_USER},
623 /* 0x0d */ { "SMBunlock",reply_unlock,AS_USER},
624 /* 0x0e */ { "SMBctemp",reply_ctemp,AS_USER },
625 /* 0x0f */ { "SMBmknew",reply_mknew,AS_USER},
626 /* 0x10 */ { "SMBcheckpath",reply_checkpath,AS_USER},
627 /* 0x11 */ { "SMBexit",reply_exit,DO_CHDIR},
628 /* 0x12 */ { "SMBlseek",reply_lseek,AS_USER},
629 /* 0x13 */ { "SMBlockread",reply_lockread,AS_USER},
630 /* 0x14 */ { "SMBwriteunlock",reply_writeunlock,AS_USER},
631 /* 0x15 */ { NULL, NULL, 0 },
632 /* 0x16 */ { NULL, NULL, 0 },
633 /* 0x17 */ { NULL, NULL, 0 },
634 /* 0x18 */ { NULL, NULL, 0 },
635 /* 0x19 */ { NULL, NULL, 0 },
636 /* 0x1a */ { "SMBreadbraw",reply_readbraw,AS_USER},
637 /* 0x1b */ { "SMBreadBmpx",reply_readbmpx,AS_USER},
638 /* 0x1c */ { "SMBreadBs",NULL,0 },
639 /* 0x1d */ { "SMBwritebraw",reply_writebraw,AS_USER},
640 /* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,AS_USER},
641 /* 0x1f */ { "SMBwriteBs",reply_writebs,AS_USER},
642 /* 0x20 */ { "SMBwritec",NULL,0},
643 /* 0x21 */ { NULL, NULL, 0 },
644 /* 0x22 */ { "SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE },
645 /* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER },
646 /* 0x24 */ { "SMBlockingX",reply_lockingX,AS_USER },
647 /* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC },
648 /* 0x26 */ { "SMBtranss",reply_transs,AS_USER | CAN_IPC},
649 /* 0x27 */ { "SMBioctl",reply_ioctl,0},
650 /* 0x28 */ { "SMBioctls",NULL,AS_USER},
651 /* 0x29 */ { "SMBcopy",reply_copy,AS_USER | NEED_WRITE },
652 /* 0x2a */ { "SMBmove",NULL,AS_USER | NEED_WRITE },
653 /* 0x2b */ { "SMBecho",reply_echo,0},
654 /* 0x2c */ { "SMBwriteclose",reply_writeclose,AS_USER},
655 /* 0x2d */ { "SMBopenX",reply_open_and_X,AS_USER | CAN_IPC },
656 /* 0x2e */ { "SMBreadX",reply_read_and_X,AS_USER | CAN_IPC },
657 /* 0x2f */ { "SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC },
658 /* 0x30 */ { NULL, NULL, 0 },
659 /* 0x31 */ { NULL, NULL, 0 },
660 /* 0x32 */ { "SMBtrans2", reply_trans2, AS_USER | CAN_IPC },
661 /* 0x33 */ { "SMBtranss2", reply_transs2, AS_USER},
662 /* 0x34 */ { "SMBfindclose", reply_findclose,AS_USER},
663 /* 0x35 */ { "SMBfindnclose", reply_findnclose, AS_USER},
664 /* 0x36 */ { NULL, NULL, 0 },
665 /* 0x37 */ { NULL, NULL, 0 },
666 /* 0x38 */ { NULL, NULL, 0 },
667 /* 0x39 */ { NULL, NULL, 0 },
668 /* 0x3a */ { NULL, NULL, 0 },
669 /* 0x3b */ { NULL, NULL, 0 },
670 /* 0x3c */ { NULL, NULL, 0 },
671 /* 0x3d */ { NULL, NULL, 0 },
672 /* 0x3e */ { NULL, NULL, 0 },
673 /* 0x3f */ { NULL, NULL, 0 },
674 /* 0x40 */ { NULL, NULL, 0 },
675 /* 0x41 */ { NULL, NULL, 0 },
676 /* 0x42 */ { NULL, NULL, 0 },
677 /* 0x43 */ { NULL, NULL, 0 },
678 /* 0x44 */ { NULL, NULL, 0 },
679 /* 0x45 */ { NULL, NULL, 0 },
680 /* 0x46 */ { NULL, NULL, 0 },
681 /* 0x47 */ { NULL, NULL, 0 },
682 /* 0x48 */ { NULL, NULL, 0 },
683 /* 0x49 */ { NULL, NULL, 0 },
684 /* 0x4a */ { NULL, NULL, 0 },
685 /* 0x4b */ { NULL, NULL, 0 },
686 /* 0x4c */ { NULL, NULL, 0 },
687 /* 0x4d */ { NULL, NULL, 0 },
688 /* 0x4e */ { NULL, NULL, 0 },
689 /* 0x4f */ { NULL, NULL, 0 },
690 /* 0x50 */ { NULL, NULL, 0 },
691 /* 0x51 */ { NULL, NULL, 0 },
692 /* 0x52 */ { NULL, NULL, 0 },
693 /* 0x53 */ { NULL, NULL, 0 },
694 /* 0x54 */ { NULL, NULL, 0 },
695 /* 0x55 */ { NULL, NULL, 0 },
696 /* 0x56 */ { NULL, NULL, 0 },
697 /* 0x57 */ { NULL, NULL, 0 },
698 /* 0x58 */ { NULL, NULL, 0 },
699 /* 0x59 */ { NULL, NULL, 0 },
700 /* 0x5a */ { NULL, NULL, 0 },
701 /* 0x5b */ { NULL, NULL, 0 },
702 /* 0x5c */ { NULL, NULL, 0 },
703 /* 0x5d */ { NULL, NULL, 0 },
704 /* 0x5e */ { NULL, NULL, 0 },
705 /* 0x5f */ { NULL, NULL, 0 },
706 /* 0x60 */ { NULL, NULL, 0 },
707 /* 0x61 */ { NULL, NULL, 0 },
708 /* 0x62 */ { NULL, NULL, 0 },
709 /* 0x63 */ { NULL, NULL, 0 },
710 /* 0x64 */ { NULL, NULL, 0 },
711 /* 0x65 */ { NULL, NULL, 0 },
712 /* 0x66 */ { NULL, NULL, 0 },
713 /* 0x67 */ { NULL, NULL, 0 },
714 /* 0x68 */ { NULL, NULL, 0 },
715 /* 0x69 */ { NULL, NULL, 0 },
716 /* 0x6a */ { NULL, NULL, 0 },
717 /* 0x6b */ { NULL, NULL, 0 },
718 /* 0x6c */ { NULL, NULL, 0 },
719 /* 0x6d */ { NULL, NULL, 0 },
720 /* 0x6e */ { NULL, NULL, 0 },
721 /* 0x6f */ { NULL, NULL, 0 },
722 /* 0x70 */ { "SMBtcon",reply_tcon,0},
723 /* 0x71 */ { "SMBtdis",reply_tdis,DO_CHDIR},
724 /* 0x72 */ { "SMBnegprot",reply_negprot,0},
725 /* 0x73 */ { "SMBsesssetupX",reply_sesssetup_and_X,0},
726 /* 0x74 */ { "SMBulogoffX", reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
727 /* 0x75 */ { "SMBtconX",reply_tcon_and_X,0},
728 /* 0x76 */ { NULL, NULL, 0 },
729 /* 0x77 */ { NULL, NULL, 0 },
730 /* 0x78 */ { NULL, NULL, 0 },
731 /* 0x79 */ { NULL, NULL, 0 },
732 /* 0x7a */ { NULL, NULL, 0 },
733 /* 0x7b */ { NULL, NULL, 0 },
734 /* 0x7c */ { NULL, NULL, 0 },
735 /* 0x7d */ { NULL, NULL, 0 },
736 /* 0x7e */ { NULL, NULL, 0 },
737 /* 0x7f */ { NULL, NULL, 0 },
738 /* 0x80 */ { "SMBdskattr",reply_dskattr,AS_USER},
739 /* 0x81 */ { "SMBsearch",reply_search,AS_USER},
740 /* 0x82 */ { "SMBffirst",reply_search,AS_USER},
741 /* 0x83 */ { "SMBfunique",reply_search,AS_USER},
742 /* 0x84 */ { "SMBfclose",reply_fclose,AS_USER},
743 /* 0x85 */ { NULL, NULL, 0 },
744 /* 0x86 */ { NULL, NULL, 0 },
745 /* 0x87 */ { NULL, NULL, 0 },
746 /* 0x88 */ { NULL, NULL, 0 },
747 /* 0x89 */ { NULL, NULL, 0 },
748 /* 0x8a */ { NULL, NULL, 0 },
749 /* 0x8b */ { NULL, NULL, 0 },
750 /* 0x8c */ { NULL, NULL, 0 },
751 /* 0x8d */ { NULL, NULL, 0 },
752 /* 0x8e */ { NULL, NULL, 0 },
753 /* 0x8f */ { NULL, NULL, 0 },
754 /* 0x90 */ { NULL, NULL, 0 },
755 /* 0x91 */ { NULL, NULL, 0 },
756 /* 0x92 */ { NULL, NULL, 0 },
757 /* 0x93 */ { NULL, NULL, 0 },
758 /* 0x94 */ { NULL, NULL, 0 },
759 /* 0x95 */ { NULL, NULL, 0 },
760 /* 0x96 */ { NULL, NULL, 0 },
761 /* 0x97 */ { NULL, NULL, 0 },
762 /* 0x98 */ { NULL, NULL, 0 },
763 /* 0x99 */ { NULL, NULL, 0 },
764 /* 0x9a */ { NULL, NULL, 0 },
765 /* 0x9b */ { NULL, NULL, 0 },
766 /* 0x9c */ { NULL, NULL, 0 },
767 /* 0x9d */ { NULL, NULL, 0 },
768 /* 0x9e */ { NULL, NULL, 0 },
769 /* 0x9f */ { NULL, NULL, 0 },
770 /* 0xa0 */ { "SMBnttrans", reply_nttrans, AS_USER | CAN_IPC },
771 /* 0xa1 */ { "SMBnttranss", reply_nttranss, AS_USER | CAN_IPC },
772 /* 0xa2 */ { "SMBntcreateX", reply_ntcreate_and_X, AS_USER | CAN_IPC },
773 /* 0xa3 */ { NULL, NULL, 0 },
774 /* 0xa4 */ { "SMBntcancel", reply_ntcancel, 0 },
775 /* 0xa5 */ { "SMBntrename", reply_ntrename, AS_USER | NEED_WRITE },
776 /* 0xa6 */ { NULL, NULL, 0 },
777 /* 0xa7 */ { NULL, NULL, 0 },
778 /* 0xa8 */ { NULL, NULL, 0 },
779 /* 0xa9 */ { NULL, NULL, 0 },
780 /* 0xaa */ { NULL, NULL, 0 },
781 /* 0xab */ { NULL, NULL, 0 },
782 /* 0xac */ { NULL, NULL, 0 },
783 /* 0xad */ { NULL, NULL, 0 },
784 /* 0xae */ { NULL, NULL, 0 },
785 /* 0xaf */ { NULL, NULL, 0 },
786 /* 0xb0 */ { NULL, NULL, 0 },
787 /* 0xb1 */ { NULL, NULL, 0 },
788 /* 0xb2 */ { NULL, NULL, 0 },
789 /* 0xb3 */ { NULL, NULL, 0 },
790 /* 0xb4 */ { NULL, NULL, 0 },
791 /* 0xb5 */ { NULL, NULL, 0 },
792 /* 0xb6 */ { NULL, NULL, 0 },
793 /* 0xb7 */ { NULL, NULL, 0 },
794 /* 0xb8 */ { NULL, NULL, 0 },
795 /* 0xb9 */ { NULL, NULL, 0 },
796 /* 0xba */ { NULL, NULL, 0 },
797 /* 0xbb */ { NULL, NULL, 0 },
798 /* 0xbc */ { NULL, NULL, 0 },
799 /* 0xbd */ { NULL, NULL, 0 },
800 /* 0xbe */ { NULL, NULL, 0 },
801 /* 0xbf */ { NULL, NULL, 0 },
802 /* 0xc0 */ { "SMBsplopen",reply_printopen,AS_USER},
803 /* 0xc1 */ { "SMBsplwr",reply_printwrite,AS_USER},
804 /* 0xc2 */ { "SMBsplclose",reply_printclose,AS_USER},
805 /* 0xc3 */ { "SMBsplretq",reply_printqueue,AS_USER},
806 /* 0xc4 */ { NULL, NULL, 0 },
807 /* 0xc5 */ { NULL, NULL, 0 },
808 /* 0xc6 */ { NULL, NULL, 0 },
809 /* 0xc7 */ { NULL, NULL, 0 },
810 /* 0xc8 */ { NULL, NULL, 0 },
811 /* 0xc9 */ { NULL, NULL, 0 },
812 /* 0xca */ { NULL, NULL, 0 },
813 /* 0xcb */ { NULL, NULL, 0 },
814 /* 0xcc */ { NULL, NULL, 0 },
815 /* 0xcd */ { NULL, NULL, 0 },
816 /* 0xce */ { NULL, NULL, 0 },
817 /* 0xcf */ { NULL, NULL, 0 },
818 /* 0xd0 */ { "SMBsends",reply_sends,AS_GUEST},
819 /* 0xd1 */ { "SMBsendb",NULL,AS_GUEST},
820 /* 0xd2 */ { "SMBfwdname",NULL,AS_GUEST},
821 /* 0xd3 */ { "SMBcancelf",NULL,AS_GUEST},
822 /* 0xd4 */ { "SMBgetmac",NULL,AS_GUEST},
823 /* 0xd5 */ { "SMBsendstrt",reply_sendstrt,AS_GUEST},
824 /* 0xd6 */ { "SMBsendend",reply_sendend,AS_GUEST},
825 /* 0xd7 */ { "SMBsendtxt",reply_sendtxt,AS_GUEST},
826 /* 0xd8 */ { NULL, NULL, 0 },
827 /* 0xd9 */ { NULL, NULL, 0 },
828 /* 0xda */ { NULL, NULL, 0 },
829 /* 0xdb */ { NULL, NULL, 0 },
830 /* 0xdc */ { NULL, NULL, 0 },
831 /* 0xdd */ { NULL, NULL, 0 },
832 /* 0xde */ { NULL, NULL, 0 },
833 /* 0xdf */ { NULL, NULL, 0 },
834 /* 0xe0 */ { NULL, NULL, 0 },
835 /* 0xe1 */ { NULL, NULL, 0 },
836 /* 0xe2 */ { NULL, NULL, 0 },
837 /* 0xe3 */ { NULL, NULL, 0 },
838 /* 0xe4 */ { NULL, NULL, 0 },
839 /* 0xe5 */ { NULL, NULL, 0 },
840 /* 0xe6 */ { NULL, NULL, 0 },
841 /* 0xe7 */ { NULL, NULL, 0 },
842 /* 0xe8 */ { NULL, NULL, 0 },
843 /* 0xe9 */ { NULL, NULL, 0 },
844 /* 0xea */ { NULL, NULL, 0 },
845 /* 0xeb */ { NULL, NULL, 0 },
846 /* 0xec */ { NULL, NULL, 0 },
847 /* 0xed */ { NULL, NULL, 0 },
848 /* 0xee */ { NULL, NULL, 0 },
849 /* 0xef */ { NULL, NULL, 0 },
850 /* 0xf0 */ { NULL, NULL, 0 },
851 /* 0xf1 */ { NULL, NULL, 0 },
852 /* 0xf2 */ { NULL, NULL, 0 },
853 /* 0xf3 */ { NULL, NULL, 0 },
854 /* 0xf4 */ { NULL, NULL, 0 },
855 /* 0xf5 */ { NULL, NULL, 0 },
856 /* 0xf6 */ { NULL, NULL, 0 },
857 /* 0xf7 */ { NULL, NULL, 0 },
858 /* 0xf8 */ { NULL, NULL, 0 },
859 /* 0xf9 */ { NULL, NULL, 0 },
860 /* 0xfa */ { NULL, NULL, 0 },
861 /* 0xfb */ { NULL, NULL, 0 },
862 /* 0xfc */ { NULL, NULL, 0 },
863 /* 0xfd */ { NULL, NULL, 0 },
864 /* 0xfe */ { NULL, NULL, 0 },
865 /* 0xff */ { NULL, NULL, 0 }
869 /*******************************************************************
870 Dump a packet to a file.
871 ********************************************************************/
873 static void smb_dump(const char *name, int type, char *data, ssize_t len)
877 if (DEBUGLEVEL < 50) return;
879 if (len < 4) len = smb_len(data)+4;
880 for (i=1;i<100;i++) {
881 slprintf(fname,sizeof(fname)-1, "/tmp/%s.%d.%s", name, i,
882 type ? "req" : "resp");
883 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644);
884 if (fd != -1 || errno != EEXIST) break;
887 ssize_t ret = write(fd, data, len);
889 DEBUG(0,("smb_dump: problem: write returned %d\n", (int)ret ));
891 DEBUG(0,("created %s len %lu\n", fname, (unsigned long)len));
896 /****************************************************************************
897 Do a switch on the message type, and return the response size
898 ****************************************************************************/
900 static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize)
902 static pid_t pid= (pid_t)-1;
907 if (pid == (pid_t)-1)
914 /* Make sure this is an SMB packet. smb_size contains NetBIOS header so subtract 4 from it. */
915 if ((strncmp(smb_base(inbuf),"\377SMB",4) != 0) || (size < (smb_size - 4))) {
916 DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",smb_len(inbuf)));
917 exit_server_cleanly("Non-SMB packet");
921 /* yuck! this is an interim measure before we get rid of our
922 current inbuf/outbuf system */
923 global_smbpid = SVAL(inbuf,smb_pid);
925 if (smb_messages[type].fn == NULL) {
926 DEBUG(0,("Unknown message type %d!\n",type));
927 smb_dump("Unknown", 1, inbuf, size);
928 outsize = reply_unknown(inbuf,outbuf);
930 int flags = smb_messages[type].flags;
931 static uint16 last_session_tag = UID_FIELD_INVALID;
932 /* In share mode security we must ignore the vuid. */
933 uint16 session_tag = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(inbuf,smb_uid);
934 connection_struct *conn = conn_find(SVAL(inbuf,smb_tid));
936 DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n",smb_fn_name(type),(int)pid,(unsigned long)conn));
938 smb_dump(smb_fn_name(type), 1, inbuf, size);
940 /* Ensure this value is replaced in the incoming packet. */
941 SSVAL(inbuf,smb_uid,session_tag);
944 * Ensure the correct username is in current_user_info.
945 * This is a really ugly bugfix for problems with
946 * multiple session_setup_and_X's being done and
947 * allowing %U and %G substitutions to work correctly.
948 * There is a reason this code is done here, don't
949 * move it unless you know what you're doing... :-).
953 if (session_tag != last_session_tag) {
954 user_struct *vuser = NULL;
956 last_session_tag = session_tag;
957 if(session_tag != UID_FIELD_INVALID) {
958 vuser = get_valid_user_struct(session_tag);
960 set_current_user_info(&vuser->user);
965 /* Does this call need to be run as the connected user? */
966 if (flags & AS_USER) {
968 /* Does this call need a valid tree connection? */
970 /* Amazingly, the error code depends on the command (from Samba4). */
971 if (type == SMBntcreateX) {
972 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
974 return ERROR_DOS(ERRSRV, ERRinvnid);
978 if (!change_to_user(conn,session_tag)) {
979 return(ERROR_NT(NT_STATUS_DOS(ERRSRV,ERRbaduid)));
982 /* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */
984 /* Does it need write permission? */
985 if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) {
986 return ERROR_NT(NT_STATUS_MEDIA_WRITE_PROTECTED);
989 /* IPC services are limited */
990 if (IS_IPC(conn) && !(flags & CAN_IPC)) {
991 return(ERROR_DOS(ERRSRV,ERRaccess));
994 /* This call needs to be run as root */
995 change_to_root_user();
998 /* load service specific parameters */
1000 if (!set_current_service(conn,SVAL(inbuf,smb_flg),(flags & (AS_USER|DO_CHDIR)?True:False))) {
1001 return(ERROR_DOS(ERRSRV,ERRaccess));
1003 conn->num_smb_operations++;
1006 /* does this protocol need to be run as guest? */
1007 if ((flags & AS_GUEST) && (!change_to_guest() ||
1008 !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1)))) {
1009 return(ERROR_DOS(ERRSRV,ERRaccess));
1012 current_inbuf = inbuf; /* In case we need to defer this message in open... */
1013 outsize = smb_messages[type].fn(conn, inbuf,outbuf,size,bufsize);
1016 smb_dump(smb_fn_name(type), 0, outbuf, outsize);
1021 /****************************************************************************
1022 Construct a reply to the incoming packet.
1023 ****************************************************************************/
1025 static int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
1027 int type = CVAL(inbuf,smb_com);
1029 int msg_type = CVAL(inbuf,0);
1036 return(reply_special(inbuf,outbuf));
1038 construct_reply_common(inbuf, outbuf);
1040 outsize = switch_message(type,inbuf,outbuf,size,bufsize);
1042 outsize += chain_size;
1045 smb_setlen(inbuf,outbuf,outsize - 4);
1050 /****************************************************************************
1051 Process an smb from the client
1052 ****************************************************************************/
1054 static void process_smb(char *inbuf, char *outbuf)
1056 static int trans_num;
1057 int msg_type = CVAL(inbuf,0);
1058 int32 len = smb_len(inbuf);
1059 int nread = len + 4;
1061 DO_PROFILE_INC(smb_count);
1063 if (trans_num == 0) {
1064 /* on the first packet, check the global hosts allow/ hosts
1065 deny parameters before doing any parsing of the packet
1066 passed to us by the client. This prevents attacks on our
1067 parsing code from hosts not in the hosts allow list */
1068 if (!check_access(smbd_server_fd(), lp_hostsallow(-1),
1069 lp_hostsdeny(-1))) {
1070 /* send a negative session response "not listening on calling name" */
1071 static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
1072 DEBUG( 1, ( "Connection denied from %s\n", client_addr() ) );
1073 (void)send_smb(smbd_server_fd(),(char *)buf);
1074 exit_server_cleanly("connection denied");
1078 DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type, len ) );
1079 DEBUG( 3, ( "Transaction %d of length %d\n", trans_num, nread ) );
1083 else if(msg_type == SMBkeepalive)
1084 return; /* Keepalive packet. */
1086 nread = construct_reply(inbuf,outbuf,nread,max_send);
1089 if (CVAL(outbuf,0) == 0)
1092 if (nread != smb_len(outbuf) + 4) {
1093 DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
1094 nread, smb_len(outbuf)));
1095 } else if (!send_smb(smbd_server_fd(),outbuf)) {
1096 exit_server_cleanly("process_smb: send_smb failed.");
1102 /****************************************************************************
1103 Return a string containing the function name of a SMB command.
1104 ****************************************************************************/
1106 const char *smb_fn_name(int type)
1108 const char *unknown_name = "SMBunknown";
1110 if (smb_messages[type].name == NULL)
1111 return(unknown_name);
1113 return(smb_messages[type].name);
1116 /****************************************************************************
1117 Helper functions for contruct_reply.
1118 ****************************************************************************/
1120 static uint32 common_flags2 = FLAGS2_LONG_PATH_COMPONENTS|FLAGS2_32_BIT_ERROR_CODES;
1122 void add_to_common_flags2(uint32 v)
1127 void remove_from_common_flags2(uint32 v)
1129 common_flags2 &= ~v;
1132 void construct_reply_common(const char *inbuf, char *outbuf)
1134 set_message(inbuf,outbuf,0,0,False);
1136 SCVAL(outbuf,smb_com,CVAL(inbuf,smb_com));
1137 SIVAL(outbuf,smb_rcls,0);
1138 SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES));
1139 SSVAL(outbuf,smb_flg2,
1140 (SVAL(inbuf,smb_flg2) & FLAGS2_UNICODE_STRINGS) |
1142 memset(outbuf+smb_pidhigh,'\0',(smb_tid-smb_pidhigh));
1144 SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
1145 SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
1146 SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
1147 SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
1150 /****************************************************************************
1151 Construct a chained reply and add it to the already made reply
1152 ****************************************************************************/
1154 int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
1156 static char *orig_inbuf;
1157 static char *orig_outbuf;
1158 int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0);
1159 unsigned smb_off2 = SVAL(inbuf,smb_vwv1);
1160 char *inbuf2, *outbuf2;
1163 char inbuf_saved[smb_wct];
1164 char outbuf_saved[smb_wct];
1165 int outsize = smb_len(outbuf) + 4;
1167 /* Maybe its not chained, or it's an error packet. */
1168 if (smb_com2 == 0xFF || SVAL(outbuf,smb_rcls) != 0) {
1169 SCVAL(outbuf,smb_vwv0,0xFF);
1173 if (chain_size == 0) {
1174 /* this is the first part of the chain */
1176 orig_outbuf = outbuf;
1180 * The original Win95 redirector dies on a reply to
1181 * a lockingX and read chain unless the chain reply is
1182 * 4 byte aligned. JRA.
1185 outsize = (outsize + 3) & ~3;
1187 /* we need to tell the client where the next part of the reply will be */
1188 SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf));
1189 SCVAL(outbuf,smb_vwv0,smb_com2);
1191 /* remember how much the caller added to the chain, only counting stuff
1192 after the parameter words */
1193 chain_size += outsize - smb_wct;
1195 /* work out pointers into the original packets. The
1196 headers on these need to be filled in */
1197 inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct;
1198 outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct;
1200 /* remember the original command type */
1201 smb_com1 = CVAL(orig_inbuf,smb_com);
1203 /* save the data which will be overwritten by the new headers */
1204 memcpy(inbuf_saved,inbuf2,smb_wct);
1205 memcpy(outbuf_saved,outbuf2,smb_wct);
1207 /* give the new packet the same header as the last part of the SMB */
1208 memmove(inbuf2,inbuf,smb_wct);
1210 /* create the in buffer */
1211 SCVAL(inbuf2,smb_com,smb_com2);
1213 /* work out the new size for the in buffer. */
1214 new_size = size - (inbuf2 - inbuf);
1216 DEBUG(0,("chain_reply: chain packet size incorrect "
1217 "(orig size = %d, offset = %d)\n",
1218 size, (int)(inbuf2 - inbuf) ));
1219 exit_server_cleanly("Bad chained packet");
1223 /* And set it in the header. */
1224 smb_setlen(inbuf, inbuf2, new_size);
1226 /* create the out buffer */
1227 construct_reply_common(inbuf2, outbuf2);
1229 DEBUG(3,("Chained message\n"));
1232 /* process the request */
1233 outsize2 = switch_message(smb_com2,inbuf2,outbuf2,new_size,
1234 bufsize-chain_size);
1236 /* copy the new reply and request headers over the old ones, but
1237 preserve the smb_com field */
1238 memmove(orig_outbuf,outbuf2,smb_wct);
1239 SCVAL(orig_outbuf,smb_com,smb_com1);
1241 /* restore the saved data, being careful not to overwrite any
1242 data from the reply header */
1243 memcpy(inbuf2,inbuf_saved,smb_wct);
1246 int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf);
1250 memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs);
1256 /****************************************************************************
1257 Setup the needed select timeout in milliseconds.
1258 ****************************************************************************/
1260 static int setup_select_timeout(void)
1264 select_timeout = SMBD_SELECT_TIMEOUT*1000;
1266 if (print_notify_messages_pending()) {
1267 select_timeout = MIN(select_timeout, 1000);
1270 return select_timeout;
1273 /****************************************************************************
1274 Check if services need reloading.
1275 ****************************************************************************/
1277 void check_reload(time_t t)
1279 static pid_t mypid = 0;
1280 static time_t last_smb_conf_reload_time = 0;
1281 static time_t last_printer_reload_time = 0;
1282 time_t printcap_cache_time = (time_t)lp_printcap_cache_time();
1284 if(last_smb_conf_reload_time == 0) {
1285 last_smb_conf_reload_time = t;
1286 /* Our printing subsystem might not be ready at smbd start up.
1287 Then no printer is available till the first printers check
1288 is performed. A lower initial interval circumvents this. */
1289 if ( printcap_cache_time > 60 )
1290 last_printer_reload_time = t - printcap_cache_time + 60;
1292 last_printer_reload_time = t;
1295 if (mypid != getpid()) { /* First time or fork happened meanwhile */
1296 /* randomize over 60 second the printcap reload to avoid all
1297 * process hitting cupsd at the same time */
1298 int time_range = 60;
1300 last_printer_reload_time += random() % time_range;
1304 if (reload_after_sighup || (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK)) {
1305 reload_services(True);
1306 reload_after_sighup = False;
1307 last_smb_conf_reload_time = t;
1310 /* 'printcap cache time = 0' disable the feature */
1312 if ( printcap_cache_time != 0 )
1314 /* see if it's time to reload or if the clock has been set back */
1316 if ( (t >= last_printer_reload_time+printcap_cache_time)
1317 || (t-last_printer_reload_time < 0) )
1319 DEBUG( 3,( "Printcap cache time expired.\n"));
1321 last_printer_reload_time = t;
1326 /****************************************************************************
1327 Process any timeout housekeeping. Return False if the caller should exit.
1328 ****************************************************************************/
1330 static BOOL timeout_processing(int *select_timeout,
1331 time_t *last_timeout_processing_time)
1335 if (smb_read_error == READ_EOF) {
1336 DEBUG(3,("timeout_processing: End of file from client (client has disconnected).\n"));
1340 if (smb_read_error == READ_ERROR) {
1341 DEBUG(3,("timeout_processing: receive_smb error (%s) Exiting\n",
1346 if (smb_read_error == READ_BAD_SIG) {
1347 DEBUG(3,("timeout_processing: receive_smb error bad smb signature. Exiting\n"));
1351 *last_timeout_processing_time = t = time(NULL);
1353 /* become root again if waiting */
1354 change_to_root_user();
1356 /* check if we need to reload services */
1359 if(global_machine_password_needs_changing &&
1360 /* for ADS we need to do a regular ADS password change, not a domain
1362 lp_security() == SEC_DOMAIN) {
1364 unsigned char trust_passwd_hash[16];
1368 * We're in domain level security, and the code that
1369 * read the machine password flagged that the machine
1370 * password needs changing.
1374 * First, open the machine password file with an exclusive lock.
1377 if (secrets_lock_trust_account_password(lp_workgroup(), True) == False) {
1378 DEBUG(0,("process: unable to lock the machine account password for \
1379 machine %s in domain %s.\n", global_myname(), lp_workgroup() ));
1383 if(!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd_hash, &lct, NULL)) {
1384 DEBUG(0,("process: unable to read the machine account password for \
1385 machine %s in domain %s.\n", global_myname(), lp_workgroup()));
1386 secrets_lock_trust_account_password(lp_workgroup(), False);
1391 * Make sure someone else hasn't already done this.
1394 if(t < lct + lp_machine_password_timeout()) {
1395 global_machine_password_needs_changing = False;
1396 secrets_lock_trust_account_password(lp_workgroup(), False);
1400 /* always just contact the PDC here */
1402 change_trust_account_password( lp_workgroup(), NULL);
1403 global_machine_password_needs_changing = False;
1404 secrets_lock_trust_account_password(lp_workgroup(), False);
1407 /* update printer queue caches if necessary */
1409 update_monitored_printq_cache();
1412 * Now we are root, check if the log files need pruning.
1413 * Force a log file check.
1415 force_check_log_size();
1418 /* Send any queued printer notify message to interested smbd's. */
1420 print_notify_send_messages(smbd_messaging_context(), 0);
1423 * Modify the select timeout depending upon
1424 * what we have remaining in our queues.
1427 *select_timeout = setup_select_timeout();
1432 /****************************************************************************
1433 Accessor functions for InBuffer, OutBuffer.
1434 ****************************************************************************/
1436 char *get_InBuffer(void)
1441 char *get_OutBuffer(void)
1446 const int total_buffer_size = (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN);
1448 /****************************************************************************
1449 Allocate a new InBuffer. Returns the new and old ones.
1450 ****************************************************************************/
1452 static char *NewInBuffer(char **old_inbuf)
1454 char *new_inbuf = (char *)SMB_MALLOC(total_buffer_size);
1459 *old_inbuf = InBuffer;
1461 InBuffer = new_inbuf;
1462 #if defined(DEVELOPER)
1463 clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size);
1468 /****************************************************************************
1469 Allocate a new OutBuffer. Returns the new and old ones.
1470 ****************************************************************************/
1472 static char *NewOutBuffer(char **old_outbuf)
1474 char *new_outbuf = (char *)SMB_MALLOC(total_buffer_size);
1479 *old_outbuf = OutBuffer;
1481 OutBuffer = new_outbuf;
1482 #if defined(DEVELOPER)
1483 clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer, total_buffer_size);
1488 /****************************************************************************
1489 Process commands from the client
1490 ****************************************************************************/
1492 void smbd_process(void)
1494 time_t last_timeout_processing_time = time(NULL);
1495 unsigned int num_smbs = 0;
1497 /* Allocate the primary Inbut/Output buffers. */
1499 if ((NewInBuffer(NULL) == NULL) || (NewOutBuffer(NULL) == NULL))
1502 max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
1505 int select_timeout = setup_select_timeout();
1510 /* free up temporary memory */
1512 main_loop_TALLOC_FREE();
1514 /* Did someone ask for immediate checks on things like blocking locks ? */
1515 if (select_timeout == 0) {
1516 if(!timeout_processing(&select_timeout,
1517 &last_timeout_processing_time))
1519 num_smbs = 0; /* Reset smb counter. */
1522 run_events(smbd_event_context(), 0, NULL, NULL);
1524 #if defined(DEVELOPER)
1525 clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size);
1528 while (!receive_message_or_smb(InBuffer,BUFFER_SIZE+LARGE_WRITEX_HDR_SIZE,select_timeout)) {
1529 if(!timeout_processing(&select_timeout,
1530 &last_timeout_processing_time))
1532 num_smbs = 0; /* Reset smb counter. */
1536 * Ensure we do timeout processing if the SMB we just got was
1537 * only an echo request. This allows us to set the select
1538 * timeout in 'receive_message_or_smb()' to any value we like
1539 * without worrying that the client will send echo requests
1540 * faster than the select timeout, thus starving out the
1541 * essential processing (change notify, blocking locks) that
1542 * the timeout code does. JRA.
1544 num_echos = smb_echo_count;
1546 clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer, total_buffer_size);
1548 process_smb(InBuffer, OutBuffer);
1550 if (smb_echo_count != num_echos) {
1551 if(!timeout_processing( &select_timeout, &last_timeout_processing_time))
1553 num_smbs = 0; /* Reset smb counter. */
1559 * If we are getting smb requests in a constant stream
1560 * with no echos, make sure we attempt timeout processing
1561 * every select_timeout milliseconds - but only check for this
1562 * every 200 smb requests.
1565 if ((num_smbs % 200) == 0) {
1566 time_t new_check_time = time(NULL);
1567 if(new_check_time - last_timeout_processing_time >= (select_timeout/1000)) {
1568 if(!timeout_processing(
1570 &last_timeout_processing_time))
1572 num_smbs = 0; /* Reset smb counter. */
1573 last_timeout_processing_time = new_check_time; /* Reset time. */
1577 /* The timeout_processing function isn't run nearly
1578 often enough to implement 'max log size' without
1579 overrunning the size of the file by many megabytes.
1580 This is especially true if we are running at debug
1581 level 10. Checking every 50 SMBs is a nice
1582 tradeoff of performance vs log file size overrun. */
1584 if ((num_smbs % 50) == 0 && need_to_check_log_size()) {
1585 change_to_root_user();