]> jfr.im git - irc/ircd-hybrid/bopm.git/commitdiff
bopm.conf.sample: Added config parameter FDLIMIT (default 512), which is maximum...
authorstrtok <redacted>
Tue, 12 Feb 2002 06:10:42 +0000 (06:10 +0000)
committerstrtok <redacted>
Tue, 12 Feb 2002 06:10:42 +0000 (06:10 +0000)
    of file descriptors that can be open at any time (for scanning).
config.c: Added -d debug output of set config parameters
misc.c: Fixed bug involving clean()
scan.c: Added scan_establish() code to socket()/connect() to a socket, connections
        are now queued if the FDLIMIT cap is reached.

bopm.conf.sample
config.c
extern.h
misc.c
scan.c
scan.h

index 4946d380f81f63b61707a908d7dbc58f76c124fb..a3b230802dc2245803ce484aed00320d3e9c8d39 100644 (file)
@@ -196,3 +196,10 @@ HELP_EMAIL help@lists.blitzed.org
 #                       message as soon as it connects.
 
 AWAY I'm a bot.  Your messages will be ignored.
+
+# FDLIMIT <limit> : Limit number of open file descriptors for SCAN ONLY (this does
+#                   not include file descriptors used for the IRC socket or log files.
+#                   Once limit has been reached, any further scans are queued until
+#                   there are file descriptors free
+
+FDLIMIT 512
index 438b36807ddb05bf7b00849d5b2bb33fb35ec36f..7440a2e7b66e1218d4ace8b1040a373110dc648e 100644 (file)
--- a/config.c
+++ b/config.c
@@ -30,6 +30,7 @@ along with this program; if not, write to the Free Software
 #include "config.h"
 #include "log.h"
 #include "misc.h"
+#include "extern.h"
 
 /* Global Configuration Variables */
 
@@ -71,7 +72,7 @@ config_hash hash[] = {
        {"SCANPORT",            TYPE_INT   , 1,0,    &CONF_SCANPORT           },
        {"BINDIRC",             TYPE_STRING, 0,0,    &CONF_BINDIRC            },
        {"BINDSCAN",            TYPE_STRING, 0,0,    &CONF_BINDSCAN           },
-       {"FDLIMIT",             TYPE_INT   , 0,0,    &CONF_FDLIMIT            },
+       {"FDLIMIT",             TYPE_INT   , 1,0,    &CONF_FDLIMIT            },
        {"CHANNELS",            TYPE_STRING, 1,0,    &CONF_CHANNELS           },
        {"NICKSERV_IDENT",      TYPE_STRING, 0,0,    &CONF_NICKSERV_IDENT     },
        {"CHANSERV_INVITE",     TYPE_STRING, 0,0,    &CONF_CHANSERV_INVITE    },
@@ -170,6 +171,19 @@ void config_checkreq()
             log("CONFIG -> Parameter [%s] required but not defined in config.", hash[i].key);
             errfnd++;
          }
+        else if(OPT_DEBUG && hash[i].reqmet)
+         {
+            switch(hash[i].type)
+             {
+                 case TYPE_STRING:
+                      log("CONFIG -> Set [%s]: %s", hash[i].key, *(char**) hash[i].var);
+                      break;
+                 case TYPE_INT:
+                      log("CONFIG -> Set [%s]: %d", hash[i].key, *(int *) hash[i].var);
+                      break;
+             }
+         }
+
 
       if(errfnd)
        {
index 58ebe1ad9d51b5f867e63aa86c71cbef3203df98..5c614321d26875be51633991c71b47353c49a9f3 100644 (file)
--- a/extern.h
+++ b/extern.h
     extern char *CONF_HELP_EMAIL;
     extern char *CONF_AWAY;
 
+
     extern int   CONF_PORT;
     extern int   CONF_SCANPORT;
+    extern int   CONF_FDLIMIT;
 
     extern int   OPT_DEBUG;
  
diff --git a/misc.c b/misc.c
index a52a7c6ce03fa64f4371aa064a6a4a5e7c341563..13eebafe93888038629e5f64bdc718b8664cb6a1 100644 (file)
--- a/misc.c
+++ b/misc.c
@@ -128,6 +128,9 @@ char *clean(char *str)
 
     lastnon = 0;
     firstnon = 0;
+    
+    if(strlen(str) <= 1) /* Dont need to deal with 1 character */
+       return str;
 
     for(i = 0; i < strlen(str);i++)
      {
diff --git a/scan.c b/scan.c
index 35ec8be3013c45353354c0dd8ebbba99817d8e9d..12daec14488b8bbdc524bd1e0b4853f7a2740d5e 100644 (file)
--- a/scan.c
+++ b/scan.c
@@ -49,6 +49,7 @@ struct scan_struct *CONNECTIONS = 0;  /* Linked list head for connections */
 char SENDBUFF[513];
 char RECVBUFF[513];
 
+unsigned int FD_USE = 0;                 /* Keep track of numbers of open FD's, for use with FDLIMIT */
 
 
 /*    Protocol Name, Port, Write Handler, Read Handler */ 
@@ -92,27 +93,10 @@ void scan_connect(char *addr, char *irc_addr, char *irc_nick,
 
       int i;                
       scan_struct *newconn; 
-      struct sockaddr_in  SCAN_LOCAL; /* For local bind() */ 
 
       if(OPT_DEBUG)
              log("SCAN -> checking user %s!%s@%s", irc_nick, irc_user, irc_addr);
 
-      memset(&SCAN_LOCAL, 0, sizeof(struct sockaddr_in));
-
-      /* Setup SCAN_LOCAL for local bind() */
-      if(CONF_BINDSCAN)
-        {      
-
-               if(!inet_aton(CONF_BINDSCAN, &(SCAN_LOCAL.sin_addr)))
-                   {
-                       log("SCAN -> bind(): %s is an invalid address", CONF_BINDSCAN);
-                       exit(1);
-                   }
-
-               SCAN_LOCAL.sin_family = AF_INET;
-               SCAN_LOCAL.sin_port = 0;
-        }
-
  
      /* Loop through the protocols creating a 
        * seperate connection struct for each 
@@ -144,54 +128,84 @@ void scan_connect(char *addr, char *irc_addr, char *irc_nick,
             newconn->sockaddr.sin_family = AF_INET;                    /* Fill in sockaddr with information about remote host */
             newconn->sockaddr.sin_port = htons(newconn->protocol->port); 
             newconn->sockaddr.sin_addr.s_addr = inet_addr(addr);
-      
-            newconn->fd = socket(PF_INET, SOCK_STREAM, 0);             /* Request file descriptor for socket */
-
-            if(newconn->fd == -1)                                      /* If error, free memory for this struct and continue */
-              {
-                 log("SCAN -> Error allocating file descriptor.");
-                 free(newconn->addr);
-                 free(newconn->irc_addr);
-                 free(newconn->irc_user);
-                 free(newconn->irc_nick);
-                if(newconn->conn_notice)
-                   free(newconn->conn_notice);
-                 free(newconn);
-                 continue;
-              }
-
-
-            /* Bind to specific interface designated in conf file */
-            if(CONF_BINDSCAN)
-             {
-                if(bind(newconn->fd, (struct sockaddr *)&SCAN_LOCAL, sizeof(struct sockaddr_in)) == -1)     
-                  {     
-                   
-                      switch(errno)     
-                        {     
-                               case EACCES:     
-                                 log("SCAN -> bind(): No access to bind to %s", CONF_BINDSCAN);     
-                                 exit(1);     
-                               default:     
-                                 log("SCAN -> bind(): Error binding to %s", CONF_BINDSCAN);     
-                                 exit(1);     
-     
-                        }     
-     
-     
-                  }      
-
-             }
-
-            time(&(newconn->create_time));                               /* Log create time of connection for timeouts */
-            newconn->state = STATE_ESTABLISHED;                          /* Connection is just established             */
-            scan_add(newconn);                                           /* Add struct to list of connections          */                                                             
-            fcntl(newconn->fd, F_SETFL, O_NONBLOCK);                     /* Set socket non blocking                    */
-            connect(newconn->fd, (struct sockaddr *) &(newconn->sockaddr), sizeof(newconn->sockaddr));  /* Connect !   */
+
+            newconn->state = STATE_UNESTABLISHED;                        /* Queue connection                           */
+
+            scan_add(newconn);                                           /* Add struct to list of connections          */
+
+            if(FD_USE < CONF_FDLIMIT)                                    /* If we have available FD's, overide queue   */
+               scan_establish(newconn);        
+            else if(OPT_DEBUG >= 3)
+               log("SCAN -> File Descriptor limit (%d) reached, queuing scan for %s", CONF_FDLIMIT ,newconn->addr);
+
         }    
 
 }
 
+/*  Get FD for new socket, bind to interface and connect() (non blocking)
+ *  then set conn to ESTABLISHED for write check.
+ */
+
+void scan_establish(scan_struct *conn)
+{
+    struct sockaddr_in  SCAN_LOCAL; /* For local bind() */
+
+    memset(&SCAN_LOCAL, 0, sizeof(struct sockaddr_in));
+
+    /* Setup SCAN_LOCAL for local bind() */
+    if(CONF_BINDSCAN)
+     {
+
+           if(!inet_aton(CONF_BINDSCAN, &(SCAN_LOCAL.sin_addr)))
+            {
+                 log("SCAN -> bind(): %s is an invalid address", CONF_BINDSCAN);
+                 exit(1);
+            }
+
+           SCAN_LOCAL.sin_family = AF_INET;
+           SCAN_LOCAL.sin_port = 0;
+      }
+
+      conn->fd = socket(PF_INET, SOCK_STREAM, 0);                /* Request file descriptor for socket */
+
+      if(conn->fd == -1)                                         /* If error, free memory for this struct */
+       {
+           log("SCAN -> Error allocating file descriptor.");
+           scan_del(conn);
+           return;
+       }
+
+
+       /* Bind to specific interface designated in conf file */
+      if(CONF_BINDSCAN)
+       {
+           if(bind(conn->fd, (struct sockaddr *)&SCAN_LOCAL, sizeof(struct sockaddr_in)) == -1)
+            {
+
+                switch(errno)
+                 {
+                     case EACCES:
+                        log("SCAN -> bind(): No access to bind to %s", CONF_BINDSCAN);
+                        exit(1);
+                     default:
+                        log("SCAN -> bind(): Error binding to %s", CONF_BINDSCAN);
+                        exit(1);
+
+                 }
+
+            }
+
+       }
+
+
+     time(&(conn->create_time));                             /* Log create time of connection for timeouts */
+     conn->state = STATE_ESTABLISHED;                        /* Flag conn established (for write)          */
+     fcntl(conn->fd, F_SETFL, O_NONBLOCK);                   /* Set socket non blocking                    */
+     connect(conn->fd, (struct sockaddr *) &(conn->sockaddr), sizeof(conn->sockaddr));  /* Connect !   */
+     FD_USE++;                                               /* Increase global FD Use counter             */      
+}
+
+
 /*  Pass one cycle to the proxy scanner so it can do neccessary functions 
  *  like testing for sockets to be written to and read from.
  */
@@ -365,6 +379,7 @@ void scan_del(scan_struct *delconn)
      scan_struct *lastss;
 
      close(delconn->fd);
+     FD_USE--;            /* 1 file descriptor freed up for use */
 
      lastss = 0;
 
@@ -416,12 +431,30 @@ void scan_timer()
     scan_struct *nextss;
  
     time_t present;
-   
     time(&present);
 
-    for(ss = CONNECTIONS;ss;)
+    /* Check for timed out connections and also check if queued (UNESTABLISHED) connections
+     * can be established now */
+
+    for(ss = CONNECTIONS; ss;)
       {
-          if(((present - ss->create_time) >= 30) || (ss->state == STATE_CLOSED)) /* State closed or timed out, remove */ 
+
+          if((ss->state == STATE_UNESTABLISHED))
+            { 
+               if(FD_USE < CONF_FDLIMIT)
+                {
+                  scan_establish(ss);
+                  if(OPT_DEBUG >= 3)
+                    log("SCAN -> File descriptor free, continuing queued scan on %s", ss->addr);
+                }
+               else
+                {
+                  ss = ss->next;
+                  continue;              /* Continue to avoid timeout checks on an unestablished connection */
+                }
+            }
+
+          if(( ((present - ss->create_time) >= 30)) || (ss->state == STATE_CLOSED)) /* State closed or timed out, remove */ 
             {
                 if(ss->verbose && (ss->state != STATE_CLOSED))
                  {
@@ -439,6 +472,7 @@ void scan_timer()
    
           ss = ss->next;
       }
+
 }
 
 
diff --git a/scan.h b/scan.h
index 5c491d11dad196bda69041660af100c56844bb8a..9e290b7fc7e8869ce3577bc3d3ba5bb7c87bc08e 100644 (file)
--- a/scan.h
+++ b/scan.h
@@ -40,6 +40,7 @@
      void do_scan_init();
      void scan_connect(char *addr, char *irc_addr, char *irc_nick,
                       char *irc_user, int verbose, char *conn_notice);
+     void scan_establish(scan_struct *conn);
      void scan_add(scan_struct *newcon);
      void scan_del(scan_struct *ss);
      void scan_cycle();