Author: Isomer <isomer@coders.net>
authorPerry Lorier <isomer@undernet.org>
Sat, 15 Jul 2000 23:55:33 +0000 (23:55 +0000)
committerPerry Lorier <isomer@undernet.org>
Sat, 15 Jul 2000 23:55:33 +0000 (23:55 +0000)
Log message:

IP gline's / k:lines are now done with bit tests.  This should be much
much faster.

As a side effect you can now gline/kline  10.0.0.0/8 for instance.

git-svn-id: file:///home/klmitch/undernet-ircu/undernet-ircu-svn/ircu2/trunk@271 c9e4aea6-c8fd-4c43-8297-357d70d61c8c

ChangeLog
include/gline.h
include/s_conf.h
include/support.h
ircd/gline.c
ircd/list.c
ircd/s_conf.c
ircd/support.c

index f78ed10a88b3bcf90b7e04c4f4ab11c73209709f..68dcd218b8294d1b991c5e9782d17c2957fdd08b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2000-07-15  Perry Lorier       <Isomer@coders.net>
+       * various: IP only k:'s and G:'s now do bit tests instead of two(!) 
+                 match()'s.  Major Major cpu savings.  Also speed up the
+                 other case slightly.  As a side effect you can now
+                k/Gline *@10.0.0.0/8.  I'll do bans tomorrow, it's nearing
+                3am.
+
 2000-07-15  Perry Lorier       <Isomer@coders.net>
        * various: Fixed warnings after compiling on an alpha.
 2000-07-09  Perry Lorier       <Isomer@coders.net>
 #
 # ChangeLog for ircu2.10.11
 #
-# $Id: ChangeLog,v 1.157 2000-07-15 12:29:15 isomer Exp $
+# $Id: ChangeLog,v 1.158 2000-07-15 23:55:32 isomer Exp $
 #
 # Insert new changes at beginning of the change list.
 #
index d623e856639a178b01c8f6b5d219e73aca6e94ea..4a904664b0f57a88058a18d2844b13d7c1ef2a39 100644 (file)
@@ -30,6 +30,7 @@
 #define INCLUDED_sys_types_h
 #endif
 
+#include <netinet/in.h>
 
 struct Client;
 
@@ -43,6 +44,8 @@ struct Gline {
   char        *gl_reason;
   time_t       gl_expire;
   time_t       gl_lastmod;
+  struct in_addr ipnum;  /* We store the IP in binary for ip glines */
+  char                 bits;
   unsigned int gl_flags;
 };
 
index 6d3f7f124fe86468bef9c40c7602e65c8dc67fca..62a7f39e4e81dbb2e1e95e5ac41cb134d937bd8b 100644 (file)
@@ -66,6 +66,7 @@ struct ConfItem {
   unsigned int       status;    /* If CONF_ILLEGAL, delete when no clients */
   unsigned int       clients;   /* Number of *LOCAL* clients using this */
   struct in_addr     ipnum;     /* ip number of host field */
+  char                      bits;      /* Number of bits for ipkills */
   char*              host;
   char*              passwd;
   char*              name;
index 3d07a303e5af52023237b423611c2d9407ce1cdb..09ce20d638c5ed395a42dcbb1ae3623cd25a6137 100644 (file)
 #endif /* 0 */
 
 /*
- * Prototypes
+ * Given a number of bits, make a netmask out of it.
  */
+#define NETMASK(bits) htonl((0xffffffff>>(32-(bits)))<<(32-(bits)))
+
 
+/*
+ * Prototypes
+ */
+  
 extern int check_if_ipmask(const char *mask);
 extern void write_log(const char *filename, const char *pattern, ...);
 
index 53bd096e60e0c5db5bebbb3ee582bfe4de732496..bc18f39ce2c49eb9671364535e1122bab176f4f7 100644 (file)
@@ -28,6 +28,7 @@
 #include "match.h"
 #include "numeric.h"
 #include "s_bsd.h"
+#include "s_debug.h"
 #include "s_misc.h"
 #include "send.h"
 #include "struct.h"
@@ -39,6 +40,8 @@
 
 #include <assert.h>
 #include <string.h>
+#include <stdio.h>
+#include <arpa/inet.h> /* for inet_ntoa */
 
 struct Gline* GlobalGlineList  = 0;
 struct Gline* BadChanGlineList = 0;
@@ -109,8 +112,25 @@ make_gline(char *userhost, char *reason, time_t expire, time_t lastmod,
     DupString(gline->gl_user, user); /* remember them... */
     DupString(gline->gl_host, host);
 
-    if (check_if_ipmask(host)) /* mark if it's an IP mask */
+    if (check_if_ipmask(host)) { /* mark if it's an IP mask */
+      int class;
+      char ipname[16];
+      int ad[4] = { 0 };
+      int bits2 = 0;
+       
+      class = sscanf(host,"%d.%d.%d.%d/%d",
+                     &ad[0],&ad[1],&ad[2],&ad[3], &bits2);
+      if (class!=5) {
+        gline->bits=class*8;
+      }
+      else {
+        gline->bits=bits2;
+      }
+      sprintf_irc(ipname,"%d.%d.%d.%d",ad[0],ad[1],ad[2],ad[3]);
+      gline->ipnum.s_addr = inet_addr(ipname);
+      Debug((DEBUG_DEBUG,"IP gline: %08x/%i",gline->ipnum.s_addr,gline->bits));
       gline->gl_flags |= GLINE_IPMASK;
+    }
 
     if (after) {
       gline->gl_next = after->gl_next;
@@ -146,27 +166,35 @@ do_gline(struct Client *cptr, struct Client *sptr, struct Gline *gline)
     if ((acptr = LocalClientArray[fd])) {
       if (!acptr->user)
        continue;
-
-      if ((GlineIsIpMask(gline) ? match(gline->gl_host, acptr->sock_ip) :
-          match(gline->gl_host, acptr->sockhost)) == 0 &&
-         (!acptr->user->username ||
-          match(gline->gl_user, acptr->user->username) == 0)) {
-       /* ok, here's one that got G-lined */
-       send_reply(acptr, SND_EXPLICIT | ERR_YOUREBANNEDCREEP, ":%s",
-                  gline->gl_reason);
-
-       /* let the ops know about it */
-       sendto_opmask_butone(0, SNO_GLINE, "G-line active for %s",
-                            get_client_name(acptr, FALSE));
-
-       /* and get rid of him */
-       if ((tval = exit_client_msg(cptr, acptr, &me, "G-lined (%s)",
-                                   gline->gl_reason)))
-         retval = tval; /* retain killed status */
+       
+      if (acptr->user->username && 
+          match(gline->gl_user, acptr->user->username) == 0)
+          continue;
+          
+      if (GlineIsIpMask(gline)) {
+        Debug((DEBUG_DEBUG,"IP gline: %08x %08x/%i",cptr->ip.s_addr,gline->ipnum.s_addr,gline->bits));
+        if ((cptr->ip.s_addr & NETMASK(gline->bits)) != gline->ipnum.s_addr)
+          continue;
+      }
+      else {
+        if (match(gline->gl_host, acptr->sock_ip) != 0)
+          continue;
       }
+
+      /* ok, here's one that got G-lined */
+      send_reply(acptr, SND_EXPLICIT | ERR_YOUREBANNEDCREEP, ":%s",
+          gline->gl_reason);
+
+      /* let the ops know about it */
+      sendto_opmask_butone(0, SNO_GLINE, "G-line active for %s",
+                    get_client_name(acptr, FALSE));
+
+      /* and get rid of him */
+      if ((tval = exit_client_msg(cptr, acptr, &me, "G-lined (%s)",
+          gline->gl_reason)))
+        retval = tval; /* retain killed status */
     }
   }
-
   return retval;
 }
 
@@ -268,7 +296,6 @@ gline_activate(struct Client *cptr, struct Client *sptr, struct Gline *gline,
   unsigned int saveflags = 0;
 
   assert(0 != gline);
-  assert(!GlineIsLocal(gline));
 
   saveflags = gline->gl_flags;
 
@@ -436,18 +463,32 @@ gline_lookup(struct Client *cptr, unsigned int flags)
   for (gline = GlobalGlineList; gline; gline = sgline) {
     sgline = gline->gl_next;
 
-    if (gline->gl_expire <= CurrentTime)
+    if (gline->gl_expire <= CurrentTime) {
       gline_free(gline);
-    else if ((flags & GLINE_GLOBAL && gline->gl_flags & GLINE_LOCAL) ||
+      continue;
+    }
+    
+    if ((flags & GLINE_GLOBAL && gline->gl_flags & GLINE_LOCAL) ||
             (flags & GLINE_LASTMOD && !gline->gl_lastmod))
       continue;
-    else if ((GlineIsIpMask(gline) ?
-             match(gline->gl_host, ircd_ntoa((const char *)&cptr->ip)) :
-             match(gline->gl_host, cptr->user->host)) == 0 &&
-            match(gline->gl_user, cptr->user->username) == 0)
-      return gline;
+     
+    if (match(gline->gl_user, cptr->user->username) != 0)
+      continue;
+        
+    if (GlineIsIpMask(gline)) {
+      Debug((DEBUG_DEBUG,"IP gline: %08x %08x/%i",cptr->ip.s_addr,gline->ipnum.s_addr,gline->bits));
+      if ((cptr->ip.s_addr & NETMASK(gline->bits)) != gline->ipnum.s_addr)
+        continue;
+    }
+    else {
+      if (match(gline->gl_host, cptr->user->host) != 0) 
+        continue;
+    }
+    return gline;
   }
-
+  /*
+   * No Glines matched
+   */
   return 0;
 }
 
index fb86192e2b9ea85bd776038586eefcdec9f646f3..af65ddeb5e2e7b4549aca0d315eb3dd405286ba9 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "class.h"
 #include "client.h"
+#include "IPcheck.h"
 #include "ircd.h"
 #include "ircd_alloc.h"
 #include "ircd_reply.h"
index 83b0b0fae09bedb0d2b82dbc7e6729e63ef49b6a..a6b7d13299b5ab75c74d0e3178393c22694617bf 100644 (file)
@@ -75,79 +75,6 @@ struct TRecord*  tdata = NULL;
 struct tm        motd_tm;
 
 
-/*
- *  is the K line field an interval or a comment? - Mmmm
- */
-static int is_comment(const char *comment)
-{
-  unsigned int i;
-  unsigned int len = strlen(comment);
-  for (i = 0; i < len; ++i) {
-    if (!IsKTimeChar(comment[i]))
-      return 1;
-  }
-  return 0;
-}
-
-/*
- *  check against a set of time intervals
- */
-static int check_time_interval(char *interval, char *reply, size_t reply_size)
-{
-  struct tm* tptr;
-  char*      p;
-  int        perm_min_hours;
-  int        perm_min_minutes;
-  int        perm_max_hours;
-  int        perm_max_minutes;
-  int        nowm;
-  int        perm_min;
-  int        perm_max;
-
-  tptr = localtime(&CurrentTime);
-  nowm = tptr->tm_hour * 60 + tptr->tm_min;
-
-  while (interval) {
-    p = strchr(interval, ',');
-    if (p)
-      *p = '\0';
-    if (sscanf(interval, "%2d%2d-%2d%2d", &perm_min_hours, &perm_min_minutes,
-               &perm_max_hours, &perm_max_minutes) != 4)
-    {
-      if (p)
-        *p = ',';
-      return 0;
-    }
-    if (p)
-      *(p++) = ',';
-    perm_min = 60 * perm_min_hours + perm_min_minutes;
-    perm_max = 60 * perm_max_hours + perm_max_minutes;
-    /*
-     * The following check allows intervals over midnight ...
-     */
-    if ((perm_min < perm_max)
-        ? (perm_min <= nowm && nowm <= perm_max)
-        : (perm_min <= nowm || nowm <= perm_max))
-    {
-      ircd_snprintf(0, reply, reply_size, ":You are not allowed to connect "
-                   "from %d:%02d to %d:%02d.", perm_min_hours,
-                   perm_min_minutes, perm_max_hours, perm_max_minutes);
-      return (ERR_YOUREBANNEDCREEP);
-    }
-    if ((perm_min < perm_max)
-        ? (perm_min <= nowm + 5 && nowm + 5 <= perm_max)
-        : (perm_min <= nowm + 5 || nowm + 5 <= perm_max))
-    {
-      ircd_snprintf(0, reply, reply_size, ":%d minute%s and you will be "
-                   "denied for further access", perm_min - nowm,
-                   (perm_min - nowm) > 1 ? "s" : "");
-      return (ERR_YOUWILLBEBANNED);
-    }
-    interval = p;
-  }
-  return 0;
-}
-
 /*
  * output the reason for being k lined from a file  - Mmmm
  * sptr is server
@@ -1066,6 +993,7 @@ int conf_init(void)
     /* Could we test if it's conf line at all?      -Vesa */
     if (line[1] != ':') {
       Debug((DEBUG_ERROR, "Bad config line: %s", line));
+      sendto_op_mask(SNO_OLDSNO,"Bad Config line");
       continue;
     }
     if (aconf)
@@ -1144,6 +1072,7 @@ int conf_init(void)
       break;
     default:
       Debug((DEBUG_ERROR, "Error in config file: %s", line));
+      sendto_op_mask(SNO_OLDSNO,"Unknown prefix in config file: %c",*tmp);
       break;
     }
     if (IsIllegal(aconf))
@@ -1167,9 +1096,9 @@ int conf_init(void)
       if (aconf->status & CONF_ME) {
         if (!tmp) {
           Debug((DEBUG_FATAL, "Your M: line must have the Numeric, "
-              "assigned to you by routing-com, behind the port number!\n"));
+              "assigned to you by routing-com!\n"));
           ircd_log(L_WARNING, "Your M: line must have the Numeric, "
-              "assigned to you by routing-com, behind the port number!\n");
+              "assigned to you by routing-com!\n");
           exit(-1);
         }
         SetYXXServerName(&me, atoi(tmp));        /* Our Numeric Nick */
@@ -1278,6 +1207,31 @@ int conf_init(void)
     if (aconf->status == CONF_ME) {
       ircd_strncpy(me.info, aconf->name, REALLEN);
     }
+    
+    if (aconf->status == CONF_IPKILL) {
+      /* 
+       * Here we use the same kludge as in listener.c to parse
+       * a.b.c.d, or a.b.c.*, or a.b.c.d/e.
+       */
+      int class;
+      char ipname[16];
+      int ad[4] = { 0 };
+      int bits2=0;
+      class=sscanf(aconf->host,"%d.%d.%d.%d/%d",
+                   &ad[0], &ad[1], &ad[2], &ad[3], &bits2);
+      if (class!=5) {
+        aconf->bits=class*8;
+      }
+      else {
+        aconf->bits=bits2;
+      }
+      sprintf_irc(ipname,"%d.%d.%d.%d",ad[0], ad[1], ad[2], ad[3]);
+      
+      /* This ensures endian correctness */
+      aconf->ipnum.s_addr = inet_addr(ipname);
+      Debug((DEBUG_DEBUG,"IPkill: %s = %08x/%i (%08x)",ipname,
+       aconf->ipnum.s_addr,aconf->bits,NETMASK(aconf->bits)));
+    }
 
     /*
      * Juped nicks are listed in the 'password' field of U:lines,
@@ -1357,9 +1311,19 @@ void read_tlines()
   }
 }
 
+/*
+ * find_kill
+ * input:
+ *  client pointer
+ * returns:
+ *  0: Client may continue to try and connect
+ * -1: Client was K/k:'d - sideeffect: reason was sent.
+ * -2: Client was G/g:'d - sideeffect: reason was sent.
+ * sideeffects:
+ *  Client may have been sent a reason why they are denied, as above.
+ */
 int find_kill(struct Client *cptr)
 {
-  char             reply[256];
   const char*      host;
   const char*      name;
   struct ConfItem* tmp;
@@ -1373,47 +1337,43 @@ int find_kill(struct Client *cptr)
   host = cptr->sockhost;
   name = cptr->user->username;
 
-#if 0
-  /*
-   * whee :)
-   * XXX - if this ever happens, we're already screwed
+  assert(strlen(host) <= HOSTLEN);
+  assert((name ? strlen(name) : 0) <= HOSTLEN);
+  
+  /* 2000-07-14: Rewrote this loop for massive speed increases.
+   *             -- Isomer
    */
-  if (strlen(host) > HOSTLEN ||
-      (name ? strlen(name) : 0) > HOSTLEN)
-    return (0);
-#endif
-
-  reply[0] = '\0';
-
   for (tmp = GlobalConfList; tmp; tmp = tmp->next) {
-    /* Added a check against the user's IP address as well.
-     * If the line is either CONF_KILL or CONF_IPKILL, check it; if and only
-     * if it's CONF_IPKILL, check the IP address as well (the && below will
-     * short circuit and the match won't even get run) -Kev
+  
+    if ((tmp->status & CONF_KLINE) == 0)
+       continue;
+       
+    /*
+     * What is this for?  You can K: by port?!
+     *   -- Isomer
      */
-    if ((tmp->status & CONF_KLINE) && tmp->host && tmp->name &&
-        (match(tmp->host, host) == 0 ||
-        ((tmp->status == CONF_IPKILL) &&
-        match(tmp->host, ircd_ntoa((const char*) &cptr->ip)) == 0)) &&
-        (!name || match(tmp->name, name) == 0) &&
-        (!tmp->port || (tmp->port == cptr->listener->port)))
-    {
-      /*
-       * Can short-circuit evaluation - not taking chances
-       * because check_time_interval destroys tmp->passwd
-       * - Mmmm
-       */
-      if (EmptyString(tmp->passwd))
-        break;
-      else if (is_comment(tmp->passwd))
-        break;
-      else if (check_time_interval(tmp->passwd, reply, sizeof(reply)))
-        break;
+    if (tmp->port && tmp->port != cptr->listener->port)
+       continue;
+
+    if (!tmp->name || match(tmp->name, name) != 0)
+       continue;
+       
+    if (!tmp->host)
+       break;
+    
+    if (tmp->status != CONF_IPKILL) {
+       if (match(tmp->host, host) == 0)
+         break;
+    }
+    else { /* k: by IP */
+       Debug((DEBUG_DEBUG, "ip: %08x network: %08x/%i mask: %08x",
+               cptr->ip.s_addr, tmp->ipnum.s_addr, tmp->bits, 
+               NETMASK(tmp->bits)));
+       if ((cptr->ip.s_addr & NETMASK(tmp->bits)) == tmp->ipnum.s_addr)
+               break;
     }
   }
-  if (reply[0])
-    send_reply(cptr, SND_EXPLICIT | ERR_YOUREBANNEDCREEP, reply);
-  else if (tmp) {
+  if (tmp) {
     if (EmptyString(tmp->passwd))
       send_reply(cptr, SND_EXPLICIT | ERR_YOUREBANNEDCREEP,
                 ":Connection from your host is refused on this server.");
@@ -1442,7 +1402,12 @@ int find_kill(struct Client *cptr)
   else
     agline = NULL;                /* if a gline was found, it was inactive */
 
-  return (tmp ? -1 : (agline ? -2 : 0));
+  if (tmp)
+    return -1;
+  if (agline)
+    return -2;
+    
+  return 0;
 }
 
 struct MotdItem* read_motd(const char* motdfile)
index ac1f7d49be7bb89d6e0dd7013aceea63cbdb7dd0..93a94e362bc6235c112e19aecc7926020671b821 100644 (file)
@@ -42,7 +42,7 @@ int check_if_ipmask(const char *mask)
   const char *p;
 
   for (p = mask; *p; ++p)
-    if (*p != '*' && *p != '?' && *p != '.')
+    if (*p != '*' && *p != '?' && *p != '.' && *p != '/')
     {
       if (!IsDigit(*p))
         return 0;