3 Unix SMB/Netbios implementation.
5 process incoming packets - main loop
6 Copyright (C) Andrew Tridgell 1992-1998
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 extern int DEBUGLEVEL;
27 struct timeval smb_last_time;
29 static char *InBuffer = NULL;
30 char *OutBuffer = NULL;
31 char *last_inbuf = NULL;
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.
38 int max_send = BUFFER_SIZE;
40 * Size of the data we can receive. Set by us.
41 * Can be modified by the max xmit parameter.
43 int max_recv = BUFFER_SIZE;
45 extern int last_message;
46 extern int global_oplock_break;
47 extern pstring sesssetup_user;
48 extern char *last_inbuf;
49 extern char *InBuffer;
50 extern char *OutBuffer;
51 extern int smb_read_error;
52 extern VOLATILE SIG_ATOMIC_T reload_after_sighup;
53 extern BOOL global_machine_password_needs_changing;
54 extern fstring global_myworkgroup;
55 extern pstring global_myname;
58 /****************************************************************************
59 structure to hold a linked list of queued messages.
61 ****************************************************************************/
67 } pending_message_list;
69 static ubi_slList smb_oplock_queue = { NULL, (ubi_slNodePtr)&smb_oplock_queue, 0};
71 /****************************************************************************
72 Function to push a message onto the tail of a linked list of smb messages ready
74 ****************************************************************************/
76 static BOOL push_message(ubi_slList *list_head, char *buf, int msg_len)
78 pending_message_list *msg = (pending_message_list *)
79 malloc(sizeof(pending_message_list));
83 DEBUG(0,("push_message: malloc fail (1)\n"));
87 msg->msg_buf = (char *)malloc(msg_len);
88 if(msg->msg_buf == NULL)
90 DEBUG(0,("push_message: malloc fail (2)\n"));
95 memcpy(msg->msg_buf, buf, msg_len);
96 msg->msg_len = msg_len;
98 ubi_slAddTail( list_head, msg);
103 /****************************************************************************
104 Function to push a smb message onto a linked list of local smb messages ready
106 ****************************************************************************/
108 BOOL push_oplock_pending_smb_message(char *buf, int msg_len)
110 return push_message(&smb_oplock_queue, buf, msg_len);
113 /****************************************************************************
114 Do a select on an two fd's - with timeout.
116 If a local udp message has been pushed onto the
117 queue (this can only happen during oplock break
118 processing) return this first.
120 If a pending smb message has been pushed onto the
121 queue (this can only happen during oplock break
122 processing) return this next.
124 If the first smbfd is ready then read an smb from it.
125 if the second (loopback UDP) fd is ready then read a message
126 from it and setup the buffer header to identify the length
128 Returns False on timeout or error.
131 The timeout is in milli seconds
132 ****************************************************************************/
134 static BOOL receive_message_or_smb(char *buffer, int buffer_len,
135 int timeout, BOOL *got_smb)
147 * Check to see if we already have a message on the smb queue.
148 * If so - copy and return it.
151 if(ubi_slCount(&smb_oplock_queue) != 0)
153 pending_message_list *msg = (pending_message_list *)ubi_slRemHead(&smb_oplock_queue);
154 memcpy(buffer, msg->msg_buf, MIN(buffer_len, msg->msg_len));
156 /* Free the message we just copied. */
157 free((char *)msg->msg_buf);
161 DEBUG(5,("receive_message_or_smb: returning queued smb message.\n"));
166 * Setup the select read fd set.
170 FD_SET(smbd_server_fd(),&fds);
171 maxfd = setup_oplock_select_set(&fds);
173 to.tv_sec = timeout / 1000;
174 to.tv_usec = (timeout % 1000) * 1000;
176 selrtn = sys_select(MAX(maxfd,smbd_server_fd())+1,&fds,timeout>0?&to:NULL);
180 /* something is wrong. Maybe the socket is dead? */
181 smb_read_error = READ_ERROR;
185 /* Did we timeout ? */
187 smb_read_error = READ_TIMEOUT;
191 if (FD_ISSET(smbd_server_fd(),&fds))
194 return receive_smb(smbd_server_fd(), buffer, 0);
198 return receive_local_message(&fds, buffer, buffer_len, 0);
202 /****************************************************************************
203 Get the next SMB packet, doing the local message processing automatically.
204 ****************************************************************************/
206 BOOL receive_next_smb(char *inbuf, int bufsize, int timeout)
208 BOOL got_smb = False;
213 ret = receive_message_or_smb(inbuf,bufsize,timeout,&got_smb);
217 /* Deal with oplock break requests from other smbd's. */
218 process_local_message(inbuf, bufsize);
222 if(ret && (CVAL(inbuf,0) == 0x85))
224 /* Keepalive packet. */
229 while(ret && !got_smb);
234 /****************************************************************************
235 We're terminating and have closed all our files/connections etc.
236 If there are any pending local messages we need to respond to them
237 before termination so that other smbds don't think we just died whilst
239 ****************************************************************************/
241 void respond_to_all_remaining_local_messages(void)
247 * Assert we have no exclusive open oplocks.
250 if(get_number_of_exclusive_open_oplocks()) {
251 DEBUG(0,("respond_to_all_remaining_local_messages: PANIC : we have %d exclusive oplocks.\n",
252 get_number_of_exclusive_open_oplocks() ));
257 * Setup the select read fd set.
261 if(!setup_oplock_select_set(&fds))
265 * Keep doing receive_local_message with a 1 ms timeout until
266 * we have no more messages.
269 while(receive_local_message(&fds, buffer, sizeof(buffer), 1)) {
270 /* Deal with oplock break requests from other smbd's. */
271 process_local_message(buffer, sizeof(buffer));
274 (void)setup_oplock_select_set(&fds);
282 These flags determine some of the permissions required to do an operation
284 Note that I don't set NEED_WRITE on some write operations because they
285 are used by some brain-dead clients when printing, and I don't want to
286 force write permissions on print services.
288 #define AS_USER (1<<0)
289 #define NEED_WRITE (1<<1)
290 #define TIME_INIT (1<<2)
291 #define CAN_IPC (1<<3)
292 #define AS_GUEST (1<<5)
293 #define QUEUE_IN_OPLOCK (1<<6)
296 define a list of possible SMB messages and their corresponding
297 functions. Any message that has a NULL function is unimplemented -
298 please feel free to contribute implementations!
300 struct smb_message_struct
304 int (*fn)(connection_struct *conn, char *, char *, int, int);
311 {SMBnegprot,"SMBnegprot",reply_negprot,0},
312 {SMBtcon,"SMBtcon",reply_tcon,0},
313 {SMBtdis,"SMBtdis",reply_tdis,0},
314 {SMBexit,"SMBexit",reply_exit,0},
315 {SMBioctl,"SMBioctl",reply_ioctl,0},
316 {SMBecho,"SMBecho",reply_echo,0},
317 {SMBsesssetupX,"SMBsesssetupX",reply_sesssetup_and_X,0},
318 {SMBtconX,"SMBtconX",reply_tcon_and_X,0},
319 {SMBulogoffX, "SMBulogoffX", reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
320 {SMBgetatr,"SMBgetatr",reply_getatr,AS_USER},
321 {SMBsetatr,"SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
322 {SMBchkpth,"SMBchkpth",reply_chkpth,AS_USER},
323 {SMBsearch,"SMBsearch",reply_search,AS_USER},
324 {SMBopen,"SMBopen",reply_open,AS_USER | QUEUE_IN_OPLOCK },
326 /* note that SMBmknew and SMBcreate are deliberately overloaded */
327 {SMBcreate,"SMBcreate",reply_mknew,AS_USER},
328 {SMBmknew,"SMBmknew",reply_mknew,AS_USER},
330 {SMBunlink,"SMBunlink",reply_unlink,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK},
331 {SMBread,"SMBread",reply_read,AS_USER},
332 {SMBwrite,"SMBwrite",reply_write,AS_USER | CAN_IPC },
333 {SMBclose,"SMBclose",reply_close,AS_USER | CAN_IPC },
334 {SMBmkdir,"SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
335 {SMBrmdir,"SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
336 {SMBdskattr,"SMBdskattr",reply_dskattr,AS_USER},
337 {SMBmv,"SMBmv",reply_mv,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK},
339 /* this is a Pathworks specific call, allowing the
340 changing of the root path */
341 {pSETDIR,"pSETDIR",reply_setdir,AS_USER},
343 {SMBlseek,"SMBlseek",reply_lseek,AS_USER},
344 {SMBflush,"SMBflush",reply_flush,AS_USER},
345 {SMBctemp,"SMBctemp",reply_ctemp,AS_USER | QUEUE_IN_OPLOCK },
346 {SMBsplopen,"SMBsplopen",reply_printopen,AS_USER | QUEUE_IN_OPLOCK },
347 {SMBsplclose,"SMBsplclose",reply_printclose,AS_USER},
348 {SMBsplretq,"SMBsplretq",reply_printqueue,AS_USER},
349 {SMBsplwr,"SMBsplwr",reply_printwrite,AS_USER},
350 {SMBlock,"SMBlock",reply_lock,AS_USER},
351 {SMBunlock,"SMBunlock",reply_unlock,AS_USER},
353 /* CORE+ PROTOCOL FOLLOWS */
355 {SMBreadbraw,"SMBreadbraw",reply_readbraw,AS_USER},
356 {SMBwritebraw,"SMBwritebraw",reply_writebraw,AS_USER},
357 {SMBwriteclose,"SMBwriteclose",reply_writeclose,AS_USER},
358 {SMBlockread,"SMBlockread",reply_lockread,AS_USER},
359 {SMBwriteunlock,"SMBwriteunlock",reply_writeunlock,AS_USER},
361 /* LANMAN1.0 PROTOCOL FOLLOWS */
363 {SMBreadBmpx,"SMBreadBmpx",reply_readbmpx,AS_USER},
364 {SMBreadBs,"SMBreadBs",NULL,AS_USER},
365 {SMBwriteBmpx,"SMBwriteBmpx",reply_writebmpx,AS_USER},
366 {SMBwriteBs,"SMBwriteBs",reply_writebs,AS_USER},
367 {SMBwritec,"SMBwritec",NULL,AS_USER},
368 {SMBsetattrE,"SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE },
369 {SMBgetattrE,"SMBgetattrE",reply_getattrE,AS_USER },
370 {SMBtrans,"SMBtrans",reply_trans,AS_USER | CAN_IPC | QUEUE_IN_OPLOCK},
371 {SMBtranss,"SMBtranss",NULL,AS_USER | CAN_IPC},
372 {SMBioctls,"SMBioctls",NULL,AS_USER},
373 {SMBcopy,"SMBcopy",reply_copy,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK },
374 {SMBmove,"SMBmove",NULL,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK },
376 {SMBopenX,"SMBopenX",reply_open_and_X,AS_USER | CAN_IPC | QUEUE_IN_OPLOCK },
377 {SMBreadX,"SMBreadX",reply_read_and_X,AS_USER | CAN_IPC },
378 {SMBwriteX,"SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC },
379 {SMBlockingX,"SMBlockingX",reply_lockingX,AS_USER },
381 {SMBffirst,"SMBffirst",reply_search,AS_USER},
382 {SMBfunique,"SMBfunique",reply_search,AS_USER},
383 {SMBfclose,"SMBfclose",reply_fclose,AS_USER},
385 /* LANMAN2.0 PROTOCOL FOLLOWS */
386 {SMBfindnclose, "SMBfindnclose", reply_findnclose, AS_USER},
387 {SMBfindclose, "SMBfindclose", reply_findclose,AS_USER},
388 {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER | QUEUE_IN_OPLOCK | CAN_IPC },
389 {SMBtranss2, "SMBtranss2", reply_transs2, AS_USER},
391 /* NT PROTOCOL FOLLOWS */
392 {SMBntcreateX, "SMBntcreateX", reply_ntcreate_and_X, AS_USER | CAN_IPC | QUEUE_IN_OPLOCK },
393 {SMBnttrans, "SMBnttrans", reply_nttrans, AS_USER | CAN_IPC | QUEUE_IN_OPLOCK},
394 {SMBnttranss, "SMBnttranss", reply_nttranss, AS_USER | CAN_IPC },
395 {SMBntcancel, "SMBntcancel", reply_ntcancel, 0 },
397 /* messaging routines */
398 {SMBsends,"SMBsends",reply_sends,AS_GUEST},
399 {SMBsendstrt,"SMBsendstrt",reply_sendstrt,AS_GUEST},
400 {SMBsendend,"SMBsendend",reply_sendend,AS_GUEST},
401 {SMBsendtxt,"SMBsendtxt",reply_sendtxt,AS_GUEST},
403 /* NON-IMPLEMENTED PARTS OF THE CORE PROTOCOL */
405 {SMBsendb,"SMBsendb",NULL,AS_GUEST},
406 {SMBfwdname,"SMBfwdname",NULL,AS_GUEST},
407 {SMBcancelf,"SMBcancelf",NULL,AS_GUEST},
408 {SMBgetmac,"SMBgetmac",NULL,AS_GUEST}
411 /*******************************************************************
413 ********************************************************************/
414 static void smb_dump(char *name, int type, char *data, ssize_t len)
418 if (DEBUGLEVEL < 50) return;
420 if (len < 4) len = smb_buflen(data);
421 for (i=1;i<100;i++) {
422 slprintf(fname,sizeof(fname), "/tmp/%s.%d.%s", name, i,
423 type ? "req" : "resp");
424 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644);
425 if (fd != -1 || errno != EEXIST) break;
428 write(fd, data, len);
430 DEBUG(0,("created %s len %d\n", fname, len));
435 /****************************************************************************
436 do a switch on the message type, and return the response size
437 ****************************************************************************/
438 static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize)
440 static pid_t pid= (pid_t)-1;
442 static int num_smb_messages =
443 sizeof(smb_messages) / sizeof(struct smb_message_struct);
445 extern int global_smbpid;
447 if (pid == (pid_t)-1)
453 /* make sure this is an SMB packet */
454 if (strncmp(smb_base(inbuf),"\377SMB",4) != 0)
456 DEBUG(2,("Non-SMB packet of length %d\n",smb_len(inbuf)));
460 for (match=0;match<num_smb_messages;match++)
461 if (smb_messages[match].code == type)
464 /* yuck! this is an interim measure before we get rid of our
465 current inbuf/outbuf system */
466 global_smbpid = SVAL(inbuf,smb_pid);
468 if (match == num_smb_messages)
470 DEBUG(0,("Unknown message type %d!\n",type));
471 smb_dump("Unknown", 1, inbuf, size);
472 outsize = reply_unknown(inbuf,outbuf);
476 DEBUG(3,("switch message %s (pid %d)\n",smb_messages[match].name,(int)pid));
478 smb_dump(smb_messages[match].name, 1, inbuf, size);
479 if(global_oplock_break)
481 int flags = smb_messages[match].flags;
483 if(flags & QUEUE_IN_OPLOCK)
486 * Queue this message as we are the process of an oplock break.
489 DEBUG( 2, ( "switch_message: queueing message due to being in " ) );
490 DEBUGADD( 2, ( "oplock break state.\n" ) );
492 push_oplock_pending_smb_message( inbuf, size );
496 if (smb_messages[match].fn)
498 int flags = smb_messages[match].flags;
499 static uint16 last_session_tag = UID_FIELD_INVALID;
500 /* In share mode security we must ignore the vuid. */
501 uint16 session_tag = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(inbuf,smb_uid);
502 connection_struct *conn = conn_find(SVAL(inbuf,smb_tid));
505 /* Ensure this value is replaced in the incoming packet. */
506 SSVAL(inbuf,smb_uid,session_tag);
509 * Ensure the correct username is in sesssetup_user.
510 * This is a really ugly bugfix for problems with
511 * multiple session_setup_and_X's being done and
512 * allowing %U and %G substitutions to work correctly.
513 * There is a reason this code is done here, don't
514 * move it unless you know what you're doing... :-).
517 if (session_tag != last_session_tag) {
518 user_struct *vuser = NULL;
520 last_session_tag = session_tag;
521 if(session_tag != UID_FIELD_INVALID)
522 vuser = get_valid_user_struct(session_tag);
524 pstrcpy( sesssetup_user, vuser->user.smb_name);
527 /* does this protocol need to be run as root? */
528 if (!(flags & AS_USER))
531 /* does this protocol need to be run as the connected user? */
532 if ((flags & AS_USER) && !become_user(conn,session_tag)) {
533 if (flags & AS_GUEST)
536 return(ERROR(ERRSRV,ERRaccess));
538 /* this code is to work around a bug is MS client 3 without
539 introducing a security hole - it needs to be able to do
540 print queue checks as guest if it isn't logged in properly */
544 /* does it need write permission? */
545 if ((flags & NEED_WRITE) && !CAN_WRITE(conn))
546 return(ERROR(ERRSRV,ERRaccess));
548 /* ipc services are limited */
549 if (IS_IPC(conn) && (flags & AS_USER) && !(flags & CAN_IPC)) {
550 return(ERROR(ERRSRV,ERRaccess));
553 /* load service specific parameters */
555 !become_service(conn,(flags & AS_USER)?True:False)) {
556 return(ERROR(ERRSRV,ERRaccess));
559 /* does this protocol need to be run as guest? */
560 if ((flags & AS_GUEST) &&
562 !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1)))) {
563 return(ERROR(ERRSRV,ERRaccess));
568 outsize = smb_messages[match].fn(conn, inbuf,outbuf,size,bufsize);
572 outsize = reply_unknown(inbuf,outbuf);
576 smb_dump(smb_messages[match].name, 0, outbuf, outsize);
582 /****************************************************************************
583 construct a reply to the incoming packet
584 ****************************************************************************/
585 static int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
587 int type = CVAL(inbuf,smb_com);
589 int msg_type = CVAL(inbuf,0);
591 GetTimeOfDay(&smb_last_time);
598 return(reply_special(inbuf,outbuf));
600 construct_reply_common(inbuf, outbuf);
602 outsize = switch_message(type,inbuf,outbuf,size,bufsize);
604 outsize += chain_size;
607 smb_setlen(outbuf,outsize - 4);
612 /****************************************************************************
613 process an smb from the client - split out from the process() code so
614 it can be used by the oplock break code.
615 ****************************************************************************/
616 void process_smb(char *inbuf, char *outbuf)
619 extern BOOL sslEnabled; /* don't use function for performance reasons */
620 static int sslConnected = 0;
621 #endif /* WITH_SSL */
622 static int trans_num;
623 int msg_type = CVAL(inbuf,0);
624 int32 len = smb_len(inbuf);
628 profile_p->smb_count++;
631 if (trans_num == 0) {
632 /* on the first packet, check the global hosts allow/ hosts
633 deny parameters before doing any parsing of the packet
634 passed to us by the client. This prevents attacks on our
635 parsing code from hosts not in the hosts allow list */
636 if (!check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1))) {
637 /* send a negative session response "not listining on calling
639 static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
640 DEBUG( 1, ( "Connection denied from %s\n",
642 send_smb(smbd_server_fd(),(char *)buf);
643 exit_server("connection denied");
647 DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type, len ) );
648 DEBUG( 3, ( "Transaction %d of length %d\n", trans_num, nread ) );
651 if(sslEnabled && !sslConnected){
652 sslConnected = sslutil_negotiate_ssl(smbd_server_fd(), msg_type);
653 if(sslConnected < 0){ /* an error occured */
654 exit_server("SSL negotiation failed");
655 }else if(sslConnected){
660 #endif /* WITH_SSL */
664 else if(msg_type == 0x85)
665 return; /* Keepalive packet. */
667 nread = construct_reply(inbuf,outbuf,nread,max_send);
671 if (CVAL(outbuf,0) == 0)
674 if (nread != smb_len(outbuf) + 4)
676 DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
677 nread, smb_len(outbuf)));
680 send_smb(smbd_server_fd(),outbuf);
687 /****************************************************************************
688 return a string containing the function name of a SMB command
689 ****************************************************************************/
690 char *smb_fn_name(int type)
692 static char *unknown_name = "SMBunknown";
693 static int num_smb_messages =
694 sizeof(smb_messages) / sizeof(struct smb_message_struct);
697 for (match=0;match<num_smb_messages;match++)
698 if (smb_messages[match].code == type)
701 if (match == num_smb_messages)
702 return(unknown_name);
704 return(smb_messages[match].name);
708 /****************************************************************************
709 Helper function for contruct_reply.
710 ****************************************************************************/
712 void construct_reply_common(char *inbuf,char *outbuf)
714 memset(outbuf,'\0',smb_size);
716 set_message(outbuf,0,0,True);
717 CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com);
719 memcpy(outbuf+4,inbuf+4,4);
720 CVAL(outbuf,smb_rcls) = SMB_SUCCESS;
721 CVAL(outbuf,smb_reh) = 0;
722 SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES)); /* bit 7 set
724 SSVAL(outbuf,smb_flg2,FLAGS2_LONG_PATH_COMPONENTS);
725 /* say we support long filenames */
727 SSVAL(outbuf,smb_err,SMB_SUCCESS);
728 SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
729 SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
730 SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
731 SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
734 /****************************************************************************
735 construct a chained reply and add it to the already made reply
736 **************************************************************************/
737 int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
739 static char *orig_inbuf;
740 static char *orig_outbuf;
741 int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0);
742 unsigned smb_off2 = SVAL(inbuf,smb_vwv1);
743 char *inbuf2, *outbuf2;
745 char inbuf_saved[smb_wct];
746 char outbuf_saved[smb_wct];
747 int wct = CVAL(outbuf,smb_wct);
748 int outsize = smb_size + 2*wct + SVAL(outbuf,smb_vwv0+2*wct);
750 /* maybe its not chained */
751 if (smb_com2 == 0xFF) {
752 CVAL(outbuf,smb_vwv0) = 0xFF;
756 if (chain_size == 0) {
757 /* this is the first part of the chain */
759 orig_outbuf = outbuf;
763 * The original Win95 redirector dies on a reply to
764 * a lockingX and read chain unless the chain reply is
765 * 4 byte aligned. JRA.
768 outsize = (outsize + 3) & ~3;
770 /* we need to tell the client where the next part of the reply will be */
771 SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf));
772 CVAL(outbuf,smb_vwv0) = smb_com2;
774 /* remember how much the caller added to the chain, only counting stuff
775 after the parameter words */
776 chain_size += outsize - smb_wct;
778 /* work out pointers into the original packets. The
779 headers on these need to be filled in */
780 inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct;
781 outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct;
783 /* remember the original command type */
784 smb_com1 = CVAL(orig_inbuf,smb_com);
786 /* save the data which will be overwritten by the new headers */
787 memcpy(inbuf_saved,inbuf2,smb_wct);
788 memcpy(outbuf_saved,outbuf2,smb_wct);
790 /* give the new packet the same header as the last part of the SMB */
791 memmove(inbuf2,inbuf,smb_wct);
793 /* create the in buffer */
794 CVAL(inbuf2,smb_com) = smb_com2;
796 /* create the out buffer */
797 construct_reply_common(inbuf2, outbuf2);
799 DEBUG(3,("Chained message\n"));
802 /* process the request */
803 outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size,
806 /* copy the new reply and request headers over the old ones, but
807 preserve the smb_com field */
808 memmove(orig_outbuf,outbuf2,smb_wct);
809 CVAL(orig_outbuf,smb_com) = smb_com1;
811 /* restore the saved data, being careful not to overwrite any
812 data from the reply header */
813 memcpy(inbuf2,inbuf_saved,smb_wct);
815 int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf);
816 if (ofs < 0) ofs = 0;
817 memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs);
823 /****************************************************************************
824 Setup the needed select timeout.
825 ****************************************************************************/
827 static int setup_select_timeout(void)
829 int change_notify_timeout = lp_change_notify_timeout() * 1000;
833 * Increase the select timeout back to SMBD_SELECT_TIMEOUT if we
834 * have removed any blocking locks. JRA.
837 select_timeout = blocking_locks_pending() ? SMBD_SELECT_TIMEOUT_WITH_PENDING_LOCKS*1000 :
838 SMBD_SELECT_TIMEOUT*1000;
840 if (change_notifies_pending())
841 select_timeout = MIN(select_timeout, change_notify_timeout);
843 return select_timeout;
846 /****************************************************************************
847 Check if services need reloading.
848 ****************************************************************************/
850 void check_reload(int t)
852 static time_t last_smb_conf_reload_time = 0;
854 if(last_smb_conf_reload_time == 0)
855 last_smb_conf_reload_time = t;
857 if (reload_after_sighup || (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK))
859 reload_services(True);
860 reload_after_sighup = False;
861 last_smb_conf_reload_time = t;
865 /****************************************************************************
866 Process any timeout housekeeping. Return False if the caller should exit.
867 ****************************************************************************/
869 static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_timeout_processing_time)
871 static time_t last_keepalive_sent_time = 0;
872 static time_t last_idle_closed_check = 0;
875 extern int keepalive;
877 if (smb_read_error == READ_EOF)
879 DEBUG(3,("end of file from client\n"));
883 if (smb_read_error == READ_ERROR)
885 DEBUG(3,("receive_smb error (%s) exiting\n",
890 *last_timeout_processing_time = t = time(NULL);
892 if(last_keepalive_sent_time == 0)
893 last_keepalive_sent_time = t;
895 if(last_idle_closed_check == 0)
896 last_idle_closed_check = t;
898 /* become root again if waiting */
901 /* check if we need to reload services */
904 /* automatic timeout if all connections are closed */
905 if (conn_num_open()==0 && (t - last_idle_closed_check) >= IDLE_CLOSED_TIMEOUT)
907 DEBUG( 2, ( "Closing idle connection\n" ) );
911 last_idle_closed_check = t;
913 if (keepalive && (t - last_keepalive_sent_time)>keepalive)
915 struct cli_state *cli = server_client();
916 if (!send_keepalive(smbd_server_fd())) {
917 DEBUG( 2, ( "Keepalive failed - exiting.\n" ) );
920 /* also send a keepalive to the password server if its still
922 if (cli && cli->initialised)
923 send_keepalive(cli->fd);
924 last_keepalive_sent_time = t;
927 /* check for connection timeouts */
928 allidle = conn_idle_all(t, deadtime);
930 if (allidle && conn_num_open()>0) {
931 DEBUG(2,("Closing idle connection 2.\n"));
935 if(global_machine_password_needs_changing)
937 unsigned char trust_passwd_hash[16];
939 pstring remote_machine_list;
942 * We're in domain level security, and the code that
943 * read the machine password flagged that the machine
944 * password needs changing.
948 * First, open the machine password file with an exclusive lock.
951 if(!get_trust_account_password(global_myworkgroup, trust_passwd_hash, &lct)) {
952 DEBUG(0,("process: unable to read the machine account password for \
953 machine %s in domain %s.\n", global_myname, global_myworkgroup ));
958 * Make sure someone else hasn't already done this.
961 if(t < lct + lp_machine_password_timeout()) {
962 global_machine_password_needs_changing = False;
966 pstrcpy(remote_machine_list, lp_passwordserver());
968 change_trust_account_password( global_myworkgroup, remote_machine_list);
969 global_machine_password_needs_changing = False;
973 * Check to see if we have any blocking locks
974 * outstanding on the queue.
976 process_blocking_lock_queue(t);
979 * Check to see if we have any change notifies
980 * outstanding on the queue.
982 process_pending_change_notify_queue(t);
985 * Now we are root, check if the log files need pruning.
987 if(need_to_check_log_size())
991 * Modify the select timeout depending upon
992 * what we have remaining in our queues.
995 *select_timeout = setup_select_timeout();
1000 /****************************************************************************
1001 process commands from the client
1002 ****************************************************************************/
1004 void smbd_process(void)
1006 extern int smb_echo_count;
1007 time_t last_timeout_processing_time = time(NULL);
1008 unsigned int num_smbs = 0;
1010 InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1011 OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1012 if ((InBuffer == NULL) || (OutBuffer == NULL))
1015 InBuffer += SMB_ALIGNMENT;
1016 OutBuffer += SMB_ALIGNMENT;
1018 max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
1020 /* re-initialise the timezone */
1025 int deadtime = lp_deadtime()*60;
1026 BOOL got_smb = False;
1027 int select_timeout = setup_select_timeout();
1030 deadtime = DEFAULT_SMBD_TIMEOUT;
1034 /* free up temporary memory */
1038 * If reload_after_sighup == True then we got a SIGHUP
1039 * and are being asked to reload. Fix from <branko.cibej@hermes.si>
1041 if (reload_after_sighup) {
1044 DEBUG(1,("Reloading services after SIGHUP\n"));
1045 reload_services(False);
1046 reload_after_sighup = False;
1049 while(!receive_message_or_smb(InBuffer,BUFFER_SIZE,select_timeout,&got_smb))
1051 if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1053 num_smbs = 0; /* Reset smb counter. */
1058 * Ensure we do timeout processing if the SMB we just got was
1059 * only an echo request. This allows us to set the select
1060 * timeout in 'receive_message_or_smb()' to any value we like
1061 * without worrying that the client will send echo requests
1062 * faster than the select timeout, thus starving out the
1063 * essential processing (change notify, blocking locks) that
1064 * the timeout code does. JRA.
1066 int num_echos = smb_echo_count;
1068 process_smb(InBuffer, OutBuffer);
1070 if(smb_echo_count != num_echos) {
1071 if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1073 num_smbs = 0; /* Reset smb counter. */
1079 * If we are getting smb requests in a constant stream
1080 * with no echos, make sure we attempt timeout processing
1081 * every select_timeout milliseconds - but only check for this
1082 * every 200 smb requests.
1085 if((num_smbs % 200) == 0) {
1086 time_t new_check_time = time(NULL);
1087 if(last_timeout_processing_time - new_check_time >= (select_timeout/1000)) {
1088 if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1090 num_smbs = 0; /* Reset smb counter. */
1091 last_timeout_processing_time = new_check_time; /* Reset time. */
1096 process_local_message(InBuffer, BUFFER_SIZE);