finally got sick of the "extern int Client" code and the stupid
[abartlet/samba.git/.git] / source3 / smbd / process.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    process incoming packets - main loop
5    Copyright (C) Andrew Tridgell 1992-1998
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23
24 extern int DEBUGLEVEL;
25
26 struct timeval smb_last_time;
27
28 static char *InBuffer = NULL;
29 char *OutBuffer = NULL;
30 char *last_inbuf = NULL;
31
32 /* 
33  * Size of data we can send to client. Set
34  *  by the client for all protocols above CORE.
35  *  Set by us for CORE protocol.
36  */
37 int max_send = BUFFER_SIZE;
38 /*
39  * Size of the data we can receive. Set by us.
40  * Can be modified by the max xmit parameter.
41  */
42 int max_recv = BUFFER_SIZE;
43
44 extern int last_message;
45 extern int global_oplock_break;
46 extern pstring sesssetup_user;
47 extern char *last_inbuf;
48 extern char *InBuffer;
49 extern char *OutBuffer;
50 extern int smb_read_error;
51 extern VOLATILE SIG_ATOMIC_T reload_after_sighup;
52 extern BOOL global_machine_password_needs_changing;
53 extern fstring global_myworkgroup;
54 extern pstring global_myname;
55 extern int max_send;
56
57 /****************************************************************************
58  structure to hold a linked list of queued messages.
59  for processing.
60 ****************************************************************************/
61
62 typedef struct {
63    ubi_slNode msg_next;
64    char *msg_buf;
65    int msg_len;
66 } pending_message_list;
67
68 static ubi_slList smb_oplock_queue = { NULL, (ubi_slNodePtr)&smb_oplock_queue, 0};
69
70 /****************************************************************************
71  Function to push a message onto the tail of a linked list of smb messages ready
72  for processing.
73 ****************************************************************************/
74
75 static BOOL push_message(ubi_slList *list_head, char *buf, int msg_len)
76 {
77   pending_message_list *msg = (pending_message_list *)
78                                malloc(sizeof(pending_message_list));
79
80   if(msg == NULL)
81   {
82     DEBUG(0,("push_message: malloc fail (1)\n"));
83     return False;
84   }
85
86   msg->msg_buf = (char *)malloc(msg_len);
87   if(msg->msg_buf == NULL)
88   {
89     DEBUG(0,("push_message: malloc fail (2)\n"));
90     free((char *)msg);
91     return False;
92   }
93
94   memcpy(msg->msg_buf, buf, msg_len);
95   msg->msg_len = msg_len;
96
97   ubi_slAddTail( list_head, msg);
98
99   return True;
100 }
101
102 /****************************************************************************
103  Function to push a smb message onto a linked list of local smb messages ready
104  for processing.
105 ****************************************************************************/
106
107 BOOL push_oplock_pending_smb_message(char *buf, int msg_len)
108 {
109   return push_message(&smb_oplock_queue, buf, msg_len);
110 }
111
112 /****************************************************************************
113   Do a select on an two fd's - with timeout. 
114
115   If a local udp message has been pushed onto the
116   queue (this can only happen during oplock break
117   processing) return this first.
118
119   If a pending smb message has been pushed onto the
120   queue (this can only happen during oplock break
121   processing) return this next.
122
123   If the first smbfd is ready then read an smb from it.
124   if the second (loopback UDP) fd is ready then read a message
125   from it and setup the buffer header to identify the length
126   and from address.
127   Returns False on timeout or error.
128   Else returns True.
129
130 The timeout is in milli seconds
131 ****************************************************************************/
132
133 static BOOL receive_message_or_smb(char *buffer, int buffer_len, 
134                                    int timeout, BOOL *got_smb)
135 {
136   fd_set fds;
137   int selrtn;
138   struct timeval to;
139   int maxfd;
140
141   smb_read_error = 0;
142
143   *got_smb = False;
144
145   /*
146    * Check to see if we already have a message on the smb queue.
147    * If so - copy and return it.
148    */
149   
150   if(ubi_slCount(&smb_oplock_queue) != 0)
151   {
152     pending_message_list *msg = (pending_message_list *)ubi_slRemHead(&smb_oplock_queue);
153     memcpy(buffer, msg->msg_buf, MIN(buffer_len, msg->msg_len));
154   
155     /* Free the message we just copied. */
156     free((char *)msg->msg_buf);
157     free((char *)msg);
158     *got_smb = True;
159
160     DEBUG(5,("receive_message_or_smb: returning queued smb message.\n"));
161     return True;
162   }
163
164   /*
165    * Setup the select read fd set.
166    */
167
168   FD_ZERO(&fds);
169   FD_SET(smbd_server_fd(),&fds);
170   maxfd = setup_oplock_select_set(&fds);
171
172   to.tv_sec = timeout / 1000;
173   to.tv_usec = (timeout % 1000) * 1000;
174
175   selrtn = sys_select(MAX(maxfd,smbd_server_fd())+1,&fds,timeout>0?&to:NULL);
176
177   /* Check if error */
178   if(selrtn == -1) {
179     /* something is wrong. Maybe the socket is dead? */
180     smb_read_error = READ_ERROR;
181     return False;
182   } 
183     
184   /* Did we timeout ? */
185   if (selrtn == 0) {
186     smb_read_error = READ_TIMEOUT;
187     return False;
188   }
189
190   if (FD_ISSET(smbd_server_fd(),&fds))
191   {
192     *got_smb = True;
193     return receive_smb(smbd_server_fd(), buffer, 0);
194   }
195   else
196   {
197     return receive_local_message(&fds, buffer, buffer_len, 0);
198   }
199 }
200
201 /****************************************************************************
202 Get the next SMB packet, doing the local message processing automatically.
203 ****************************************************************************/
204
205 BOOL receive_next_smb(char *inbuf, int bufsize, int timeout)
206 {
207   BOOL got_smb = False;
208   BOOL ret;
209
210   do
211   {
212     ret = receive_message_or_smb(inbuf,bufsize,timeout,&got_smb);
213
214     if(ret && !got_smb)
215     {
216       /* Deal with oplock break requests from other smbd's. */
217       process_local_message(inbuf, bufsize);
218       continue;
219     }
220
221     if(ret && (CVAL(inbuf,0) == 0x85))
222     {
223       /* Keepalive packet. */
224       got_smb = False;
225     }
226
227   }
228   while(ret && !got_smb);
229
230   return ret;
231 }
232
233 /****************************************************************************
234  We're terminating and have closed all our files/connections etc.
235  If there are any pending local messages we need to respond to them
236  before termination so that other smbds don't think we just died whilst
237  holding oplocks.
238 ****************************************************************************/
239
240 void respond_to_all_remaining_local_messages(void)
241 {
242   char buffer[1024];
243   fd_set fds;
244
245   /*
246    * Assert we have no exclusive open oplocks.
247    */
248
249   if(get_number_of_exclusive_open_oplocks()) {
250     DEBUG(0,("respond_to_all_remaining_local_messages: PANIC : we have %d exclusive oplocks.\n",
251           get_number_of_exclusive_open_oplocks() ));
252     return;
253   }
254
255   /*
256    * Setup the select read fd set.
257    */
258
259   FD_ZERO(&fds);
260   if(!setup_oplock_select_set(&fds))
261     return;
262
263   /*
264    * Keep doing receive_local_message with a 1 ms timeout until
265    * we have no more messages.
266    */
267
268   while(receive_local_message(&fds, buffer, sizeof(buffer), 1)) {
269     /* Deal with oplock break requests from other smbd's. */
270     process_local_message(buffer, sizeof(buffer));
271
272     FD_ZERO(&fds);
273     (void)setup_oplock_select_set(&fds);
274   }
275
276   return;
277 }
278
279
280 /*
281 These flags determine some of the permissions required to do an operation 
282
283 Note that I don't set NEED_WRITE on some write operations because they
284 are used by some brain-dead clients when printing, and I don't want to
285 force write permissions on print services.
286 */
287 #define AS_USER (1<<0)
288 #define NEED_WRITE (1<<1)
289 #define TIME_INIT (1<<2)
290 #define CAN_IPC (1<<3)
291 #define AS_GUEST (1<<5)
292 #define QUEUE_IN_OPLOCK (1<<6)
293
294 /* 
295    define a list of possible SMB messages and their corresponding
296    functions. Any message that has a NULL function is unimplemented -
297    please feel free to contribute implementations!
298 */
299 struct smb_message_struct
300 {
301   int code;
302   char *name;
303   int (*fn)(connection_struct *conn, char *, char *, int, int);
304   int flags;
305 }
306  smb_messages[] = {
307
308     /* CORE PROTOCOL */
309
310    {SMBnegprot,"SMBnegprot",reply_negprot,0},
311    {SMBtcon,"SMBtcon",reply_tcon,0},
312    {SMBtdis,"SMBtdis",reply_tdis,0},
313    {SMBexit,"SMBexit",reply_exit,0},
314    {SMBioctl,"SMBioctl",reply_ioctl,0},
315    {SMBecho,"SMBecho",reply_echo,0},
316    {SMBsesssetupX,"SMBsesssetupX",reply_sesssetup_and_X,0},
317    {SMBtconX,"SMBtconX",reply_tcon_and_X,0},
318    {SMBulogoffX, "SMBulogoffX", reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
319    {SMBgetatr,"SMBgetatr",reply_getatr,AS_USER},
320    {SMBsetatr,"SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
321    {SMBchkpth,"SMBchkpth",reply_chkpth,AS_USER},
322    {SMBsearch,"SMBsearch",reply_search,AS_USER},
323    {SMBopen,"SMBopen",reply_open,AS_USER | QUEUE_IN_OPLOCK },
324
325    /* note that SMBmknew and SMBcreate are deliberately overloaded */   
326    {SMBcreate,"SMBcreate",reply_mknew,AS_USER},
327    {SMBmknew,"SMBmknew",reply_mknew,AS_USER}, 
328
329    {SMBunlink,"SMBunlink",reply_unlink,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK},
330    {SMBread,"SMBread",reply_read,AS_USER},
331    {SMBwrite,"SMBwrite",reply_write,AS_USER | CAN_IPC },
332    {SMBclose,"SMBclose",reply_close,AS_USER | CAN_IPC },
333    {SMBmkdir,"SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
334    {SMBrmdir,"SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
335    {SMBdskattr,"SMBdskattr",reply_dskattr,AS_USER},
336    {SMBmv,"SMBmv",reply_mv,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK},
337
338    /* this is a Pathworks specific call, allowing the 
339       changing of the root path */
340    {pSETDIR,"pSETDIR",reply_setdir,AS_USER}, 
341
342    {SMBlseek,"SMBlseek",reply_lseek,AS_USER},
343    {SMBflush,"SMBflush",reply_flush,AS_USER},
344    {SMBctemp,"SMBctemp",reply_ctemp,AS_USER | QUEUE_IN_OPLOCK },
345    {SMBsplopen,"SMBsplopen",reply_printopen,AS_USER | QUEUE_IN_OPLOCK },
346    {SMBsplclose,"SMBsplclose",reply_printclose,AS_USER},
347    {SMBsplretq,"SMBsplretq",reply_printqueue,AS_USER},
348    {SMBsplwr,"SMBsplwr",reply_printwrite,AS_USER},
349    {SMBlock,"SMBlock",reply_lock,AS_USER},
350    {SMBunlock,"SMBunlock",reply_unlock,AS_USER},
351    
352    /* CORE+ PROTOCOL FOLLOWS */
353    
354    {SMBreadbraw,"SMBreadbraw",reply_readbraw,AS_USER},
355    {SMBwritebraw,"SMBwritebraw",reply_writebraw,AS_USER},
356    {SMBwriteclose,"SMBwriteclose",reply_writeclose,AS_USER},
357    {SMBlockread,"SMBlockread",reply_lockread,AS_USER},
358    {SMBwriteunlock,"SMBwriteunlock",reply_writeunlock,AS_USER},
359    
360    /* LANMAN1.0 PROTOCOL FOLLOWS */
361    
362    {SMBreadBmpx,"SMBreadBmpx",reply_readbmpx,AS_USER},
363    {SMBreadBs,"SMBreadBs",NULL,AS_USER},
364    {SMBwriteBmpx,"SMBwriteBmpx",reply_writebmpx,AS_USER},
365    {SMBwriteBs,"SMBwriteBs",reply_writebs,AS_USER},
366    {SMBwritec,"SMBwritec",NULL,AS_USER},
367    {SMBsetattrE,"SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE },
368    {SMBgetattrE,"SMBgetattrE",reply_getattrE,AS_USER },
369    {SMBtrans,"SMBtrans",reply_trans,AS_USER | CAN_IPC | QUEUE_IN_OPLOCK},
370    {SMBtranss,"SMBtranss",NULL,AS_USER | CAN_IPC},
371    {SMBioctls,"SMBioctls",NULL,AS_USER},
372    {SMBcopy,"SMBcopy",reply_copy,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK },
373    {SMBmove,"SMBmove",NULL,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK },
374    
375    {SMBopenX,"SMBopenX",reply_open_and_X,AS_USER | CAN_IPC | QUEUE_IN_OPLOCK },
376    {SMBreadX,"SMBreadX",reply_read_and_X,AS_USER | CAN_IPC },
377    {SMBwriteX,"SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC },
378    {SMBlockingX,"SMBlockingX",reply_lockingX,AS_USER },
379    
380    {SMBffirst,"SMBffirst",reply_search,AS_USER},
381    {SMBfunique,"SMBfunique",reply_search,AS_USER},
382    {SMBfclose,"SMBfclose",reply_fclose,AS_USER},
383
384    /* LANMAN2.0 PROTOCOL FOLLOWS */
385    {SMBfindnclose, "SMBfindnclose", reply_findnclose, AS_USER},
386    {SMBfindclose, "SMBfindclose", reply_findclose,AS_USER},
387    {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER | QUEUE_IN_OPLOCK | CAN_IPC },
388    {SMBtranss2, "SMBtranss2", reply_transs2, AS_USER},
389
390    /* NT PROTOCOL FOLLOWS */
391    {SMBntcreateX, "SMBntcreateX", reply_ntcreate_and_X, AS_USER | CAN_IPC | QUEUE_IN_OPLOCK },
392    {SMBnttrans, "SMBnttrans", reply_nttrans, AS_USER | CAN_IPC | QUEUE_IN_OPLOCK},
393    {SMBnttranss, "SMBnttranss", reply_nttranss, AS_USER | CAN_IPC },
394    {SMBntcancel, "SMBntcancel", reply_ntcancel, 0 },
395
396    /* messaging routines */
397    {SMBsends,"SMBsends",reply_sends,AS_GUEST},
398    {SMBsendstrt,"SMBsendstrt",reply_sendstrt,AS_GUEST},
399    {SMBsendend,"SMBsendend",reply_sendend,AS_GUEST},
400    {SMBsendtxt,"SMBsendtxt",reply_sendtxt,AS_GUEST},
401
402    /* NON-IMPLEMENTED PARTS OF THE CORE PROTOCOL */
403    
404    {SMBsendb,"SMBsendb",NULL,AS_GUEST},
405    {SMBfwdname,"SMBfwdname",NULL,AS_GUEST},
406    {SMBcancelf,"SMBcancelf",NULL,AS_GUEST},
407    {SMBgetmac,"SMBgetmac",NULL,AS_GUEST}
408  };
409
410
411 /****************************************************************************
412 do a switch on the message type, and return the response size
413 ****************************************************************************/
414 static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize)
415 {
416   static pid_t pid= (pid_t)-1;
417   int outsize = 0;
418   static int num_smb_messages = 
419     sizeof(smb_messages) / sizeof(struct smb_message_struct);
420   int match;
421   extern int global_smbpid;
422
423   if (pid == (pid_t)-1)
424     pid = getpid();
425
426   errno = 0;
427   last_message = type;
428
429   /* make sure this is an SMB packet */
430   if (strncmp(smb_base(inbuf),"\377SMB",4) != 0)
431   {
432     DEBUG(2,("Non-SMB packet of length %d\n",smb_len(inbuf)));
433     return(-1);
434   }
435
436   for (match=0;match<num_smb_messages;match++)
437     if (smb_messages[match].code == type)
438       break;
439
440   /* yuck! this is an interim measure before we get rid of our
441      current inbuf/outbuf system */
442   global_smbpid = SVAL(inbuf,smb_pid);
443
444   if (match == num_smb_messages)
445   {
446     DEBUG(0,("Unknown message type %d!\n",type));
447     outsize = reply_unknown(inbuf,outbuf);
448   }
449   else
450   {
451     DEBUG(3,("switch message %s (pid %d)\n",smb_messages[match].name,(int)pid));
452
453     if(global_oplock_break)
454     {
455       int flags = smb_messages[match].flags;
456
457       if(flags & QUEUE_IN_OPLOCK)
458       {
459         /* 
460          * Queue this message as we are the process of an oplock break.
461          */
462
463         DEBUG( 2, ( "switch_message: queueing message due to being in " ) );
464         DEBUGADD( 2, ( "oplock break state.\n" ) );
465
466         push_oplock_pending_smb_message( inbuf, size );
467         return -1;
468       }          
469     }
470     if (smb_messages[match].fn)
471     {
472       int flags = smb_messages[match].flags;
473       static uint16 last_session_tag = UID_FIELD_INVALID;
474       /* In share mode security we must ignore the vuid. */
475       uint16 session_tag = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(inbuf,smb_uid);
476       connection_struct *conn = conn_find(SVAL(inbuf,smb_tid));
477
478
479       /* Ensure this value is replaced in the incoming packet. */
480       SSVAL(inbuf,smb_uid,session_tag);
481
482       /*
483        * Ensure the correct username is in sesssetup_user.
484        * This is a really ugly bugfix for problems with
485        * multiple session_setup_and_X's being done and
486        * allowing %U and %G substitutions to work correctly.
487        * There is a reason this code is done here, don't
488        * move it unless you know what you're doing... :-).
489        * JRA.
490        */
491       if (session_tag != last_session_tag) {
492         user_struct *vuser = NULL;
493
494         last_session_tag = session_tag;
495         if(session_tag != UID_FIELD_INVALID)
496           vuser = get_valid_user_struct(session_tag);           
497         if(vuser != NULL)
498           pstrcpy( sesssetup_user, vuser->requested_name);
499       }
500
501       /* does this protocol need to be run as root? */
502       if (!(flags & AS_USER))
503         unbecome_user();
504
505       /* does this protocol need to be run as the connected user? */
506       if ((flags & AS_USER) && !become_user(conn,session_tag)) {
507         if (flags & AS_GUEST) 
508           flags &= ~AS_USER;
509         else
510           return(ERROR(ERRSRV,ERRaccess));
511       }
512       /* this code is to work around a bug is MS client 3 without
513          introducing a security hole - it needs to be able to do
514          print queue checks as guest if it isn't logged in properly */
515       if (flags & AS_USER)
516         flags &= ~AS_GUEST;
517
518       /* does it need write permission? */
519       if ((flags & NEED_WRITE) && !CAN_WRITE(conn))
520         return(ERROR(ERRSRV,ERRaccess));
521
522       /* ipc services are limited */
523       if (IS_IPC(conn) && (flags & AS_USER) && !(flags & CAN_IPC)) {
524         return(ERROR(ERRSRV,ERRaccess));            
525       }
526
527       /* load service specific parameters */
528       if (conn && 
529           !become_service(conn,(flags & AS_USER)?True:False)) {
530         return(ERROR(ERRSRV,ERRaccess));
531       }
532
533       /* does this protocol need to be run as guest? */
534       if ((flags & AS_GUEST) && 
535           (!become_guest() || 
536            !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1)))) {
537         return(ERROR(ERRSRV,ERRaccess));
538       }
539
540       last_inbuf = inbuf;
541
542       outsize = smb_messages[match].fn(conn, inbuf,outbuf,size,bufsize);
543     }
544     else
545     {
546       outsize = reply_unknown(inbuf,outbuf);
547     }
548   }
549
550   return(outsize);
551 }
552
553
554 /****************************************************************************
555   construct a reply to the incoming packet
556 ****************************************************************************/
557 static int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
558 {
559   int type = CVAL(inbuf,smb_com);
560   int outsize = 0;
561   int msg_type = CVAL(inbuf,0);
562
563   GetTimeOfDay(&smb_last_time);
564
565   chain_size = 0;
566   file_chain_reset();
567   reset_chain_p();
568
569   if (msg_type != 0)
570     return(reply_special(inbuf,outbuf));  
571
572   construct_reply_common(inbuf, outbuf);
573
574   outsize = switch_message(type,inbuf,outbuf,size,bufsize);
575
576   outsize += chain_size;
577
578   if(outsize > 4)
579     smb_setlen(outbuf,outsize - 4);
580   return(outsize);
581 }
582
583
584 /****************************************************************************
585   process an smb from the client - split out from the process() code so
586   it can be used by the oplock break code.
587 ****************************************************************************/
588 void process_smb(char *inbuf, char *outbuf)
589 {
590 #ifdef WITH_SSL
591   extern BOOL sslEnabled;     /* don't use function for performance reasons */
592   static int sslConnected = 0;
593 #endif /* WITH_SSL */
594   static int trans_num;
595   int msg_type = CVAL(inbuf,0);
596   int32 len = smb_len(inbuf);
597   int nread = len + 4;
598
599 #ifdef WITH_PROFILE
600   profile_p->smb_count++;
601 #endif
602
603   if (trans_num == 0) {
604           /* on the first packet, check the global hosts allow/ hosts
605              deny parameters before doing any parsing of the packet
606              passed to us by the client.  This prevents attacks on our
607              parsing code from hosts not in the hosts allow list */
608           if (!check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1))) {
609                   /* send a negative session response "not listining on calling
610                    name" */
611                   static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
612                   DEBUG( 1, ( "Connection denied from %s\n",
613                               client_addr() ) );
614                   send_smb(smbd_server_fd(),(char *)buf);
615                   exit_server("connection denied");
616           }
617   }
618
619   DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type, len ) );
620   DEBUG( 3, ( "Transaction %d of length %d\n", trans_num, nread ) );
621
622 #ifdef WITH_SSL
623     if(sslEnabled && !sslConnected){
624         sslConnected = sslutil_negotiate_ssl(smbd_server_fd(), msg_type);
625         if(sslConnected < 0){   /* an error occured */
626             exit_server("SSL negotiation failed");
627         }else if(sslConnected){
628             trans_num++;
629             return;
630         }
631     }
632 #endif  /* WITH_SSL */
633
634 #ifdef WITH_VTP
635   if(trans_num == 1 && VT_Check(inbuf)) 
636   {
637     VT_Process();
638     return;
639   }
640 #endif
641
642   if (msg_type == 0)
643     show_msg(inbuf);
644   else if(msg_type == 0x85)
645     return; /* Keepalive packet. */
646
647   nread = construct_reply(inbuf,outbuf,nread,max_send);
648       
649   if(nread > 0) 
650   {
651     if (CVAL(outbuf,0) == 0)
652       show_msg(outbuf);
653         
654     if (nread != smb_len(outbuf) + 4) 
655     {
656       DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
657                  nread, smb_len(outbuf)));
658     }
659     else
660       send_smb(smbd_server_fd(),outbuf);
661   }
662   trans_num++;
663 }
664
665
666
667 /****************************************************************************
668 return a string containing the function name of a SMB command
669 ****************************************************************************/
670 char *smb_fn_name(int type)
671 {
672         static char *unknown_name = "SMBunknown";
673         static int num_smb_messages = 
674                 sizeof(smb_messages) / sizeof(struct smb_message_struct);
675         int match;
676
677         for (match=0;match<num_smb_messages;match++)
678                 if (smb_messages[match].code == type)
679                         break;
680
681         if (match == num_smb_messages)
682                 return(unknown_name);
683
684         return(smb_messages[match].name);
685 }
686
687
688 /****************************************************************************
689  Helper function for contruct_reply.
690 ****************************************************************************/
691
692 void construct_reply_common(char *inbuf,char *outbuf)
693 {
694   memset(outbuf,'\0',smb_size);
695
696   set_message(outbuf,0,0,True);
697   CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com);
698
699   memcpy(outbuf+4,inbuf+4,4);
700   CVAL(outbuf,smb_rcls) = SMB_SUCCESS;
701   CVAL(outbuf,smb_reh) = 0;
702   SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES)); /* bit 7 set
703                                  means a reply */
704   SSVAL(outbuf,smb_flg2,FLAGS2_LONG_PATH_COMPONENTS);
705         /* say we support long filenames */
706
707   SSVAL(outbuf,smb_err,SMB_SUCCESS);
708   SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
709   SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
710   SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
711   SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
712 }
713
714 /****************************************************************************
715   construct a chained reply and add it to the already made reply
716   **************************************************************************/
717 int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
718 {
719   static char *orig_inbuf;
720   static char *orig_outbuf;
721   int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0);
722   unsigned smb_off2 = SVAL(inbuf,smb_vwv1);
723   char *inbuf2, *outbuf2;
724   int outsize2;
725   char inbuf_saved[smb_wct];
726   char outbuf_saved[smb_wct];
727   int wct = CVAL(outbuf,smb_wct);
728   int outsize = smb_size + 2*wct + SVAL(outbuf,smb_vwv0+2*wct);
729
730   /* maybe its not chained */
731   if (smb_com2 == 0xFF) {
732     CVAL(outbuf,smb_vwv0) = 0xFF;
733     return outsize;
734   }
735
736   if (chain_size == 0) {
737     /* this is the first part of the chain */
738     orig_inbuf = inbuf;
739     orig_outbuf = outbuf;
740   }
741
742   /*
743    * The original Win95 redirector dies on a reply to
744    * a lockingX and read chain unless the chain reply is
745    * 4 byte aligned. JRA.
746    */
747
748   outsize = (outsize + 3) & ~3;
749
750   /* we need to tell the client where the next part of the reply will be */
751   SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf));
752   CVAL(outbuf,smb_vwv0) = smb_com2;
753
754   /* remember how much the caller added to the chain, only counting stuff
755      after the parameter words */
756   chain_size += outsize - smb_wct;
757
758   /* work out pointers into the original packets. The
759      headers on these need to be filled in */
760   inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct;
761   outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct;
762
763   /* remember the original command type */
764   smb_com1 = CVAL(orig_inbuf,smb_com);
765
766   /* save the data which will be overwritten by the new headers */
767   memcpy(inbuf_saved,inbuf2,smb_wct);
768   memcpy(outbuf_saved,outbuf2,smb_wct);
769
770   /* give the new packet the same header as the last part of the SMB */
771   memmove(inbuf2,inbuf,smb_wct);
772
773   /* create the in buffer */
774   CVAL(inbuf2,smb_com) = smb_com2;
775
776   /* create the out buffer */
777   construct_reply_common(inbuf2, outbuf2);
778
779   DEBUG(3,("Chained message\n"));
780   show_msg(inbuf2);
781
782   /* process the request */
783   outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size,
784                             bufsize-chain_size);
785
786   /* copy the new reply and request headers over the old ones, but
787      preserve the smb_com field */
788   memmove(orig_outbuf,outbuf2,smb_wct);
789   CVAL(orig_outbuf,smb_com) = smb_com1;
790
791   /* restore the saved data, being careful not to overwrite any
792    data from the reply header */
793   memcpy(inbuf2,inbuf_saved,smb_wct);
794   {
795     int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf);
796     if (ofs < 0) ofs = 0;
797     memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs);
798   }
799
800   return outsize2;
801 }
802
803 /****************************************************************************
804  Setup the needed select timeout.
805 ****************************************************************************/
806
807 static int setup_select_timeout(void)
808 {
809   int change_notify_timeout = lp_change_notify_timeout() * 1000;
810   int select_timeout;
811
812   /*
813    * Increase the select timeout back to SMBD_SELECT_TIMEOUT if we
814    * have removed any blocking locks. JRA.
815    */
816
817   select_timeout = blocking_locks_pending() ? SMBD_SELECT_TIMEOUT_WITH_PENDING_LOCKS*1000 :
818                                               SMBD_SELECT_TIMEOUT*1000;
819
820   if (change_notifies_pending())
821     select_timeout = MIN(select_timeout, change_notify_timeout);
822
823   return select_timeout;
824 }
825
826 /****************************************************************************
827  Check if services need reloading.
828 ****************************************************************************/
829
830 void check_reload(int t)
831 {
832   static time_t last_smb_conf_reload_time = 0;
833
834   if(last_smb_conf_reload_time == 0)
835     last_smb_conf_reload_time = t;
836
837   if (reload_after_sighup || (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK))
838   {
839     reload_services(True);
840     reload_after_sighup = False;
841     last_smb_conf_reload_time = t;
842   }
843 }
844
845 /****************************************************************************
846  Process any timeout housekeeping. Return False if the caller should exit.
847 ****************************************************************************/
848
849 static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_timeout_processing_time)
850 {
851   static time_t last_keepalive_sent_time = 0;
852   static time_t last_idle_closed_check = 0;
853   time_t t;
854   BOOL allidle = True;
855   extern int keepalive;
856
857   if (smb_read_error == READ_EOF) 
858   {
859     DEBUG(3,("end of file from client\n"));
860     return False;
861   }
862
863   if (smb_read_error == READ_ERROR) 
864   {
865     DEBUG(3,("receive_smb error (%s) exiting\n",
866               strerror(errno)));
867     return False;
868   }
869
870   *last_timeout_processing_time = t = time(NULL);
871
872   if(last_keepalive_sent_time == 0)
873     last_keepalive_sent_time = t;
874
875   if(last_idle_closed_check == 0)
876     last_idle_closed_check = t;
877
878   /* become root again if waiting */
879   unbecome_user();
880
881   /* check if we need to reload services */
882   check_reload(t);
883
884   /* automatic timeout if all connections are closed */      
885   if (conn_num_open()==0 && (t - last_idle_closed_check) >= IDLE_CLOSED_TIMEOUT) 
886   {
887     DEBUG( 2, ( "Closing idle connection\n" ) );
888     return False;
889   }
890   else
891     last_idle_closed_check = t;
892
893   if (keepalive && (t - last_keepalive_sent_time)>keepalive) 
894   {
895     struct cli_state *cli = server_client();
896     if (!send_keepalive(smbd_server_fd())) {
897       DEBUG( 2, ( "Keepalive failed - exiting.\n" ) );
898       return False;
899     }       
900     /* also send a keepalive to the password server if its still
901        connected */
902     if (cli && cli->initialised)
903       send_keepalive(cli->fd);
904     last_keepalive_sent_time = t;
905   }
906
907   /* check for connection timeouts */
908   allidle = conn_idle_all(t, deadtime);
909
910   if (allidle && conn_num_open()>0) {
911     DEBUG(2,("Closing idle connection 2.\n"));
912     return False;
913   }
914
915   if(global_machine_password_needs_changing)
916   {
917     unsigned char trust_passwd_hash[16];
918     time_t lct;
919     pstring remote_machine_list;
920
921     /*
922      * We're in domain level security, and the code that
923      * read the machine password flagged that the machine
924      * password needs changing.
925      */
926
927     /*
928      * First, open the machine password file with an exclusive lock.
929      */
930
931     if(!trust_password_lock( global_myworkgroup, global_myname, True)) {
932       DEBUG(0,("process: unable to open the machine account password file for \
933 machine %s in domain %s.\n", global_myname, global_myworkgroup ));
934       return True;
935     }
936
937     if(!get_trust_account_password( trust_passwd_hash, &lct)) {
938       DEBUG(0,("process: unable to read the machine account password for \
939 machine %s in domain %s.\n", global_myname, global_myworkgroup ));
940       trust_password_unlock();
941       return True;
942     }
943
944     /*
945      * Make sure someone else hasn't already done this.
946      */
947
948     if(t < lct + lp_machine_password_timeout()) {
949       trust_password_unlock();
950       global_machine_password_needs_changing = False;
951       return True;
952     }
953
954     pstrcpy(remote_machine_list, lp_passwordserver());
955
956     change_trust_account_password( global_myworkgroup, remote_machine_list);
957     trust_password_unlock();
958     global_machine_password_needs_changing = False;
959   }
960
961   /*
962    * Check to see if we have any blocking locks
963    * outstanding on the queue.
964    */
965   process_blocking_lock_queue(t);
966
967   /*
968    * Check to see if we have any change notifies 
969    * outstanding on the queue.
970    */
971   process_pending_change_notify_queue(t);
972
973   /*
974    * Modify the select timeout depending upon
975    * what we have remaining in our queues.
976    */
977
978   *select_timeout = setup_select_timeout();
979
980   return True;
981 }
982
983 /****************************************************************************
984   process commands from the client
985 ****************************************************************************/
986
987 void smbd_process(void)
988 {
989   extern int smb_echo_count;
990   time_t last_timeout_processing_time = time(NULL);
991   unsigned int num_smbs = 0;
992
993   InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
994   OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
995   if ((InBuffer == NULL) || (OutBuffer == NULL)) 
996     return;
997
998   InBuffer += SMB_ALIGNMENT;
999   OutBuffer += SMB_ALIGNMENT;
1000
1001   max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
1002
1003   /* re-initialise the timezone */
1004   TimeInit();
1005
1006   while (True)
1007   {
1008     int deadtime = lp_deadtime()*60;
1009     BOOL got_smb = False;
1010     int select_timeout = setup_select_timeout();
1011
1012     if (deadtime <= 0)
1013       deadtime = DEFAULT_SMBD_TIMEOUT;
1014
1015 #if USE_READ_PREDICTION
1016     if (lp_readprediction())
1017       do_read_prediction();
1018 #endif
1019
1020     errno = 0;      
1021
1022     /* free up temporary memory */
1023     lp_talloc_free();
1024
1025     while(!receive_message_or_smb(InBuffer,BUFFER_SIZE,select_timeout,&got_smb))
1026     {
1027       if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1028         return;
1029       num_smbs = 0; /* Reset smb counter. */
1030     }
1031
1032     if(got_smb) {
1033       /*
1034        * Ensure we do timeout processing if the SMB we just got was
1035        * only an echo request. This allows us to set the select
1036        * timeout in 'receive_message_or_smb()' to any value we like
1037        * without worrying that the client will send echo requests
1038        * faster than the select timeout, thus starving out the
1039        * essential processing (change notify, blocking locks) that
1040        * the timeout code does. JRA.
1041        */ 
1042       int num_echos = smb_echo_count;
1043
1044       process_smb(InBuffer, OutBuffer);
1045
1046       if(smb_echo_count != num_echos) {
1047         if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1048           return;
1049         num_smbs = 0; /* Reset smb counter. */
1050       }
1051
1052       num_smbs++;
1053
1054       /*
1055        * If we are getting smb requests in a constant stream
1056        * with no echos, make sure we attempt timeout processing
1057        * every select_timeout milliseconds - but only check for this
1058        * every 200 smb requests.
1059        */
1060
1061       if((num_smbs % 200) == 0) {
1062         time_t new_check_time = time(NULL);
1063         if(last_timeout_processing_time - new_check_time >= (select_timeout/1000)) {
1064           if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
1065             return;
1066           num_smbs = 0; /* Reset smb counter. */
1067           last_timeout_processing_time = new_check_time; /* Reset time. */
1068         }
1069       }
1070     }
1071     else
1072       process_local_message(InBuffer, BUFFER_SIZE);
1073   }
1074 }