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