added IPNode for storing real IP's of users
[NeonServV5.git] / src / IPNode.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);
+}
+