Blame


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