move where got_sig_term and reload_after_sighup are defined.
[tprouty/samba.git] / source / smbd / process.c
index ff53acbd9eee803e148211b7221f7724ad1becd7..f2b2a5c15a62eab18db26cbcfd4b76cfa2258c97 100644 (file)
@@ -1,6 +1,5 @@
 /* 
-   Unix SMB/Netbios implementation.
-   Version 1.9.
+   Unix SMB/CIFS implementation.
    process incoming packets - main loop
    Copyright (C) Andrew Tridgell 1992-1998
    
@@ -43,7 +42,8 @@ extern int last_message;
 extern int global_oplock_break;
 extern userdom_struct current_user_info;
 extern int smb_read_error;
-extern VOLATILE sig_atomic_t reload_after_sighup;
+SIG_ATOMIC_T reload_after_sighup = 0;
+SIG_ATOMIC_T got_sig_term = 0;
 extern BOOL global_machine_password_needs_changing;
 extern fstring global_myworkgroup;
 extern pstring global_myname;
@@ -105,16 +105,23 @@ BOOL push_oplock_pending_smb_message(char *buf, int msg_len)
 }
 
 /****************************************************************************
-do all async processing in here. This includes UDB oplock messages, kernel
-oplock messages, change notify events etc.
+ Do all async processing in here. This includes UDB oplock messages, kernel
+ oplock messages, change notify events etc.
 ****************************************************************************/
-static void async_processing(fd_set *fds, char *buffer, int buffer_len)
+
+static void async_processing(char *buffer, int buffer_len)
 {
+       DEBUG(10,("async_processing: Doing async processing.\n"));
+
        /* check for oplock messages (both UDP and kernel) */
-       if (receive_local_message(fds, buffer, buffer_len, 0)) {
+       if (receive_local_message(buffer, buffer_len, 1)) {
                process_local_message(buffer, buffer_len);
        }
 
+       if (got_sig_term) {
+               exit_server("Caught TERM signal");
+       }
+
        /* check for async change notify events */
        process_pending_change_notify_queue(0);
 
@@ -123,7 +130,7 @@ static void async_processing(fd_set *fds, char *buffer, int buffer_len)
                change_to_root_user();
                DEBUG(1,("Reloading services after SIGHUP\n"));
                reload_services(False);
-               reload_after_sighup = False;
+               reload_after_sighup = 0;
        }
 }
 
@@ -145,7 +152,7 @@ static void async_processing(fd_set *fds, char *buffer, int buffer_len)
   Returns False on timeout or error.
   Else returns True.
 
-The timeout is in milli seconds
+The timeout is in milliseconds
 ****************************************************************************/
 
 static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
@@ -188,20 +195,41 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
         */
 
        FD_ZERO(&fds);
+
+       /*
+        * Ensure we process oplock break messages by preference.
+        * We have to do this before the select, after the select
+        * and if the select returns EINTR. This is due to the fact
+        * that the selects called from async_processing can eat an EINTR
+        * caused by a signal (we can't take the break message there).
+        * This is hideously complex - *MUST* be simplified for 3.0 ! JRA.
+        */
+
+       if (oplock_message_waiting(&fds)) {
+               DEBUG(10,("receive_message_or_smb: oplock_message is waiting.\n"));
+               async_processing(buffer, buffer_len);
+               /*
+                * After async processing we must go and do the select again, as
+                * the state of the flag in fds for the server file descriptor is
+                * indeterminate - we may have done I/O on it in the oplock processing. JRA.
+                */
+               goto again;
+       }
+       
        FD_SET(smbd_server_fd(),&fds);
        maxfd = setup_oplock_select_set(&fds);
 
        to.tv_sec = timeout / 1000;
        to.tv_usec = (timeout % 1000) * 1000;
 
-       selrtn = sys_select(MAX(maxfd,smbd_server_fd())+1,&fds,timeout>0?&to:NULL);
+       selrtn = sys_select(MAX(maxfd,smbd_server_fd())+1,&fds,NULL,NULL,timeout>0?&to:NULL);
 
        /* if we get EINTR then maybe we have received an oplock
           signal - treat this as select returning 1. This is ugly, but
           is the best we can do until the oplock code knows more about
           signals */
        if (selrtn == -1 && errno == EINTR) {
-               async_processing(&fds, buffer, buffer_len);
+               async_processing(buffer, buffer_len);
                /*
                 * After async processing we must go and do the select again, as
                 * the state of the flag in fds for the server file descriptor is
@@ -230,7 +258,7 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
         */
 
        if (oplock_message_waiting(&fds)) {
-               async_processing(&fds, buffer, buffer_len);
+               async_processing(buffer, buffer_len);
                /*
                 * After async processing we must go and do the select again, as
                 * the state of the flag in fds for the server file descriptor is
@@ -270,7 +298,6 @@ BOOL receive_next_smb(char *inbuf, int bufsize, int timeout)
 void respond_to_all_remaining_local_messages(void)
 {
   char buffer[1024];
-  fd_set fds;
 
   /*
    * Assert we have no exclusive open oplocks.
@@ -282,24 +309,13 @@ void respond_to_all_remaining_local_messages(void)
     return;
   }
 
-  /*
-   * Setup the select read fd set.
-   */
-
-  FD_ZERO(&fds);
-  if(!setup_oplock_select_set(&fds))
-    return;
-
   /*
    * Keep doing receive_local_message with a 1 ms timeout until
    * we have no more messages.
    */
-  while(receive_local_message(&fds, buffer, sizeof(buffer), 1)) {
+  while(receive_local_message(buffer, sizeof(buffer), 1)) {
          /* Deal with oplock break requests from other smbd's. */
          process_local_message(buffer, sizeof(buffer));
-
-         FD_ZERO(&fds);
-         (void)setup_oplock_select_set(&fds);
   }
 
   return;
@@ -325,9 +341,9 @@ force write permissions on print services.
    functions. Any message that has a NULL function is unimplemented -
    please feel free to contribute implementations!
 */
-static struct smb_message_struct
+const static struct smb_message_struct
 {
-  char *name;
+  const char *name;
   int (*fn)(connection_struct *conn, char *, char *, int, int);
   int flags;
 }
@@ -370,7 +386,7 @@ static struct smb_message_struct
 /* 0x22 */ { "SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE },
 /* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER },
 /* 0x24 */ { "SMBlockingX",reply_lockingX,AS_USER },
-/* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC | QUEUE_IN_OPLOCK},
+/* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC },
 /* 0x26 */ { "SMBtranss",NULL,AS_USER | CAN_IPC},
 /* 0x27 */ { "SMBioctl",reply_ioctl,0},
 /* 0x28 */ { "SMBioctls",NULL,AS_USER},
@@ -383,7 +399,7 @@ static struct smb_message_struct
 /* 0x2f */ { "SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC },
 /* 0x30 */ { NULL, NULL, 0 },
 /* 0x31 */ { NULL, NULL, 0 },
-/* 0x32 */ { "SMBtrans2", reply_trans2, AS_USER | QUEUE_IN_OPLOCK | CAN_IPC },
+/* 0x32 */ { "SMBtrans2", reply_trans2, AS_USER | CAN_IPC },
 /* 0x33 */ { "SMBtranss2", reply_transs2, AS_USER},
 /* 0x34 */ { "SMBfindclose", reply_findclose,AS_USER},
 /* 0x35 */ { "SMBfindnclose", reply_findnclose, AS_USER},
@@ -595,7 +611,7 @@ static struct smb_message_struct
 /*******************************************************************
 dump a prs to a file
  ********************************************************************/
-static void smb_dump(char *name, int type, char *data, ssize_t len)
+static void smb_dump(const char *name, int type, char *data, ssize_t len)
 {
        int fd, i;
        pstring fname;
@@ -609,7 +625,9 @@ static void smb_dump(char *name, int type, char *data, ssize_t len)
                if (fd != -1 || errno != EEXIST) break;
        }
        if (fd != -1) {
-               write(fd, data, len);
+               ssize_t ret = write(fd, data, len);
+               if (ret != len)
+                       DEBUG(0,("smb_dump: problem: write returned %d\n", (int)ret ));
                close(fd);
                DEBUG(0,("created %s len %d\n", fname, len));
        }
@@ -817,15 +835,11 @@ set. Ignoring max smbd restriction.\n"));
 }
 
 /****************************************************************************
-  process an smb from the client - split out from the process() code so
+  process an smb from the client - split out from the smbd_process() code so
   it can be used by the oplock break code.
 ****************************************************************************/
 void process_smb(char *inbuf, char *outbuf)
 {
-#ifdef WITH_SSL
-  extern BOOL sslEnabled;     /* don't use function for performance reasons */
-  static int sslConnected = 0;
-#endif /* WITH_SSL */
   static int trans_num;
   int msg_type = CVAL(inbuf,0);
   int32 len = smb_len(inbuf);
@@ -853,18 +867,6 @@ void process_smb(char *inbuf, char *outbuf)
   DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type, len ) );
   DEBUG( 3, ( "Transaction %d of length %d\n", trans_num, nread ) );
 
-#ifdef WITH_SSL
-    if(sslEnabled && !sslConnected){
-        sslConnected = sslutil_negotiate_ssl(smbd_server_fd(), msg_type);
-        if(sslConnected < 0){   /* an error occured */
-            exit_server("SSL negotiation failed");
-        }else if(sslConnected){
-            trans_num++;
-            return;
-        }
-    }
-#endif  /* WITH_SSL */
-
   if (msg_type == 0)
     show_msg(inbuf);
   else if(msg_type == SMBkeepalive)
@@ -894,7 +896,7 @@ void process_smb(char *inbuf, char *outbuf)
 /****************************************************************************
 return a string containing the function name of a SMB command
 ****************************************************************************/
-char *smb_fn_name(int type)
+const char *smb_fn_name(int type)
 {
        static char *unknown_name = "SMBunknown";
 
@@ -914,14 +916,15 @@ void construct_reply_common(char *inbuf,char *outbuf)
        memset(outbuf,'\0',smb_size);
 
        set_message(outbuf,0,0,True);
-       CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com);
+       SCVAL(outbuf,smb_com,CVAL(inbuf,smb_com));
        
        memcpy(outbuf+4,inbuf+4,4);
-       CVAL(outbuf,smb_rcls) = SMB_SUCCESS;
-       CVAL(outbuf,smb_reh) = 0;
+       SCVAL(outbuf,smb_rcls,SMB_SUCCESS);
+       SCVAL(outbuf,smb_reh,0);
        SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES)); 
        SSVAL(outbuf,smb_flg2,
-             FLAGS2_UNICODE_STRINGS | FLAGS2_LONG_PATH_COMPONENTS |
+             (SVAL(inbuf,smb_flg2) & FLAGS2_UNICODE_STRINGS) |
+             FLAGS2_LONG_PATH_COMPONENTS |
              FLAGS2_32_BIT_ERROR_CODES | FLAGS2_EXTENDED_SECURITY);
 
        SSVAL(outbuf,smb_err,SMB_SUCCESS);
@@ -949,7 +952,7 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
 
   /* maybe its not chained */
   if (smb_com2 == 0xFF) {
-    CVAL(outbuf,smb_vwv0) = 0xFF;
+    SCVAL(outbuf,smb_vwv0,0xFF);
     return outsize;
   }
 
@@ -969,7 +972,7 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
 
   /* we need to tell the client where the next part of the reply will be */
   SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf));
-  CVAL(outbuf,smb_vwv0) = smb_com2;
+  SCVAL(outbuf,smb_vwv0,smb_com2);
 
   /* remember how much the caller added to the chain, only counting stuff
      after the parameter words */
@@ -991,7 +994,7 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
   memmove(inbuf2,inbuf,smb_wct);
 
   /* create the in buffer */
-  CVAL(inbuf2,smb_com) = smb_com2;
+  SCVAL(inbuf2,smb_com,smb_com2);
 
   /* create the out buffer */
   construct_reply_common(inbuf2, outbuf2);
@@ -1006,7 +1009,7 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
   /* copy the new reply and request headers over the old ones, but
      preserve the smb_com field */
   memmove(orig_outbuf,outbuf2,smb_wct);
-  CVAL(orig_outbuf,smb_com) = smb_com1;
+  SCVAL(orig_outbuf,smb_com,smb_com1);
 
   /* restore the saved data, being careful not to overwrite any
    data from the reply header */
@@ -1029,13 +1032,8 @@ static int setup_select_timeout(void)
        int select_timeout;
        int t;
 
-       /*
-        * Increase the select timeout back to SMBD_SELECT_TIMEOUT if we
-        * have removed any blocking locks. JRA.
-        */
-
-       select_timeout = blocking_locks_pending() ? SMBD_SELECT_TIMEOUT_WITH_PENDING_LOCKS*1000 :
-               SMBD_SELECT_TIMEOUT*1000;
+       select_timeout = blocking_locks_timeout(SMBD_SELECT_TIMEOUT);
+       select_timeout *= 1000;
 
        t = change_notify_timeout();
        if (t != -1) select_timeout = MIN(select_timeout, t*1000);
@@ -1225,13 +1223,6 @@ void smbd_process(void)
 
        max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
 
-       /* re-initialise the timezone */
-       TimeInit();
-
-       /* register our message handlers */
-       message_register(MSG_SMB_FORCE_TDIS, msg_force_tdis);
-       talloc_init_named("dummy!");
-
        while (True) {
                int deadtime = lp_deadtime()*60;
                int select_timeout = setup_select_timeout();