Blame


1 864007e3 2010-03-09 pbug /*
2 48603f7d 2014-04-13 pjp * Copyright (c) 2010-2014 Peter J. Philipp
3 864007e3 2010-03-09 pbug * All rights reserved.
4 864007e3 2010-03-09 pbug *
5 864007e3 2010-03-09 pbug * Redistribution and use in source and binary forms, with or without
6 864007e3 2010-03-09 pbug * modification, are permitted provided that the following conditions
7 864007e3 2010-03-09 pbug * are met:
8 864007e3 2010-03-09 pbug * 1. Redistributions of source code must retain the above copyright
9 864007e3 2010-03-09 pbug * notice, this list of conditions and the following disclaimer.
10 864007e3 2010-03-09 pbug * 2. Redistributions in binary form must reproduce the above copyright
11 864007e3 2010-03-09 pbug * notice, this list of conditions and the following disclaimer in the
12 864007e3 2010-03-09 pbug * documentation and/or other materials provided with the distribution.
13 864007e3 2010-03-09 pbug * 3. The name of the author may not be used to endorse or promote products
14 864007e3 2010-03-09 pbug * derived from this software without specific prior written permission
15 864007e3 2010-03-09 pbug *
16 864007e3 2010-03-09 pbug * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 864007e3 2010-03-09 pbug * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 864007e3 2010-03-09 pbug * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 864007e3 2010-03-09 pbug * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 864007e3 2010-03-09 pbug * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 864007e3 2010-03-09 pbug * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 864007e3 2010-03-09 pbug * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 864007e3 2010-03-09 pbug * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 864007e3 2010-03-09 pbug * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 864007e3 2010-03-09 pbug * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 864007e3 2010-03-09 pbug *
27 864007e3 2010-03-09 pbug */
28 864007e3 2010-03-09 pbug #include "include.h"
29 864007e3 2010-03-09 pbug #include "dns.h"
30 864007e3 2010-03-09 pbug #include "db.h"
31 864007e3 2010-03-09 pbug
32 0e7d94ac 2014-05-18 pjp u_int8_t find_region(struct sockaddr_storage *, int);
33 0e7d94ac 2014-05-18 pjp in_addr_t getmask(int);
34 0e7d94ac 2014-05-18 pjp int getmask6(int, struct sockaddr_in6 *);
35 0e7d94ac 2014-05-18 pjp void init_region(void);
36 0e7d94ac 2014-05-18 pjp int insert_region(char *, char *, u_int8_t);
37 864007e3 2010-03-09 pbug
38 864007e3 2010-03-09 pbug SLIST_HEAD(listhead, entry) head;
39 864007e3 2010-03-09 pbug
40 c0963faf 2014-05-01 pjp static struct entry {
41 10133795 2010-03-27 pbug char name[INET6_ADDRSTRLEN];
42 10133795 2010-03-27 pbug int family;
43 10133795 2010-03-27 pbug struct sockaddr_storage hostmask;
44 10133795 2010-03-27 pbug struct sockaddr_storage netmask;
45 864007e3 2010-03-09 pbug u_int8_t region;
46 10133795 2010-03-27 pbug u_int8_t prefixlen;
47 c0963faf 2014-05-01 pjp SLIST_ENTRY(entry) region_entry;
48 c0963faf 2014-05-01 pjp } *n2, *np;
49 864007e3 2010-03-09 pbug
50 864007e3 2010-03-09 pbug
51 0e7d94ac 2014-05-18 pjp static const char rcsid[] = "$Id: region.c,v 1.11 2014/05/18 17:14:05 pjp Exp $";
52 864007e3 2010-03-09 pbug
53 10133795 2010-03-27 pbug /*
54 10133795 2010-03-27 pbug * INIT_REGION - initialize the region singly linked list
55 10133795 2010-03-27 pbug */
56 10133795 2010-03-27 pbug
57 864007e3 2010-03-09 pbug void
58 864007e3 2010-03-09 pbug init_region(void)
59 864007e3 2010-03-09 pbug {
60 864007e3 2010-03-09 pbug SLIST_INIT(&head);
61 864007e3 2010-03-09 pbug return;
62 864007e3 2010-03-09 pbug }
63 864007e3 2010-03-09 pbug
64 10133795 2010-03-27 pbug /*
65 10133795 2010-03-27 pbug * INSERT_REGION - insert particular address and prefix length and region
66 10133795 2010-03-27 pbug * into the
67 10133795 2010-03-27 pbug * singly linked list at "head", if the address contains
68 10133795 2010-03-27 pbug * a colon then it is assumed to be an IPv6 address.
69 10133795 2010-03-27 pbug * return -1 on error, 0 on successful insertion
70 10133795 2010-03-27 pbug */
71 10133795 2010-03-27 pbug
72 10133795 2010-03-27 pbug int
73 10133795 2010-03-27 pbug insert_region(char *address, char *prefixlen, u_int8_t region)
74 864007e3 2010-03-09 pbug {
75 10133795 2010-03-27 pbug struct sockaddr_in *sin;
76 10133795 2010-03-27 pbug struct sockaddr_in6 *sin6;
77 864007e3 2010-03-09 pbug int pnum;
78 10133795 2010-03-27 pbug int ret;
79 864007e3 2010-03-09 pbug
80 10133795 2010-03-27 pbug pnum = atoi(prefixlen);
81 864007e3 2010-03-09 pbug n2 = malloc(sizeof(struct entry)); /* Insert after. */
82 864007e3 2010-03-09 pbug
83 10133795 2010-03-27 pbug if (strchr(address, ':') != NULL) {
84 10133795 2010-03-27 pbug n2->family = AF_INET6;
85 10133795 2010-03-27 pbug sin6 = (struct sockaddr_in6 *)&n2->hostmask;
86 10133795 2010-03-27 pbug if ((ret = inet_pton(AF_INET6, address, &sin6->sin6_addr.s6_addr)) != 1)
87 10133795 2010-03-27 pbug return (-1);
88 10133795 2010-03-27 pbug sin6->sin6_family = AF_INET6;
89 10133795 2010-03-27 pbug sin6 = (struct sockaddr_in6 *)&n2->netmask;
90 10133795 2010-03-27 pbug sin6->sin6_family = AF_INET6;
91 10133795 2010-03-27 pbug if (getmask6(pnum, sin6) < 0)
92 10133795 2010-03-27 pbug return(-1);
93 10133795 2010-03-27 pbug n2->region = region;
94 10133795 2010-03-27 pbug n2->prefixlen = pnum;
95 10133795 2010-03-27 pbug } else {
96 864007e3 2010-03-09 pbug
97 10133795 2010-03-27 pbug n2->family = AF_INET;
98 10133795 2010-03-27 pbug sin = (struct sockaddr_in *)&n2->hostmask;
99 10133795 2010-03-27 pbug sin->sin_family = AF_INET;
100 10133795 2010-03-27 pbug sin->sin_addr.s_addr = inet_addr(address);
101 10133795 2010-03-27 pbug sin = (struct sockaddr_in *)&n2->netmask;
102 10133795 2010-03-27 pbug sin->sin_family = AF_INET;
103 10133795 2010-03-27 pbug sin->sin_addr.s_addr = getmask(pnum);
104 10133795 2010-03-27 pbug n2->region = region;
105 10133795 2010-03-27 pbug n2->prefixlen = pnum;
106 10133795 2010-03-27 pbug
107 10133795 2010-03-27 pbug }
108 10133795 2010-03-27 pbug
109 c0963faf 2014-05-01 pjp SLIST_INSERT_HEAD(&head, n2, region_entry);
110 10133795 2010-03-27 pbug
111 10133795 2010-03-27 pbug return (0);
112 864007e3 2010-03-09 pbug }
113 864007e3 2010-03-09 pbug
114 864007e3 2010-03-09 pbug /*
115 864007e3 2010-03-09 pbug * FIND_REGION - walk the region list and find the correponding network with
116 10133795 2010-03-27 pbug * the highest prefix length, so that a /24 has more precedence
117 10133795 2010-03-27 pbug * than
118 10133795 2010-03-27 pbug * a /8 for example. IPv6 and IPv4 addresses are kept seperate
119 864007e3 2010-03-09 pbug */
120 864007e3 2010-03-09 pbug
121 864007e3 2010-03-09 pbug u_int8_t
122 10133795 2010-03-27 pbug find_region(struct sockaddr_storage *sst, int family)
123 864007e3 2010-03-09 pbug {
124 10133795 2010-03-27 pbug struct sockaddr_in *sin, *sin0;
125 10133795 2010-03-27 pbug struct sockaddr_in6 *sin6, *sin60, *sin61;
126 864007e3 2010-03-09 pbug u_int32_t hostmask, netmask;
127 10133795 2010-03-27 pbug u_int32_t a;
128 10133795 2010-03-27 pbug #ifdef __amd64
129 10133795 2010-03-27 pbug u_int64_t *hm[2], *nm[2], *a6[2];
130 10133795 2010-03-27 pbug #else
131 10133795 2010-03-27 pbug u_int32_t *hm[4], *nm[4], *a6[4];
132 10133795 2010-03-27 pbug #endif
133 864007e3 2010-03-09 pbug u_int8_t region = 0xff;
134 10133795 2010-03-27 pbug u_int8_t prefixlen = 0;
135 864007e3 2010-03-09 pbug
136 c0963faf 2014-05-01 pjp SLIST_FOREACH(np, &head, region_entry) {
137 10133795 2010-03-27 pbug if (np->family == AF_INET) {
138 10133795 2010-03-27 pbug if (family != AF_INET)
139 10133795 2010-03-27 pbug continue;
140 10133795 2010-03-27 pbug sin = (struct sockaddr_in *)sst;
141 10133795 2010-03-27 pbug a = sin->sin_addr.s_addr;
142 10133795 2010-03-27 pbug sin = (struct sockaddr_in *)&np->hostmask;
143 10133795 2010-03-27 pbug sin0 = (struct sockaddr_in *)&np->netmask;
144 10133795 2010-03-27 pbug hostmask = sin->sin_addr.s_addr;
145 10133795 2010-03-27 pbug netmask = sin0->sin_addr.s_addr;
146 10133795 2010-03-27 pbug if ((hostmask & netmask) == (a & netmask)) {
147 10133795 2010-03-27 pbug if (np->prefixlen >= prefixlen) {
148 10133795 2010-03-27 pbug region = np->region;
149 10133795 2010-03-27 pbug prefixlen = np->prefixlen;
150 10133795 2010-03-27 pbug }
151 10133795 2010-03-27 pbug } /* if hostmask */
152 10133795 2010-03-27 pbug } else if (np->family == AF_INET6) {
153 10133795 2010-03-27 pbug if (family != AF_INET6)
154 10133795 2010-03-27 pbug continue;
155 10133795 2010-03-27 pbug sin6 = (struct sockaddr_in6 *)sst;
156 10133795 2010-03-27 pbug sin60 = (struct sockaddr_in6 *)&np->hostmask;
157 10133795 2010-03-27 pbug sin61 = (struct sockaddr_in6 *)&np->netmask;
158 10133795 2010-03-27 pbug #ifdef __amd64
159 10133795 2010-03-27 pbug /*
160 10133795 2010-03-27 pbug * If this is on a 64 bit machine, we'll benefit
161 10133795 2010-03-27 pbug * by using 64 bit registers, this should make it
162 10133795 2010-03-27 pbug * a tad faster...
163 10133795 2010-03-27 pbug */
164 10133795 2010-03-27 pbug hm[0] = (u_int64_t *)&sin60->sin6_addr.s6_addr;
165 10133795 2010-03-27 pbug hm[1] = (hm[0] + 1);
166 10133795 2010-03-27 pbug nm[0] = (u_int64_t *)&sin61->sin6_addr.s6_addr;
167 10133795 2010-03-27 pbug nm[1] = (nm[0] + 1);
168 10133795 2010-03-27 pbug a6[0] = (u_int64_t *)&sin6->sin6_addr.s6_addr;
169 10133795 2010-03-27 pbug a6[1] = (a6[0] + 1);
170 10133795 2010-03-27 pbug if ( ((*hm[0] & *nm[0]) == (*a6[0] & *nm[0]))&&
171 10133795 2010-03-27 pbug ((*hm[1] & *nm[1]) == (*a6[1] & *nm[1]))) {
172 10133795 2010-03-27 pbug #else
173 10133795 2010-03-27 pbug hm[0] = (u_int32_t *)&sin60->sin6_addr.s6_addr;
174 10133795 2010-03-27 pbug hm[1] = (hm[0] + 1); hm[2] = (hm[1] + 1);
175 10133795 2010-03-27 pbug hm[3] = (hm[2] + 1);
176 10133795 2010-03-27 pbug nm[0] = (u_int32_t *)&sin61->sin6_addr.s6_addr;
177 10133795 2010-03-27 pbug nm[1] = (nm[0] + 1); nm[2] = (nm[1] + 1);
178 10133795 2010-03-27 pbug nm[3] = (nm[2] + 1);
179 10133795 2010-03-27 pbug a6[0] = (u_int32_t *)&sin6->sin6_addr.s6_addr;
180 10133795 2010-03-27 pbug a6[1] = (a6[0] + 1); a6[2] = (a6[1] + 1);
181 10133795 2010-03-27 pbug a6[3] = (a6[2] + 1);
182 10133795 2010-03-27 pbug if ( ((*hm[0] & *nm[0]) == (*a6[0] & *nm[0]))&&
183 10133795 2010-03-27 pbug ((*hm[1] & *nm[1]) == (*a6[1] & *nm[1]))&&
184 10133795 2010-03-27 pbug ((*hm[2] & *nm[2]) == (*a6[2] & *nm[2]))&&
185 10133795 2010-03-27 pbug ((*hm[3] & *nm[3]) == (*a6[3] & *nm[3]))) {
186 10133795 2010-03-27 pbug #endif
187 10133795 2010-03-27 pbug
188 10133795 2010-03-27 pbug if (np->prefixlen >= prefixlen) {
189 10133795 2010-03-27 pbug region = np->region;
190 10133795 2010-03-27 pbug prefixlen = np->prefixlen;
191 10133795 2010-03-27 pbug }
192 10133795 2010-03-27 pbug } /* if ip6 address */
193 10133795 2010-03-27 pbug
194 10133795 2010-03-27 pbug } /* if AF_INET6 */
195 864007e3 2010-03-09 pbug } /* SLIST */
196 864007e3 2010-03-09 pbug
197 864007e3 2010-03-09 pbug return (region);
198 864007e3 2010-03-09 pbug }
199 864007e3 2010-03-09 pbug
200 10133795 2010-03-27 pbug /*
201 10133795 2010-03-27 pbug * GETMASK - get the v4 netmask given by prefix length, return netmask in
202 10133795 2010-03-27 pbug * network byte order, function can't fail unless prefix length
203 10133795 2010-03-27 pbug * supplied is > 32
204 10133795 2010-03-27 pbug */
205 10133795 2010-03-27 pbug
206 864007e3 2010-03-09 pbug in_addr_t
207 10133795 2010-03-27 pbug getmask(int prefixlen)
208 864007e3 2010-03-09 pbug {
209 864007e3 2010-03-09 pbug in_addr_t ret = 0xffffffff;
210 864007e3 2010-03-09 pbug
211 959d1769 2010-04-05 pbug /* I know it's cheating */
212 959d1769 2010-04-05 pbug if (prefixlen > 31)
213 959d1769 2010-04-05 pbug return (htonl(ret));
214 959d1769 2010-04-05 pbug
215 10133795 2010-03-27 pbug ret >>= prefixlen; /* 0x00ffffff */
216 864007e3 2010-03-09 pbug ret = ~ret; /* 0xff000000 */
217 864007e3 2010-03-09 pbug
218 864007e3 2010-03-09 pbug return (htonl(ret));
219 864007e3 2010-03-09 pbug }
220 10133795 2010-03-27 pbug
221 10133795 2010-03-27 pbug /*
222 10133795 2010-03-27 pbug * GETMASK6 - like getmask() but works on a supplied sockaddr_in6 instead of
223 10133795 2010-03-27 pbug * returning results as return address. Function cannot fail
224 10133795 2010-03-27 pbug * unless prefix length supplied is > 128. At which point a buffer
225 10133795 2010-03-27 pbug * overflow is possible.
226 10133795 2010-03-27 pbug */
227 10133795 2010-03-27 pbug
228 10133795 2010-03-27 pbug int
229 10133795 2010-03-27 pbug getmask6(int prefixlen, struct sockaddr_in6 *sin6)
230 10133795 2010-03-27 pbug {
231 10133795 2010-03-27 pbug int i, j;
232 10133795 2010-03-27 pbug u_int32_t *nm[4];
233 10133795 2010-03-27 pbug
234 10133795 2010-03-27 pbug if (prefixlen > 128 || prefixlen < 0)
235 10133795 2010-03-27 pbug return (-1);
236 10133795 2010-03-27 pbug
237 10133795 2010-03-27 pbug memset(&sin6->sin6_addr.s6_addr, 0xff, sizeof(sin6->sin6_addr.s6_addr));
238 10133795 2010-03-27 pbug nm[0] = (u_int32_t *)sin6->sin6_addr.s6_addr;
239 10133795 2010-03-27 pbug nm[1] = (nm[0] + 1); nm[2] = (nm[1] + 1);
240 10133795 2010-03-27 pbug nm[3] = (nm[2] + 1);
241 10133795 2010-03-27 pbug
242 10133795 2010-03-27 pbug for (i = 0, j = 0; j < prefixlen; j++) {
243 959d1769 2010-04-05 pbug if (*nm[i] == 1) {
244 959d1769 2010-04-05 pbug *nm[i] = 0;
245 10133795 2010-03-27 pbug i++;
246 959d1769 2010-04-05 pbug } else
247 959d1769 2010-04-05 pbug *nm[i] >>= 1;
248 10133795 2010-03-27 pbug }
249 10133795 2010-03-27 pbug *nm[0] = htonl(~ *nm[0]);
250 10133795 2010-03-27 pbug *nm[1] = htonl(~ *nm[1]);
251 10133795 2010-03-27 pbug *nm[2] = htonl(~ *nm[2]);
252 10133795 2010-03-27 pbug *nm[3] = htonl(~ *nm[3]);
253 10133795 2010-03-27 pbug
254 10133795 2010-03-27 pbug return (0);
255 10133795 2010-03-27 pbug }