Blob


1 /*
2 * Copyright (c) 2014 Peter J. Philipp
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 */
28 #include "include.h"
29 #include "dns.h"
30 #include "db.h"
32 int find_filter(struct sockaddr_storage *, int);
33 void init_filter(void);
34 int insert_filter(char *, char *);
36 extern void dolog(int, char *, ...);
37 extern in_addr_t getmask(int);
38 extern int getmask6(int, struct sockaddr_in6 *);
40 extern int debug, verbose;
42 SLIST_HEAD(listhead, filterentry) filterhead;
44 static struct filterentry {
45 char name[INET6_ADDRSTRLEN];
46 int family;
47 struct sockaddr_storage hostmask;
48 struct sockaddr_storage netmask;
49 u_int8_t prefixlen;
50 SLIST_ENTRY(filterentry) filter_entry;
51 } *fn2, *fnp;
54 static const char rcsid[] = "$Id: filter.c,v 1.3 2014/05/18 17:14:05 pjp Exp $";
56 /*
57 * INIT_FILTER - initialize the filter singly linked list
58 */
60 void
61 init_filter(void)
62 {
63 SLIST_INIT(&filterhead);
64 return;
65 }
67 /*
68 * INSERT_FILTER - insert an address and prefixlen into the filter slist
69 */
71 int
72 insert_filter(char *address, char *prefixlen)
73 {
74 struct sockaddr_in *sin;
75 struct sockaddr_in6 *sin6;
76 int pnum;
77 int ret;
79 pnum = atoi(prefixlen);
80 fn2 = malloc(sizeof(struct filterentry)); /* Insert after. */
82 if (strchr(address, ':') != NULL) {
83 fn2->family = AF_INET6;
84 sin6 = (struct sockaddr_in6 *)&fn2->hostmask;
85 if ((ret = inet_pton(AF_INET6, address, &sin6->sin6_addr.s6_addr)) != 1)
86 return (-1);
87 sin6->sin6_family = AF_INET6;
88 sin6 = (struct sockaddr_in6 *)&fn2->netmask;
89 sin6->sin6_family = AF_INET6;
90 if (getmask6(pnum, sin6) < 0)
91 return(-1);
92 fn2->prefixlen = pnum;
93 } else {
95 fn2->family = AF_INET;
96 sin = (struct sockaddr_in *)&fn2->hostmask;
97 sin->sin_family = AF_INET;
98 sin->sin_addr.s_addr = inet_addr(address);
99 sin = (struct sockaddr_in *)&fn2->netmask;
100 sin->sin_family = AF_INET;
101 sin->sin_addr.s_addr = getmask(pnum);
102 fn2->prefixlen = pnum;
106 SLIST_INSERT_HEAD(&filterhead, fn2, filter_entry);
108 return (0);
111 /*
112 * FIND_FILTER - walk the filter list and find the correponding network
113 * if a network matches return 1, if no match is found return
114 * 0.
115 */
117 int
118 find_filter(struct sockaddr_storage *sst, int family)
120 struct sockaddr_in *sin, *sin0;
121 struct sockaddr_in6 *sin6, *sin60, *sin61;
122 u_int32_t hostmask, netmask;
123 u_int32_t a;
124 #ifdef __amd64
125 u_int64_t *hm[2], *nm[2], *a6[2];
126 #else
127 u_int32_t *hm[4], *nm[4], *a6[4];
128 #endif
130 SLIST_FOREACH(fnp, &filterhead, filter_entry) {
131 if (fnp->family == AF_INET) {
132 if (family != AF_INET)
133 continue;
134 sin = (struct sockaddr_in *)sst;
135 a = sin->sin_addr.s_addr;
136 sin = (struct sockaddr_in *)&fnp->hostmask;
137 sin0 = (struct sockaddr_in *)&fnp->netmask;
138 hostmask = sin->sin_addr.s_addr;
139 netmask = sin0->sin_addr.s_addr;
140 if ((hostmask & netmask) == (a & netmask)) {
141 return (1);
142 } /* if hostmask */
143 } else if (fnp->family == AF_INET6) {
144 if (family != AF_INET6)
145 continue;
146 sin6 = (struct sockaddr_in6 *)sst;
147 sin60 = (struct sockaddr_in6 *)&fnp->hostmask;
148 sin61 = (struct sockaddr_in6 *)&fnp->netmask;
149 #ifdef __amd64
150 /*
151 * If this is on a 64 bit machine, we'll benefit
152 * by using 64 bit registers, this should make it
153 * a tad faster...
154 */
155 hm[0] = (u_int64_t *)&sin60->sin6_addr.s6_addr;
156 hm[1] = (hm[0] + 1);
157 nm[0] = (u_int64_t *)&sin61->sin6_addr.s6_addr;
158 nm[1] = (nm[0] + 1);
159 a6[0] = (u_int64_t *)&sin6->sin6_addr.s6_addr;
160 a6[1] = (a6[0] + 1);
161 if ( ((*hm[0] & *nm[0]) == (*a6[0] & *nm[0]))&&
162 ((*hm[1] & *nm[1]) == (*a6[1] & *nm[1]))) {
163 #else
164 hm[0] = (u_int32_t *)&sin60->sin6_addr.s6_addr;
165 hm[1] = (hm[0] + 1); hm[2] = (hm[1] + 1);
166 hm[3] = (hm[2] + 1);
167 nm[0] = (u_int32_t *)&sin61->sin6_addr.s6_addr;
168 nm[1] = (nm[0] + 1); nm[2] = (nm[1] + 1);
169 nm[3] = (nm[2] + 1);
170 a6[0] = (u_int32_t *)&sin6->sin6_addr.s6_addr;
171 a6[1] = (a6[0] + 1); a6[2] = (a6[1] + 1);
172 a6[3] = (a6[2] + 1);
174 if ( ((*hm[0] & *nm[0]) == (*a6[0] & *nm[0]))&&
175 ((*hm[1] & *nm[1]) == (*a6[1] & *nm[1]))&&
176 ((*hm[2] & *nm[2]) == (*a6[2] & *nm[2]))&&
177 ((*hm[3] & *nm[3]) == (*a6[3] & *nm[3]))) {
178 #endif
180 return (1);
181 } /* if ip6 address */
183 } /* if AF_INET6 */
184 } /* SLIST */
186 return (0);