(thanks to the people reading git and excessively exploiting this bug... It was undet...
[NeonServV5.git] / src / IPNode.c
1 /* IPNode.c - NeonServ v5.6
2  * Copyright (C) 2011-2012  Philipp Kreil (pk910)
3  * 
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  * 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * 
14  * You should have received a copy of the GNU General Public License 
15  * along with this program. If not, see <http://www.gnu.org/licenses/>. 
16  */
17 #include "IPNode.h"
18
19 #define hex2dec(x) (isxdigit(x) ? (isdigit(x) ? x - '0' : (isupper(x) ? x - 'A' : x - 'a') + 10) : 0)
20
21 static struct IPNode *parseIP(struct IPNode *ip, const char *org_ipstr);
22
23 struct IPNode *createIPNode(const char *ipstr) {
24     struct IPNode *ip = malloc(sizeof(*ip));
25     if(!ip) return NULL;
26     ip->flags = 0;
27     if(!parseIP(ip, ipstr)) {
28         free(ip);
29         ip = NULL;
30     }
31     return ip;
32 }
33
34 static struct IPNode *parseIP(struct IPNode *ip, const char *org_ipstr) {
35     char ipstr[strlen(org_ipstr)+1];
36     strcpy(ipstr, org_ipstr);
37     if(strchr(ipstr, ':')) {
38         ip->flags |= IPNODE_IS_IPV6;
39         char *p1 = ipstr;
40         char *p2;
41         int blocks = 1;
42         while(*p1) {
43             if(p1[0] == ':' && p1[1] == ':') {
44                 //double ::
45                 p1++;
46             }
47             if(*p1 == ':')
48                 blocks++;
49             if(*p1 == '/') {
50                 *p1 = '\0';
51                 break;
52             }
53             p1++;
54         }
55         if(blocks > 8) return 0;
56         char hexa[32];
57         int i;
58         for(i = 0; i < 32; i++)
59             hexa[i] = '0';
60         i = 0;
61         int p = 0;
62         int len;
63         while(*p1) {
64             if(p1[0] == ':' && p1[1] == ':') {
65                 i = 8 - blocks;
66                 p1 += 2;
67                 p = 0;
68                 p2 = p1;
69                 len = 0;
70                 while(*p2 && *p2 != ':') {
71                     len++;
72                     p2++;
73                 }
74                 continue;
75             }
76             else if(*p1 == ':') {
77                 p1++;
78                 i++;
79                 p = 0;
80                 len = 0;
81                 while(*p2 && *p2 != ':') {
82                     len++;
83                     p2++;
84                 }
85                 continue;
86             }
87             if(p >= 4 || i >= 8) return NULL;
88             hexa[i*4 + ((4-len) + (p++))] = *p1;
89             p1++;
90         }
91         for(i = 0, p = 0; i < 32; i+=2, p++) {
92             ip->ipdata[p] = hex2dec(hexa[i]) << 4;
93             ip->ipdata[p] |= hex2dec(hexa[i+1]);
94         }
95     } else if(strchr(ipstr, '.')) {
96         char *ippart = ipstr;
97         char *next = strchr(ipstr, '/');
98         int i = 0;
99         if(next) {
100             *next = '\0';
101             next = NULL;
102         }
103         do {
104             next = strchr(ippart, '.');
105             if(next) *next = '\0';
106             if(i >= 4) return NULL;
107             ip->ipdata[12+(i++)] = (unsigned char) atoi(ippart);
108             if(next) {
109                 ippart = next+1;
110                 continue;
111             }
112             break;
113         } while(1);
114         if(i != 3) return NULL;
115     } else
116         return NULL;
117     return ip;
118 }
119
120 int ipmatch(struct IPNode *ip1, struct IPNode *ip2, int bits) {
121     if(!bits) return 0;
122     bits = (ip2->flags & IPNODE_IS_IPV6 ? bits : bits + (12*8));
123     if(bits > 128) return 1;
124     int sbit = (bits % 8);
125     int check = (bits / 8) + (sbit ? 1 : 0);
126     int i;
127     for(i = 0; i < check; i++) {
128         if(i == check-1 && sbit) {
129             int bitmask = 0;
130             int j = 0;
131             for(;j < sbit; j++) {
132                 bitmask <<= 1;
133                 bitmask |= 1;
134             }
135             for(;j < 8; j++) {
136                 bitmask <<= 1;
137                 bitmask |= 0;
138             }
139             if((ip1->ipdata[i] & bitmask) != (ip2->ipdata[i] & bitmask))
140                 return 1;
141         } else if(ip1->ipdata[i] != ip2->ipdata[i])
142             return 1;
143     }
144     return 0;
145 }
146
147 void freeIPNode(struct IPNode *ip) {
148     free(ip);
149 }
150