ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/ermyth/src/cidr.C
Revision: 1.1
Committed: Thu Jul 19 08:24:56 2007 UTC (16 years, 10 months ago) by pippijn
Content type: text/plain
Branch: MAIN
Log Message:
initial import. the most important changes since Atheme are:
- fixed many memory leaks
- fixed many bugs
- converted to C++ and use more STL containers
- added a (not very enhanced yet) perl module
- greatly improved XML-RPC speed
- added a JSON-RPC module with code from json-cpp
- added a valgrind memcheck module to operserv
- added a more object oriented base64 implementation
- added a specialised unit test framework
- improved stability
- use gettimeofday() if available
- reworked adding/removing commands
- MemoServ IGNORE DEL can now remove indices

File Contents

# Content
1 /**
2 * cidr.C: CIDR matching.
3 * Rights to this code are documented in doc/LICENSE.
4 *
5 * Most code in this file has been copied from ratbox, src/match.c and
6 * src/irc_string.c. It provides CIDR matching for IPv4 and IPv6 without
7 * special OS support.
8 *
9 * Copyright © 1996-2002 Hybrid Development Team
10 * Copyright © 2002-2005 ircd-ratbox development team
11 * Copyright © 2005-2007 Atheme Project (http://www.atheme.org)
12 */
13
14 static char const rcsid[] = "$Id";
15
16 #include "atheme.h"
17
18 #ifndef INADDRSZ
19 #define INADDRSZ 4
20 #endif
21 #ifndef IN6ADDRSZ
22 #define IN6ADDRSZ 16
23 #endif
24 #ifndef INT16SZ
25 #define INT16SZ 2
26 #endif
27
28 /* compares the first 'mask' bits
29 * returns 1 if equal, 0 if not */
30 static int
31 comp_with_mask (void *addr, void *dest, unsigned mask)
32 {
33 if (memcmp (addr, dest, mask / 8) == 0)
34 {
35 int n = mask / 8;
36 int m = ((-1) << (8 - (mask % 8)));
37 if (mask % 8 == 0 || (((unsigned char *) addr)[n] & m) == (((unsigned char *) dest)[n] & m))
38 {
39 return (1);
40 }
41 }
42 return (0);
43 }
44
45 /*
46 * inet_pton4() and inet_pton6() are
47 * Copyright © 1996-1999 by Internet Software Consortium.
48 *
49 * Permission to use, copy, modify, and distribute this software for any
50 * purpose with or without fee is hereby granted, provided that the above
51 * copyright notice and this permission notice appear in all copies.
52 *
53 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
54 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
55 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
56 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
57 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
58 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
59 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
60 * SOFTWARE.
61 */
62
63 /*
64 * WARNING: Don't even consider trying to compile this on a system where
65 * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
66 */
67
68 /* int
69 * inet_pton4(src, dst)
70 * like inet_aton() but without all the hexadecimal and shorthand.
71 * return:
72 * 1 if `src' is a valid dotted quad, else 0.
73 * notice:
74 * does not touch `dst' unless it's returning 1.
75 * author:
76 * Paul Vixie, 1996.
77 */
78 static int
79 inet_pton4 (char const *src, unsigned char *dst)
80 {
81 int saw_digit, octets, ch;
82 unsigned char tmp[INADDRSZ], *tp;
83
84 saw_digit = 0;
85 octets = 0;
86 *(tp = tmp) = 0;
87 while ((ch = *src++) != '\0')
88 {
89 if (ch >= '0' && ch <= '9')
90 {
91 unsigned newtp = *tp * 10 + (ch - '0');
92
93 if (newtp > 255)
94 return (0);
95 *tp = newtp;
96 if (!saw_digit)
97 {
98 if (++octets > 4)
99 return (0);
100 saw_digit = 1;
101 }
102 }
103 else if (ch == '.' && saw_digit)
104 {
105 if (octets == 4)
106 return (0);
107 *++tp = 0;
108 saw_digit = 0;
109 }
110 else
111 return (0);
112 }
113 if (octets < 4)
114 return (0);
115 memcpy (dst, tmp, INADDRSZ);
116 return (1);
117 }
118
119 /* int
120 * inet_pton6(src, dst)
121 * convert presentation level address to network order binary form.
122 * return:
123 * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
124 * notice:
125 * (1) does not touch `dst' unless it's returning 1.
126 * (2) :: in a full address is silently ignored.
127 * credit:
128 * inspired by Mark Andrews.
129 * author:
130 * Paul Vixie, 1996.
131 */
132 static int
133 inet_pton6 (char const *src, unsigned char *dst)
134 {
135 static const char xdigits[] = "0123456789abcdef";
136 unsigned char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
137 const char *curtok;
138 int ch, saw_xdigit;
139 unsigned val;
140
141 tp = static_cast<unsigned char *> (memset (tmp, '\0', IN6ADDRSZ));
142 endp = tp + IN6ADDRSZ;
143 colonp = NULL;
144 /* Leading :: requires some special handling. */
145 if (*src == ':')
146 if (*++src != ':')
147 return (0);
148 curtok = src;
149 saw_xdigit = 0;
150 val = 0;
151 while ((ch = tolower (*src++)) != '\0')
152 {
153 const char *pch;
154
155 pch = strchr (xdigits, ch);
156 if (pch != NULL)
157 {
158 val <<= 4;
159 val |= (pch - xdigits);
160 if (val > 0xffff)
161 return (0);
162 saw_xdigit = 1;
163 continue;
164 }
165 if (ch == ':')
166 {
167 curtok = src;
168 if (!saw_xdigit)
169 {
170 if (colonp)
171 return (0);
172 colonp = tp;
173 continue;
174 }
175 else if (*src == '\0')
176 {
177 return (0);
178 }
179 if (tp + INT16SZ > endp)
180 return (0);
181 *tp++ = (unsigned char) (val >> 8) & 0xff;
182 *tp++ = (unsigned char) val & 0xff;
183 saw_xdigit = 0;
184 val = 0;
185 continue;
186 }
187 if (*src != '\0' && ch == '.')
188 {
189 if (((tp + INADDRSZ) <= endp) && inet_pton4 (curtok, tp) > 0)
190 {
191 tp += INADDRSZ;
192 saw_xdigit = 0;
193 break; /* '\0' was seen by inet_pton4(). */
194 }
195 }
196 else
197 continue;
198 return (0);
199 }
200 if (saw_xdigit)
201 {
202 if (tp + INT16SZ > endp)
203 return (0);
204 *tp++ = (unsigned char) (val >> 8) & 0xff;
205 *tp++ = (unsigned char) val & 0xff;
206 }
207 if (colonp != NULL)
208 {
209 /*
210 * Since some memmove()'s erroneously fail to handle
211 * overlapping regions, we'll do the shift by hand.
212 */
213 const int n = tp - colonp;
214 int i;
215
216 if (tp == endp)
217 return (0);
218 for (i = 1; i <= n; i++)
219 {
220 endp[-i] = colonp[n - i];
221 colonp[n - i] = 0;
222 }
223 tp = endp;
224 }
225 if (tp != endp)
226 return (0);
227 memcpy (dst, tmp, IN6ADDRSZ);
228 return (1);
229 }
230
231 /*
232 * match_ips()
233 *
234 * Input - cidr ip mask, address
235 * Output - 0 = Matched 1 = Did not match
236 * switched 0 and 1 to be consistent with match() -- jilles
237 */
238 int
239 match_ips (const char *s1, const char *s2)
240 {
241 unsigned char ipaddr[IN6ADDRSZ], maskaddr[IN6ADDRSZ];
242 char ipmask[BUFSIZE];
243 char ip[HOSTLEN + 1];
244 char *len;
245 int cidrlen;
246
247 strlcpy (ipmask, s1, sizeof ipmask);
248 strlcpy (ip, s2, sizeof ip);
249
250 len = strrchr (ipmask, '/');
251 if (len == NULL)
252 return 1;
253
254 *len++ = '\0';
255
256 cidrlen = atoi (len);
257 if (cidrlen == 0)
258 return 1;
259
260 if (strchr (ip, ':') && strchr (ipmask, ':'))
261 {
262 if (cidrlen > 128)
263 return 1;
264 if (!inet_pton6 (ip, ipaddr))
265 return 1;
266 if (!inet_pton6 (ipmask, maskaddr))
267 return 1;
268 return !comp_with_mask (ipaddr, maskaddr, cidrlen);
269 }
270 else if (!strchr (ip, ':') && !strchr (ipmask, ':'))
271 {
272 if (cidrlen > 32)
273 return 1;
274 if (!inet_pton4 (ip, ipaddr))
275 return 1;
276 if (!inet_pton4 (ipmask, maskaddr))
277 return 1;
278 return !comp_with_mask (ipaddr, maskaddr, cidrlen);
279 }
280 else
281 return 1;
282 }
283
284 /* match_cidr()
285 *
286 * Input - mask n!u@i/c, address n!u@i
287 * Output - 0 = Matched 1 = Did not match
288 * switched 0 and 1 to be consistent with match() -- jilles
289 */
290 int
291 match_cidr (const char *s1, const char *s2)
292 {
293 unsigned char ipaddr[IN6ADDRSZ], maskaddr[IN6ADDRSZ];
294 char mask[BUFSIZE];
295 char address[NICKLEN + USERLEN + HOSTLEN + 6];
296 char *ipmask;
297 char *ip;
298 char *len;
299 int cidrlen;
300
301 strlcpy (mask, s1, sizeof mask);
302 strlcpy (address, s2, sizeof address);
303
304 ipmask = strrchr (mask, '@');
305 if (ipmask == NULL)
306 return 1;
307
308 *ipmask++ = '\0';
309
310 ip = strrchr (address, '@');
311 if (ip == NULL)
312 return 1;
313 *ip++ = '\0';
314
315 len = strrchr (ipmask, '/');
316 if (len == NULL)
317 return 1;
318
319 *len++ = '\0';
320
321 cidrlen = atoi (len);
322 if (cidrlen == 0)
323 return 1;
324
325 if (strchr (ip, ':') && strchr (ipmask, ':'))
326 {
327 if (cidrlen > 128)
328 return 1;
329 if (!inet_pton6 (ip, ipaddr))
330 return 1;
331 if (!inet_pton6 (ipmask, maskaddr))
332 return 1;
333 return !comp_with_mask (ipaddr, maskaddr, cidrlen) || match (mask, address);
334 }
335 else if (!strchr (ip, ':') && !strchr (ipmask, ':'))
336 {
337 if (cidrlen > 32)
338 return 1;
339 if (!inet_pton4 (ip, ipaddr))
340 return 1;
341 if (!inet_pton4 (ipmask, maskaddr))
342 return 1;
343 return !comp_with_mask (ipaddr, maskaddr, cidrlen) || match (mask, address);
344 }
345 else
346 return 1;
347 }
348
349 /* vim:cinoptions=>s,e0,n0,f0,{0,}0,^0,=s,ps,t0,c3,+s,(2s,us,)20,*30,gs,hs
350 * vim:ts=8
351 * vim:sw=8
352 * vim:noexpandtab
353 */