]> jfr.im git - irc/quakenet/newserv.git/blobdiff - bans/bans.c
LUA: port luadb to dbapi2 to drop postgres dependency
[irc/quakenet/newserv.git] / bans / bans.c
index b98f7ae79eef44be92433e08af32d98f8f37f235..7c4cc989b286fab55cd40377468d1156733f4034 100644 (file)
 #include "../irc/irc_config.h"
 #include "../core/nsmalloc.h"
 #include "../lib/flags.h"
+#include "../lib/version.h"
 
-#define ALLOCUNIT 100
-
-chanban *freebans;
-
-void _init() {
-  freebans=NULL;  
-}
+MODULE_VERSION("")
 
 void _fini() {
   nsfreeall(POOL_BANS);
 }
 
 chanban *getchanban() {
-  int i;
   chanban *cbp;
 
-  if (freebans==NULL) {
-    freebans=(chanban *)nsmalloc(POOL_BANS, ALLOCUNIT*sizeof(chanban));
-    for (i=0;i<ALLOCUNIT-1;i++) {
-      freebans[i].next=(struct chanban *)&(freebans[i+1]);
-    }
-    freebans[ALLOCUNIT-1].next=NULL;
-  }
-
-  cbp=freebans;
-  freebans=cbp->next;
+  cbp = nsmalloc(POOL_BANS, sizeof(chanban));
+  if (!cbp)
+    return NULL;
 
   cbp->nick=NULL;
   cbp->user=NULL;
@@ -46,16 +33,11 @@ chanban *getchanban() {
 }
 
 void freechanban(chanban *cbp) {
-  cbp->next=(struct chanban *)freebans;
-
-  if (cbp->nick)
-    freesstring(cbp->nick);
-  if (cbp->user)
-    freesstring(cbp->user);
-  if (cbp->host)
-    freesstring(cbp->host);
+  freesstring(cbp->nick);
+  freesstring(cbp->user);
+  freesstring(cbp->host);
 
-  freebans=cbp;
+  nsfree(POOL_BANS, cbp);
 }
 
 /*
@@ -66,13 +48,11 @@ void freechanban(chanban *cbp) {
 chanban *makeban(const char *mask) {
   int len;
   int foundat=-1,foundbang=-1;
-  int dotcount=0;
-  int notip=0;
   int foundwild=0;
-  int foundslash=0;
   int i;
   int checklen;
   chanban *cbp;
+  char tmpbuf[512];
   
   cbp=getchanban();  
   len=strlen(mask);
@@ -94,8 +74,10 @@ chanban *makeban(const char *mask) {
       /* Got @ sign: everything after here is host */
       if ((len-i)-1 > HOSTLEN) {
         /* This is too long, we need to truncate it */
-        cbp->host=getsstring(&mask[len-HOSTLEN],HOSTLEN);
-        cbp->host->content[0]='*';
+        strncpy(tmpbuf,&mask[len-HOSTLEN],HOSTLEN);
+        tmpbuf[HOSTLEN]='\0';
+        tmpbuf[0]='*';
+        cbp->host=getsstring(tmpbuf,HOSTLEN);
         cbp->flags |= CHANBAN_HOSTMASK;
       } else if (i==(len-1)) {
         /* Ban ending with @, just mark it invalid */
@@ -106,38 +88,15 @@ chanban *makeban(const char *mask) {
         /* Special case: "@*" */
         cbp->flags |= CHANBAN_HOSTANY;
         cbp->host=NULL;      
-      } else if (foundslash) {
-        /* If we found a slash (/), this can only be a CIDR ban */
-        /* However, it might be broken, so we need to retain the exact string
-         * to track it accurately */
-        cbp->host=getsstring(&mask[i+1],HOSTLEN);
-        if ((notip || dotcount!=3) && !foundwild) {
-          cbp->flags |= (CHANBAN_INVALID | CHANBAN_HOSTEXACT);
-        } else if (foundwild) {
-          cbp->flags |= (CHANBAN_INVALID | CHANBAN_HOSTMASK);
-        } else {
-          unsigned int a,b,c,d,l;
-          /* CIDR bans have to match this pattern.  */
-          if ((sscanf(&mask[i+1], "%u.%u.%u.%u/%u",&a,&b,&c,&d,&l) != 5) ||
-               (a>255) || (b>255) || (c>255) || (d>255) || (l>32) ) {
-            cbp->flags |= (CHANBAN_HOSTEXACT | CHANBAN_INVALID);
-          } else {
-            /* Save the IP address and mask for later */
-            cbp->ipaddr=(a<<24)|(b<<16)|(c<<8)|d;
-            cbp->mask=0xffffffff;
-            if (l==0) {
-              cbp->mask=0;
-            } else if (l<32) {
-              cbp->mask<<=(32-l);
-            }
-            /* pre-AND the IP with the mask here. */
-            cbp->ipaddr &= cbp->mask;
-            cbp->flags |= (CHANBAN_HOSTEXACT | CHANBAN_CIDR);
-          }
-        }
       } else {
         /* We have some string with between 1 and HOSTLEN characters.. */
         cbp->host=getsstring(&mask[i+1],HOSTLEN);
+
+        /* If it matches an IP address, flag it as such */
+        if (ipmask_parse(cbp->host->content, &(cbp->ipaddr), &(cbp->prefixlen))) {
+          cbp->flags |= CHANBAN_IP;
+        }
+
         if (foundwild) {
           /* We check all characters after the last wildcard (if any).. if they match
            * the corresponding bits of the hidden host string we mark it accordingly */
@@ -154,38 +113,20 @@ chanban *makeban(const char *mask) {
             }
           }
           cbp->flags |= CHANBAN_HOSTMASK;
-          if (!notip && dotcount<=3)
-            cbp->flags |= CHANBAN_IP;
         } else {
           /* Exact host: see if it ends with the "hidden host" string */
           cbp->flags |= CHANBAN_HOSTEXACT;
           if ((cbp->host->length > (strlen(HIS_HIDDENHOST)+1)) && 
               !ircd_strcmp(cbp->host->content+(cbp->host->length-strlen(HIS_HIDDENHOST)), HIS_HIDDENHOST)) {
             cbp->flags |= CHANBAN_HIDDENHOST;
-          } else if (!notip && dotcount==3) {
-            unsigned int a,b,c,d;
-            if ((sscanf(&mask[i+1], "%u.%u.%u.%u",&a,&b,&c,&d) != 4) ||
-                  (a > 255) || (b > 255) || (c > 255) || (d > 255) ) {
-              /* Something with only numbers and exactly 3 dots that isn't an IP address can't match anything. */
-              cbp->flags |= CHANBAN_INVALID; 
-            } else {
-              cbp->ipaddr=(a<<24)|(b<<16)|(c<<8)|d;
-              cbp->flags |= CHANBAN_IP;
-            }
           }
         }
       }
       foundat=i;
       break;
-    } else if (mask[i]=='/') {
-      foundslash=1;
-    } else if (mask[i]=='.') {
-      dotcount++;
     } else if (mask[i]=='?' || mask[i]=='*') {
       if (!foundwild)  /* Mark last wildcard in string */
         foundwild=i;
-    } else if (mask[i]<'0' || mask[i]>'9') {
-      notip=1;
     }
   }
 
@@ -264,8 +205,10 @@ chanban *makeban(const char *mask) {
       cbp->user=NULL;
     } else if (foundat - foundbang - 1 > USERLEN) {
       /* It's too long.. */
-      cbp->user=getsstring(&mask[foundat-USERLEN],USERLEN);
-      cbp->user->content[0]='*';
+      strncpy(tmpbuf,&mask[foundat-USERLEN],USERLEN);
+      tmpbuf[USERLEN]='\0';
+      tmpbuf[0]='*';
+      cbp->user=getsstring(tmpbuf,USERLEN);
       cbp->flags |= CHANBAN_USERMASK;
     } else if ((foundat - foundbang - 1 == 1) && mask[foundbang+1]=='*') {
       cbp->user=NULL;
@@ -277,6 +220,10 @@ chanban *makeban(const char *mask) {
       else
         cbp->flags |= CHANBAN_USEREXACT;
     }
+    /* Username part can't contain an @ */
+    if (cbp->user && strchr(cbp->user->content,'@')) {
+      cbp->flags |= CHANBAN_INVALID;
+    }
   }
 
   assert(cbp->flags & (CHANBAN_USEREXACT | CHANBAN_USERMASK | CHANBAN_USERANY | CHANBAN_USERNULL));
@@ -452,9 +399,9 @@ char *bantostring(chanban *bp) {
   strpos += sprintf(outstring+strpos,"@");
 
   if (bp->flags & CHANBAN_HOSTANY) {
-    strpos += sprintf(outstring+strpos,"*");
+    sprintf(outstring+strpos,"*");
   } else if (bp->host) {
-    strpos += sprintf(outstring+strpos,"%s",bp->host->content);
+    sprintf(outstring+strpos,"%s",bp->host->content);
   }
 
   return outstring;
@@ -484,12 +431,11 @@ char *bantostringdebug(chanban *bp) {
   }
 
   if (bp->host) {
-    strpos += sprintf(outstring+strpos, "host=%s ",bp->host->content);
+    sprintf(outstring+strpos, "host=%s ",bp->host->content);
   } else {
-    strpos += sprintf(outstring+strpos, "nohost ");
+    sprintf(outstring+strpos, "nohost ");
   }
 
-
   return outstring;
 }