Blob


1 /*
2 * Copyright (c) 2010-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 extern in_addr_t getmask(int);
33 extern int getmask6(int, struct sockaddr_in6 *);
35 int find_wildcard(struct sockaddr_storage *, int);
36 void init_wildcard(void);
37 int insert_wildcard(char *, char *);
39 SLIST_HEAD(listhead, wildentry) wildhead;
41 static struct wildentry {
42 char name[INET6_ADDRSTRLEN];
43 int family;
44 struct sockaddr_storage hostmask;
45 struct sockaddr_storage netmask;
46 u_int8_t prefixlen;
47 SLIST_ENTRY(wildentry) wildcard_entry;
48 } *wn2, *wnp;
51 static const char rcsid[] = "$Id: wildcard.c,v 1.7 2014/05/18 17:14:05 pjp Exp $";
53 /*
54 * INIT_WILDCARD - initialize the wildcard singly linked list
55 */
57 void
58 init_wildcard(void)
59 {
60 SLIST_INIT(&wildhead);
61 return;
62 }
64 /*
65 * INSERT_WILDCARD - insert an address and prefixlen into the wildcard slist
66 */
68 int
69 insert_wildcard(char *address, char *prefixlen)
70 {
71 struct sockaddr_in *sin;
72 struct sockaddr_in6 *sin6;
73 int pnum;
74 int ret;
76 pnum = atoi(prefixlen);
77 wn2 = malloc(sizeof(struct wildentry)); /* Insert after. */
79 if (strchr(address, ':') != NULL) {
80 wn2->family = AF_INET6;
81 sin6 = (struct sockaddr_in6 *)&wn2->hostmask;
82 if ((ret = inet_pton(AF_INET6, address, &sin6->sin6_addr.s6_addr)) != 1)
83 return (-1);
84 sin6->sin6_family = AF_INET6;
85 sin6 = (struct sockaddr_in6 *)&wn2->netmask;
86 sin6->sin6_family = AF_INET6;
87 if (getmask6(pnum, sin6) < 0)
88 return(-1);
89 wn2->prefixlen = pnum;
90 } else {
92 wn2->family = AF_INET;
93 sin = (struct sockaddr_in *)&wn2->hostmask;
94 sin->sin_family = AF_INET;
95 sin->sin_addr.s_addr = inet_addr(address);
96 sin = (struct sockaddr_in *)&wn2->netmask;
97 sin->sin_family = AF_INET;
98 sin->sin_addr.s_addr = getmask(pnum);
99 wn2->prefixlen = pnum;
103 SLIST_INSERT_HEAD(&wildhead, wn2, wildcard_entry);
105 return (0);
108 /*
109 * FIND_WILDCARD - walk the wildcard list and find the correponding network
110 * if a network matches return 1, if no match is found return
111 * 0.
112 */
114 int
115 find_wildcard(struct sockaddr_storage *sst, int family)
117 struct sockaddr_in *sin, *sin0;
118 struct sockaddr_in6 *sin6, *sin60, *sin61;
119 u_int32_t hostmask, netmask;
120 u_int32_t a;
121 #ifdef __amd64
122 u_int64_t *hm[2], *nm[2], *a6[2];
123 #else
124 u_int32_t *hm[4], *nm[4], *a6[4];
125 #endif
127 SLIST_FOREACH(wnp, &wildhead, wildcard_entry) {
128 if (wnp->family == AF_INET) {
129 if (family != AF_INET)
130 continue;
131 sin = (struct sockaddr_in *)sst;
132 a = sin->sin_addr.s_addr;
133 sin = (struct sockaddr_in *)&wnp->hostmask;
134 sin0 = (struct sockaddr_in *)&wnp->netmask;
135 hostmask = sin->sin_addr.s_addr;
136 netmask = sin0->sin_addr.s_addr;
137 if ((hostmask & netmask) == (a & netmask)) {
138 return (1);
139 } /* if hostmask */
140 } else if (wnp->family == AF_INET6) {
141 if (family != AF_INET6)
142 continue;
143 sin6 = (struct sockaddr_in6 *)sst;
144 sin60 = (struct sockaddr_in6 *)&wnp->hostmask;
145 sin61 = (struct sockaddr_in6 *)&wnp->netmask;
146 #ifdef __amd64
147 /*
148 * If this is on a 64 bit machine, we'll benefit
149 * by using 64 bit registers, this should make it
150 * a tad faster...
151 */
152 hm[0] = (u_int64_t *)&sin60->sin6_addr.s6_addr;
153 hm[1] = (hm[0] + 1);
154 nm[0] = (u_int64_t *)&sin61->sin6_addr.s6_addr;
155 nm[1] = (nm[0] + 1);
156 a6[0] = (u_int64_t *)&sin6->sin6_addr.s6_addr;
157 a6[1] = (a6[0] + 1);
158 if ( ((*hm[0] & *nm[0]) == (*a6[0] & *nm[0]))&&
159 ((*hm[1] & *nm[1]) == (*a6[1] & *nm[1]))) {
160 #else
161 hm[0] = (u_int32_t *)&sin60->sin6_addr.s6_addr;
162 hm[1] = (hm[0] + 1); hm[2] = (hm[1] + 1);
163 hm[3] = (hm[2] + 1);
164 nm[0] = (u_int32_t *)&sin61->sin6_addr.s6_addr;
165 nm[1] = (nm[0] + 1); nm[2] = (nm[1] + 1);
166 nm[3] = (nm[2] + 1);
167 a6[0] = (u_int32_t *)&sin6->sin6_addr.s6_addr;
168 a6[1] = (a6[0] + 1); a6[2] = (a6[1] + 1);
169 a6[3] = (a6[2] + 1);
171 if ( ((*hm[0] & *nm[0]) == (*a6[0] & *nm[0]))&&
172 ((*hm[1] & *nm[1]) == (*a6[1] & *nm[1]))&&
173 ((*hm[2] & *nm[2]) == (*a6[2] & *nm[2]))&&
174 ((*hm[3] & *nm[3]) == (*a6[3] & *nm[3]))) {
175 #endif
177 return (1);
178 } /* if ip6 address */
180 } /* if AF_INET6 */
181 } /* SLIST */
183 return (0);