Blame


1 f98bb34d 2011-09-19 pbug /*
2 48603f7d 2014-04-13 pjp * Copyright (c) 2011-2014 Peter J. Philipp
3 f98bb34d 2011-09-19 pbug * All rights reserved.
4 f98bb34d 2011-09-19 pbug *
5 f98bb34d 2011-09-19 pbug * Redistribution and use in source and binary forms, with or without
6 f98bb34d 2011-09-19 pbug * modification, are permitted provided that the following conditions
7 f98bb34d 2011-09-19 pbug * are met:
8 f98bb34d 2011-09-19 pbug * 1. Redistributions of source code must retain the above copyright
9 f98bb34d 2011-09-19 pbug * notice, this list of conditions and the following disclaimer.
10 f98bb34d 2011-09-19 pbug * 2. Redistributions in binary form must reproduce the above copyright
11 f98bb34d 2011-09-19 pbug * notice, this list of conditions and the following disclaimer in the
12 f98bb34d 2011-09-19 pbug * documentation and/or other materials provided with the distribution.
13 f98bb34d 2011-09-19 pbug * 3. The name of the author may not be used to endorse or promote products
14 f98bb34d 2011-09-19 pbug * derived from this software without specific prior written permission
15 f98bb34d 2011-09-19 pbug *
16 f98bb34d 2011-09-19 pbug * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 f98bb34d 2011-09-19 pbug * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 f98bb34d 2011-09-19 pbug * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 f98bb34d 2011-09-19 pbug * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 f98bb34d 2011-09-19 pbug * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 f98bb34d 2011-09-19 pbug * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 f98bb34d 2011-09-19 pbug * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 f98bb34d 2011-09-19 pbug * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 f98bb34d 2011-09-19 pbug * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 f98bb34d 2011-09-19 pbug * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 f98bb34d 2011-09-19 pbug *
27 f98bb34d 2011-09-19 pbug */
28 f98bb34d 2011-09-19 pbug #include "include.h"
29 f98bb34d 2011-09-19 pbug #include "dns.h"
30 f98bb34d 2011-09-19 pbug #include "db.h"
31 f98bb34d 2011-09-19 pbug
32 f98bb34d 2011-09-19 pbug
33 0e7d94ac 2014-05-18 pjp void axfrloop(int *, int, char **, DB *);
34 0e7d94ac 2014-05-18 pjp void axfr_connection(int, char *, int, DB *);
35 0e7d94ac 2014-05-18 pjp int build_header(DB *, char *, char *, struct question *, int);
36 0e7d94ac 2014-05-18 pjp int build_soa(DB *, char *, int, struct domain *, struct question *);
37 0e7d94ac 2014-05-18 pjp int checklabel(DB *, struct domain *, struct domain *, struct question *);
38 0e7d94ac 2014-05-18 pjp void gather_notifydomains(DB *);
39 0e7d94ac 2014-05-18 pjp void init_axfr(void);
40 0e7d94ac 2014-05-18 pjp void init_notifyslave(void);
41 0e7d94ac 2014-05-18 pjp int insert_axfr(char *, char *);
42 0e7d94ac 2014-05-18 pjp int insert_notifyslave(char *, char *);
43 0e7d94ac 2014-05-18 pjp void notifypacket(int, void *, void *, int);
44 0e7d94ac 2014-05-18 pjp void notifyslaves(int *);
45 0e7d94ac 2014-05-18 pjp void reap(int);
46 58eafea4 2014-05-17 pjp
47 0e7d94ac 2014-05-18 pjp extern in_addr_t getmask(int);
48 0e7d94ac 2014-05-18 pjp extern int getmask6(int, struct sockaddr_in6 *);
49 0e7d94ac 2014-05-18 pjp extern void reply_fmterror(struct sreply *);
50 0e7d94ac 2014-05-18 pjp extern void reply_nxdomain(struct sreply *);
51 0e7d94ac 2014-05-18 pjp extern int get_soa(DB *, struct question *, struct domain *, int);
52 0e7d94ac 2014-05-18 pjp extern int compress_label(u_char *, int, int);
53 0e7d94ac 2014-05-18 pjp extern u_int16_t create_anyreply(struct sreply *, char *, int, int, int);
54 0e7d94ac 2014-05-18 pjp extern struct question *build_fake_question(char *, int, u_int16_t);
55 0e7d94ac 2014-05-18 pjp extern struct question *build_question(char *, int, int);
56 0e7d94ac 2014-05-18 pjp extern int free_question(struct question *);
57 0e7d94ac 2014-05-18 pjp extern void dolog(int, char *, ...);
58 0e7d94ac 2014-05-18 pjp extern void build_reply(struct sreply *, int, char *, int, struct question *, struct sockaddr *, socklen_t, struct domain *, struct domain *, u_int8_t, int, int, struct recurses *);
59 0e7d94ac 2014-05-18 pjp
60 0e7d94ac 2014-05-18 pjp
61 0e7d94ac 2014-05-18 pjp int notify = 0; /* do not notify when set to 0 */
62 f98bb34d 2011-09-19 pbug
63 dd869383 2013-02-16 pjp extern int debug, verbose;
64 58eafea4 2014-05-17 pjp extern time_t time_changed;
65 f98bb34d 2011-09-19 pbug
66 f98bb34d 2011-09-19 pbug SLIST_HEAD(listhead, axfrentry) axfrhead;
67 f98bb34d 2011-09-19 pbug
68 c0963faf 2014-05-01 pjp static struct axfrentry {
69 f98bb34d 2011-09-19 pbug char name[INET6_ADDRSTRLEN];
70 f98bb34d 2011-09-19 pbug int family;
71 f98bb34d 2011-09-19 pbug struct sockaddr_storage hostmask;
72 f98bb34d 2011-09-19 pbug struct sockaddr_storage netmask;
73 f98bb34d 2011-09-19 pbug u_int8_t prefixlen;
74 c0963faf 2014-05-01 pjp SLIST_ENTRY(axfrentry) axfr_entry;
75 c0963faf 2014-05-01 pjp } *an2, *anp;
76 f98bb34d 2011-09-19 pbug
77 58eafea4 2014-05-17 pjp SLIST_HEAD(notifyslavelisthead, notifyslaveentry) notifyslavehead;
78 f98bb34d 2011-09-19 pbug
79 58eafea4 2014-05-17 pjp static struct notifyslaveentry {
80 58eafea4 2014-05-17 pjp char name[INET6_ADDRSTRLEN];
81 58eafea4 2014-05-17 pjp int family;
82 58eafea4 2014-05-17 pjp struct sockaddr_storage hostmask;
83 58eafea4 2014-05-17 pjp struct sockaddr_storage netmask;
84 58eafea4 2014-05-17 pjp u_int8_t prefixlen;
85 58eafea4 2014-05-17 pjp SLIST_ENTRY(notifyslaveentry) notifyslave_entry;
86 58eafea4 2014-05-17 pjp } *nfslnp2, *nfslnp;
87 f98bb34d 2011-09-19 pbug
88 58eafea4 2014-05-17 pjp
89 58eafea4 2014-05-17 pjp
90 58eafea4 2014-05-17 pjp SLIST_HEAD(notifylisthead, notifyentry) notifyhead;
91 58eafea4 2014-05-17 pjp
92 58eafea4 2014-05-17 pjp static struct notifyentry {
93 58eafea4 2014-05-17 pjp char domain[DNS_MAXNAME];
94 58eafea4 2014-05-17 pjp int domainlen;
95 58eafea4 2014-05-17 pjp u_int16_t *ids;
96 58eafea4 2014-05-17 pjp u_int16_t *attempts;
97 58eafea4 2014-05-17 pjp SLIST_ENTRY(notifyentry) notify_entry;
98 58eafea4 2014-05-17 pjp } *notn2, *notnp;
99 58eafea4 2014-05-17 pjp
100 58eafea4 2014-05-17 pjp
101 0e7d94ac 2014-05-18 pjp static const char rcsid[] = "$Id: axfr.c,v 1.10 2014/05/18 17:14:05 pjp Exp $";
102 58eafea4 2014-05-17 pjp
103 f98bb34d 2011-09-19 pbug /*
104 f98bb34d 2011-09-19 pbug * INIT_AXFR - initialize the axfr singly linked list
105 f98bb34d 2011-09-19 pbug */
106 f98bb34d 2011-09-19 pbug
107 f98bb34d 2011-09-19 pbug void
108 f98bb34d 2011-09-19 pbug init_axfr(void)
109 f98bb34d 2011-09-19 pbug {
110 f98bb34d 2011-09-19 pbug SLIST_INIT(&axfrhead);
111 f98bb34d 2011-09-19 pbug return;
112 f98bb34d 2011-09-19 pbug }
113 f98bb34d 2011-09-19 pbug
114 f98bb34d 2011-09-19 pbug /*
115 f98bb34d 2011-09-19 pbug * INSERT_AXFR - insert an address and prefixlen into the axfr slist
116 f98bb34d 2011-09-19 pbug */
117 f98bb34d 2011-09-19 pbug
118 f98bb34d 2011-09-19 pbug int
119 f98bb34d 2011-09-19 pbug insert_axfr(char *address, char *prefixlen)
120 f98bb34d 2011-09-19 pbug {
121 f98bb34d 2011-09-19 pbug struct sockaddr_in *sin;
122 f98bb34d 2011-09-19 pbug struct sockaddr_in6 *sin6;
123 f98bb34d 2011-09-19 pbug int pnum;
124 f98bb34d 2011-09-19 pbug int ret;
125 f98bb34d 2011-09-19 pbug
126 f98bb34d 2011-09-19 pbug pnum = atoi(prefixlen);
127 f98bb34d 2011-09-19 pbug an2 = malloc(sizeof(struct axfrentry)); /* Insert after. */
128 f98bb34d 2011-09-19 pbug
129 f98bb34d 2011-09-19 pbug if (strchr(address, ':') != NULL) {
130 f98bb34d 2011-09-19 pbug an2->family = AF_INET6;
131 f98bb34d 2011-09-19 pbug sin6 = (struct sockaddr_in6 *)&an2->hostmask;
132 f98bb34d 2011-09-19 pbug if ((ret = inet_pton(AF_INET6, address, &sin6->sin6_addr.s6_addr)) != 1)
133 f98bb34d 2011-09-19 pbug return (-1);
134 f98bb34d 2011-09-19 pbug sin6->sin6_family = AF_INET6;
135 f98bb34d 2011-09-19 pbug sin6 = (struct sockaddr_in6 *)&an2->netmask;
136 f98bb34d 2011-09-19 pbug sin6->sin6_family = AF_INET6;
137 f98bb34d 2011-09-19 pbug if (getmask6(pnum, sin6) < 0)
138 f98bb34d 2011-09-19 pbug return(-1);
139 f98bb34d 2011-09-19 pbug an2->prefixlen = pnum;
140 f98bb34d 2011-09-19 pbug } else {
141 f98bb34d 2011-09-19 pbug
142 f98bb34d 2011-09-19 pbug an2->family = AF_INET;
143 f98bb34d 2011-09-19 pbug sin = (struct sockaddr_in *)&an2->hostmask;
144 f98bb34d 2011-09-19 pbug sin->sin_family = AF_INET;
145 f98bb34d 2011-09-19 pbug sin->sin_addr.s_addr = inet_addr(address);
146 f98bb34d 2011-09-19 pbug sin = (struct sockaddr_in *)&an2->netmask;
147 f98bb34d 2011-09-19 pbug sin->sin_family = AF_INET;
148 f98bb34d 2011-09-19 pbug sin->sin_addr.s_addr = getmask(pnum);
149 f98bb34d 2011-09-19 pbug an2->prefixlen = pnum;
150 f98bb34d 2011-09-19 pbug
151 f98bb34d 2011-09-19 pbug }
152 f98bb34d 2011-09-19 pbug
153 c0963faf 2014-05-01 pjp SLIST_INSERT_HEAD(&axfrhead, an2, axfr_entry);
154 f98bb34d 2011-09-19 pbug
155 f98bb34d 2011-09-19 pbug return (0);
156 f98bb34d 2011-09-19 pbug }
157 f98bb34d 2011-09-19 pbug
158 f98bb34d 2011-09-19 pbug /*
159 f98bb34d 2011-09-19 pbug * FIND_AXFR - walk the axfr list and find the correponding network
160 f98bb34d 2011-09-19 pbug * if a network matches return 1, if no match is found return
161 f98bb34d 2011-09-19 pbug * 0.
162 f98bb34d 2011-09-19 pbug */
163 f98bb34d 2011-09-19 pbug
164 f98bb34d 2011-09-19 pbug int
165 f98bb34d 2011-09-19 pbug find_axfr(struct sockaddr_storage *sst, int family)
166 f98bb34d 2011-09-19 pbug {
167 f98bb34d 2011-09-19 pbug struct sockaddr_in *sin, *sin0;
168 f98bb34d 2011-09-19 pbug struct sockaddr_in6 *sin6, *sin60, *sin61;
169 f98bb34d 2011-09-19 pbug u_int32_t hostmask, netmask;
170 f98bb34d 2011-09-19 pbug u_int32_t a;
171 f98bb34d 2011-09-19 pbug #ifdef __amd64
172 f98bb34d 2011-09-19 pbug u_int64_t *hm[2], *nm[2], *a6[2];
173 f98bb34d 2011-09-19 pbug #else
174 f98bb34d 2011-09-19 pbug u_int32_t *hm[4], *nm[4], *a6[4];
175 f98bb34d 2011-09-19 pbug #endif
176 f98bb34d 2011-09-19 pbug
177 c0963faf 2014-05-01 pjp SLIST_FOREACH(anp, &axfrhead, axfr_entry) {
178 f98bb34d 2011-09-19 pbug if (anp->family == AF_INET) {
179 f98bb34d 2011-09-19 pbug if (family != AF_INET)
180 f98bb34d 2011-09-19 pbug continue;
181 f98bb34d 2011-09-19 pbug sin = (struct sockaddr_in *)sst;
182 f98bb34d 2011-09-19 pbug a = sin->sin_addr.s_addr;
183 f98bb34d 2011-09-19 pbug sin = (struct sockaddr_in *)&anp->hostmask;
184 f98bb34d 2011-09-19 pbug sin0 = (struct sockaddr_in *)&anp->netmask;
185 f98bb34d 2011-09-19 pbug hostmask = sin->sin_addr.s_addr;
186 f98bb34d 2011-09-19 pbug netmask = sin0->sin_addr.s_addr;
187 f98bb34d 2011-09-19 pbug if ((hostmask & netmask) == (a & netmask)) {
188 f98bb34d 2011-09-19 pbug return (1);
189 f98bb34d 2011-09-19 pbug } /* if hostmask */
190 f98bb34d 2011-09-19 pbug } else if (anp->family == AF_INET6) {
191 f98bb34d 2011-09-19 pbug if (family != AF_INET6)
192 f98bb34d 2011-09-19 pbug continue;
193 f98bb34d 2011-09-19 pbug sin6 = (struct sockaddr_in6 *)sst;
194 f98bb34d 2011-09-19 pbug sin60 = (struct sockaddr_in6 *)&anp->hostmask;
195 f98bb34d 2011-09-19 pbug sin61 = (struct sockaddr_in6 *)&anp->netmask;
196 f98bb34d 2011-09-19 pbug #ifdef __amd64
197 f98bb34d 2011-09-19 pbug /*
198 f98bb34d 2011-09-19 pbug * If this is on a 64 bit machine, we'll benefit
199 f98bb34d 2011-09-19 pbug * by using 64 bit registers, this should make it
200 f98bb34d 2011-09-19 pbug * a tad faster...
201 f98bb34d 2011-09-19 pbug */
202 f98bb34d 2011-09-19 pbug hm[0] = (u_int64_t *)&sin60->sin6_addr.s6_addr;
203 f98bb34d 2011-09-19 pbug hm[1] = (hm[0] + 1);
204 f98bb34d 2011-09-19 pbug nm[0] = (u_int64_t *)&sin61->sin6_addr.s6_addr;
205 f98bb34d 2011-09-19 pbug nm[1] = (nm[0] + 1);
206 f98bb34d 2011-09-19 pbug a6[0] = (u_int64_t *)&sin6->sin6_addr.s6_addr;
207 f98bb34d 2011-09-19 pbug a6[1] = (a6[0] + 1);
208 f98bb34d 2011-09-19 pbug if ( ((*hm[0] & *nm[0]) == (*a6[0] & *nm[0]))&&
209 f98bb34d 2011-09-19 pbug ((*hm[1] & *nm[1]) == (*a6[1] & *nm[1]))) {
210 f98bb34d 2011-09-19 pbug #else
211 f98bb34d 2011-09-19 pbug hm[0] = (u_int32_t *)&sin60->sin6_addr.s6_addr;
212 f98bb34d 2011-09-19 pbug hm[1] = (hm[0] + 1); hm[2] = (hm[1] + 1);
213 f98bb34d 2011-09-19 pbug hm[3] = (hm[2] + 1);
214 f98bb34d 2011-09-19 pbug nm[0] = (u_int32_t *)&sin61->sin6_addr.s6_addr;
215 f98bb34d 2011-09-19 pbug nm[1] = (nm[0] + 1); nm[2] = (nm[1] + 1);
216 f98bb34d 2011-09-19 pbug nm[3] = (nm[2] + 1);
217 f98bb34d 2011-09-19 pbug a6[0] = (u_int32_t *)&sin6->sin6_addr.s6_addr;
218 f98bb34d 2011-09-19 pbug a6[1] = (a6[0] + 1); a6[2] = (a6[1] + 1);
219 f98bb34d 2011-09-19 pbug a6[3] = (a6[2] + 1);
220 f98bb34d 2011-09-19 pbug
221 f98bb34d 2011-09-19 pbug if ( ((*hm[0] & *nm[0]) == (*a6[0] & *nm[0]))&&
222 f98bb34d 2011-09-19 pbug ((*hm[1] & *nm[1]) == (*a6[1] & *nm[1]))&&
223 f98bb34d 2011-09-19 pbug ((*hm[2] & *nm[2]) == (*a6[2] & *nm[2]))&&
224 f98bb34d 2011-09-19 pbug ((*hm[3] & *nm[3]) == (*a6[3] & *nm[3]))) {
225 f98bb34d 2011-09-19 pbug #endif
226 f98bb34d 2011-09-19 pbug
227 f98bb34d 2011-09-19 pbug return (1);
228 f98bb34d 2011-09-19 pbug } /* if ip6 address */
229 f98bb34d 2011-09-19 pbug
230 f98bb34d 2011-09-19 pbug } /* if AF_INET6 */
231 f98bb34d 2011-09-19 pbug } /* SLIST */
232 f98bb34d 2011-09-19 pbug
233 f98bb34d 2011-09-19 pbug return (0);
234 f98bb34d 2011-09-19 pbug }
235 f98bb34d 2011-09-19 pbug
236 58eafea4 2014-05-17 pjp /*
237 58eafea4 2014-05-17 pjp * INIT_NOTIFYSLAVE - initialize the axfr singly linked list
238 58eafea4 2014-05-17 pjp */
239 58eafea4 2014-05-17 pjp
240 58eafea4 2014-05-17 pjp void
241 58eafea4 2014-05-17 pjp init_notifyslave(void)
242 58eafea4 2014-05-17 pjp {
243 58eafea4 2014-05-17 pjp SLIST_INIT(&notifyslavehead);
244 58eafea4 2014-05-17 pjp return;
245 58eafea4 2014-05-17 pjp }
246 58eafea4 2014-05-17 pjp
247 58eafea4 2014-05-17 pjp /*
248 58eafea4 2014-05-17 pjp * INSERT_NOTIFYSLAVE - insert an address and prefixlen into the notifyslave slist
249 58eafea4 2014-05-17 pjp */
250 58eafea4 2014-05-17 pjp
251 58eafea4 2014-05-17 pjp int
252 58eafea4 2014-05-17 pjp insert_notifyslave(char *address, char *prefixlen)
253 58eafea4 2014-05-17 pjp {
254 58eafea4 2014-05-17 pjp struct sockaddr_in *sin;
255 58eafea4 2014-05-17 pjp struct sockaddr_in6 *sin6;
256 58eafea4 2014-05-17 pjp int pnum;
257 58eafea4 2014-05-17 pjp int ret;
258 58eafea4 2014-05-17 pjp
259 58eafea4 2014-05-17 pjp pnum = atoi(prefixlen);
260 58eafea4 2014-05-17 pjp nfslnp2 = calloc(1, sizeof(struct notifyslaveentry)); /* Insert after. */
261 58eafea4 2014-05-17 pjp if (nfslnp2 == NULL)
262 58eafea4 2014-05-17 pjp return (-1);
263 58eafea4 2014-05-17 pjp
264 58eafea4 2014-05-17 pjp
265 58eafea4 2014-05-17 pjp if (strchr(address, ':') != NULL) {
266 58eafea4 2014-05-17 pjp nfslnp2->family = AF_INET6;
267 58eafea4 2014-05-17 pjp sin6 = (struct sockaddr_in6 *)&nfslnp2->hostmask;
268 58eafea4 2014-05-17 pjp if ((ret = inet_pton(AF_INET6, address, &sin6->sin6_addr.s6_addr)) != 1)
269 58eafea4 2014-05-17 pjp return (-1);
270 58eafea4 2014-05-17 pjp sin6->sin6_family = AF_INET6;
271 58eafea4 2014-05-17 pjp sin6->sin6_port = htons(53);
272 58eafea4 2014-05-17 pjp sin6 = (struct sockaddr_in6 *)&nfslnp2->netmask;
273 58eafea4 2014-05-17 pjp sin6->sin6_family = AF_INET6;
274 58eafea4 2014-05-17 pjp if (getmask6(pnum, sin6) < 0)
275 58eafea4 2014-05-17 pjp return(-1);
276 58eafea4 2014-05-17 pjp nfslnp2->prefixlen = pnum;
277 58eafea4 2014-05-17 pjp } else {
278 58eafea4 2014-05-17 pjp
279 58eafea4 2014-05-17 pjp nfslnp2->family = AF_INET;
280 58eafea4 2014-05-17 pjp sin = (struct sockaddr_in *)&nfslnp2->hostmask;
281 58eafea4 2014-05-17 pjp sin->sin_family = AF_INET;
282 58eafea4 2014-05-17 pjp sin->sin_addr.s_addr = inet_addr(address);
283 58eafea4 2014-05-17 pjp sin->sin_port = htons(53);
284 58eafea4 2014-05-17 pjp sin = (struct sockaddr_in *)&nfslnp2->netmask;
285 58eafea4 2014-05-17 pjp sin->sin_family = AF_INET;
286 58eafea4 2014-05-17 pjp sin->sin_addr.s_addr = getmask(pnum);
287 58eafea4 2014-05-17 pjp nfslnp2->prefixlen = pnum;
288 58eafea4 2014-05-17 pjp
289 58eafea4 2014-05-17 pjp }
290 58eafea4 2014-05-17 pjp
291 58eafea4 2014-05-17 pjp SLIST_INSERT_HEAD(&notifyslavehead, nfslnp2, notifyslave_entry);
292 58eafea4 2014-05-17 pjp
293 58eafea4 2014-05-17 pjp return (0);
294 58eafea4 2014-05-17 pjp }
295 58eafea4 2014-05-17 pjp
296 f98bb34d 2011-09-19 pbug void
297 f98bb34d 2011-09-19 pbug axfrloop(int *afd, int sockcount, char **ident, DB *db)
298 f98bb34d 2011-09-19 pbug {
299 f98bb34d 2011-09-19 pbug fd_set rset;
300 f98bb34d 2011-09-19 pbug
301 f98bb34d 2011-09-19 pbug struct timeval tv;
302 f98bb34d 2011-09-19 pbug struct sockaddr_storage from;
303 58eafea4 2014-05-17 pjp struct sockaddr_in6 *sin6, *sin62;
304 58eafea4 2014-05-17 pjp struct sockaddr_in *sin, *sin2;
305 58eafea4 2014-05-17 pjp struct dns_header *dh;
306 58eafea4 2014-05-17 pjp struct question *question;
307 f98bb34d 2011-09-19 pbug
308 58eafea4 2014-05-17 pjp int i, so, len;
309 f98bb34d 2011-09-19 pbug int sel, maxso = 0;
310 f98bb34d 2011-09-19 pbug int is_ipv6, axfr_acl;
311 58eafea4 2014-05-17 pjp int notifyfd[2];
312 58eafea4 2014-05-17 pjp
313 f98bb34d 2011-09-19 pbug socklen_t fromlen;
314 58eafea4 2014-05-17 pjp char buf[512];
315 58eafea4 2014-05-17 pjp
316 58eafea4 2014-05-17 pjp time_t now;
317 f98bb34d 2011-09-19 pbug pid_t pid;
318 f98bb34d 2011-09-19 pbug
319 f98bb34d 2011-09-19 pbug char address[INET6_ADDRSTRLEN];
320 f98bb34d 2011-09-19 pbug
321 f98bb34d 2011-09-19 pbug signal(SIGCHLD, reap);
322 f98bb34d 2011-09-19 pbug
323 f98bb34d 2011-09-19 pbug for (i = 0; i < sockcount; i++) {
324 f98bb34d 2011-09-19 pbug listen(afd[i], 5);
325 58eafea4 2014-05-17 pjp }
326 58eafea4 2014-05-17 pjp
327 58eafea4 2014-05-17 pjp if (notify) {
328 58eafea4 2014-05-17 pjp /*
329 58eafea4 2014-05-17 pjp * If a zonefile has changed in the last half hour then
330 58eafea4 2014-05-17 pjp * gather all notifydomains and start the notify process
331 58eafea4 2014-05-17 pjp */
332 58eafea4 2014-05-17 pjp
333 58eafea4 2014-05-17 pjp notifyfd[0] = -1;
334 58eafea4 2014-05-17 pjp notifyfd[1] = -1;
335 58eafea4 2014-05-17 pjp
336 58eafea4 2014-05-17 pjp now = time(NULL);
337 58eafea4 2014-05-17 pjp if (difftime(now, time_changed) <= 1800) {
338 58eafea4 2014-05-17 pjp gather_notifydomains(db);
339 58eafea4 2014-05-17 pjp notifyfd[0] = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
340 58eafea4 2014-05-17 pjp notifyfd[1] = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
341 58eafea4 2014-05-17 pjp
342 58eafea4 2014-05-17 pjp memset((char *)&from, 0, sizeof(from));
343 58eafea4 2014-05-17 pjp sin = (struct sockaddr_in *)&from;
344 58eafea4 2014-05-17 pjp sin->sin_family = AF_INET;
345 58eafea4 2014-05-17 pjp sin->sin_port = htons(0);
346 58eafea4 2014-05-17 pjp
347 58eafea4 2014-05-17 pjp if (bind(notifyfd[0], (struct sockaddr *)sin, sizeof(*sin)) < 0) {
348 58eafea4 2014-05-17 pjp dolog(LOG_INFO, "bind notify: %s\n", strerror(errno));
349 58eafea4 2014-05-17 pjp }
350 58eafea4 2014-05-17 pjp
351 58eafea4 2014-05-17 pjp memset((char *)&from, 0, sizeof(from));
352 58eafea4 2014-05-17 pjp sin6 = (struct sockaddr_in6 *)&from;
353 58eafea4 2014-05-17 pjp sin->sin_family = AF_INET6;
354 58eafea4 2014-05-17 pjp sin->sin_port = htons(0);
355 58eafea4 2014-05-17 pjp
356 58eafea4 2014-05-17 pjp if (bind(notifyfd[1], (struct sockaddr *)sin, sizeof(*sin6)) < 0) {
357 58eafea4 2014-05-17 pjp dolog(LOG_INFO, "bind notify6: %s\n", strerror(errno));
358 58eafea4 2014-05-17 pjp }
359 58eafea4 2014-05-17 pjp
360 58eafea4 2014-05-17 pjp memset((char *)&from, 0, sizeof(from));
361 58eafea4 2014-05-17 pjp
362 58eafea4 2014-05-17 pjp notifyslaves((int *)&notifyfd);
363 58eafea4 2014-05-17 pjp }
364 f98bb34d 2011-09-19 pbug }
365 f98bb34d 2011-09-19 pbug
366 f98bb34d 2011-09-19 pbug for (;;) {
367 f98bb34d 2011-09-19 pbug
368 f98bb34d 2011-09-19 pbug FD_ZERO(&rset);
369 58eafea4 2014-05-17 pjp maxso = 0;
370 f98bb34d 2011-09-19 pbug
371 f98bb34d 2011-09-19 pbug for (i = 0; i < sockcount; i++) {
372 f98bb34d 2011-09-19 pbug FD_SET(afd[i], &rset);
373 58eafea4 2014-05-17 pjp if (maxso < afd[i])
374 58eafea4 2014-05-17 pjp maxso = afd[i];
375 f98bb34d 2011-09-19 pbug }
376 58eafea4 2014-05-17 pjp
377 58eafea4 2014-05-17 pjp if (notify) {
378 58eafea4 2014-05-17 pjp if (notifyfd[0] > -1) {
379 58eafea4 2014-05-17 pjp FD_SET(notifyfd[0], &rset);
380 58eafea4 2014-05-17 pjp if (maxso < notifyfd[0])
381 58eafea4 2014-05-17 pjp maxso = notifyfd[0];
382 58eafea4 2014-05-17 pjp }
383 58eafea4 2014-05-17 pjp
384 58eafea4 2014-05-17 pjp if (notifyfd[1] > -1) {
385 58eafea4 2014-05-17 pjp FD_SET(notifyfd[1], &rset);
386 58eafea4 2014-05-17 pjp if (maxso < notifyfd[1])
387 58eafea4 2014-05-17 pjp maxso = notifyfd[1];
388 58eafea4 2014-05-17 pjp }
389 58eafea4 2014-05-17 pjp }
390 f98bb34d 2011-09-19 pbug
391 f98bb34d 2011-09-19 pbug tv.tv_sec = 10;
392 f98bb34d 2011-09-19 pbug tv.tv_usec = 0;
393 f98bb34d 2011-09-19 pbug
394 58eafea4 2014-05-17 pjp sel = select(maxso + 1, &rset, NULL, NULL, &tv);
395 f98bb34d 2011-09-19 pbug
396 58eafea4 2014-05-17 pjp if (sel == 0) {
397 58eafea4 2014-05-17 pjp if (notify) {
398 58eafea4 2014-05-17 pjp if (notifyfd[0] > -1 || notifyfd[1] > -1)
399 58eafea4 2014-05-17 pjp notifyslaves((int *)&notifyfd);
400 58eafea4 2014-05-17 pjp }
401 58eafea4 2014-05-17 pjp
402 58eafea4 2014-05-17 pjp continue;
403 58eafea4 2014-05-17 pjp }
404 f98bb34d 2011-09-19 pbug if (sel < 0) {
405 dd869383 2013-02-16 pjp dolog(LOG_INFO, "select: %s\n", strerror(errno));
406 f98bb34d 2011-09-19 pbug continue;
407 f98bb34d 2011-09-19 pbug }
408 f98bb34d 2011-09-19 pbug
409 f98bb34d 2011-09-19 pbug for (i = 0; i < sockcount; i++) {
410 f98bb34d 2011-09-19 pbug if (FD_ISSET(afd[i], &rset)) {
411 f98bb34d 2011-09-19 pbug fromlen = sizeof(struct sockaddr_storage);
412 f98bb34d 2011-09-19 pbug
413 f98bb34d 2011-09-19 pbug so = accept(afd[i], (struct sockaddr*)&from, &fromlen);
414 f98bb34d 2011-09-19 pbug if (so < 0) {
415 dd869383 2013-02-16 pjp dolog(LOG_INFO, "afd accept: %s\n", strerror(errno));
416 f98bb34d 2011-09-19 pbug continue;
417 f98bb34d 2011-09-19 pbug }
418 f98bb34d 2011-09-19 pbug
419 f98bb34d 2011-09-19 pbug if (from.ss_family == AF_INET6) {
420 f98bb34d 2011-09-19 pbug is_ipv6 = 1;
421 f98bb34d 2011-09-19 pbug
422 f98bb34d 2011-09-19 pbug fromlen = sizeof(struct sockaddr_in6);
423 f98bb34d 2011-09-19 pbug sin6 = (struct sockaddr_in6 *)&from;
424 f98bb34d 2011-09-19 pbug inet_ntop(AF_INET6, (void*)&sin6->sin6_addr, (char*)&address, sizeof(address));
425 f98bb34d 2011-09-19 pbug axfr_acl = find_axfr((struct sockaddr_storage *)sin6, AF_INET6);
426 f98bb34d 2011-09-19 pbug
427 f98bb34d 2011-09-19 pbug } else if (from.ss_family == AF_INET) {
428 f98bb34d 2011-09-19 pbug is_ipv6 = 0;
429 f98bb34d 2011-09-19 pbug
430 f98bb34d 2011-09-19 pbug fromlen = sizeof(struct sockaddr_in);
431 f98bb34d 2011-09-19 pbug sin = (struct sockaddr_in *)&from;
432 f98bb34d 2011-09-19 pbug inet_ntop(AF_INET, (void*)&sin->sin_addr, (char*)&address, sizeof(address));
433 f98bb34d 2011-09-19 pbug
434 f98bb34d 2011-09-19 pbug axfr_acl = find_axfr((struct sockaddr_storage *)sin, AF_INET);
435 f98bb34d 2011-09-19 pbug
436 f98bb34d 2011-09-19 pbug } else {
437 dd869383 2013-02-16 pjp dolog(LOG_INFO, "afd accept unknown family %d, close\n", from.ss_family);
438 f98bb34d 2011-09-19 pbug close(so);
439 f98bb34d 2011-09-19 pbug continue;
440 f98bb34d 2011-09-19 pbug }
441 f98bb34d 2011-09-19 pbug
442 f98bb34d 2011-09-19 pbug if (! axfr_acl) {
443 dd869383 2013-02-16 pjp dolog(LOG_INFO, "connection from %s was not in our axfr acl, drop\n", address);
444 f98bb34d 2011-09-19 pbug close(so);
445 f98bb34d 2011-09-19 pbug continue;
446 f98bb34d 2011-09-19 pbug }
447 f98bb34d 2011-09-19 pbug
448 dd869383 2013-02-16 pjp dolog(LOG_INFO, "AXFR connection from %s on interface \"%s\"\n", address, ident[i]);
449 f98bb34d 2011-09-19 pbug
450 f98bb34d 2011-09-19 pbug switch (pid = fork()) {
451 f98bb34d 2011-09-19 pbug case 0:
452 f98bb34d 2011-09-19 pbug axfr_connection(so, address, is_ipv6, db);
453 f98bb34d 2011-09-19 pbug exit(0);
454 f98bb34d 2011-09-19 pbug /*NOTREACHED*/
455 f98bb34d 2011-09-19 pbug default:
456 f98bb34d 2011-09-19 pbug close(so);
457 f98bb34d 2011-09-19 pbug break;
458 f98bb34d 2011-09-19 pbug }
459 f98bb34d 2011-09-19 pbug
460 f98bb34d 2011-09-19 pbug } /* if(FD_ISSET..) */
461 f98bb34d 2011-09-19 pbug
462 f98bb34d 2011-09-19 pbug } /* for (i.. */
463 58eafea4 2014-05-17 pjp
464 58eafea4 2014-05-17 pjp if (notify) {
465 58eafea4 2014-05-17 pjp if (notifyfd[0] > -1 && FD_ISSET(notifyfd[0], &rset)) {
466 58eafea4 2014-05-17 pjp fromlen = sizeof(struct sockaddr_storage);
467 58eafea4 2014-05-17 pjp len = recvfrom(notifyfd[0], buf, sizeof(buf), 0, (struct sockaddr *)&from, &fromlen);
468 58eafea4 2014-05-17 pjp if (len < 0) {
469 58eafea4 2014-05-17 pjp dolog(LOG_INFO, "recvfrom: %s\n", strerror(errno));
470 58eafea4 2014-05-17 pjp }
471 58eafea4 2014-05-17 pjp
472 58eafea4 2014-05-17 pjp if (len < sizeof(struct dns_header)) {
473 58eafea4 2014-05-17 pjp dolog(LOG_INFO, "received bogus reply on notify port, drop\n");
474 58eafea4 2014-05-17 pjp continue;
475 58eafea4 2014-05-17 pjp }
476 58eafea4 2014-05-17 pjp
477 58eafea4 2014-05-17 pjp dh = (struct dns_header *)&buf[0];
478 58eafea4 2014-05-17 pjp if (ntohs(dh->question) != 1) {
479 58eafea4 2014-05-17 pjp dolog(LOG_INFO, "question header on notify reply not 1, drop\n");
480 58eafea4 2014-05-17 pjp continue;
481 58eafea4 2014-05-17 pjp }
482 58eafea4 2014-05-17 pjp
483 58eafea4 2014-05-17 pjp if (! (ntohs(dh->query) & DNS_REPLY)) {
484 58eafea4 2014-05-17 pjp dolog(LOG_INFO, "question header is not a reply, drop\n");
485 58eafea4 2014-05-17 pjp continue;
486 58eafea4 2014-05-17 pjp }
487 58eafea4 2014-05-17 pjp
488 58eafea4 2014-05-17 pjp question = build_question(buf, len, ntohs(dh->additional));
489 58eafea4 2014-05-17 pjp if (question == NULL) {
490 58eafea4 2014-05-17 pjp dolog(LOG_INFO, "build_question failed on notify reply, drop\n");
491 58eafea4 2014-05-17 pjp continue;
492 58eafea4 2014-05-17 pjp }
493 58eafea4 2014-05-17 pjp
494 58eafea4 2014-05-17 pjp sin = (struct sockaddr_in *)&from;
495 58eafea4 2014-05-17 pjp inet_ntop(AF_INET, (void*)&sin->sin_addr, (char*)&address, sizeof(address));
496 58eafea4 2014-05-17 pjp
497 05b37e84 2014-05-18 pjp #ifdef __linux__
498 05b37e84 2014-05-18 pjp SLIST_FOREACH(notnp, &notifyhead, notify_entry) {
499 05b37e84 2014-05-18 pjp #else
500 58eafea4 2014-05-17 pjp SLIST_FOREACH_SAFE(notnp, &notifyhead, notify_entry, notn2) {
501 05b37e84 2014-05-18 pjp #endif
502 58eafea4 2014-05-17 pjp
503 58eafea4 2014-05-17 pjp for (i = 0; i < notify; i++) {
504 58eafea4 2014-05-17 pjp if (ntohs(dh->id) == notnp->ids[i] &&
505 58eafea4 2014-05-17 pjp (ntohs(dh->query) & DNS_NOTIFY) &&
506 58eafea4 2014-05-17 pjp (ntohs(dh->query) & DNS_AUTH) &&
507 58eafea4 2014-05-17 pjp ntohs(question->hdr->qtype) == DNS_TYPE_SOA &&
508 58eafea4 2014-05-17 pjp ntohs(question->hdr->qclass) == DNS_CLASS_IN &&
509 58eafea4 2014-05-17 pjp question->hdr->namelen == notnp->domainlen &&
510 58eafea4 2014-05-17 pjp memcmp(question->hdr->name, notnp->domain, notnp->domainlen) == 0) {
511 05b37e84 2014-05-18 pjp #ifdef __linux__
512 05b37e84 2014-05-18 pjp SLIST_FOREACH(nfslnp, &notifyslavehead, notifyslave_entry) {
513 05b37e84 2014-05-18 pjp #else
514 58eafea4 2014-05-17 pjp SLIST_FOREACH_SAFE(nfslnp, &notifyslavehead, notifyslave_entry, nfslnp2) {
515 05b37e84 2014-05-18 pjp #endif
516 58eafea4 2014-05-17 pjp if (nfslnp->family != AF_INET)
517 58eafea4 2014-05-17 pjp continue;
518 58eafea4 2014-05-17 pjp
519 58eafea4 2014-05-17 pjp sin2 = (struct sockaddr_in *)&nfslnp->hostmask;
520 58eafea4 2014-05-17 pjp if (sin->sin_addr.s_addr == sin2->sin_addr.s_addr) {
521 58eafea4 2014-05-17 pjp dolog(LOG_INFO, "notify success! removing address \"%s\" from notify contact list\n", address);
522 58eafea4 2014-05-17 pjp SLIST_REMOVE(&notifyslavehead, nfslnp, notifyslaveentry, notifyslave_entry);
523 58eafea4 2014-05-17 pjp }
524 58eafea4 2014-05-17 pjp }
525 58eafea4 2014-05-17 pjp } else {
526 58eafea4 2014-05-17 pjp dolog(LOG_INFO, "got a reply from a notify host (%s) DNS->ID %u that says: %04x\n", address, ntohs(dh->id), ntohs(dh->query));
527 58eafea4 2014-05-17 pjp }
528 58eafea4 2014-05-17 pjp }
529 58eafea4 2014-05-17 pjp }
530 58eafea4 2014-05-17 pjp
531 58eafea4 2014-05-17 pjp free_question(question);
532 58eafea4 2014-05-17 pjp
533 58eafea4 2014-05-17 pjp if (SLIST_EMPTY(&notifyslavehead)) {
534 58eafea4 2014-05-17 pjp dolog(LOG_INFO, "notifys have been completed, closing notify descriptors!\n");
535 58eafea4 2014-05-17 pjp if (notifyfd[0] > -1)
536 58eafea4 2014-05-17 pjp close(notifyfd[0]);
537 58eafea4 2014-05-17 pjp
538 58eafea4 2014-05-17 pjp if (notifyfd[1] > -1)
539 58eafea4 2014-05-17 pjp close(notifyfd[1]);
540 58eafea4 2014-05-17 pjp
541 58eafea4 2014-05-17 pjp notifyfd[0] = -1;
542 58eafea4 2014-05-17 pjp notifyfd[1] = -1;
543 58eafea4 2014-05-17 pjp }
544 58eafea4 2014-05-17 pjp }
545 f98bb34d 2011-09-19 pbug
546 58eafea4 2014-05-17 pjp if (notifyfd[1] > -1 && FD_ISSET(notifyfd[1], &rset)) {
547 58eafea4 2014-05-17 pjp fromlen = sizeof(struct sockaddr_storage);
548 58eafea4 2014-05-17 pjp len = recvfrom(notifyfd[1], buf, sizeof(buf), 0, (struct sockaddr *)&from, &fromlen);
549 58eafea4 2014-05-17 pjp if (len < 0) {
550 58eafea4 2014-05-17 pjp dolog(LOG_INFO, "recvfrom: %s\n", strerror(errno));
551 58eafea4 2014-05-17 pjp }
552 58eafea4 2014-05-17 pjp
553 58eafea4 2014-05-17 pjp if (len < sizeof(struct dns_header)) {
554 58eafea4 2014-05-17 pjp dolog(LOG_INFO, "received bogus reply on notify port, drop\n");
555 58eafea4 2014-05-17 pjp continue;
556 58eafea4 2014-05-17 pjp }
557 58eafea4 2014-05-17 pjp
558 58eafea4 2014-05-17 pjp dh = (struct dns_header *)&buf[0];
559 58eafea4 2014-05-17 pjp if (ntohs(dh->question) != 1) {
560 58eafea4 2014-05-17 pjp dolog(LOG_INFO, "question header on notify reply not 1, drop\n");
561 58eafea4 2014-05-17 pjp continue;
562 58eafea4 2014-05-17 pjp }
563 58eafea4 2014-05-17 pjp
564 58eafea4 2014-05-17 pjp if (! (ntohs(dh->query) & DNS_REPLY)) {
565 58eafea4 2014-05-17 pjp dolog(LOG_INFO, "question header is not a reply, drop\n");
566 58eafea4 2014-05-17 pjp continue;
567 58eafea4 2014-05-17 pjp }
568 58eafea4 2014-05-17 pjp
569 58eafea4 2014-05-17 pjp question = build_question(buf, len, ntohs(dh->additional));
570 58eafea4 2014-05-17 pjp if (question == NULL) {
571 58eafea4 2014-05-17 pjp dolog(LOG_INFO, "build_question failed on notify reply, drop\n");
572 58eafea4 2014-05-17 pjp continue;
573 58eafea4 2014-05-17 pjp }
574 58eafea4 2014-05-17 pjp
575 58eafea4 2014-05-17 pjp sin6 = (struct sockaddr_in6 *)&from;
576 58eafea4 2014-05-17 pjp inet_ntop(AF_INET6, (void*)&sin6->sin6_addr, (char*)&address, sizeof(address));
577 58eafea4 2014-05-17 pjp
578 05b37e84 2014-05-18 pjp #ifdef __linux
579 05b37e84 2014-05-18 pjp SLIST_FOREACH(notnp, &notifyhead, notify_entry) {
580 05b37e84 2014-05-18 pjp #else
581 58eafea4 2014-05-17 pjp SLIST_FOREACH_SAFE(notnp, &notifyhead, notify_entry, notn2) {
582 05b37e84 2014-05-18 pjp #endif
583 58eafea4 2014-05-17 pjp for (i = 0; i < notify; i++) {
584 58eafea4 2014-05-17 pjp if (ntohs(dh->id) == notnp->ids[i] &&
585 58eafea4 2014-05-17 pjp (ntohs(dh->query) & DNS_NOTIFY) &&
586 58eafea4 2014-05-17 pjp (ntohs(dh->query) & DNS_AUTH) &&
587 58eafea4 2014-05-17 pjp ntohs(question->hdr->qtype) == DNS_TYPE_SOA &&
588 58eafea4 2014-05-17 pjp ntohs(question->hdr->qclass) == DNS_CLASS_IN &&
589 58eafea4 2014-05-17 pjp question->hdr->namelen == notnp->domainlen &&
590 58eafea4 2014-05-17 pjp memcmp(question->hdr->name, notnp->domain, notnp->domainlen) == 0) {
591 05b37e84 2014-05-18 pjp #ifdef __linux__
592 05b37e84 2014-05-18 pjp SLIST_FOREACH(nfslnp, &notifyslavehead, notifyslave_entry) {
593 05b37e84 2014-05-18 pjp #else
594 58eafea4 2014-05-17 pjp SLIST_FOREACH_SAFE(nfslnp, &notifyslavehead, notifyslave_entry, nfslnp2) {
595 05b37e84 2014-05-18 pjp #endif
596 58eafea4 2014-05-17 pjp if (nfslnp->family != AF_INET6)
597 58eafea4 2014-05-17 pjp continue;
598 58eafea4 2014-05-17 pjp
599 58eafea4 2014-05-17 pjp sin62 = (struct sockaddr_in6 *)&nfslnp->hostmask;
600 58eafea4 2014-05-17 pjp if (memcmp(&sin6->sin6_addr, &sin62->sin6_addr, 16) == 0) {
601 58eafea4 2014-05-17 pjp dolog(LOG_INFO, "notify success! removing address \"%s\" from notify contact list\n", address);
602 58eafea4 2014-05-17 pjp SLIST_REMOVE(&notifyslavehead, nfslnp, notifyslaveentry, notifyslave_entry);
603 58eafea4 2014-05-17 pjp }
604 58eafea4 2014-05-17 pjp }
605 58eafea4 2014-05-17 pjp } else {
606 58eafea4 2014-05-17 pjp dolog(LOG_INFO, "got a reply from a notify host (%s) DNS->ID %u that says: %04x\n", address, ntohs(dh->id), ntohs(dh->query));
607 58eafea4 2014-05-17 pjp }
608 58eafea4 2014-05-17 pjp }
609 58eafea4 2014-05-17 pjp }
610 58eafea4 2014-05-17 pjp
611 58eafea4 2014-05-17 pjp free_question(question);
612 58eafea4 2014-05-17 pjp
613 58eafea4 2014-05-17 pjp if (SLIST_EMPTY(&notifyslavehead)) {
614 58eafea4 2014-05-17 pjp dolog(LOG_INFO, "notifys have been completed, closing notify descriptors!\n");
615 58eafea4 2014-05-17 pjp if (notifyfd[0] > -1)
616 58eafea4 2014-05-17 pjp close(notifyfd[0]);
617 58eafea4 2014-05-17 pjp
618 58eafea4 2014-05-17 pjp if (notifyfd[1] > -1)
619 58eafea4 2014-05-17 pjp close(notifyfd[1]);
620 58eafea4 2014-05-17 pjp
621 58eafea4 2014-05-17 pjp notifyfd[0] = -1;
622 58eafea4 2014-05-17 pjp notifyfd[1] = -1;
623 58eafea4 2014-05-17 pjp }
624 58eafea4 2014-05-17 pjp }
625 58eafea4 2014-05-17 pjp
626 58eafea4 2014-05-17 pjp }
627 58eafea4 2014-05-17 pjp
628 f98bb34d 2011-09-19 pbug } /* for (;;) */
629 f98bb34d 2011-09-19 pbug
630 f98bb34d 2011-09-19 pbug }
631 f98bb34d 2011-09-19 pbug
632 f98bb34d 2011-09-19 pbug /*
633 f98bb34d 2011-09-19 pbug * AXFR_CONNECTION - this is the main core of AXFR engine, forked
634 f98bb34d 2011-09-19 pbug *
635 f98bb34d 2011-09-19 pbug */
636 f98bb34d 2011-09-19 pbug
637 f98bb34d 2011-09-19 pbug void
638 f98bb34d 2011-09-19 pbug axfr_connection(int so, char *address, int is_ipv6, DB *db)
639 f98bb34d 2011-09-19 pbug {
640 f98bb34d 2011-09-19 pbug
641 f98bb34d 2011-09-19 pbug char buf[4000];
642 f98bb34d 2011-09-19 pbug char *p = &buf[0];
643 f98bb34d 2011-09-19 pbug char *q;
644 f98bb34d 2011-09-19 pbug char *reply;
645 f98bb34d 2011-09-19 pbug
646 f98bb34d 2011-09-19 pbug int len, dnslen;
647 f98bb34d 2011-09-19 pbug int offset = 0;
648 f98bb34d 2011-09-19 pbug int ret;
649 f98bb34d 2011-09-19 pbug int qlen;
650 f98bb34d 2011-09-19 pbug int outlen, i;
651 f98bb34d 2011-09-19 pbug int rrcount;
652 f98bb34d 2011-09-19 pbug
653 f98bb34d 2011-09-19 pbug u_int16_t *tmp;
654 f98bb34d 2011-09-19 pbug
655 f98bb34d 2011-09-19 pbug struct dns_header *dh, *odh;
656 f98bb34d 2011-09-19 pbug struct sreply sreply;
657 f98bb34d 2011-09-19 pbug struct question *question, *fq;
658 f98bb34d 2011-09-19 pbug struct domain soa, sdomain, nsdomain, savesd;
659 f98bb34d 2011-09-19 pbug
660 f98bb34d 2011-09-19 pbug DBT key, data;
661 f98bb34d 2011-09-19 pbug DBC *cursor;
662 f98bb34d 2011-09-19 pbug
663 f98bb34d 2011-09-19 pbug for (;;) {
664 f98bb34d 2011-09-19 pbug len = recv(so, p + offset, sizeof(buf) - offset, 0);
665 f98bb34d 2011-09-19 pbug if (len <= 0) {
666 f98bb34d 2011-09-19 pbug close(so);
667 f98bb34d 2011-09-19 pbug exit(1);
668 f98bb34d 2011-09-19 pbug }
669 f98bb34d 2011-09-19 pbug
670 f98bb34d 2011-09-19 pbug /*
671 f98bb34d 2011-09-19 pbug * do a little dance here because we don't know if the
672 f98bb34d 2011-09-19 pbug * input is fragmented or not...
673 f98bb34d 2011-09-19 pbug */
674 f98bb34d 2011-09-19 pbug if (offset + len >= 2) {
675 f98bb34d 2011-09-19 pbug tmp = (u_int16_t *)p;
676 f98bb34d 2011-09-19 pbug dnslen = ntohs(*tmp);
677 f98bb34d 2011-09-19 pbug } else {
678 f98bb34d 2011-09-19 pbug offset += len;
679 f98bb34d 2011-09-19 pbug continue;
680 f98bb34d 2011-09-19 pbug }
681 f98bb34d 2011-09-19 pbug if (dnslen + 2 != offset + len) {
682 f98bb34d 2011-09-19 pbug offset += len;
683 f98bb34d 2011-09-19 pbug continue;
684 f98bb34d 2011-09-19 pbug }
685 f98bb34d 2011-09-19 pbug
686 f98bb34d 2011-09-19 pbug
687 f98bb34d 2011-09-19 pbug /* by now the packet should be normalized */
688 f98bb34d 2011-09-19 pbug
689 f98bb34d 2011-09-19 pbug dh = (struct dns_header *)(p + 2);
690 f98bb34d 2011-09-19 pbug
691 f98bb34d 2011-09-19 pbug if ((ntohs(dh->query) & DNS_REPLY)) {
692 dd869383 2013-02-16 pjp dolog(LOG_INFO, "AXFR dns packet is not a question, drop\n");
693 f98bb34d 2011-09-19 pbug goto drop;
694 f98bb34d 2011-09-19 pbug }
695 f98bb34d 2011-09-19 pbug
696 f98bb34d 2011-09-19 pbug if (ntohs(dh->question) != 1) {
697 dd869383 2013-02-16 pjp dolog(LOG_INFO, "AXFR dns packet does not have a question count of 1 (RFC 5936, page 9), reply fmterror\n");
698 f98bb34d 2011-09-19 pbug
699 f98bb34d 2011-09-19 pbug build_reply(&sreply, so, (p + 2), dnslen, NULL, NULL, 0, NULL, NULL, 0xff, 1, 0, NULL);
700 f98bb34d 2011-09-19 pbug
701 f98bb34d 2011-09-19 pbug reply_fmterror(&sreply);
702 f98bb34d 2011-09-19 pbug goto drop;
703 f98bb34d 2011-09-19 pbug }
704 f98bb34d 2011-09-19 pbug
705 58eafea4 2014-05-17 pjp if ((question = build_question((p + 2), dnslen, 0)) == NULL) {
706 dd869383 2013-02-16 pjp dolog(LOG_INFO, "AXFR malformed question, drop\n");
707 f98bb34d 2011-09-19 pbug goto drop;
708 f98bb34d 2011-09-19 pbug }
709 f98bb34d 2011-09-19 pbug
710 f98bb34d 2011-09-19 pbug if (ntohs(question->hdr->qclass) != DNS_CLASS_IN) {
711 dd869383 2013-02-16 pjp dolog(LOG_INFO, "AXFR question wasn't for class DNS_CLASS_IN, drop\n");
712 f98bb34d 2011-09-19 pbug goto drop;
713 f98bb34d 2011-09-19 pbug }
714 f98bb34d 2011-09-19 pbug
715 8d753d40 2011-09-22 pbug switch (ntohs(question->hdr->qtype)) {
716 8d753d40 2011-09-22 pbug case DNS_TYPE_AXFR:
717 8d753d40 2011-09-22 pbug case DNS_TYPE_IXFR:
718 8d753d40 2011-09-22 pbug case DNS_TYPE_SOA:
719 8d753d40 2011-09-22 pbug break;
720 8d753d40 2011-09-22 pbug default:
721 dd869383 2013-02-16 pjp dolog(LOG_INFO, "AXFR question wasn't for valid types (ixfr, axfr, soa) with requested type %d, drop\n", ntohs(question->hdr->qtype));
722 f98bb34d 2011-09-19 pbug goto drop;
723 8d753d40 2011-09-22 pbug
724 f98bb34d 2011-09-19 pbug }
725 f98bb34d 2011-09-19 pbug
726 f98bb34d 2011-09-19 pbug /* now we can be reasonably sure that it's an AXFR for us */
727 f98bb34d 2011-09-19 pbug
728 f98bb34d 2011-09-19 pbug reply = calloc(1, 65538);
729 f98bb34d 2011-09-19 pbug if (reply == NULL) {
730 dd869383 2013-02-16 pjp dolog(LOG_INFO, "internal error: %s\n", strerror(errno));
731 f98bb34d 2011-09-19 pbug goto drop;
732 f98bb34d 2011-09-19 pbug }
733 f98bb34d 2011-09-19 pbug
734 f98bb34d 2011-09-19 pbug odh = (struct dns_header *)(reply + 2);
735 f98bb34d 2011-09-19 pbug
736 f98bb34d 2011-09-19 pbug q = question->hdr->name;
737 f98bb34d 2011-09-19 pbug qlen = question->hdr->namelen;
738 f98bb34d 2011-09-19 pbug
739 f98bb34d 2011-09-19 pbug memset(&key, 0, sizeof(key));
740 f98bb34d 2011-09-19 pbug memset(&data, 0, sizeof(data));
741 f98bb34d 2011-09-19 pbug
742 f98bb34d 2011-09-19 pbug key.data = (char *)q;
743 f98bb34d 2011-09-19 pbug key.size = qlen;
744 f98bb34d 2011-09-19 pbug
745 f98bb34d 2011-09-19 pbug data.data = NULL;
746 f98bb34d 2011-09-19 pbug data.size = 0;
747 f98bb34d 2011-09-19 pbug
748 f98bb34d 2011-09-19 pbug ret = db->get(db, NULL, &key, &data, 0);
749 f98bb34d 2011-09-19 pbug
750 f98bb34d 2011-09-19 pbug if (ret != 0) {
751 f98bb34d 2011-09-19 pbug memset(&sdomain, 0, sizeof(sdomain));
752 f98bb34d 2011-09-19 pbug (void)get_soa(db, question, &sdomain, 0);
753 f98bb34d 2011-09-19 pbug build_reply(&sreply, so, (p + 2), dnslen, question, NULL, 0, &sdomain, NULL, 0xff, 1, 0, NULL);
754 f98bb34d 2011-09-19 pbug reply_nxdomain(&sreply);
755 dd869383 2013-02-16 pjp dolog(LOG_INFO, "AXFR request for zone %s, no db entry, nxdomain -> drop\n", question->converted_name);
756 f98bb34d 2011-09-19 pbug goto drop;
757 f98bb34d 2011-09-19 pbug }
758 f98bb34d 2011-09-19 pbug
759 f98bb34d 2011-09-19 pbug if (data.size != sizeof(struct domain)) {
760 dd869383 2013-02-16 pjp dolog(LOG_INFO, "AXFR btree db is damaged, drop\n");
761 f98bb34d 2011-09-19 pbug goto drop;
762 f98bb34d 2011-09-19 pbug }
763 f98bb34d 2011-09-19 pbug
764 f98bb34d 2011-09-19 pbug memcpy((char *)&soa, (char *)data.data, data.size);
765 f98bb34d 2011-09-19 pbug
766 f98bb34d 2011-09-19 pbug /*
767 f98bb34d 2011-09-19 pbug * check if we have an SOA record
768 f98bb34d 2011-09-19 pbug */
769 f98bb34d 2011-09-19 pbug
770 f98bb34d 2011-09-19 pbug if (! (soa.flags & DOMAIN_HAVE_SOA)) {
771 f98bb34d 2011-09-19 pbug memset(&sdomain, 0, sizeof(sdomain));
772 f98bb34d 2011-09-19 pbug (void)get_soa(db, question, &sdomain, 0);
773 f98bb34d 2011-09-19 pbug build_reply(&sreply, so, (p + 2), dnslen, question, NULL, 0, &sdomain, NULL, 0xff, 1, 0, NULL);
774 f98bb34d 2011-09-19 pbug reply_nxdomain(&sreply);
775 f98bb34d 2011-09-19 pbug
776 dd869383 2013-02-16 pjp dolog(LOG_INFO, "AXFR request for zone %s, which has no SOA for the zone, nxdomain -> drop\n", question->converted_name);
777 f98bb34d 2011-09-19 pbug goto drop;
778 f98bb34d 2011-09-19 pbug }
779 f98bb34d 2011-09-19 pbug
780 f98bb34d 2011-09-19 pbug if (ntohs(question->hdr->qtype) == DNS_TYPE_SOA) {
781 dd869383 2013-02-16 pjp dolog(LOG_INFO, "TCP SOA request for zone \"%s\", replying...\n", question->converted_name);
782 f98bb34d 2011-09-19 pbug outlen = 0;
783 f98bb34d 2011-09-19 pbug outlen = build_header(db, (reply + 2), (p + 2), question, 1);
784 f98bb34d 2011-09-19 pbug outlen = build_soa(db, (reply + 2), outlen, &soa, question);
785 f98bb34d 2011-09-19 pbug
786 f98bb34d 2011-09-19 pbug tmp = (u_int16_t *)reply;
787 f98bb34d 2011-09-19 pbug *tmp = htons(outlen);
788 f98bb34d 2011-09-19 pbug
789 f98bb34d 2011-09-19 pbug len = send(so, reply, outlen + 2, 0);
790 f98bb34d 2011-09-19 pbug if (len <= 0) {
791 f98bb34d 2011-09-19 pbug goto drop;
792 f98bb34d 2011-09-19 pbug }
793 f98bb34d 2011-09-19 pbug
794 f98bb34d 2011-09-19 pbug outlen = 0;
795 f98bb34d 2011-09-19 pbug offset = 0;
796 f98bb34d 2011-09-19 pbug p = &buf[0];
797 f98bb34d 2011-09-19 pbug
798 f98bb34d 2011-09-19 pbug free (reply);
799 f98bb34d 2011-09-19 pbug
800 f98bb34d 2011-09-19 pbug continue;
801 f98bb34d 2011-09-19 pbug }
802 f98bb34d 2011-09-19 pbug
803 dd869383 2013-02-16 pjp dolog(LOG_INFO, "%s request for zone \"%s\", replying...\n",
804 8d753d40 2011-09-22 pbug (ntohs(question->hdr->qtype) == DNS_TYPE_AXFR ? "AXFR"
805 8d753d40 2011-09-22 pbug : "IXFR"), question->converted_name);
806 f98bb34d 2011-09-19 pbug
807 f98bb34d 2011-09-19 pbug outlen = build_header(db, (reply + 2), (p + 2), question, 0);
808 f98bb34d 2011-09-19 pbug outlen = build_soa(db, (reply + 2), outlen, &soa, question);
809 f98bb34d 2011-09-19 pbug rrcount = 1;
810 f98bb34d 2011-09-19 pbug
811 f98bb34d 2011-09-19 pbug if (db->cursor(db, NULL, &cursor, 0) != 0) {
812 dd869383 2013-02-16 pjp dolog(LOG_INFO, "db->cursor: %s\n", strerror(errno));
813 f98bb34d 2011-09-19 pbug goto drop;
814 f98bb34d 2011-09-19 pbug }
815 f98bb34d 2011-09-19 pbug
816 f98bb34d 2011-09-19 pbug memset(&key, 0, sizeof(key));
817 f98bb34d 2011-09-19 pbug memset(&data, 0, sizeof(data));
818 f98bb34d 2011-09-19 pbug
819 f98bb34d 2011-09-19 pbug
820 f98bb34d 2011-09-19 pbug if (cursor->c_get(cursor, &key, &data, DB_FIRST) != 0) {
821 dd869383 2013-02-16 pjp dolog(LOG_INFO, "cursor->c_get: %s\n", strerror(errno));
822 f98bb34d 2011-09-19 pbug goto drop;
823 f98bb34d 2011-09-19 pbug }
824 f98bb34d 2011-09-19 pbug
825 f98bb34d 2011-09-19 pbug do {
826 f98bb34d 2011-09-19 pbug if (data.size != sizeof(struct domain)) {
827 dd869383 2013-02-16 pjp dolog(LOG_INFO, "AXFR btree db is damaged (%d), drop\n", __LINE__);
828 f98bb34d 2011-09-19 pbug goto drop;
829 f98bb34d 2011-09-19 pbug }
830 f98bb34d 2011-09-19 pbug
831 f98bb34d 2011-09-19 pbug memcpy((char *)&sdomain, (char *)data.data, data.size);
832 f98bb34d 2011-09-19 pbug memcpy((char *)&savesd, (char *)data.data, data.size);
833 f98bb34d 2011-09-19 pbug
834 f98bb34d 2011-09-19 pbug if (checklabel(db, &sdomain, &soa, question)) {
835 f98bb34d 2011-09-19 pbug fq = build_fake_question(sdomain.zone, sdomain.zonelen, 0);
836 f98bb34d 2011-09-19 pbug build_reply(&sreply, so, (p + 2), dnslen, fq, NULL, 0, &sdomain, NULL, 0xff, 1, 0, NULL);
837 f98bb34d 2011-09-19 pbug outlen = create_anyreply(&sreply, (reply + 2), 65535, outlen, 0);
838 f98bb34d 2011-09-19 pbug free_question(fq);
839 f98bb34d 2011-09-19 pbug
840 f98bb34d 2011-09-19 pbug if ((savesd.flags & DOMAIN_HAVE_NS) &&
841 f98bb34d 2011-09-19 pbug (savesd.ns_type & NS_TYPE_DELEGATE)) {
842 f98bb34d 2011-09-19 pbug for (i = 0; i < savesd.ns_count; i++) {
843 f98bb34d 2011-09-19 pbug fq = build_fake_question(savesd.ns[i].nsserver,
844 f98bb34d 2011-09-19 pbug savesd.ns[i].nslen, 0);
845 f98bb34d 2011-09-19 pbug memset(&key, 0, sizeof(key));
846 f98bb34d 2011-09-19 pbug memset(&data, 0, sizeof(data));
847 f98bb34d 2011-09-19 pbug
848 f98bb34d 2011-09-19 pbug key.data = fq->hdr->name;
849 f98bb34d 2011-09-19 pbug key.size = fq->hdr->namelen;
850 f98bb34d 2011-09-19 pbug
851 f98bb34d 2011-09-19 pbug data.data = NULL;
852 f98bb34d 2011-09-19 pbug data.size = 0;
853 f98bb34d 2011-09-19 pbug
854 f98bb34d 2011-09-19 pbug ret = db->get(db, NULL, &key, &data, 0);
855 f98bb34d 2011-09-19 pbug if (ret != 0) {
856 f98bb34d 2011-09-19 pbug free_question(fq);
857 f98bb34d 2011-09-19 pbug continue;
858 f98bb34d 2011-09-19 pbug }
859 f98bb34d 2011-09-19 pbug
860 f98bb34d 2011-09-19 pbug if (data.size != sizeof(struct domain)) {
861 dd869383 2013-02-16 pjp dolog(LOG_INFO, "AXFR btree db is damaged (%d), drop\n", __LINE__);
862 f98bb34d 2011-09-19 pbug goto drop;
863 f98bb34d 2011-09-19 pbug }
864 f98bb34d 2011-09-19 pbug
865 f98bb34d 2011-09-19 pbug memcpy((char *)&nsdomain, (char*)data.data, data.size);
866 f98bb34d 2011-09-19 pbug
867 f98bb34d 2011-09-19 pbug build_reply(&sreply, so, (p + 2), dnslen, fq, NULL, 0, &nsdomain, NULL, 0xff, 1, 0, NULL);
868 f98bb34d 2011-09-19 pbug outlen = create_anyreply(&sreply, (reply + 2), 65535, outlen, 0);
869 f98bb34d 2011-09-19 pbug free_question(fq);
870 f98bb34d 2011-09-19 pbug
871 f98bb34d 2011-09-19 pbug } /* for (i.. */
872 f98bb34d 2011-09-19 pbug } /* if (sdomain.flags */
873 f98bb34d 2011-09-19 pbug
874 f98bb34d 2011-09-19 pbug } /* if (checklabel */
875 f98bb34d 2011-09-19 pbug
876 f98bb34d 2011-09-19 pbug /*
877 f98bb34d 2011-09-19 pbug * if we accumulate 60000 bytes out of the maximum
878 f98bb34d 2011-09-19 pbug * 65535 bytes then we fragment.
879 f98bb34d 2011-09-19 pbug */
880 f98bb34d 2011-09-19 pbug /* XXX */
881 f98bb34d 2011-09-19 pbug if (outlen > 60000) {
882 f98bb34d 2011-09-19 pbug tmp = (u_int16_t *)reply;
883 f98bb34d 2011-09-19 pbug *tmp = htons(outlen);
884 f98bb34d 2011-09-19 pbug
885 f98bb34d 2011-09-19 pbug /* set the rrcount in there */
886 f98bb34d 2011-09-19 pbug
887 f98bb34d 2011-09-19 pbug NTOHS(odh->answer);
888 f98bb34d 2011-09-19 pbug odh->answer += rrcount;
889 f98bb34d 2011-09-19 pbug HTONS(odh->answer);
890 f98bb34d 2011-09-19 pbug
891 f98bb34d 2011-09-19 pbug len = send(so, reply, outlen + 2, 0);
892 f98bb34d 2011-09-19 pbug if (len <= 0) {
893 f98bb34d 2011-09-19 pbug goto drop;
894 f98bb34d 2011-09-19 pbug }
895 f98bb34d 2011-09-19 pbug
896 f98bb34d 2011-09-19 pbug rrcount = 0;
897 f98bb34d 2011-09-19 pbug outlen = build_header(db, (reply + 2), (p + 2), question, 0);
898 f98bb34d 2011-09-19 pbug }
899 f98bb34d 2011-09-19 pbug
900 f98bb34d 2011-09-19 pbug memset(&key, 0, sizeof(key));
901 f98bb34d 2011-09-19 pbug memset(&data, 0, sizeof(data));
902 f98bb34d 2011-09-19 pbug } while (cursor->c_get(cursor, &key, &data, DB_NEXT) == 0);
903 f98bb34d 2011-09-19 pbug
904 f98bb34d 2011-09-19 pbug cursor->c_close(cursor);
905 f98bb34d 2011-09-19 pbug
906 f98bb34d 2011-09-19 pbug outlen = build_soa(db, (reply + 2), outlen, &soa, question);
907 f98bb34d 2011-09-19 pbug rrcount++;
908 f98bb34d 2011-09-19 pbug
909 f98bb34d 2011-09-19 pbug tmp = (u_int16_t *)reply;
910 f98bb34d 2011-09-19 pbug *tmp = htons(outlen);
911 f98bb34d 2011-09-19 pbug
912 f98bb34d 2011-09-19 pbug /* set the rrcount in there */
913 f98bb34d 2011-09-19 pbug
914 f98bb34d 2011-09-19 pbug NTOHS(odh->answer);
915 f98bb34d 2011-09-19 pbug odh->answer += rrcount;
916 f98bb34d 2011-09-19 pbug HTONS(odh->answer);
917 f98bb34d 2011-09-19 pbug
918 f98bb34d 2011-09-19 pbug len = send(so, reply, outlen + 2, 0);
919 f98bb34d 2011-09-19 pbug if (len <= 0)
920 f98bb34d 2011-09-19 pbug goto drop;
921 f98bb34d 2011-09-19 pbug
922 f98bb34d 2011-09-19 pbug goto drop;
923 f98bb34d 2011-09-19 pbug
924 f98bb34d 2011-09-19 pbug } /* for(;;) */
925 f98bb34d 2011-09-19 pbug
926 f98bb34d 2011-09-19 pbug
927 f98bb34d 2011-09-19 pbug
928 f98bb34d 2011-09-19 pbug drop:
929 f98bb34d 2011-09-19 pbug close(so);
930 f98bb34d 2011-09-19 pbug exit(0);
931 f98bb34d 2011-09-19 pbug }
932 f98bb34d 2011-09-19 pbug
933 f98bb34d 2011-09-19 pbug /*
934 f98bb34d 2011-09-19 pbug * REAP - reap the child that is zombied by now, this is a sighandler for
935 f98bb34d 2011-09-19 pbug * SIGCHLD
936 f98bb34d 2011-09-19 pbug */
937 f98bb34d 2011-09-19 pbug
938 f98bb34d 2011-09-19 pbug void
939 f98bb34d 2011-09-19 pbug reap(int sig)
940 f98bb34d 2011-09-19 pbug {
941 f98bb34d 2011-09-19 pbug int status;
942 f98bb34d 2011-09-19 pbug pid_t pid;
943 f98bb34d 2011-09-19 pbug
944 f98bb34d 2011-09-19 pbug while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
945 f98bb34d 2011-09-19 pbug }
946 f98bb34d 2011-09-19 pbug }
947 f98bb34d 2011-09-19 pbug
948 f98bb34d 2011-09-19 pbug
949 f98bb34d 2011-09-19 pbug /*
950 f98bb34d 2011-09-19 pbug * build_header - build a header reply
951 f98bb34d 2011-09-19 pbug *
952 f98bb34d 2011-09-19 pbug */
953 f98bb34d 2011-09-19 pbug
954 f98bb34d 2011-09-19 pbug int
955 f98bb34d 2011-09-19 pbug build_header(DB *db, char *reply, char *buf, struct question *q, int answercount)
956 f98bb34d 2011-09-19 pbug {
957 f98bb34d 2011-09-19 pbug struct dns_header *odh;
958 f98bb34d 2011-09-19 pbug u_int16_t outlen;
959 f98bb34d 2011-09-19 pbug
960 f98bb34d 2011-09-19 pbug odh = (struct dns_header *)reply;
961 f98bb34d 2011-09-19 pbug outlen = sizeof(struct dns_header);
962 f98bb34d 2011-09-19 pbug
963 f98bb34d 2011-09-19 pbug /* copy question to reply */
964 f98bb34d 2011-09-19 pbug memcpy(reply, buf, sizeof(struct dns_header) + q->hdr->namelen + 4);
965 f98bb34d 2011-09-19 pbug /* blank query */
966 f98bb34d 2011-09-19 pbug memset((char *)&odh->query, 0, sizeof(u_int16_t));
967 f98bb34d 2011-09-19 pbug
968 f98bb34d 2011-09-19 pbug outlen += (q->hdr->namelen + 4);
969 f98bb34d 2011-09-19 pbug
970 f98bb34d 2011-09-19 pbug SET_DNS_REPLY(odh);
971 f98bb34d 2011-09-19 pbug SET_DNS_AUTHORITATIVE(odh);
972 f98bb34d 2011-09-19 pbug
973 f98bb34d 2011-09-19 pbug NTOHS(odh->query);
974 f98bb34d 2011-09-19 pbug
975 f98bb34d 2011-09-19 pbug odh->question = htons(1);
976 f98bb34d 2011-09-19 pbug odh->answer = htons(answercount);
977 f98bb34d 2011-09-19 pbug odh->nsrr = 0;
978 f98bb34d 2011-09-19 pbug odh->additional = 0;
979 f98bb34d 2011-09-19 pbug
980 f98bb34d 2011-09-19 pbug return (outlen);
981 f98bb34d 2011-09-19 pbug }
982 f98bb34d 2011-09-19 pbug
983 f98bb34d 2011-09-19 pbug
984 f98bb34d 2011-09-19 pbug
985 f98bb34d 2011-09-19 pbug /*
986 f98bb34d 2011-09-19 pbug * BUILD_SOA - build an SOA answer
987 f98bb34d 2011-09-19 pbug */
988 f98bb34d 2011-09-19 pbug
989 f98bb34d 2011-09-19 pbug int
990 f98bb34d 2011-09-19 pbug build_soa(DB *db, char *reply, int offset, struct domain *sd, struct question *q)
991 f98bb34d 2011-09-19 pbug {
992 f98bb34d 2011-09-19 pbug char *p;
993 f98bb34d 2011-09-19 pbug char *label;
994 f98bb34d 2011-09-19 pbug char *plabel;
995 f98bb34d 2011-09-19 pbug
996 f98bb34d 2011-09-19 pbug int labellen;
997 f98bb34d 2011-09-19 pbug int tmplen;
998 f98bb34d 2011-09-19 pbug u_int32_t *soa_val;
999 f98bb34d 2011-09-19 pbug
1000 f98bb34d 2011-09-19 pbug struct answer {
1001 f98bb34d 2011-09-19 pbug char name[2];
1002 f98bb34d 2011-09-19 pbug u_int16_t type;
1003 f98bb34d 2011-09-19 pbug u_int16_t class;
1004 f98bb34d 2011-09-19 pbug u_int32_t ttl;
1005 f98bb34d 2011-09-19 pbug u_int16_t rdlength; /* 12 */
1006 f98bb34d 2011-09-19 pbug char rdata;
1007 f98bb34d 2011-09-19 pbug } __attribute__((packed));
1008 f98bb34d 2011-09-19 pbug
1009 f98bb34d 2011-09-19 pbug struct answer *answer;
1010 f98bb34d 2011-09-19 pbug answer = (struct answer *)(&reply[offset]);
1011 f98bb34d 2011-09-19 pbug
1012 f98bb34d 2011-09-19 pbug answer->name[0] = 0xc0;
1013 f98bb34d 2011-09-19 pbug answer->name[1] = 0x0c;
1014 f98bb34d 2011-09-19 pbug answer->type = htons(DNS_TYPE_SOA);
1015 f98bb34d 2011-09-19 pbug answer->class = htons(DNS_CLASS_IN);
1016 f98bb34d 2011-09-19 pbug answer->ttl = htonl(sd->ttl);
1017 f98bb34d 2011-09-19 pbug
1018 f98bb34d 2011-09-19 pbug offset += 12; /* up to rdata length */
1019 f98bb34d 2011-09-19 pbug
1020 f98bb34d 2011-09-19 pbug p = (char *)&answer->rdata;
1021 f98bb34d 2011-09-19 pbug
1022 f98bb34d 2011-09-19 pbug
1023 f98bb34d 2011-09-19 pbug label = sd->soa.nsserver;
1024 f98bb34d 2011-09-19 pbug labellen = sd->soa.nsserver_len;
1025 f98bb34d 2011-09-19 pbug
1026 f98bb34d 2011-09-19 pbug plabel = label;
1027 f98bb34d 2011-09-19 pbug
1028 f98bb34d 2011-09-19 pbug if (offset + labellen <= 65535)
1029 f98bb34d 2011-09-19 pbug memcpy(&reply[offset], (char *)plabel, labellen);
1030 f98bb34d 2011-09-19 pbug else
1031 f98bb34d 2011-09-19 pbug return (offset); /* XXX */
1032 f98bb34d 2011-09-19 pbug
1033 f98bb34d 2011-09-19 pbug offset += labellen;
1034 f98bb34d 2011-09-19 pbug
1035 f98bb34d 2011-09-19 pbug /* compress the label if possible */
1036 f98bb34d 2011-09-19 pbug if ((tmplen = compress_label((u_char*)reply, offset, labellen)) > 0) {
1037 f98bb34d 2011-09-19 pbug offset = tmplen;
1038 f98bb34d 2011-09-19 pbug }
1039 f98bb34d 2011-09-19 pbug
1040 f98bb34d 2011-09-19 pbug label = sd->soa.responsible_person;
1041 f98bb34d 2011-09-19 pbug labellen = sd->soa.rp_len;
1042 f98bb34d 2011-09-19 pbug plabel = label;
1043 f98bb34d 2011-09-19 pbug
1044 f98bb34d 2011-09-19 pbug if (offset + labellen <= 65535)
1045 f98bb34d 2011-09-19 pbug memcpy(&reply[offset], (char *)plabel, labellen);
1046 f98bb34d 2011-09-19 pbug else
1047 f98bb34d 2011-09-19 pbug return (offset); /* XXX */
1048 f98bb34d 2011-09-19 pbug
1049 f98bb34d 2011-09-19 pbug offset += labellen;
1050 f98bb34d 2011-09-19 pbug
1051 f98bb34d 2011-09-19 pbug /* 2 compress the label if possible */
1052 f98bb34d 2011-09-19 pbug
1053 f98bb34d 2011-09-19 pbug if ((tmplen = compress_label((u_char*)reply, offset, labellen)) > 0) {
1054 f98bb34d 2011-09-19 pbug offset = tmplen;
1055 f98bb34d 2011-09-19 pbug }
1056 f98bb34d 2011-09-19 pbug
1057 f98bb34d 2011-09-19 pbug
1058 f98bb34d 2011-09-19 pbug /* XXX */
1059 f98bb34d 2011-09-19 pbug if ((offset + sizeof(sd->soa.serial)) >= 65535 ) {
1060 f98bb34d 2011-09-19 pbug /* XXX server error reply? */
1061 f98bb34d 2011-09-19 pbug return (offset);
1062 f98bb34d 2011-09-19 pbug }
1063 f98bb34d 2011-09-19 pbug soa_val = (u_int32_t *)&reply[offset];
1064 f98bb34d 2011-09-19 pbug *soa_val = htonl(sd->soa.serial);
1065 f98bb34d 2011-09-19 pbug offset += sizeof(sd->soa.serial); /* XXX */
1066 f98bb34d 2011-09-19 pbug
1067 f98bb34d 2011-09-19 pbug /* XXX */
1068 f98bb34d 2011-09-19 pbug if ((offset + sizeof(sd->soa.refresh)) >= 65535 ) {
1069 f98bb34d 2011-09-19 pbug return (offset);
1070 f98bb34d 2011-09-19 pbug }
1071 f98bb34d 2011-09-19 pbug soa_val = (u_int32_t *)&reply[offset];
1072 f98bb34d 2011-09-19 pbug *soa_val = htonl(sd->soa.refresh);
1073 f98bb34d 2011-09-19 pbug offset += sizeof(sd->soa.refresh); /* XXX */
1074 f98bb34d 2011-09-19 pbug
1075 f98bb34d 2011-09-19 pbug if ((offset + sizeof(sd->soa.retry)) >= 65535 ) {
1076 f98bb34d 2011-09-19 pbug return (offset);
1077 f98bb34d 2011-09-19 pbug }
1078 f98bb34d 2011-09-19 pbug soa_val = (u_int32_t *)&reply[offset];
1079 f98bb34d 2011-09-19 pbug *soa_val = htonl(sd->soa.retry);
1080 f98bb34d 2011-09-19 pbug offset += sizeof(sd->soa.retry); /* XXX */
1081 f98bb34d 2011-09-19 pbug
1082 f98bb34d 2011-09-19 pbug if ((offset + sizeof(sd->soa.expire)) >= 65535 ) {
1083 f98bb34d 2011-09-19 pbug return (offset);
1084 f98bb34d 2011-09-19 pbug }
1085 f98bb34d 2011-09-19 pbug soa_val = (u_int32_t *)&reply[offset];
1086 f98bb34d 2011-09-19 pbug *soa_val = htonl(sd->soa.expire);
1087 f98bb34d 2011-09-19 pbug offset += sizeof(sd->soa.expire);
1088 f98bb34d 2011-09-19 pbug
1089 f98bb34d 2011-09-19 pbug if ((offset + sizeof(sd->soa.minttl)) > 65535 ) {
1090 f98bb34d 2011-09-19 pbug return (offset);
1091 f98bb34d 2011-09-19 pbug }
1092 f98bb34d 2011-09-19 pbug soa_val = (u_int32_t *)&reply[offset];
1093 f98bb34d 2011-09-19 pbug *soa_val = htonl(sd->soa.minttl);
1094 f98bb34d 2011-09-19 pbug offset += sizeof(sd->soa.minttl);
1095 f98bb34d 2011-09-19 pbug
1096 f98bb34d 2011-09-19 pbug answer->rdlength = htons(&reply[offset] - &answer->rdata);
1097 f98bb34d 2011-09-19 pbug
1098 f98bb34d 2011-09-19 pbug return (offset);
1099 f98bb34d 2011-09-19 pbug }
1100 f98bb34d 2011-09-19 pbug
1101 f98bb34d 2011-09-19 pbug int
1102 f98bb34d 2011-09-19 pbug checklabel(DB *db, struct domain *sd, struct domain *soa, struct question *q)
1103 f98bb34d 2011-09-19 pbug {
1104 f98bb34d 2011-09-19 pbug struct domain tmpsd;
1105 f98bb34d 2011-09-19 pbug char *p;
1106 f98bb34d 2011-09-19 pbug int plen, ret;
1107 f98bb34d 2011-09-19 pbug
1108 f98bb34d 2011-09-19 pbug DBT key, data;
1109 f98bb34d 2011-09-19 pbug
1110 f98bb34d 2011-09-19 pbug if (memcmp(sd, soa, sizeof(struct domain)) == 0)
1111 f98bb34d 2011-09-19 pbug return 1;
1112 f98bb34d 2011-09-19 pbug
1113 f98bb34d 2011-09-19 pbug p = sd->zone;
1114 f98bb34d 2011-09-19 pbug plen = sd->zonelen;
1115 f98bb34d 2011-09-19 pbug
1116 f98bb34d 2011-09-19 pbug do {
1117 f98bb34d 2011-09-19 pbug if (*p == '\0')
1118 f98bb34d 2011-09-19 pbug return (0);
1119 f98bb34d 2011-09-19 pbug
1120 f98bb34d 2011-09-19 pbug memset(&key, 0, sizeof(key));
1121 f98bb34d 2011-09-19 pbug memset(&data, 0, sizeof(data));
1122 f98bb34d 2011-09-19 pbug
1123 f98bb34d 2011-09-19 pbug key.data = (char *)p;
1124 f98bb34d 2011-09-19 pbug key.size = plen;
1125 f98bb34d 2011-09-19 pbug
1126 f98bb34d 2011-09-19 pbug data.data = NULL;
1127 f98bb34d 2011-09-19 pbug data.size = 0;
1128 f98bb34d 2011-09-19 pbug
1129 f98bb34d 2011-09-19 pbug ret = db->get(db, NULL, &key, &data, 0);
1130 f98bb34d 2011-09-19 pbug if (ret == DB_NOTFOUND) {
1131 f98bb34d 2011-09-19 pbug plen -= (*p + 1);
1132 f98bb34d 2011-09-19 pbug p = (p + (*p + 1));
1133 f98bb34d 2011-09-19 pbug
1134 f98bb34d 2011-09-19 pbug continue;
1135 f98bb34d 2011-09-19 pbug }
1136 f98bb34d 2011-09-19 pbug
1137 f98bb34d 2011-09-19 pbug if (data.size != sizeof(struct domain)) {
1138 dd869383 2013-02-16 pjp dolog(LOG_INFO, "AXFR btree db is damaged (%d), drop\n", __LINE__);
1139 f98bb34d 2011-09-19 pbug return (0);
1140 f98bb34d 2011-09-19 pbug }
1141 f98bb34d 2011-09-19 pbug
1142 f98bb34d 2011-09-19 pbug memcpy(&tmpsd, data.data, sizeof(tmpsd));
1143 f98bb34d 2011-09-19 pbug
1144 f98bb34d 2011-09-19 pbug /*
1145 f98bb34d 2011-09-19 pbug * the encountered label has an SOA before we got to the
1146 f98bb34d 2011-09-19 pbug * root, so we skip this record entirely...
1147 f98bb34d 2011-09-19 pbug */
1148 f98bb34d 2011-09-19 pbug
1149 f98bb34d 2011-09-19 pbug if (tmpsd.flags & DOMAIN_HAVE_SOA)
1150 f98bb34d 2011-09-19 pbug return (0);
1151 f98bb34d 2011-09-19 pbug
1152 f98bb34d 2011-09-19 pbug
1153 f98bb34d 2011-09-19 pbug /*
1154 f98bb34d 2011-09-19 pbug * and check the next label...
1155 f98bb34d 2011-09-19 pbug */
1156 f98bb34d 2011-09-19 pbug
1157 f98bb34d 2011-09-19 pbug plen -= (*p + 1);
1158 f98bb34d 2011-09-19 pbug p = (p + (*p + 1));
1159 f98bb34d 2011-09-19 pbug
1160 f98bb34d 2011-09-19 pbug
1161 f98bb34d 2011-09-19 pbug } while (memcmp(p, q->hdr->name, q->hdr->namelen) != 0);
1162 f98bb34d 2011-09-19 pbug
1163 f98bb34d 2011-09-19 pbug
1164 f98bb34d 2011-09-19 pbug return (1);
1165 f98bb34d 2011-09-19 pbug }
1166 58eafea4 2014-05-17 pjp
1167 58eafea4 2014-05-17 pjp void
1168 58eafea4 2014-05-17 pjp gather_notifydomains(DB *db)
1169 58eafea4 2014-05-17 pjp {
1170 58eafea4 2014-05-17 pjp DBT key, data;
1171 58eafea4 2014-05-17 pjp DBC *cursor;
1172 58eafea4 2014-05-17 pjp
1173 58eafea4 2014-05-17 pjp time_t now, soatime;
1174 58eafea4 2014-05-17 pjp struct tm *tm;
1175 58eafea4 2014-05-17 pjp
1176 58eafea4 2014-05-17 pjp char timestring[128];
1177 58eafea4 2014-05-17 pjp char buf[128];
1178 58eafea4 2014-05-17 pjp
1179 58eafea4 2014-05-17 pjp struct domain *sd;
1180 58eafea4 2014-05-17 pjp
1181 58eafea4 2014-05-17 pjp
1182 58eafea4 2014-05-17 pjp SLIST_INIT(&notifyhead);
1183 58eafea4 2014-05-17 pjp
1184 58eafea4 2014-05-17 pjp now = time(NULL);
1185 58eafea4 2014-05-17 pjp tm = localtime(&now);
1186 58eafea4 2014-05-17 pjp if (tm != NULL)
1187 58eafea4 2014-05-17 pjp strftime(timestring, sizeof(timestring), "%Y%m%d", tm);
1188 58eafea4 2014-05-17 pjp else
1189 58eafea4 2014-05-17 pjp snprintf(timestring, sizeof(timestring), "19700101");
1190 58eafea4 2014-05-17 pjp
1191 58eafea4 2014-05-17 pjp now = time(NULL);
1192 58eafea4 2014-05-17 pjp
1193 58eafea4 2014-05-17 pjp if (db->cursor(db, NULL, &cursor, 0) != 0) {
1194 58eafea4 2014-05-17 pjp dolog(LOG_INFO, "db->cursor: %s\n", strerror(errno));
1195 58eafea4 2014-05-17 pjp return;
1196 58eafea4 2014-05-17 pjp }
1197 58eafea4 2014-05-17 pjp
1198 58eafea4 2014-05-17 pjp memset(&key, 0, sizeof(key));
1199 58eafea4 2014-05-17 pjp memset(&data, 0, sizeof(data));
1200 58eafea4 2014-05-17 pjp
1201 58eafea4 2014-05-17 pjp
1202 58eafea4 2014-05-17 pjp if (cursor->c_get(cursor, &key, &data, DB_FIRST) != 0) {
1203 58eafea4 2014-05-17 pjp dolog(LOG_INFO, "cursor->c_get: %s\n", strerror(errno));
1204 58eafea4 2014-05-17 pjp cursor->c_close(cursor);
1205 58eafea4 2014-05-17 pjp return;
1206 58eafea4 2014-05-17 pjp }
1207 58eafea4 2014-05-17 pjp
1208 58eafea4 2014-05-17 pjp do {
1209 58eafea4 2014-05-17 pjp if (data.size != sizeof(struct domain)) {
1210 58eafea4 2014-05-17 pjp dolog(LOG_INFO, "btree db is damaged\n");
1211 58eafea4 2014-05-17 pjp cursor->c_close(cursor);
1212 58eafea4 2014-05-17 pjp return;
1213 58eafea4 2014-05-17 pjp }
1214 58eafea4 2014-05-17 pjp
1215 58eafea4 2014-05-17 pjp sd = (struct domain *)data.data;
1216 58eafea4 2014-05-17 pjp
1217 58eafea4 2014-05-17 pjp if ((sd->flags & DOMAIN_HAVE_SOA) == DOMAIN_HAVE_SOA) {
1218 58eafea4 2014-05-17 pjp notn2 = malloc(sizeof(struct notifyentry));
1219 58eafea4 2014-05-17 pjp if (notn2 == NULL) {
1220 58eafea4 2014-05-17 pjp continue;
1221 58eafea4 2014-05-17 pjp }
1222 58eafea4 2014-05-17 pjp
1223 58eafea4 2014-05-17 pjp notn2->ids = calloc(notify, sizeof(u_int16_t));
1224 58eafea4 2014-05-17 pjp if (notn2->ids == NULL) {
1225 58eafea4 2014-05-17 pjp free(notn2);
1226 58eafea4 2014-05-17 pjp continue;
1227 58eafea4 2014-05-17 pjp }
1228 58eafea4 2014-05-17 pjp
1229 58eafea4 2014-05-17 pjp notn2->attempts = calloc(notify, sizeof(u_int16_t));
1230 58eafea4 2014-05-17 pjp if (notn2->attempts == NULL) {
1231 58eafea4 2014-05-17 pjp free(notn2);
1232 58eafea4 2014-05-17 pjp continue;
1233 58eafea4 2014-05-17 pjp }
1234 58eafea4 2014-05-17 pjp
1235 58eafea4 2014-05-17 pjp memcpy(notn2->domain, sd->zone, sd->zonelen);
1236 58eafea4 2014-05-17 pjp notn2->domainlen = sd->zonelen;
1237 58eafea4 2014-05-17 pjp
1238 58eafea4 2014-05-17 pjp soatime = (time_t)sd->soa.serial;
1239 58eafea4 2014-05-17 pjp snprintf(buf, sizeof(buf), "%u", sd->soa.serial);
1240 58eafea4 2014-05-17 pjp
1241 58eafea4 2014-05-17 pjp if (strncmp(buf, timestring, strlen(timestring)) == 0) {
1242 58eafea4 2014-05-17 pjp dolog(LOG_INFO, "inserting zone \"%s\" for notification...\n", sd->zonename);
1243 58eafea4 2014-05-17 pjp SLIST_INSERT_HEAD(&notifyhead, notn2, notify_entry);
1244 58eafea4 2014-05-17 pjp } else if (difftime(now, soatime) < 1800 && difftime(now, soatime) > 0) {
1245 58eafea4 2014-05-17 pjp dolog(LOG_INFO, "2 inserting zone \"%s\" for notification...\n", sd->zonename);
1246 58eafea4 2014-05-17 pjp SLIST_INSERT_HEAD(&notifyhead, notn2, notify_entry);
1247 58eafea4 2014-05-17 pjp } else {
1248 58eafea4 2014-05-17 pjp #if 0
1249 58eafea4 2014-05-17 pjp dolog(LOG_INFO, "SOA serial for zone \"%s\" did not make sense (%s), not notifying\n", sd->zonename, buf);
1250 58eafea4 2014-05-17 pjp #endif
1251 58eafea4 2014-05-17 pjp free(notn2);
1252 58eafea4 2014-05-17 pjp }
1253 58eafea4 2014-05-17 pjp }
1254 58eafea4 2014-05-17 pjp
1255 58eafea4 2014-05-17 pjp memset(&key, 0, sizeof(key));
1256 58eafea4 2014-05-17 pjp memset(&data, 0, sizeof(data));
1257 58eafea4 2014-05-17 pjp } while (cursor->c_get(cursor, &key, &data, DB_NEXT) == 0);
1258 58eafea4 2014-05-17 pjp
1259 58eafea4 2014-05-17 pjp cursor->c_close(cursor);
1260 58eafea4 2014-05-17 pjp
1261 58eafea4 2014-05-17 pjp return;
1262 58eafea4 2014-05-17 pjp }
1263 58eafea4 2014-05-17 pjp
1264 58eafea4 2014-05-17 pjp void
1265 58eafea4 2014-05-17 pjp notifyslaves(int *notifyfd)
1266 58eafea4 2014-05-17 pjp {
1267 58eafea4 2014-05-17 pjp int so;
1268 58eafea4 2014-05-17 pjp int i;
1269 58eafea4 2014-05-17 pjp
1270 58eafea4 2014-05-17 pjp i = 0;
1271 58eafea4 2014-05-17 pjp SLIST_FOREACH(nfslnp, &notifyslavehead, notifyslave_entry) {
1272 58eafea4 2014-05-17 pjp if (nfslnp->family == AF_INET6) {
1273 58eafea4 2014-05-17 pjp so = notifyfd[1];
1274 58eafea4 2014-05-17 pjp } else {
1275 58eafea4 2014-05-17 pjp so = notifyfd[0];
1276 58eafea4 2014-05-17 pjp }
1277 58eafea4 2014-05-17 pjp #if 0
1278 58eafea4 2014-05-17 pjp dolog(LOG_INFO, "notifying %s...\n", nfslnp->name);
1279 58eafea4 2014-05-17 pjp #endif
1280 58eafea4 2014-05-17 pjp
1281 05b37e84 2014-05-18 pjp #ifdef __linux__
1282 05b37e84 2014-05-18 pjp SLIST_FOREACH(notnp, &notifyhead, notify_entry) {
1283 05b37e84 2014-05-18 pjp #else
1284 58eafea4 2014-05-17 pjp SLIST_FOREACH_SAFE(notnp, &notifyhead, notify_entry, notn2) {
1285 05b37e84 2014-05-18 pjp #endif
1286 58eafea4 2014-05-17 pjp notnp->ids[i] = arc4random() & 0xffff;
1287 58eafea4 2014-05-17 pjp notnp->attempts[i]++;
1288 58eafea4 2014-05-17 pjp if (notnp->attempts[i] > 10) {
1289 58eafea4 2014-05-17 pjp dolog(LOG_INFO, "notify entry removed due to timeout\n");
1290 58eafea4 2014-05-17 pjp SLIST_REMOVE(&notifyhead, notnp, notifyentry, notify_entry);
1291 58eafea4 2014-05-17 pjp }
1292 58eafea4 2014-05-17 pjp
1293 58eafea4 2014-05-17 pjp notifypacket(so, nfslnp, notnp, i);
1294 58eafea4 2014-05-17 pjp }
1295 58eafea4 2014-05-17 pjp
1296 58eafea4 2014-05-17 pjp i++;
1297 58eafea4 2014-05-17 pjp }
1298 58eafea4 2014-05-17 pjp
1299 58eafea4 2014-05-17 pjp return;
1300 58eafea4 2014-05-17 pjp }
1301 58eafea4 2014-05-17 pjp
1302 58eafea4 2014-05-17 pjp void
1303 58eafea4 2014-05-17 pjp notifypacket(int so, void *vnse, void *vnotnp, int packetcount)
1304 58eafea4 2014-05-17 pjp {
1305 58eafea4 2014-05-17 pjp struct notifyslaveentry *nse = (struct notifyslaveentry *)vnse;
1306 58eafea4 2014-05-17 pjp struct notifyentry *notnp = (struct notifyentry *)vnotnp;
1307 58eafea4 2014-05-17 pjp struct sockaddr_in bsin, *sin;
1308 58eafea4 2014-05-17 pjp struct sockaddr_in6 bsin6, *sin6;
1309 58eafea4 2014-05-17 pjp char packet[512];
1310 58eafea4 2014-05-17 pjp char *questionname;
1311 58eafea4 2014-05-17 pjp u_int16_t *classtype;
1312 58eafea4 2014-05-17 pjp struct dns_header *dnh;
1313 58eafea4 2014-05-17 pjp int outlen = 0, slen, ret;
1314 58eafea4 2014-05-17 pjp
1315 58eafea4 2014-05-17 pjp memset(&packet, 0, sizeof(packet));
1316 58eafea4 2014-05-17 pjp dnh = (struct dns_header *)&packet[0];
1317 58eafea4 2014-05-17 pjp
1318 58eafea4 2014-05-17 pjp dnh->id = htons(notnp->ids[packetcount]);
1319 58eafea4 2014-05-17 pjp SET_DNS_NOTIFY(dnh);
1320 58eafea4 2014-05-17 pjp SET_DNS_AUTHORITATIVE(dnh);
1321 58eafea4 2014-05-17 pjp SET_DNS_QUERY(dnh);
1322 58eafea4 2014-05-17 pjp HTONS(dnh->query);
1323 58eafea4 2014-05-17 pjp
1324 58eafea4 2014-05-17 pjp dnh->question = htons(1);
1325 58eafea4 2014-05-17 pjp
1326 58eafea4 2014-05-17 pjp outlen += sizeof(struct dns_header);
1327 58eafea4 2014-05-17 pjp questionname = (char *)&packet[outlen];
1328 58eafea4 2014-05-17 pjp
1329 58eafea4 2014-05-17 pjp memcpy(questionname, notnp->domain, notnp->domainlen);
1330 58eafea4 2014-05-17 pjp outlen += notnp->domainlen;
1331 58eafea4 2014-05-17 pjp
1332 58eafea4 2014-05-17 pjp classtype = (u_int16_t *)&packet[outlen];
1333 58eafea4 2014-05-17 pjp classtype[0] = htons(DNS_TYPE_SOA);
1334 58eafea4 2014-05-17 pjp classtype[1] = htons(DNS_CLASS_IN);
1335 58eafea4 2014-05-17 pjp
1336 58eafea4 2014-05-17 pjp outlen += (2 * sizeof(u_int16_t));
1337 58eafea4 2014-05-17 pjp
1338 58eafea4 2014-05-17 pjp if (nse->family == AF_INET) {
1339 58eafea4 2014-05-17 pjp slen = sizeof(struct sockaddr_in);
1340 58eafea4 2014-05-17 pjp sin = (struct sockaddr_in *)&nse->hostmask;
1341 58eafea4 2014-05-17 pjp memset(&bsin, 0, sizeof(bsin));
1342 58eafea4 2014-05-17 pjp bsin.sin_family = AF_INET;
1343 58eafea4 2014-05-17 pjp bsin.sin_port = htons(53);
1344 58eafea4 2014-05-17 pjp bsin.sin_addr.s_addr = sin->sin_addr.s_addr;
1345 58eafea4 2014-05-17 pjp
1346 58eafea4 2014-05-17 pjp ret = sendto(so, packet, outlen, 0, (struct sockaddr *)&bsin, slen);
1347 58eafea4 2014-05-17 pjp } else {
1348 58eafea4 2014-05-17 pjp slen = sizeof(struct sockaddr_in6);
1349 58eafea4 2014-05-17 pjp sin6 = (struct sockaddr_in6 *)&nse->hostmask;
1350 58eafea4 2014-05-17 pjp memset(&bsin6, 0, sizeof(bsin6));
1351 58eafea4 2014-05-17 pjp bsin6.sin6_family = AF_INET6;
1352 58eafea4 2014-05-17 pjp bsin6.sin6_port = htons(53);
1353 58eafea4 2014-05-17 pjp memcpy(&bsin6.sin6_addr, &sin6->sin6_addr, 16);
1354 58eafea4 2014-05-17 pjp
1355 58eafea4 2014-05-17 pjp ret = sendto(so, packet, outlen, 0, (struct sockaddr *)sin6, slen);
1356 58eafea4 2014-05-17 pjp }
1357 58eafea4 2014-05-17 pjp
1358 58eafea4 2014-05-17 pjp if (ret < 0) {
1359 58eafea4 2014-05-17 pjp dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
1360 58eafea4 2014-05-17 pjp }
1361 58eafea4 2014-05-17 pjp
1362 58eafea4 2014-05-17 pjp return;
1363 58eafea4 2014-05-17 pjp }