added IPNode for storing real IP's of users
authorpk910 <philipp@zoelle1.de>
Thu, 12 Jan 2012 07:09:23 +0000 (08:09 +0100)
committerpk910 <philipp@zoelle1.de>
Thu, 12 Jan 2012 07:17:05 +0000 (08:17 +0100)
Makefile.am
src/IPNode.c [new file with mode: 0644]
src/IPNode.h [new file with mode: 0644]
src/UserNode.c
src/UserNode.h
src/WHOHandler.c
src/tools.c
src/tools.h

index dee97f345ffd22a5642c210dd35f4d233384ab77..1f7d907f521ef3e41d68054cf84f7b8996308ef6 100644 (file)
@@ -19,6 +19,7 @@ neonserv_SOURCES = src/version.c \
       src/ChanUser.c \
       src/ModeNode.c \
       src/BanNode.c \
+      src/IPNode.c \
       src/WHOHandler.c \
       src/modcmd.c \
       src/mysqlConn.c \
diff --git a/src/IPNode.c b/src/IPNode.c
new file mode 100644 (file)
index 0000000..7e1c499
--- /dev/null
@@ -0,0 +1,150 @@
+/* IPNode.c - NeonServ v5.3
+ * Copyright (C) 2011-2012  Philipp Kreil (pk910)
+ * 
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License 
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. 
+ */
+#include "IPNode.h"
+
+#define hex2dec(x) (isxdigit(x) ? (isdigit(x) ? x - '0' : (isupper(x) ? x - 'A' : x - 'a') + 10) : 0)
+
+static struct IPNode *parseIP(struct IPNode *ip, const char *org_ipstr);
+
+struct IPNode *createIPNode(const char *ipstr) {
+    struct IPNode *ip = malloc(sizeof(*ip));
+    if(!ip) return NULL;
+    ip->flags = 0;
+    if(!parseIP(ip, ipstr)) {
+        free(ip);
+        ip = NULL;
+    }
+    return ip;
+}
+
+static struct IPNode *parseIP(struct IPNode *ip, const char *org_ipstr) {
+    char ipstr[strlen(org_ipstr)+1];
+    strcpy(ipstr, org_ipstr);
+    if(strchr(ipstr, ':')) {
+        ip->flags |= IPNODE_IS_IPV6;
+        char *p1 = ipstr;
+        char *p2;
+        int blocks = 1;
+        while(*p1) {
+            if(p1[0] == ':' && p1[1] == ':') {
+                //double ::
+                p1++;
+            }
+            if(*p1 == ':')
+                blocks++;
+            if(*p1 == '/') {
+                *p1 = '\0';
+                break;
+            }
+            p1++;
+        }
+        if(blocks > 8) return 0;
+        char hexa[32];
+        int i;
+        for(i = 0; i < 32; i++)
+            hexa[i] = '0';
+        i = 0;
+        int p = 0;
+        int len;
+        while(*p1) {
+            if(p1[0] == ':' && p1[1] == ':') {
+                i = 8 - blocks;
+                p1 += 2;
+                p = 0;
+                p2 = p1;
+                len = 0;
+                while(*p2 && *p2 != ':') {
+                    len++;
+                    p2++;
+                }
+                continue;
+            }
+            else if(*p1 == ':') {
+                p1++;
+                i++;
+                p = 0;
+                len = 0;
+                while(*p2 && *p2 != ':') {
+                    len++;
+                    p2++;
+                }
+                continue;
+            }
+            if(p >= 4 || i >= 8) return NULL;
+            hexa[i*4 + ((4-len) + (p++))] = *p1;
+            p1++;
+        }
+        for(i = 0, p = 0; i < 32; i+=2, p++) {
+            ip->ipdata[p] = hex2dec(hexa[i]) << 4;
+            ip->ipdata[p] |= hex2dec(hexa[i+1]);
+        }
+    } else if(strchr(ipstr, '.')) {
+        char *ippart = ipstr;
+        char *next = strchr(ipstr, '/');
+        int i = 0;
+        if(next) {
+            *next = '\0';
+            next = NULL;
+        }
+        do {
+            next = strchr(ippart, '.');
+            if(next) *next = '\0';
+            if(i >= 4) return NULL;
+            ip->ipdata[12+(i++)] = (unsigned char) atoi(ippart);
+            if(next) {
+                ippart = next+1;
+                continue;
+            }
+            break;
+        } while(1);
+        if(i != 3) return NULL;
+    } else
+        return NULL;
+    return ip;
+}
+
+int ipmatch(struct IPNode *ip1, struct IPNode *ip2, int bits) {
+    if(!bits) return 0;
+    bits = (ip2->flags & IPNODE_IS_IPV6 ? bits : bits + (12*8));
+    if(bits > 128) return 1;
+    int sbit = (bits % 8);
+    int check = (bits / 8) + (sbit ? 1 : 0);
+    int i;
+    for(i = 0; i < check; i++) {
+        if(i == check-1 && sbit) {
+            int bitmask = 0;
+            int j = 0;
+            for(;j < sbit; j++) {
+                bitmask <<= 1;
+                bitmask |= 1;
+            }
+            for(;j < 8; j++) {
+                bitmask <<= 1;
+                bitmask |= 0;
+            }
+            if((ip1->ipdata[i] & bitmask) != (ip2->ipdata[i] & bitmask))
+                return 1;
+        } else if(ip1->ipdata[i] != ip2->ipdata[i])
+            return 1;
+    }
+    return 0;
+}
+
+void freeIPNode(struct IPNode *ip) {
+    free(ip);
+}
+
diff --git a/src/IPNode.h b/src/IPNode.h
new file mode 100644 (file)
index 0000000..0b2fd29
--- /dev/null
@@ -0,0 +1,33 @@
+/* IPNode.h - NeonServ v5.3
+ * Copyright (C) 2011-2012  Philipp Kreil (pk910)
+ * 
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License 
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. 
+ */
+#ifndef _IPNode_h
+#define _IPNode_h
+#include "main.h"
+
+#define IPNODE_IS_IPV6  0x01
+#define IPNODE_IS_LOCAL 0x02
+
+struct IPNode {
+    unsigned char flags;
+    unsigned char ipdata[16]; // 16 * 8bit = 128bit
+};
+
+struct IPNode *createIPNode(const char *ipstr);
+int ipmatch(struct IPNode *ip1, struct IPNode *ip2, int bits);
+void freeIPNode(struct IPNode *ip);
+
+#endif
\ No newline at end of file
index 3f20a13eccdf93a8a7a85409bc405f0f8d87fbd2..21b618d1118b51a16fac594e638f44976378ba6b 100644 (file)
@@ -18,6 +18,7 @@
 #include "ChanUser.h"
 #include "tools.h"
 #include "IRCEvents.h"
+#include "IPNode.h"
 
 static struct UserNode **userList;
 
@@ -199,6 +200,7 @@ struct UserNode* addUser(const char *nick) {
     user->created = time(0);
     user->ident[0] = 0;
     user->host[0] = 0;
+    user->ip = NULL;
     user->realname[0] = 0;
     user->flags = 0;
     user->channel = NULL;
@@ -255,6 +257,7 @@ struct UserNode* createTempUser(const char *nick) {
         }
         user->ident[0] = 0;
         user->host[0] = 0;
+        user->ip = NULL;
         user->realname[0] = 0;
         user->flags = 0;
         user->channel = NULL;
@@ -299,6 +302,7 @@ struct UserNode* createTempUserMask(const char *mask) {
                 }
                 user->ident[0] = 0;
                 user->host[0] = 0;
+                user->ip = NULL;
                 user->realname[0] = 0;
                 user->flags = 0;
                 user->channel = NULL;
@@ -322,6 +326,7 @@ struct UserNode* createTempUserMask(const char *mask) {
             user->created = time(0);
             user->ident[0] = 0;
             user->host[0] = 0;
+            user->ip = NULL;
             user->realname[0] = 0;
             user->flags = USERFLAG_ISSERVER;
             user->channel = NULL;
@@ -345,6 +350,7 @@ struct UserNode* createTempUserMask(const char *mask) {
                 user->created = time(0);
                 user->ident[0] = 0;
                 user->host[0] = 0;
+                user->ip = NULL;
                 user->realname[0] = 0;
                 user->flags = 0;
                 user->channel = NULL;
@@ -417,9 +423,11 @@ void delUser(struct UserNode* user, int freeUser) {
             removeChanUserFromLists(chanUser, 1, 0, freeUser);
         }
     }
-    if(freeUser)
+    if(freeUser) {
+        if(user->ip)
+            freeIPNode(user->ip);
         free(user);
-    else
+    else
         user->next = NULL;
 }
 
index bb794b7c81ed81772431c40eca740da600e22bc7..bf07e7e133e97701b69e4e7d21e1dea382f3b20e 100644 (file)
@@ -37,6 +37,7 @@
 
 struct ChanUser;
 struct language;
+struct IPNode;
 
 struct UserNode {
     char nick[NICKLEN+1];
@@ -44,6 +45,7 @@ struct UserNode {
     char host[HOSTLEN+1];
     char realname[REALLEN+1];
     char auth[AUTHLEN+1];
+    struct IPNode *ip;
     unsigned int flags;
     time_t created, last_who;
     struct ChanUser *channel;
index eafa62fcfccfd86cba1bfeeeec4fc376fe345b03..61f2ed2afec8f894ad4353eba8eea3e976cb4ad7 100644 (file)
@@ -21,6 +21,7 @@
 #include "ChanUser.h"
 #include "ModeNode.h"
 #include "ClientSocket.h"
+#include "IPNode.h"
 
 #define WHOQUEUETYPE_ISONQUEUE 0x01
 #define WHOQUEUETYPE_USERLIST  0x02
@@ -107,7 +108,7 @@ void get_userlist(struct ChanNode *chan, userlist_callback_t callback, void *dat
         entry->data[0] = data;
         for(i = 1; i < MAXCALLBACKS; i++)
             entry->data[i] = NULL;
-        putsock(bot, "WHO %s,%d %%tuhnaf,%d", chan->name, entry->type, entry->type);
+        putsock(bot, "WHO %s,%d %%tuihnaf,%d", chan->name, entry->type, entry->type);
     } else
         callback(bot, chan, data);
 }
@@ -142,7 +143,7 @@ void _get_userlist_with_invisible(struct ChanNode *chan, userlist_callback_t cal
         entry->data[0] = data;
         for(i = 1; i < MAXCALLBACKS; i++)
             entry->data[i] = NULL;
-        putsock(bot, "WHO %s,%d d%%tuhnaf,%d", chan->name, entry->type, entry->type);
+        putsock(bot, "WHO %s,%d d%%tuihnaf,%d", chan->name, entry->type, entry->type);
     } else
         callback(bot, chan, data);
 }
@@ -209,8 +210,8 @@ void recv_whohandler_354(struct ClientSocket *client, char **argv, unsigned int
         //parse flags
         int userflags = 0;
         int chanuserflags = 0;
-        for(i = 0; i < strlen(argv[5]); i++) {
-            switch (argv[5][i]) {
+        for(i = 0; i < strlen(argv[6]); i++) {
+            switch (argv[6][i]) {
                 case '@':
                     chanuserflags |= CHANUSERFLAG_OPPED;
                     break;
@@ -231,17 +232,17 @@ void recv_whohandler_354(struct ClientSocket *client, char **argv, unsigned int
             }
         }
         
-        struct UserNode *user = getUserByNick(argv[4]);
+        struct UserNode *user = getUserByNick(argv[5]);
         struct ChanUser *chanuser;
         if((chanuserflags & CHANUSERFLAG_INVISIBLE) && (!user || !isBot(user))) {
-            user = createTempUser(argv[4]);
+            user = createTempUser(argv[5]);
             user->flags |= USERFLAG_ISTMPUSER;
             chan->flags |= CHANFLAG_HAVE_INVISIBLES;
             chanuser = addInvisibleChanUser(chan, user);
             chanuser->flags = (chanuser->flags & ~CHANUSERFLAG_OPPED_OR_VOICED) | chanuserflags;
         } else {
             if(user == NULL) {
-                user = addUser(argv[4]);
+                user = addUser(argv[5]);
             }
             if(!(chanuser = getChanUser(user, chan))) {
                 chanuser = addChanUser(chan, user);
@@ -252,10 +253,12 @@ void recv_whohandler_354(struct ClientSocket *client, char **argv, unsigned int
         user->last_who = time(0);
         if(!*user->ident)
             strcpy(user->ident, argv[2]);
+        if(!user->ip)
+            user->ip = createIPNode(argv[3]);
         if(!*user->host)
-            strcpy(user->host, argv[3]);
-        if(!(user->flags & USERFLAG_ISAUTHED) && strcmp(argv[6], "0")) {
-            strcpy(user->auth, argv[6]);
+            strcpy(user->host, argv[4]);
+        if(!(user->flags & USERFLAG_ISAUTHED) && strcmp(argv[7], "0")) {
+            strcpy(user->auth, argv[7]);
             user->flags |= USERFLAG_ISAUTHED;
         }
     } else if((type & WHOQUEUETYPE_USERAUTH) && !(entry->type & WHOQUEUETYPE_FOUND)) {
index c802bbeaf165e4f3762a5b11dd1560db0acb53b9..2cb1065fa8458b33b2235200e3269f79a1e48558 100644 (file)
@@ -19,6 +19,7 @@
 #include "ChanNode.h"
 #include "lang.h"
 #include "ClientSocket.h"
+#include "IPNode.h"
 
 static const struct default_language_entry msgtab[] = {
     {"TIME_MASK_2_ITEMS", "%s and %s"}, /* {ARGS: "2 days", "1 hour"} */
@@ -487,7 +488,7 @@ char* make_banmask(char *input, char* buffer) {
         ident = input;
         *p = '\0';
         host = p+1;
-    } else if((p = strstr(input, "."))) {
+    } else if((p = strstr(input, ".")) || (p = strstr(input, ":"))) {
         host = input;
     } else if(*input == '*' && input[1] != '\0' && !strstr(input+1, "*")) {
         //AUTH MASK
@@ -525,6 +526,26 @@ int isFakeHost(char *host) {
     return (strlen(p2+1) > 4);
 }
 
+int mask_match(char *mask, struct UserNode *user) {
+    char usermask[NICKLEN+USERLEN+HOSTLEN+3];
+    char matchmask[strlen(mask)+3];
+    strcpy(matchmask, mask);
+    char *host = strchr(mask, '@');
+    if(host) {
+        struct IPNode *ip = createIPNode(host);
+        int bits = (ip->flags & IPNODE_IS_IPV6 ? 128 : 32);
+        if((host = strchr(host, '/'))) {
+            bits = atoi(host+1);
+        }
+        if(ip && user->ip&& !ipmatch(user->ip, ip, bits)) {
+            host[1] = '*';
+            host[2] = '\0';
+        }
+    }
+    sprintf(usermask, "%s!%s@%s", user->nick, user->ident, user->host);
+    return match(matchmask, usermask);
+}
+
 static unsigned long crc_table[256];
 
 static void crc32_init() {
index dffb4a2188a4f9828b879dace81e9fd8a1bb87de..29cd337697c6e5347640b0c2d6d17cd63ce288d9 100644 (file)
@@ -82,6 +82,8 @@ char* generate_banmask(struct UserNode *user, char *buffer);
 char* make_banmask(char *input, char* buffer);
 int isFakeHost(char *host);
 
+int mask_match(char *mask, struct UserNode *user);
+
 unsigned long crc32(const char *text);
 
 void init_tools();