a cleanup of the receive_smb() usage, adding timeouts in some places
authorAndrew Tridgell <tridge@samba.org>
Mon, 10 Jun 1996 05:16:19 +0000 (05:16 +0000)
committerAndrew Tridgell <tridge@samba.org>
Mon, 10 Jun 1996 05:16:19 +0000 (05:16 +0000)
also added paranoid code in the main process() loop of smbd to detect
when smbd is looping uselessly. This should stop the "smbd is chewing
lots of cpu" reports

source/include/smb.h
source/lib/util.c
source/smbd/ipc.c
source/smbd/password.c
source/smbd/reply.c
source/smbd/server.c
source/smbd/trans2.c

index 5fd2e0846bbdebad1be7508e8326413d22131973..b9dd13a802b8387162c1af883330bdbb44ca4ecd 100644 (file)
@@ -99,6 +99,9 @@ typedef unsigned int uint32;
 #define DEFAULT_PIPE_TIMEOUT 10000000 /* Ten seconds */
 #endif
 
+/* how long to wait for secondary SMB packets (seconds) */
+#define SMB_SECONDARY_WAIT 30
+
 /* debugging code */
 #ifndef SYSLOG
 #define DEBUG(level,body) ((DEBUGLEVEL>=(level))?(Debug1 body):0)
index fc47313b57b1d5f3a2ed00f5564ab859581d9622..ee4fca3ed37eb6e75cdfca3715b889d92ac41199 100644 (file)
@@ -2079,7 +2079,7 @@ int read_smb_length(int fd,char *inbuf,int timeout)
 
       if (msg_type == 0x85) 
        {
-         DEBUG(5,( "Got keepalive packet\n"));
+         DEBUG(5,("Got keepalive packet\n"));
          ok = False;
        }
     }
@@ -2097,8 +2097,7 @@ The timeout is in milli seconds
 ****************************************************************************/
 BOOL receive_smb(int fd,char *buffer,int timeout)
 {
-  int len;
-  BOOL ok;
+  int len,ret;
 
   bzero(buffer,smb_size + 100);
 
@@ -2107,18 +2106,16 @@ BOOL receive_smb(int fd,char *buffer,int timeout)
     return(False);
 
   if (len > BUFFER_SIZE) {
-    DEBUG(0,("Invalid packet length! (%d bytes)\n",len));
+    DEBUG(0,("Invalid packet length! (%d bytes).\n",len));
     if (len > BUFFER_SIZE + (SAFETY_MARGIN/2))
       exit(1);
   }
 
-  ok = (read_data(fd,buffer+4,len) == len);
-
-  if (!ok)
-    {
-      close_sockets();
-      exit(1);
-    }
+  ret = read_data(fd,buffer+4,len);
+  if (ret != len) {
+    DEBUG(0,("ERROR: Invalid SMB length. Expected %d got %d\n",len,ret));
+    return False;
+  }
 
   return(True);
 }
index 594e067ddd4bbf2890ea405f66fb8fa401f34409..415c939bf38c2b72a4e1fa3e0fda6c516ab29f40 100644 (file)
@@ -2790,12 +2790,9 @@ int reply_trans(char *inbuf,char *outbuf)
   while (pscnt < tpscnt || dscnt < tdscnt)
     {
       int pcnt,poff,dcnt,doff,pdisp,ddisp;
-
-      receive_smb(Client,inbuf, 0);
-      show_msg(inbuf);
-         
-      /* Ensure this is still a trans packet (sanity check) */
-      if(CVAL(inbuf, smb_com) != SMBtrans)
+      
+      if (!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT*1000) ||
+         CVAL(inbuf, smb_com) != SMBtrans)
        {
          DEBUG(2,("Invalid secondary trans2 packet\n"));
          if (params) free(params);
@@ -2803,6 +2800,8 @@ int reply_trans(char *inbuf,char *outbuf)
          if (setup) free(setup);
          return(ERROR(ERRSRV,ERRerror));
        }
+
+      show_msg(inbuf);
       
       tpscnt = SVAL(inbuf,smb_vwv0);
       tdscnt = SVAL(inbuf,smb_vwv1);
index ae548b826693ac0bb8aa6c5dd4b2f239e46a4dbd..a5f597682f646cbb815789895809c9f1eab19ca7 100644 (file)
@@ -1318,9 +1318,10 @@ BOOL server_cryptkey(char *buf)
   CVAL(outbuf,0) = 0x81;
 
   send_smb(password_client,outbuf);
-  receive_smb(password_client,inbuf,5000);
+  
  
-  if (CVAL(inbuf,0) != 0x82) {
+  if (!receive_smb(password_client,inbuf,5000) ||
+      CVAL(inbuf,0) != 0x82) {
     DEBUG(1,("%s rejected the session\n",pserver));
     close(password_client); password_client = -1;
     return(False);
index 43703982ec94e5dde146e2aaf0e85caeafdb722f..4cfa001ec2144b3567e4fe833f7ca7dec62b8902 100644 (file)
@@ -1590,7 +1590,7 @@ int reply_writebraw(char *inbuf,char *outbuf)
   send_smb(Client,outbuf);
   
   /* Now read the raw data into the buffer and write it */
-  if(read_smb_length(Client,inbuf,0) == -1) {
+  if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) {
     exit_server("secondary writebraw failed");
   }
   
index ecc8e4ce9c57d18b197973bb6e4447ab7b7e767d..3ececed393a6a6bada83eb4955b3e6cc834529fd 100644 (file)
@@ -3445,6 +3445,27 @@ static void process(void)
 
          t = time(NULL);
 
+         {
+           /* the following bit of code was added to combat smbd
+               looping chewing lots of CPU time. It should never
+               actually be needed, but it seems that some systems
+               don't set error correctly, which is used to distinguish
+               a select() timeout from a read error 
+              
+              we exit if receive_smb() returns false 3 times in one second. 
+              */
+           static int error_count=0;
+           static time_t error_time=0;
+           if (error_count==0) {
+             error_time = t;
+           } else if (error_time != t) {
+             error_count = 0;
+           } else if (error_count++ > 2) {
+             exit_server("looping in process()\n");
+           }
+         }
+
+
          /* become root again if waiting */
          unbecome_user();
 
index 0b113a2ed0eec45e56b34cfa940bacd517817156..321dabc72cf280b976ad31b7aa39e7c99c817969 100644 (file)
@@ -1554,10 +1554,8 @@ int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize)
 
       while( num_data_sofar < total_data || num_params_sofar < total_params)
        {
-         receive_smb(Client,inbuf, 0);
-         
-         /* Ensure this is still a trans2 packet (sanity check) */
-         if(CVAL(inbuf, smb_com) != SMBtranss2)
+         if(!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT*1000) ||
+            CVAL(inbuf, smb_com) != SMBtranss2)
            {
              outsize = set_message(outbuf,0,0,True);
              DEBUG(2,("Invalid secondary trans2 packet\n"));