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 all async processing in here. This includes UDB oplock messages, kernel
115 oplock messages, change notify events etc.
116 ****************************************************************************/
117 static void async_processing(fd_set *fds, char *buffer, int buffer_len)
119 /* check for oplock messages (both UDP and kernel) */
120 if (receive_local_message(fds, buffer, buffer_len, 0)) {
121 process_local_message(buffer, buffer_len);
124 /* check for async change notify events */
125 process_pending_change_notify_queue(0);
127 /* check for sighup processing */
128 if (reload_after_sighup) {
130 DEBUG(1,("Reloading services after SIGHUP\n"));
131 reload_services(False);
132 reload_after_sighup = False;
136 /****************************************************************************
137 Do a select on an two fd's - with timeout.
139 If a local udp message has been pushed onto the
140 queue (this can only happen during oplock break
141 processing) call async_processing()
143 If a pending smb message has been pushed onto the
144 queue (this can only happen during oplock break
145 processing) return this next.
147 If the first smbfd is ready then read an smb from it.
148 if the second (loopback UDP) fd is ready then read a message
149 from it and setup the buffer header to identify the length
151 Returns False on timeout or error.
154 The timeout is in milli seconds
155 ****************************************************************************/
157 static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
169 * Note that this call must be before processing any SMB
170 * messages as we need to synchronously process any messages
171 * we may have sent to ourselves from the previous SMB.
176 * Check to see if we already have a message on the smb queue.
177 * If so - copy and return it.
179 if(ubi_slCount(&smb_oplock_queue) != 0) {
180 pending_message_list *msg = (pending_message_list *)ubi_slRemHead(&smb_oplock_queue);
181 memcpy(buffer, msg->msg_buf, MIN(buffer_len, msg->msg_len));
183 /* Free the message we just copied. */
184 free((char *)msg->msg_buf);
187 DEBUG(5,("receive_message_or_smb: returning queued smb message.\n"));
193 * Setup the select read fd set.
197 FD_SET(smbd_server_fd(),&fds);
198 maxfd = setup_oplock_select_set(&fds);
200 to.tv_sec = timeout / 1000;
201 to.tv_usec = (timeout % 1000) * 1000;
203 selrtn = sys_select(MAX(maxfd,smbd_server_fd())+1,&fds,timeout>0?&to:NULL);
205 /* if we get EINTR then maybe we have received an oplock
206 signal - treat this as select returning 1. This is ugly, but
207 is the best we can do until the oplock code knows more about
209 if (selrtn == -1 && errno == EINTR) {
210 async_processing(&fds, buffer, buffer_len);
216 /* something is wrong. Maybe the socket is dead? */
217 smb_read_error = READ_ERROR;
221 /* Did we timeout ? */
223 smb_read_error = READ_TIMEOUT;
227 if (!FD_ISSET(smbd_server_fd(),&fds) || selrtn > 1) {
228 async_processing(&fds, buffer, buffer_len);
229 if (!FD_ISSET(smbd_server_fd(),&fds)) goto again;
232 return receive_smb(smbd_server_fd(), buffer, 0);
235 /****************************************************************************
236 Get the next SMB packet, doing the local message processing automatically.
237 ****************************************************************************/
239 BOOL receive_next_smb(char *inbuf, int bufsize, int timeout)
245 ret = receive_message_or_smb(inbuf,bufsize,timeout);
247 got_keepalive = (ret && (CVAL(inbuf,0) == 0x85));
248 } while (ret && got_keepalive);
253 /****************************************************************************
254 We're terminating and have closed all our files/connections etc.
255 If there are any pending local messages we need to respond to them
256 before termination so that other smbds don't think we just died whilst
258 ****************************************************************************/
260 void respond_to_all_remaining_local_messages(void)
266 * Assert we have no exclusive open oplocks.
269 if(get_number_of_exclusive_open_oplocks()) {
270 DEBUG(0,("respond_to_all_remaining_local_messages: PANIC : we have %d exclusive oplocks.\n",
271 get_number_of_exclusive_open_oplocks() ));
276 * Setup the select read fd set.
280 if(!setup_oplock_select_set(&fds))
284 * Keep doing receive_local_message with a 1 ms timeout until
285 * we have no more messages.
287 while(receive_local_message(&fds, buffer, sizeof(buffer), 1)) {
288 /* Deal with oplock break requests from other smbd's. */
289 process_local_message(buffer, sizeof(buffer));
292 (void)setup_oplock_select_set(&fds);
300 These flags determine some of the permissions required to do an operation
302 Note that I don't set NEED_WRITE on some write operations because they
303 are used by some brain-dead clients when printing, and I don't want to
304 force write permissions on print services.
306 #define AS_USER (1<<0)
307 #define NEED_WRITE (1<<1)
308 #define TIME_INIT (1<<2)
309 #define CAN_IPC (1<<3)
310 #define AS_GUEST (1<<5)
311 #define QUEUE_IN_OPLOCK (1<<6)
314 define a list of possible SMB messages and their corresponding
315 functions. Any message that has a NULL function is unimplemented -
316 please feel free to contribute implementations!
318 struct smb_message_struct
322 int (*fn)(connection_struct *conn, char *, char *, int, int);
329 {SMBnegprot,"SMBnegprot",reply_negprot,0},
330 {SMBtcon,"SMBtcon",reply_tcon,0},
331 {SMBtdis,"SMBtdis",reply_tdis,0},
332 {SMBexit,"SMBexit",reply_exit,0},
333 {SMBioctl,"SMBioctl",reply_ioctl,0},
334 {SMBecho,"SMBecho",reply_echo,0},
335 {SMBsesssetupX,"SMBsesssetupX",reply_sesssetup_and_X,0},
336 {SMBtconX,"SMBtconX",reply_tcon_and_X,0},
337 {SMBulogoffX, "SMBulogoffX", reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
338 {SMBgetatr,"SMBgetatr",reply_getatr,AS_USER},
339 {SMBsetatr,"SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
340 {SMBchkpth,"SMBchkpth",reply_chkpth,AS_USER},
341 {SMBsearch,"SMBsearch",reply_search,AS_USER},
342 {SMBopen,"SMBopen",reply_open,AS_USER | QUEUE_IN_OPLOCK },
344 /* note that SMBmknew and SMBcreate are deliberately overloaded */
345 {SMBcreate,"SMBcreate",reply_mknew,AS_USER},
346 {SMBmknew,"SMBmknew",reply_mknew,AS_USER},
348 {SMBunlink,"SMBunlink",reply_unlink,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK},
349 {SMBread,"SMBread",reply_read,AS_USER},
350 {SMBwrite,"SMBwrite",reply_write,AS_USER | CAN_IPC },
351 {SMBclose,"SMBclose",reply_close,AS_USER | CAN_IPC },
352 {SMBmkdir,"SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
353 {SMBrmdir,"SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
354 {SMBdskattr,"SMBdskattr",reply_dskattr,AS_USER},
355 {SMBmv,"SMBmv",reply_mv,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK},
357 /* this is a Pathworks specific call, allowing the
358 changing of the root path */
359 {pSETDIR,"pSETDIR",reply_setdir,AS_USER},
361 {SMBlseek,"SMBlseek",reply_lseek,AS_USER},
362 {SMBflush,"SMBflush",reply_flush,AS_USER},
363 {SMBctemp,"SMBctemp",reply_ctemp,AS_USER | QUEUE_IN_OPLOCK },
364 {SMBsplopen,"SMBsplopen",reply_printopen,AS_USER | QUEUE_IN_OPLOCK },
365 {SMBsplclose,"SMBsplclose",reply_printclose,AS_USER},
366 {SMBsplretq,"SMBsplretq",reply_printqueue,AS_USER},
367 {SMBsplwr,"SMBsplwr",reply_printwrite,AS_USER},
368 {SMBlock,"SMBlock",reply_lock,AS_USER},
369 {SMBunlock,"SMBunlock",reply_unlock,AS_USER},
371 /* CORE+ PROTOCOL FOLLOWS */
373 {SMBreadbraw,"SMBreadbraw",reply_readbraw,AS_USER},
374 {SMBwritebraw,"SMBwritebraw",reply_writebraw,AS_USER},
375 {SMBwriteclose,"SMBwriteclose",reply_writeclose,AS_USER},
376 {SMBlockread,"SMBlockread",reply_lockread,AS_USER},
377 {SMBwriteunlock,"SMBwriteunlock",reply_writeunlock,AS_USER},
379 /* LANMAN1.0 PROTOCOL FOLLOWS */
381 {SMBreadBmpx,"SMBreadBmpx",reply_readbmpx,AS_USER},
382 {SMBreadBs,"SMBreadBs",NULL,AS_USER},
383 {SMBwriteBmpx,"SMBwriteBmpx",reply_writebmpx,AS_USER},
384 {SMBwriteBs,"SMBwriteBs",reply_writebs,AS_USER},
385 {SMBwritec,"SMBwritec",NULL,AS_USER},
386 {SMBsetattrE,"SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE },
387 {SMBgetattrE,"SMBgetattrE",reply_getattrE,AS_USER },
388 {SMBtrans,"SMBtrans",reply_trans,AS_USER | CAN_IPC | QUEUE_IN_OPLOCK},
389 {SMBtranss,"SMBtranss",NULL,AS_USER | CAN_IPC},
390 {SMBioctls,"SMBioctls",NULL,AS_USER},
391 {SMBcopy,"SMBcopy",reply_copy,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK },
392 {SMBmove,"SMBmove",NULL,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK },
394 {SMBopenX,"SMBopenX",reply_open_and_X,AS_USER | CAN_IPC | QUEUE_IN_OPLOCK },
395 {SMBreadX,"SMBreadX",reply_read_and_X,AS_USER | CAN_IPC },
396 {SMBwriteX,"SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC },
397 {SMBlockingX,"SMBlockingX",reply_lockingX,AS_USER },
399 {SMBffirst,"SMBffirst",reply_search,AS_USER},
400 {SMBfunique,"SMBfunique",reply_search,AS_USER},
401 {SMBfclose,"SMBfclose",reply_fclose,AS_USER},
403 /* LANMAN2.0 PROTOCOL FOLLOWS */
404 {SMBfindnclose, "SMBfindnclose", reply_findnclose, AS_USER},
405 {SMBfindclose, "SMBfindclose", reply_findclose,AS_USER},
406 {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER | QUEUE_IN_OPLOCK | CAN_IPC },
407 {SMBtranss2, "SMBtranss2", reply_transs2, AS_USER},
409 /* NT PROTOCOL FOLLOWS */
410 {SMBntcreateX, "SMBntcreateX", reply_ntcreate_and_X, AS_USER | CAN_IPC | QUEUE_IN_OPLOCK },
411 {SMBnttrans, "SMBnttrans", reply_nttrans, AS_USER | CAN_IPC | QUEUE_IN_OPLOCK},
412 {SMBnttranss, "SMBnttranss", reply_nttranss, AS_USER | CAN_IPC },
413 {SMBntcancel, "SMBntcancel", reply_ntcancel, 0 },
415 /* messaging routines */
416 {SMBsends,"SMBsends",reply_sends,AS_GUEST},
417 {SMBsendstrt,"SMBsendstrt",reply_sendstrt,AS_GUEST},
418 {SMBsendend,"SMBsendend",reply_sendend,AS_GUEST},
419 {SMBsendtxt,"SMBsendtxt",reply_sendtxt,AS_GUEST},
421 /* NON-IMPLEMENTED PARTS OF THE CORE PROTOCOL */
423 {SMBsendb,"SMBsendb",NULL,AS_GUEST},
424 {SMBfwdname,"SMBfwdname",NULL,AS_GUEST},
425 {SMBcancelf,"SMBcancelf",NULL,AS_GUEST},
426 {SMBgetmac,"SMBgetmac",NULL,AS_GUEST}
429 /*******************************************************************
431 ********************************************************************/
432 static void smb_dump(char *name, int type, char *data, ssize_t len)
436 if (DEBUGLEVEL < 50) return;
438 if (len < 4) len = smb_len(data)+4;
439 for (i=1;i<100;i++) {
440 slprintf(fname,sizeof(fname), "/tmp/%s.%d.%s", name, i,
441 type ? "req" : "resp");
442 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644);
443 if (fd != -1 || errno != EEXIST) break;
446 write(fd, data, len);
448 DEBUG(0,("created %s len %d\n", fname, len));
453 /****************************************************************************
454 do a switch on the message type, and return the response size
455 ****************************************************************************/
456 static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize)
458 static pid_t pid= (pid_t)-1;
460 static int num_smb_messages =
461 sizeof(smb_messages) / sizeof(struct smb_message_struct);
463 extern int global_smbpid;
465 if (pid == (pid_t)-1)
471 /* make sure this is an SMB packet */
472 if (strncmp(smb_base(inbuf),"\377SMB",4) != 0)
474 DEBUG(2,("Non-SMB packet of length %d\n",smb_len(inbuf)));
478 for (match=0;match<num_smb_messages;match++)
479 if (smb_messages[match].code == type)
482 /* yuck! this is an interim measure before we get rid of our
483 current inbuf/outbuf system */
484 global_smbpid = SVAL(inbuf,smb_pid);
486 if (match == num_smb_messages)
488 DEBUG(0,("Unknown message type %d!\n",type));
489 smb_dump("Unknown", 1, inbuf, size);
490 outsize = reply_unknown(inbuf,outbuf);
494 DEBUG(3,("switch message %s (pid %d)\n",smb_messages[match].name,(int)pid));
496 smb_dump(smb_messages[match].name, 1, inbuf, size);
497 if(global_oplock_break)
499 int flags = smb_messages[match].flags;
501 if(flags & QUEUE_IN_OPLOCK)
504 * Queue this message as we are the process of an oplock break.
507 DEBUG( 2, ( "switch_message: queueing message due to being in " ) );
508 DEBUGADD( 2, ( "oplock break state.\n" ) );
510 push_oplock_pending_smb_message( inbuf, size );
514 if (smb_messages[match].fn)
516 int flags = smb_messages[match].flags;
517 static uint16 last_session_tag = UID_FIELD_INVALID;
518 /* In share mode security we must ignore the vuid. */
519 uint16 session_tag = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(inbuf,smb_uid);
520 connection_struct *conn = conn_find(SVAL(inbuf,smb_tid));
523 /* Ensure this value is replaced in the incoming packet. */
524 SSVAL(inbuf,smb_uid,session_tag);
527 * Ensure the correct username is in sesssetup_user.
528 * This is a really ugly bugfix for problems with
529 * multiple session_setup_and_X's being done and
530 * allowing %U and %G substitutions to work correctly.
531 * There is a reason this code is done here, don't
532 * move it unless you know what you're doing... :-).
535 if (session_tag != last_session_tag) {
536 user_struct *vuser = NULL;
538 last_session_tag = session_tag;
539 if(session_tag != UID_FIELD_INVALID)
540 vuser = get_valid_user_struct(session_tag);
542 pstrcpy( sesssetup_user, vuser->user.smb_name);
545 /* does this protocol need to be run as root? */
546 if (!(flags & AS_USER))
549 /* does this protocol need to be run as the connected user? */
550 if ((flags & AS_USER) && !become_user(conn,session_tag)) {
551 if (flags & AS_GUEST)
554 return(ERROR(ERRSRV,ERRaccess));
556 /* this code is to work around a bug is MS client 3 without
557 introducing a security hole - it needs to be able to do
558 print queue checks as guest if it isn't logged in properly */
562 /* does it need write permission? */
563 if ((flags & NEED_WRITE) && !CAN_WRITE(conn))
564 return(ERROR(ERRSRV,ERRaccess));
566 /* ipc services are limited */
567 if (IS_IPC(conn) && (flags & AS_USER) && !(flags & CAN_IPC)) {
568 return(ERROR(ERRSRV,ERRaccess));
571 /* load service specific parameters */
572 if (conn && !become_service(conn,(flags & AS_USER)?True:False)) {
573 return(ERROR(ERRSRV,ERRaccess));
576 /* does this protocol need to be run as guest? */
577 if ((flags & AS_GUEST) &&
579 !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1)))) {
580 return(ERROR(ERRSRV,ERRaccess));
585 outsize = smb_messages[match].fn(conn, inbuf,outbuf,size,bufsize);
589 outsize = reply_unknown(inbuf,outbuf);
593 smb_dump(smb_messages[match].name, 0, outbuf, outsize);
599 /****************************************************************************
600 construct a reply to the incoming packet
601 ****************************************************************************/
602 static int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
604 int type = CVAL(inbuf,smb_com);
606 int msg_type = CVAL(inbuf,0);
608 GetTimeOfDay(&smb_last_time);
615 return(reply_special(inbuf,outbuf));
617 construct_reply_common(inbuf, outbuf);
619 outsize = switch_message(type,inbuf,outbuf,size,bufsize);
621 outsize += chain_size;
624 smb_setlen(outbuf,outsize - 4);
629 /****************************************************************************
630 process an smb from the client - split out from the process() code so
631 it can be used by the oplock break code.
632 ****************************************************************************/
633 void process_smb(char *inbuf, char *outbuf)
636 extern BOOL sslEnabled; /* don't use function for performance reasons */
637 static int sslConnected = 0;
638 #endif /* WITH_SSL */
639 static int trans_num;
640 int msg_type = CVAL(inbuf,0);
641 int32 len = smb_len(inbuf);
644 DO_PROFILE_INC(smb_count);
646 if (trans_num == 0) {
647 /* on the first packet, check the global hosts allow/ hosts
648 deny parameters before doing any parsing of the packet
649 passed to us by the client. This prevents attacks on our
650 parsing code from hosts not in the hosts allow list */
651 if (!check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1))) {
652 /* send a negative session response "not listining on calling
654 static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
655 DEBUG( 1, ( "Connection denied from %s\n",
657 send_smb(smbd_server_fd(),(char *)buf);
658 exit_server("connection denied");
662 DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type, len ) );
663 DEBUG( 3, ( "Transaction %d of length %d\n", trans_num, nread ) );
666 if(sslEnabled && !sslConnected){
667 sslConnected = sslutil_negotiate_ssl(smbd_server_fd(), msg_type);
668 if(sslConnected < 0){ /* an error occured */
669 exit_server("SSL negotiation failed");
670 }else if(sslConnected){
675 #endif /* WITH_SSL */
679 else if(msg_type == 0x85)
680 return; /* Keepalive packet. */
682 nread = construct_reply(inbuf,outbuf,nread,max_send);
686 if (CVAL(outbuf,0) == 0)
689 if (nread != smb_len(outbuf) + 4)
691 DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
692 nread, smb_len(outbuf)));
695 send_smb(smbd_server_fd(),outbuf);
702 /****************************************************************************
703 return a string containing the function name of a SMB command
704 ****************************************************************************/
705 char *smb_fn_name(int type)
707 static char *unknown_name = "SMBunknown";
708 static int num_smb_messages =
709 sizeof(smb_messages) / sizeof(struct smb_message_struct);
712 for (match=0;match<num_smb_messages;match++)
713 if (smb_messages[match].code == type)
716 if (match == num_smb_messages)
717 return(unknown_name);
719 return(smb_messages[match].name);
723 /****************************************************************************
724 Helper function for contruct_reply.
725 ****************************************************************************/
727 void construct_reply_common(char *inbuf,char *outbuf)
729 memset(outbuf,'\0',smb_size);
731 set_message(outbuf,0,0,True);
732 CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com);
734 memcpy(outbuf+4,inbuf+4,4);
735 CVAL(outbuf,smb_rcls) = SMB_SUCCESS;
736 CVAL(outbuf,smb_reh) = 0;
737 SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES)); /* bit 7 set
739 SSVAL(outbuf,smb_flg2,FLAGS2_LONG_PATH_COMPONENTS);
740 /* say we support long filenames */
742 SSVAL(outbuf,smb_err,SMB_SUCCESS);
743 SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
744 SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
745 SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
746 SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
749 /****************************************************************************
750 construct a chained reply and add it to the already made reply
751 **************************************************************************/
752 int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
754 static char *orig_inbuf;
755 static char *orig_outbuf;
756 int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0);
757 unsigned smb_off2 = SVAL(inbuf,smb_vwv1);
758 char *inbuf2, *outbuf2;
760 char inbuf_saved[smb_wct];
761 char outbuf_saved[smb_wct];
762 int wct = CVAL(outbuf,smb_wct);
763 int outsize = smb_size + 2*wct + SVAL(outbuf,smb_vwv0+2*wct);
765 /* maybe its not chained */
766 if (smb_com2 == 0xFF) {
767 CVAL(outbuf,smb_vwv0) = 0xFF;
771 if (chain_size == 0) {
772 /* this is the first part of the chain */
774 orig_outbuf = outbuf;
778 * The original Win95 redirector dies on a reply to
779 * a lockingX and read chain unless the chain reply is
780 * 4 byte aligned. JRA.
783 outsize = (outsize + 3) & ~3;
785 /* we need to tell the client where the next part of the reply will be */
786 SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf));
787 CVAL(outbuf,smb_vwv0) = smb_com2;
789 /* remember how much the caller added to the chain, only counting stuff
790 after the parameter words */
791 chain_size += outsize - smb_wct;
793 /* work out pointers into the original packets. The
794 headers on these need to be filled in */
795 inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct;
796 outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct;
798 /* remember the original command type */
799 smb_com1 = CVAL(orig_inbuf,smb_com);
801 /* save the data which will be overwritten by the new headers */
802 memcpy(inbuf_saved,inbuf2,smb_wct);
803 memcpy(outbuf_saved,outbuf2,smb_wct);
805 /* give the new packet the same header as the last part of the SMB */
806 memmove(inbuf2,inbuf,smb_wct);
808 /* create the in buffer */
809 CVAL(inbuf2,smb_com) = smb_com2;
811 /* create the out buffer */
812 construct_reply_common(inbuf2, outbuf2);
814 DEBUG(3,("Chained message\n"));
817 /* process the request */
818 outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size,
821 /* copy the new reply and request headers over the old ones, but
822 preserve the smb_com field */
823 memmove(orig_outbuf,outbuf2,smb_wct);
824 CVAL(orig_outbuf,smb_com) = smb_com1;
826 /* restore the saved data, being careful not to overwrite any
827 data from the reply header */
828 memcpy(inbuf2,inbuf_saved,smb_wct);
830 int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf);
831 if (ofs < 0) ofs = 0;
832 memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs);
838 /****************************************************************************
839 Setup the needed select timeout.
840 ****************************************************************************/
842 static int setup_select_timeout(void)
848 * Increase the select timeout back to SMBD_SELECT_TIMEOUT if we
849 * have removed any blocking locks. JRA.
852 select_timeout = blocking_locks_pending() ? SMBD_SELECT_TIMEOUT_WITH_PENDING_LOCKS*1000 :
853 SMBD_SELECT_TIMEOUT*1000;
855 t = change_notify_timeout();
856 if (t != -1) select_timeout = MIN(select_timeout, t*1000);
858 return select_timeout;
861 /****************************************************************************
862 Check if services need reloading.
863 ****************************************************************************/
865 void check_reload(int t)
867 static time_t last_smb_conf_reload_time = 0;
869 if(last_smb_conf_reload_time == 0)
870 last_smb_conf_reload_time = t;
872 if (reload_after_sighup || (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK))
874 reload_services(True);
875 reload_after_sighup = False;
876 last_smb_conf_reload_time = t;
880 /****************************************************************************
881 Process any timeout housekeeping. Return False if the caller should exit.
882 ****************************************************************************/
884 static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_timeout_processing_time)
886 static time_t last_keepalive_sent_time = 0;
887 static time_t last_idle_closed_check = 0;
890 extern int keepalive;
892 if (smb_read_error == READ_EOF)
894 DEBUG(3,("end of file from client\n"));
898 if (smb_read_error == READ_ERROR)
900 DEBUG(3,("receive_smb error (%s) exiting\n",
905 *last_timeout_processing_time = t = time(NULL);
907 if(last_keepalive_sent_time == 0)
908 last_keepalive_sent_time = t;
910 if(last_idle_closed_check == 0)
911 last_idle_closed_check = t;
913 /* become root again if waiting */
916 /* check if we need to reload services */
919 /* automatic timeout if all connections are closed */
920 if (conn_num_open()==0 && (t - last_idle_closed_check) >= IDLE_CLOSED_TIMEOUT)
922 DEBUG( 2, ( "Closing idle connection\n" ) );
926 last_idle_closed_check = t;
928 if (keepalive && (t - last_keepalive_sent_time)>keepalive)
930 struct cli_state *cli = server_client();
931 if (!send_keepalive(smbd_server_fd())) {
932 DEBUG( 2, ( "Keepalive failed - exiting.\n" ) );
935 /* also send a keepalive to the password server if its still
937 if (cli && cli->initialised)
938 send_keepalive(cli->fd);
939 last_keepalive_sent_time = t;
942 /* check for connection timeouts */
943 allidle = conn_idle_all(t, deadtime);
945 if (allidle && conn_num_open()>0) {
946 DEBUG(2,("Closing idle connection 2.\n"));
950 if(global_machine_password_needs_changing)
952 unsigned char trust_passwd_hash[16];
954 pstring remote_machine_list;
957 * We're in domain level security, and the code that
958 * read the machine password flagged that the machine
959 * password needs changing.
963 * First, open the machine password file with an exclusive lock.
966 if(!secrets_fetch_trust_account_password(global_myworkgroup, trust_passwd_hash, &lct)) {
967 DEBUG(0,("process: unable to read the machine account password for \
968 machine %s in domain %s.\n", global_myname, global_myworkgroup ));
973 * Make sure someone else hasn't already done this.
976 if(t < lct + lp_machine_password_timeout()) {
977 global_machine_password_needs_changing = False;
981 pstrcpy(remote_machine_list, lp_passwordserver());
983 change_trust_account_password( global_myworkgroup, remote_machine_list);
984 global_machine_password_needs_changing = False;
988 * Check to see if we have any blocking locks
989 * outstanding on the queue.
991 process_blocking_lock_queue(t);
994 * Check to see if we have any change notifies
995 * outstanding on the queue.
997 process_pending_change_notify_queue(t);
1000 * Now we are root, check if the log files need pruning.
1002 if(need_to_check_log_size())
1006 * Modify the select timeout depending upon
1007 * what we have remaining in our queues.
1010 *select_timeout = setup_select_timeout();
1015 /****************************************************************************
1016 process commands from the client
1017 ****************************************************************************/
1019 void smbd_process(void)
1021 extern int smb_echo_count;
1022 time_t last_timeout_processing_time = time(NULL);
1023 unsigned int num_smbs = 0;
1025 InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1026 OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
1027 if ((InBuffer == NULL) || (OutBuffer == NULL))
1030 InBuffer += SMB_ALIGNMENT;
1031 OutBuffer += SMB_ALIGNMENT;
1033 max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
1035 /* re-initialise the timezone */
1039 int deadtime = lp_deadtime()*60;
1040 int select_timeout = setup_select_timeout();
1044 deadtime = DEFAULT_SMBD_TIMEOUT;
1048 /* free up temporary memory */
1050 parse_talloc_free();
1052 while (!receive_message_or_smb(InBuffer,BUFFER_SIZE,select_timeout)) {
1053 if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1055 num_smbs = 0; /* Reset smb counter. */
1059 * Ensure we do timeout processing if the SMB we just got was
1060 * only an echo request. This allows us to set the select
1061 * timeout in 'receive_message_or_smb()' to any value we like
1062 * without worrying that the client will send echo requests
1063 * faster than the select timeout, thus starving out the
1064 * essential processing (change notify, blocking locks) that
1065 * the timeout code does. JRA.
1067 num_echos = smb_echo_count;
1069 process_smb(InBuffer, OutBuffer);
1071 if (smb_echo_count != num_echos) {
1072 if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1074 num_smbs = 0; /* Reset smb counter. */
1080 * If we are getting smb requests in a constant stream
1081 * with no echos, make sure we attempt timeout processing
1082 * every select_timeout milliseconds - but only check for this
1083 * every 200 smb requests.
1086 if ((num_smbs % 200) == 0) {
1087 time_t new_check_time = time(NULL);
1088 if(last_timeout_processing_time - new_check_time >= (select_timeout/1000)) {
1089 if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1091 num_smbs = 0; /* Reset smb counter. */
1092 last_timeout_processing_time = new_check_time; /* Reset time. */