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}
412 /****************************************************************************
413 do a switch on the message type, and return the response size
414 ****************************************************************************/
415 static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize)
417 static pid_t pid= (pid_t)-1;
419 static int num_smb_messages =
420 sizeof(smb_messages) / sizeof(struct smb_message_struct);
422 extern int global_smbpid;
424 if (pid == (pid_t)-1)
430 /* make sure this is an SMB packet */
431 if (strncmp(smb_base(inbuf),"\377SMB",4) != 0)
433 DEBUG(2,("Non-SMB packet of length %d\n",smb_len(inbuf)));
437 for (match=0;match<num_smb_messages;match++)
438 if (smb_messages[match].code == type)
441 /* yuck! this is an interim measure before we get rid of our
442 current inbuf/outbuf system */
443 global_smbpid = SVAL(inbuf,smb_pid);
445 if (match == num_smb_messages)
447 DEBUG(0,("Unknown message type %d!\n",type));
448 outsize = reply_unknown(inbuf,outbuf);
452 DEBUG(3,("switch message %s (pid %d)\n",smb_messages[match].name,(int)pid));
454 if(global_oplock_break)
456 int flags = smb_messages[match].flags;
458 if(flags & QUEUE_IN_OPLOCK)
461 * Queue this message as we are the process of an oplock break.
464 DEBUG( 2, ( "switch_message: queueing message due to being in " ) );
465 DEBUGADD( 2, ( "oplock break state.\n" ) );
467 push_oplock_pending_smb_message( inbuf, size );
471 if (smb_messages[match].fn)
473 int flags = smb_messages[match].flags;
474 static uint16 last_session_tag = UID_FIELD_INVALID;
475 /* In share mode security we must ignore the vuid. */
476 uint16 session_tag = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(inbuf,smb_uid);
477 connection_struct *conn = conn_find(SVAL(inbuf,smb_tid));
480 /* Ensure this value is replaced in the incoming packet. */
481 SSVAL(inbuf,smb_uid,session_tag);
484 * Ensure the correct username is in sesssetup_user.
485 * This is a really ugly bugfix for problems with
486 * multiple session_setup_and_X's being done and
487 * allowing %U and %G substitutions to work correctly.
488 * There is a reason this code is done here, don't
489 * move it unless you know what you're doing... :-).
492 if (session_tag != last_session_tag) {
493 user_struct *vuser = NULL;
495 last_session_tag = session_tag;
496 if(session_tag != UID_FIELD_INVALID)
497 vuser = get_valid_user_struct(session_tag);
499 pstrcpy( sesssetup_user, vuser->user.smb_name);
502 /* does this protocol need to be run as root? */
503 if (!(flags & AS_USER))
506 /* does this protocol need to be run as the connected user? */
507 if ((flags & AS_USER) && !become_user(conn,session_tag)) {
508 if (flags & AS_GUEST)
511 return(ERROR(ERRSRV,ERRaccess));
513 /* this code is to work around a bug is MS client 3 without
514 introducing a security hole - it needs to be able to do
515 print queue checks as guest if it isn't logged in properly */
519 /* does it need write permission? */
520 if ((flags & NEED_WRITE) && !CAN_WRITE(conn))
521 return(ERROR(ERRSRV,ERRaccess));
523 /* ipc services are limited */
524 if (IS_IPC(conn) && (flags & AS_USER) && !(flags & CAN_IPC)) {
525 return(ERROR(ERRSRV,ERRaccess));
528 /* load service specific parameters */
530 !become_service(conn,(flags & AS_USER)?True:False)) {
531 return(ERROR(ERRSRV,ERRaccess));
534 /* does this protocol need to be run as guest? */
535 if ((flags & AS_GUEST) &&
537 !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1)))) {
538 return(ERROR(ERRSRV,ERRaccess));
543 outsize = smb_messages[match].fn(conn, inbuf,outbuf,size,bufsize);
547 outsize = reply_unknown(inbuf,outbuf);
555 /****************************************************************************
556 construct a reply to the incoming packet
557 ****************************************************************************/
558 static int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
560 int type = CVAL(inbuf,smb_com);
562 int msg_type = CVAL(inbuf,0);
564 GetTimeOfDay(&smb_last_time);
571 return(reply_special(inbuf,outbuf));
573 construct_reply_common(inbuf, outbuf);
575 outsize = switch_message(type,inbuf,outbuf,size,bufsize);
577 outsize += chain_size;
580 smb_setlen(outbuf,outsize - 4);
585 /****************************************************************************
586 process an smb from the client - split out from the process() code so
587 it can be used by the oplock break code.
588 ****************************************************************************/
589 void process_smb(char *inbuf, char *outbuf)
592 extern BOOL sslEnabled; /* don't use function for performance reasons */
593 static int sslConnected = 0;
594 #endif /* WITH_SSL */
595 static int trans_num;
596 int msg_type = CVAL(inbuf,0);
597 int32 len = smb_len(inbuf);
601 profile_p->smb_count++;
604 if (trans_num == 0) {
605 /* on the first packet, check the global hosts allow/ hosts
606 deny parameters before doing any parsing of the packet
607 passed to us by the client. This prevents attacks on our
608 parsing code from hosts not in the hosts allow list */
609 if (!check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1))) {
610 /* send a negative session response "not listining on calling
612 static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
613 DEBUG( 1, ( "Connection denied from %s\n",
615 send_smb(smbd_server_fd(),(char *)buf);
616 exit_server("connection denied");
620 DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type, len ) );
621 DEBUG( 3, ( "Transaction %d of length %d\n", trans_num, nread ) );
624 if(sslEnabled && !sslConnected){
625 sslConnected = sslutil_negotiate_ssl(smbd_server_fd(), msg_type);
626 if(sslConnected < 0){ /* an error occured */
627 exit_server("SSL negotiation failed");
628 }else if(sslConnected){
633 #endif /* WITH_SSL */
637 else if(msg_type == 0x85)
638 return; /* Keepalive packet. */
640 nread = construct_reply(inbuf,outbuf,nread,max_send);
644 if (CVAL(outbuf,0) == 0)
647 if (nread != smb_len(outbuf) + 4)
649 DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
650 nread, smb_len(outbuf)));
653 send_smb(smbd_server_fd(),outbuf);
660 /****************************************************************************
661 return a string containing the function name of a SMB command
662 ****************************************************************************/
663 char *smb_fn_name(int type)
665 static char *unknown_name = "SMBunknown";
666 static int num_smb_messages =
667 sizeof(smb_messages) / sizeof(struct smb_message_struct);
670 for (match=0;match<num_smb_messages;match++)
671 if (smb_messages[match].code == type)
674 if (match == num_smb_messages)
675 return(unknown_name);
677 return(smb_messages[match].name);
681 /****************************************************************************
682 Helper function for contruct_reply.
683 ****************************************************************************/
685 void construct_reply_common(char *inbuf,char *outbuf)
687 memset(outbuf,'\0',smb_size);
689 set_message(outbuf,0,0,True);
690 CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com);
692 memcpy(outbuf+4,inbuf+4,4);
693 CVAL(outbuf,smb_rcls) = SMB_SUCCESS;
694 CVAL(outbuf,smb_reh) = 0;
695 SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES)); /* bit 7 set
697 SSVAL(outbuf,smb_flg2,FLAGS2_LONG_PATH_COMPONENTS);
698 /* say we support long filenames */
700 SSVAL(outbuf,smb_err,SMB_SUCCESS);
701 SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
702 SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
703 SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
704 SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
707 /****************************************************************************
708 construct a chained reply and add it to the already made reply
709 **************************************************************************/
710 int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
712 static char *orig_inbuf;
713 static char *orig_outbuf;
714 int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0);
715 unsigned smb_off2 = SVAL(inbuf,smb_vwv1);
716 char *inbuf2, *outbuf2;
718 char inbuf_saved[smb_wct];
719 char outbuf_saved[smb_wct];
720 int wct = CVAL(outbuf,smb_wct);
721 int outsize = smb_size + 2*wct + SVAL(outbuf,smb_vwv0+2*wct);
723 /* maybe its not chained */
724 if (smb_com2 == 0xFF) {
725 CVAL(outbuf,smb_vwv0) = 0xFF;
729 if (chain_size == 0) {
730 /* this is the first part of the chain */
732 orig_outbuf = outbuf;
736 * The original Win95 redirector dies on a reply to
737 * a lockingX and read chain unless the chain reply is
738 * 4 byte aligned. JRA.
741 outsize = (outsize + 3) & ~3;
743 /* we need to tell the client where the next part of the reply will be */
744 SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf));
745 CVAL(outbuf,smb_vwv0) = smb_com2;
747 /* remember how much the caller added to the chain, only counting stuff
748 after the parameter words */
749 chain_size += outsize - smb_wct;
751 /* work out pointers into the original packets. The
752 headers on these need to be filled in */
753 inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct;
754 outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct;
756 /* remember the original command type */
757 smb_com1 = CVAL(orig_inbuf,smb_com);
759 /* save the data which will be overwritten by the new headers */
760 memcpy(inbuf_saved,inbuf2,smb_wct);
761 memcpy(outbuf_saved,outbuf2,smb_wct);
763 /* give the new packet the same header as the last part of the SMB */
764 memmove(inbuf2,inbuf,smb_wct);
766 /* create the in buffer */
767 CVAL(inbuf2,smb_com) = smb_com2;
769 /* create the out buffer */
770 construct_reply_common(inbuf2, outbuf2);
772 DEBUG(3,("Chained message\n"));
775 /* process the request */
776 outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size,
779 /* copy the new reply and request headers over the old ones, but
780 preserve the smb_com field */
781 memmove(orig_outbuf,outbuf2,smb_wct);
782 CVAL(orig_outbuf,smb_com) = smb_com1;
784 /* restore the saved data, being careful not to overwrite any
785 data from the reply header */
786 memcpy(inbuf2,inbuf_saved,smb_wct);
788 int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf);
789 if (ofs < 0) ofs = 0;
790 memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs);
796 /****************************************************************************
797 Setup the needed select timeout.
798 ****************************************************************************/
800 static int setup_select_timeout(void)
802 int change_notify_timeout = lp_change_notify_timeout() * 1000;
806 * Increase the select timeout back to SMBD_SELECT_TIMEOUT if we
807 * have removed any blocking locks. JRA.
810 select_timeout = blocking_locks_pending() ? SMBD_SELECT_TIMEOUT_WITH_PENDING_LOCKS*1000 :
811 SMBD_SELECT_TIMEOUT*1000;
813 if (change_notifies_pending())
814 select_timeout = MIN(select_timeout, change_notify_timeout);
816 return select_timeout;
819 /****************************************************************************
820 Check if services need reloading.
821 ****************************************************************************/
823 void check_reload(int t)
825 static time_t last_smb_conf_reload_time = 0;
827 if(last_smb_conf_reload_time == 0)
828 last_smb_conf_reload_time = t;
830 if (reload_after_sighup || (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK))
832 reload_services(True);
833 reload_after_sighup = False;
834 last_smb_conf_reload_time = t;
838 /****************************************************************************
839 Process any timeout housekeeping. Return False if the caller should exit.
840 ****************************************************************************/
842 static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_timeout_processing_time)
844 static time_t last_keepalive_sent_time = 0;
845 static time_t last_idle_closed_check = 0;
848 extern int keepalive;
850 if (smb_read_error == READ_EOF)
852 DEBUG(3,("end of file from client\n"));
856 if (smb_read_error == READ_ERROR)
858 DEBUG(3,("receive_smb error (%s) exiting\n",
863 *last_timeout_processing_time = t = time(NULL);
865 if(last_keepalive_sent_time == 0)
866 last_keepalive_sent_time = t;
868 if(last_idle_closed_check == 0)
869 last_idle_closed_check = t;
871 /* become root again if waiting */
874 /* check if we need to reload services */
877 /* automatic timeout if all connections are closed */
878 if (conn_num_open()==0 && (t - last_idle_closed_check) >= IDLE_CLOSED_TIMEOUT)
880 DEBUG( 2, ( "Closing idle connection\n" ) );
884 last_idle_closed_check = t;
886 if (keepalive && (t - last_keepalive_sent_time)>keepalive)
888 struct cli_state *cli = server_client();
889 if (!send_keepalive(smbd_server_fd())) {
890 DEBUG( 2, ( "Keepalive failed - exiting.\n" ) );
893 /* also send a keepalive to the password server if its still
895 if (cli && cli->initialised)
896 send_keepalive(cli->fd);
897 last_keepalive_sent_time = t;
900 /* check for connection timeouts */
901 allidle = conn_idle_all(t, deadtime);
903 if (allidle && conn_num_open()>0) {
904 DEBUG(2,("Closing idle connection 2.\n"));
908 if(global_machine_password_needs_changing)
910 unsigned char trust_passwd_hash[16];
912 pstring remote_machine_list;
915 * We're in domain level security, and the code that
916 * read the machine password flagged that the machine
917 * password needs changing.
921 * First, open the machine password file with an exclusive lock.
924 if(!get_trust_account_password(global_myworkgroup, trust_passwd_hash, &lct)) {
925 DEBUG(0,("process: unable to read the machine account password for \
926 machine %s in domain %s.\n", global_myname, global_myworkgroup ));
931 * Make sure someone else hasn't already done this.
934 if(t < lct + lp_machine_password_timeout()) {
935 global_machine_password_needs_changing = False;
939 pstrcpy(remote_machine_list, lp_passwordserver());
941 change_trust_account_password( global_myworkgroup, remote_machine_list);
942 global_machine_password_needs_changing = False;
946 * Check to see if we have any blocking locks
947 * outstanding on the queue.
949 process_blocking_lock_queue(t);
952 * Check to see if we have any change notifies
953 * outstanding on the queue.
955 process_pending_change_notify_queue(t);
958 * Now we are root, check if the log files need pruning.
960 if(need_to_check_log_size())
964 * Modify the select timeout depending upon
965 * what we have remaining in our queues.
968 *select_timeout = setup_select_timeout();
973 /****************************************************************************
974 process commands from the client
975 ****************************************************************************/
977 void smbd_process(void)
979 extern int smb_echo_count;
980 time_t last_timeout_processing_time = time(NULL);
981 unsigned int num_smbs = 0;
983 InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
984 OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
985 if ((InBuffer == NULL) || (OutBuffer == NULL))
988 InBuffer += SMB_ALIGNMENT;
989 OutBuffer += SMB_ALIGNMENT;
991 max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
993 /* re-initialise the timezone */
998 int deadtime = lp_deadtime()*60;
999 BOOL got_smb = False;
1000 int select_timeout = setup_select_timeout();
1003 deadtime = DEFAULT_SMBD_TIMEOUT;
1005 #if USE_READ_PREDICTION
1006 if (lp_readprediction())
1007 do_read_prediction();
1012 /* free up temporary memory */
1016 * If reload_after_sighup == True then we got a SIGHUP
1017 * and are being asked to reload. Fix from <branko.cibej@hermes.si>
1019 if (reload_after_sighup) {
1022 DEBUG(1,("Reloading services after SIGHUP\n"));
1023 reload_services(False);
1024 reload_after_sighup = False;
1027 while(!receive_message_or_smb(InBuffer,BUFFER_SIZE,select_timeout,&got_smb))
1029 if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1031 num_smbs = 0; /* Reset smb counter. */
1036 * Ensure we do timeout processing if the SMB we just got was
1037 * only an echo request. This allows us to set the select
1038 * timeout in 'receive_message_or_smb()' to any value we like
1039 * without worrying that the client will send echo requests
1040 * faster than the select timeout, thus starving out the
1041 * essential processing (change notify, blocking locks) that
1042 * the timeout code does. JRA.
1044 int num_echos = smb_echo_count;
1046 process_smb(InBuffer, OutBuffer);
1048 if(smb_echo_count != num_echos) {
1049 if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1051 num_smbs = 0; /* Reset smb counter. */
1057 * If we are getting smb requests in a constant stream
1058 * with no echos, make sure we attempt timeout processing
1059 * every select_timeout milliseconds - but only check for this
1060 * every 200 smb requests.
1063 if((num_smbs % 200) == 0) {
1064 time_t new_check_time = time(NULL);
1065 if(last_timeout_processing_time - new_check_time >= (select_timeout/1000)) {
1066 if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1068 num_smbs = 0; /* Reset smb counter. */
1069 last_timeout_processing_time = new_check_time; /* Reset time. */
1074 process_local_message(InBuffer, BUFFER_SIZE);