blob: 5454d3134acfdd875d47398dfb4a19e803838923 [file] [log] [blame]
Simon Kelley61744352013-01-31 14:34:40 +00001/* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
Simon Kelley824af852008-02-12 20:43:05 +00005 the Free Software Foundation; version 2 dated June, 1991, or
6 (at your option) version 3 dated 29 June, 2007.
7
Simon Kelley9e4abcb2004-01-22 19:47:41 +00008 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
Simon Kelley824af852008-02-12 20:43:05 +000012
Simon Kelley73a08a22009-02-05 20:28:08 +000013 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>.
Simon Kelley9e4abcb2004-01-22 19:47:41 +000015*/
16
Simon Kelley9e4abcb2004-01-22 19:47:41 +000017#include "dnsmasq.h"
18
Simon Kelleydc27e142013-10-16 13:09:53 +010019#ifndef IN6_IS_ADDR_ULA
20#define IN6_IS_ADDR_ULA(a) ((((__const uint32_t *) (a))[0] & htonl (0xfe00000)) == htonl (0xfc000000))
21#endif
22
Simon Kelley7622fc02009-06-04 20:32:05 +010023#ifdef HAVE_LINUX_NETWORK
24
25int indextoname(int fd, int index, char *name)
26{
27 struct ifreq ifr;
28
29 if (index == 0)
30 return 0;
31
32 ifr.ifr_ifindex = index;
33 if (ioctl(fd, SIOCGIFNAME, &ifr) == -1)
34 return 0;
35
36 strncpy(name, ifr.ifr_name, IF_NAMESIZE);
37
38 return 1;
39}
40
Simon Kelley28866e92011-02-14 20:19:14 +000041
42#elif defined(HAVE_SOLARIS_NETWORK)
43
44#include <zone.h>
45#include <alloca.h>
46#ifndef LIFC_UNDER_IPMP
47# define LIFC_UNDER_IPMP 0
48#endif
49
50int indextoname(int fd, int index, char *name)
51{
52 int64_t lifc_flags;
53 struct lifnum lifn;
54 int numifs, bufsize, i;
55 struct lifconf lifc;
56 struct lifreq *lifrp;
57
58 if (index == 0)
59 return 0;
60
61 if (getzoneid() == GLOBAL_ZONEID)
62 {
63 if (!if_indextoname(index, name))
64 return 0;
65 return 1;
66 }
67
68 lifc_flags = LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES | LIFC_UNDER_IPMP;
69 lifn.lifn_family = AF_UNSPEC;
70 lifn.lifn_flags = lifc_flags;
71 if (ioctl(fd, SIOCGLIFNUM, &lifn) < 0)
72 return 0;
73
74 numifs = lifn.lifn_count;
75 bufsize = numifs * sizeof(struct lifreq);
76
77 lifc.lifc_family = AF_UNSPEC;
78 lifc.lifc_flags = lifc_flags;
79 lifc.lifc_len = bufsize;
80 lifc.lifc_buf = alloca(bufsize);
81
82 if (ioctl(fd, SIOCGLIFCONF, &lifc) < 0)
83 return 0;
84
85 lifrp = lifc.lifc_req;
86 for (i = lifc.lifc_len / sizeof(struct lifreq); i; i--, lifrp++)
87 {
88 struct lifreq lifr;
89 strncpy(lifr.lifr_name, lifrp->lifr_name, IF_NAMESIZE);
90 if (ioctl(fd, SIOCGLIFINDEX, &lifr) < 0)
91 return 0;
92
93 if (lifr.lifr_index == index) {
94 strncpy(name, lifr.lifr_name, IF_NAMESIZE);
95 return 1;
96 }
97 }
98 return 0;
99}
100
101
Simon Kelley7622fc02009-06-04 20:32:05 +0100102#else
103
104int indextoname(int fd, int index, char *name)
105{
Simon Kelley115ac3e2013-05-20 11:28:32 +0100106 (void)fd;
107
Simon Kelley7622fc02009-06-04 20:32:05 +0100108 if (index == 0 || !if_indextoname(index, name))
109 return 0;
110
111 return 1;
112}
113
114#endif
115
Simon Kelley4f7b3042012-11-28 21:27:02 +0000116int iface_check(int family, struct all_addr *addr, char *name, int *auth)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000117{
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000118 struct iname *tmp;
Simon Kelleyedf0bde2013-07-29 17:21:48 +0100119 int ret = 1, match_addr = 0;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100120
Simon Kelley309331f2006-04-22 15:05:01 +0100121 /* Note: have to check all and not bail out early, so that we set the
Simon Kelley89500e32013-09-20 16:29:20 +0100122 "used" flags.
123
124 May be called with family == AF_LOCALto check interface by name only. */
Simon Kelley429798f2012-12-10 20:45:53 +0000125
Simon Kelley4f7b3042012-11-28 21:27:02 +0000126 if (auth)
Simon Kelley429798f2012-12-10 20:45:53 +0000127 *auth = 0;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100128
Simon Kelleyc72daea2012-01-05 21:33:27 +0000129 if (daemon->if_names || daemon->if_addrs)
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100130 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100131 ret = 0;
132
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100133 for (tmp = daemon->if_names; tmp; tmp = tmp->next)
Simon Kelley49333cb2013-03-15 20:30:51 +0000134 if (tmp->name && wildcard_match(tmp->name, name))
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100135 ret = tmp->used = 1;
136
Simon Kelley429798f2012-12-10 20:45:53 +0000137 if (addr)
138 for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
139 if (tmp->addr.sa.sa_family == family)
140 {
141 if (family == AF_INET &&
142 tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
Simon Kelleyedf0bde2013-07-29 17:21:48 +0100143 ret = match_addr = tmp->used = 1;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100144#ifdef HAVE_IPV6
Simon Kelley429798f2012-12-10 20:45:53 +0000145 else if (family == AF_INET6 &&
146 IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr,
147 &addr->addr.addr6))
Simon Kelleyedf0bde2013-07-29 17:21:48 +0100148 ret = match_addr = tmp->used = 1;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100149#endif
Simon Kelley429798f2012-12-10 20:45:53 +0000150 }
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100151 }
152
Simon Kelleyedf0bde2013-07-29 17:21:48 +0100153 if (!match_addr)
154 for (tmp = daemon->if_except; tmp; tmp = tmp->next)
155 if (tmp->name && wildcard_match(tmp->name, name))
156 ret = 0;
Simon Kelleyc72daea2012-01-05 21:33:27 +0000157
Simon Kelley429798f2012-12-10 20:45:53 +0000158
159 for (tmp = daemon->authinterface; tmp; tmp = tmp->next)
160 if (tmp->name)
161 {
Simon Kelleyf25e6c62013-11-17 12:23:42 +0000162 if (strcmp(tmp->name, name) == 0 &&
163 (tmp->addr.sa.sa_family == 0 || tmp->addr.sa.sa_family == family))
Simon Kelley429798f2012-12-10 20:45:53 +0000164 break;
165 }
166 else if (addr && tmp->addr.sa.sa_family == AF_INET && family == AF_INET &&
167 tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
168 break;
169#ifdef HAVE_IPV6
170 else if (addr && tmp->addr.sa.sa_family == AF_INET6 && family == AF_INET6 &&
171 IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, &addr->addr.addr6))
172 break;
173#endif
174
175 if (tmp && auth)
176 {
177 *auth = 1;
178 ret = 1;
179 }
180
Simon Kelley309331f2006-04-22 15:05:01 +0100181 return ret;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100182}
Simon Kelleye25db1f2013-01-29 22:10:26 +0000183
184
185/* Fix for problem that the kernel sometimes reports the loopback inerface as the
186 arrival interface when a packet originates locally, even when sent to address of
187 an interface other than the loopback. Accept packet if it arrived via a loopback
188 interface, even when we're not accepting packets that way, as long as the destination
189 address is one we're believing. Interface list must be up-to-date before calling. */
190int loopback_exception(int fd, int family, struct all_addr *addr, char *name)
191{
192 struct ifreq ifr;
193 struct irec *iface;
194
195 strncpy(ifr.ifr_name, name, IF_NAMESIZE);
196 if (ioctl(fd, SIOCGIFFLAGS, &ifr) != -1 &&
197 ifr.ifr_flags & IFF_LOOPBACK)
198 {
199 for (iface = daemon->interfaces; iface; iface = iface->next)
200 if (iface->addr.sa.sa_family == family)
201 {
202 if (family == AF_INET)
203 {
204 if (iface->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
205 return 1;
206 }
207#ifdef HAVE_IPV6
208 else if (IN6_ARE_ADDR_EQUAL(&iface->addr.in6.sin6_addr, &addr->addr.addr6))
209 return 1;
210#endif
211
212 }
213 }
214 return 0;
215}
216
Simon Kelley3f2873d2013-05-14 11:28:47 +0100217/* If we're configured with something like --interface=eth0:0 then we'll listen correctly
218 on the relevant address, but the name of the arrival interface, derived from the
219 index won't match the config. Check that we found an interface address for the arrival
220 interface: daemon->interfaces must be up-to-date. */
221int label_exception(int index, int family, struct all_addr *addr)
222{
223 struct irec *iface;
224
225 /* labels only supported on IPv4 addresses. */
226 if (family != AF_INET)
227 return 0;
228
229 for (iface = daemon->interfaces; iface; iface = iface->next)
230 if (iface->index == index && iface->addr.sa.sa_family == AF_INET &&
231 iface->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
232 return 1;
233
234 return 0;
235}
236
Simon Kelley115ac3e2013-05-20 11:28:32 +0100237struct iface_param {
238 struct addrlist *spare;
239 int fd;
240};
241
242static int iface_allowed(struct iface_param *param, int if_index, char *label,
Simon Kelley376d48c2013-11-13 13:04:30 +0000243 union mysockaddr *addr, struct in_addr netmask, int prefixlen, int dad)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100244{
245 struct irec *iface;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100246 int mtu = 0, loopback;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100247 struct ifreq ifr;
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100248 int tftp_ok = !!option_bool(OPT_TFTP);
Simon Kelley9380ba72012-04-16 14:41:56 +0100249 int dhcp_ok = 1;
Simon Kelley4f7b3042012-11-28 21:27:02 +0000250 int auth_dns = 0;
Simon Kelley91543f42013-09-23 12:41:20 +0100251#if defined(HAVE_DHCP) || defined(HAVE_TFTP)
Simon Kelley832af0b2007-01-21 20:01:28 +0000252 struct iname *tmp;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100253#endif
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100254
Simon Kelley115ac3e2013-05-20 11:28:32 +0100255 if (!indextoname(param->fd, if_index, ifr.ifr_name) ||
256 ioctl(param->fd, SIOCGIFFLAGS, &ifr) == -1)
257 return 0;
Simon Kelley1f15b812009-10-13 17:49:32 +0100258
259 loopback = ifr.ifr_flags & IFF_LOOPBACK;
Simon Kelley9380ba72012-04-16 14:41:56 +0100260
261 if (loopback)
Simon Kelley3f2873d2013-05-14 11:28:47 +0100262 dhcp_ok = 0;
263
Simon Kelley115ac3e2013-05-20 11:28:32 +0100264 if (ioctl(param->fd, SIOCGIFMTU, &ifr) != -1)
Simon Kelley1f15b812009-10-13 17:49:32 +0100265 mtu = ifr.ifr_mtu;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100266
Simon Kelley115ac3e2013-05-20 11:28:32 +0100267 if (!label)
268 label = ifr.ifr_name;
269
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000270
Simon Kelley115ac3e2013-05-20 11:28:32 +0100271#ifdef HAVE_IPV6
272 if (addr->sa.sa_family != AF_INET6 || !IN6_IS_ADDR_LINKLOCAL(&addr->in6.sin6_addr))
273#endif
274 {
275 struct interface_name *int_name;
276 struct addrlist *al;
Simon Kelley376d48c2013-11-13 13:04:30 +0000277#ifdef HAVE_AUTH
278 struct auth_zone *zone;
279 struct auth_name_list *name;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100280
Simon Kelley376d48c2013-11-13 13:04:30 +0000281 /* Find subnets in auth_zones */
282 for (zone = daemon->auth_zones; zone; zone = zone->next)
283 for (name = zone->interface_names; name; name = name->next)
284 if (wildcard_match(name->name, label))
285 {
286 if (addr->sa.sa_family == AF_INET && (name->flags & AUTH4))
287 {
288 if (param->spare)
289 {
290 al = param->spare;
291 param->spare = al->next;
292 }
293 else
294 al = whine_malloc(sizeof(struct addrlist));
295
296 if (al)
297 {
298 al->next = zone->subnet;
299 zone->subnet = al;
300 al->prefixlen = prefixlen;
301 al->addr.addr.addr4 = addr->in.sin_addr;
302 al->flags = 0;
303 }
304 }
305
306#ifdef HAVE_IPV6
307 if (addr->sa.sa_family == AF_INET6 && (name->flags & AUTH6))
308 {
309 if (param->spare)
310 {
311 al = param->spare;
312 param->spare = al->next;
313 }
314 else
315 al = whine_malloc(sizeof(struct addrlist));
316
317 if (al)
318 {
319 al->next = zone->subnet;
320 zone->subnet = al;
321 al->prefixlen = prefixlen;al->addr.addr.addr6 = addr->in6.sin6_addr;
322 al->flags = ADDRLIST_IPV6;
323 }
324 }
325#endif
326
327 }
328#endif
329
330 /* Update addresses from interface_names. These are a set independent
331 of the set we're listening on. */
Simon Kelley115ac3e2013-05-20 11:28:32 +0100332 for (int_name = daemon->int_names; int_name; int_name = int_name->next)
Simon Kelleyf7029f52013-11-21 15:09:09 +0000333 if (strncmp(label, int_name->intr, IF_NAMESIZE) == 0 &&
334 (addr->sa.sa_family == int_name->family || int_name->family == 0))
Simon Kelley115ac3e2013-05-20 11:28:32 +0100335 {
336 if (param->spare)
337 {
338 al = param->spare;
339 param->spare = al->next;
340 }
341 else
342 al = whine_malloc(sizeof(struct addrlist));
343
344 if (al)
345 {
Simon Kelley376d48c2013-11-13 13:04:30 +0000346 al->next = int_name->addr;
347 int_name->addr = al;
348
Simon Kelley115ac3e2013-05-20 11:28:32 +0100349 if (addr->sa.sa_family == AF_INET)
350 {
351 al->addr.addr.addr4 = addr->in.sin_addr;
Simon Kelley376d48c2013-11-13 13:04:30 +0000352 al->flags = 0;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100353 }
354#ifdef HAVE_IPV6
355 else
356 {
357 al->addr.addr.addr6 = addr->in6.sin6_addr;
Simon Kelley376d48c2013-11-13 13:04:30 +0000358 al->flags = ADDRLIST_IPV6;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100359 }
360#endif
361 }
362 }
363 }
364
365 /* check whether the interface IP has been added already
366 we call this routine multiple times. */
367 for (iface = daemon->interfaces; iface; iface = iface->next)
368 if (sockaddr_isequal(&iface->addr, addr))
369 {
370 iface->dad = dad;
371 return 1;
372 }
373
374 /* If we are restricting the set of interfaces to use, make
Simon Kelley59353a62004-11-21 19:34:28 +0000375 sure that loopback interfaces are in that set. */
Simon Kelley1f15b812009-10-13 17:49:32 +0100376 if (daemon->if_names && loopback)
Simon Kelley59353a62004-11-21 19:34:28 +0000377 {
378 struct iname *lo;
379 for (lo = daemon->if_names; lo; lo = lo->next)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100380 if (lo->name && strcmp(lo->name, ifr.ifr_name) == 0)
Simon Kelley4ce4f372012-06-14 11:50:45 +0100381 break;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100382
Simon Kelley38365ff2013-02-05 14:35:54 +0000383 if (!lo && (lo = whine_malloc(sizeof(struct iname))))
Simon Kelley59353a62004-11-21 19:34:28 +0000384 {
Simon Kelley38365ff2013-02-05 14:35:54 +0000385 if ((lo->name = whine_malloc(strlen(ifr.ifr_name)+1)))
386 {
387 strcpy(lo->name, ifr.ifr_name);
388 lo->used = 1;
389 lo->next = daemon->if_names;
390 daemon->if_names = lo;
391 }
392 else
393 free(lo);
Simon Kelley59353a62004-11-21 19:34:28 +0000394 }
395 }
396
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100397 if (addr->sa.sa_family == AF_INET &&
Simon Kelley3f2873d2013-05-14 11:28:47 +0100398 !iface_check(AF_INET, (struct all_addr *)&addr->in.sin_addr, label, &auth_dns))
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100399 return 1;
Simon Kelley4f7b3042012-11-28 21:27:02 +0000400
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100401#ifdef HAVE_IPV6
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100402 if (addr->sa.sa_family == AF_INET6 &&
Simon Kelley3f2873d2013-05-14 11:28:47 +0100403 !iface_check(AF_INET6, (struct all_addr *)&addr->in6.sin6_addr, label, &auth_dns))
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100404 return 1;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100405#endif
Simon Kelley4f7b3042012-11-28 21:27:02 +0000406
407#ifdef HAVE_DHCP
408 /* No DHCP where we're doing auth DNS. */
409 if (auth_dns)
410 {
411 tftp_ok = 0;
412 dhcp_ok = 0;
413 }
414 else
415 for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
Simon Kelley49333cb2013-03-15 20:30:51 +0000416 if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
Simon Kelley4f7b3042012-11-28 21:27:02 +0000417 {
418 tftp_ok = 0;
419 dhcp_ok = 0;
420 }
421#endif
422
Simon Kelley2937f8a2013-07-29 19:49:07 +0100423
Simon Kelley91543f42013-09-23 12:41:20 +0100424#ifdef HAVE_TFTP
Simon Kelley2937f8a2013-07-29 19:49:07 +0100425 if (daemon->tftp_interfaces)
426 {
427 /* dedicated tftp interface list */
428 tftp_ok = 0;
429 for (tmp = daemon->tftp_interfaces; tmp; tmp = tmp->next)
430 if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
431 tftp_ok = 1;
432 }
Simon Kelley91543f42013-09-23 12:41:20 +0100433#endif
Simon Kelley2937f8a2013-07-29 19:49:07 +0100434
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100435 /* add to list */
Simon Kelley5aabfc72007-08-29 11:24:47 +0100436 if ((iface = whine_malloc(sizeof(struct irec))))
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100437 {
438 iface->addr = *addr;
439 iface->netmask = netmask;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100440 iface->tftp_ok = tftp_ok;
Simon Kelley9380ba72012-04-16 14:41:56 +0100441 iface->dhcp_ok = dhcp_ok;
Simon Kelley4f7b3042012-11-28 21:27:02 +0000442 iface->dns_auth = auth_dns;
Simon Kelley1f15b812009-10-13 17:49:32 +0100443 iface->mtu = mtu;
Simon Kelley74c95c22011-10-19 09:33:39 +0100444 iface->dad = dad;
Simon Kelleydc27e142013-10-16 13:09:53 +0100445 iface->done = iface->multicast_done = iface->warned = 0;
Simon Kelley5d162f22012-12-20 14:55:46 +0000446 iface->index = if_index;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100447 if ((iface->name = whine_malloc(strlen(ifr.ifr_name)+1)))
Simon Kelley6f13e532012-04-17 14:25:06 +0100448 {
449 strcpy(iface->name, ifr.ifr_name);
Simon Kelley115ac3e2013-05-20 11:28:32 +0100450 iface->next = daemon->interfaces;
451 daemon->interfaces = iface;
Simon Kelley6f13e532012-04-17 14:25:06 +0100452 return 1;
453 }
454 free(iface);
Simon Kelley5d162f22012-12-20 14:55:46 +0000455
Simon Kelley44a2a312004-03-10 20:04:35 +0000456 }
457
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100458 errno = ENOMEM;
459 return 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000460}
461
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100462#ifdef HAVE_IPV6
Simon Kelleyc72daea2012-01-05 21:33:27 +0000463static int iface_allowed_v6(struct in6_addr *local, int prefix,
Simon Kelleybad7b872012-12-20 22:00:39 +0000464 int scope, int if_index, int flags,
Simon Kelley1f776932012-12-16 19:46:08 +0000465 int preferred, int valid, void *vparam)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000466{
Simon Kelley59353a62004-11-21 19:34:28 +0000467 union mysockaddr addr;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100468 struct in_addr netmask; /* dummy */
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100469 netmask.s_addr = 0;
Simon Kelley52b92f42012-01-22 16:05:15 +0000470
Simon Kelley52b92f42012-01-22 16:05:15 +0000471 (void)scope; /* warning */
Simon Kelley1f776932012-12-16 19:46:08 +0000472 (void)preferred;
473 (void)valid;
Simon Kelley44a2a312004-03-10 20:04:35 +0000474
Simon Kelley849a8352006-06-09 21:02:31 +0100475 memset(&addr, 0, sizeof(addr));
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000476#ifdef HAVE_SOCKADDR_SA_LEN
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100477 addr.in6.sin6_len = sizeof(addr.in6);
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000478#endif
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100479 addr.in6.sin6_family = AF_INET6;
480 addr.in6.sin6_addr = *local;
481 addr.in6.sin6_port = htons(daemon->port);
Simon Kelley52b92f42012-01-22 16:05:15 +0000482 addr.in6.sin6_scope_id = if_index;
Simon Kelley849a8352006-06-09 21:02:31 +0100483
Simon Kelley376d48c2013-11-13 13:04:30 +0000484 return iface_allowed((struct iface_param *)vparam, if_index, NULL, &addr, netmask, prefix, !!(flags & IFACE_TENTATIVE));
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100485}
486#endif
Simon Kelley59353a62004-11-21 19:34:28 +0000487
Simon Kelley3f2873d2013-05-14 11:28:47 +0100488static int iface_allowed_v4(struct in_addr local, int if_index, char *label,
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100489 struct in_addr netmask, struct in_addr broadcast, void *vparam)
490{
491 union mysockaddr addr;
Simon Kelley376d48c2013-11-13 13:04:30 +0000492 int prefix, bit;
Simon Kelley849a8352006-06-09 21:02:31 +0100493
494 memset(&addr, 0, sizeof(addr));
Simon Kelley1ab84e22004-01-29 16:48:35 +0000495#ifdef HAVE_SOCKADDR_SA_LEN
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100496 addr.in.sin_len = sizeof(addr.in);
Simon Kelley1ab84e22004-01-29 16:48:35 +0000497#endif
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100498 addr.in.sin_family = AF_INET;
499 addr.in.sin_addr = broadcast; /* warning */
500 addr.in.sin_addr = local;
501 addr.in.sin_port = htons(daemon->port);
Simon Kelley44a2a312004-03-10 20:04:35 +0000502
Simon Kelley376d48c2013-11-13 13:04:30 +0000503 /* determine prefix length from netmask */
504 for (prefix = 32, bit = 1; (bit & ntohl(netmask.s_addr)) == 0 && prefix != 0; bit = bit << 1, prefix--);
505
506 return iface_allowed((struct iface_param *)vparam, if_index, label, &addr, netmask, prefix, 0);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100507}
508
Simon Kelley115ac3e2013-05-20 11:28:32 +0100509int enumerate_interfaces(int reset)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100510{
Simon Kelley115ac3e2013-05-20 11:28:32 +0100511 static struct addrlist *spare = NULL;
Simon Kelley397542b2013-09-05 11:27:34 +0100512 static int done = 0, active = 0;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100513 struct iface_param param;
514 int errsave, ret = 1;
515 struct addrlist *addr, *tmp;
516 struct interface_name *intname;
Simon Kelley376d48c2013-11-13 13:04:30 +0000517#ifdef HAVE_AUTH
518 struct auth_zone *zone;
519#endif
520
Simon Kelley76dd75d2013-05-23 10:04:25 +0100521 /* Do this max once per select cycle - also inhibits netlink socket use
522 in TCP child processes. */
Simon Kelley397542b2013-09-05 11:27:34 +0100523
Simon Kelley115ac3e2013-05-20 11:28:32 +0100524 if (reset)
525 {
526 done = 0;
527 return 1;
528 }
529
Simon Kelley397542b2013-09-05 11:27:34 +0100530 if (done || active)
Simon Kelley115ac3e2013-05-20 11:28:32 +0100531 return 1;
532
533 done = 1;
534
Simon Kelley397542b2013-09-05 11:27:34 +0100535 /* protect against recusive calls from iface_enumerate(); */
536 active = 1;
537
Simon Kelley115ac3e2013-05-20 11:28:32 +0100538 if ((param.fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
539 return 0;
540
541 /* remove addresses stored against interface_names */
542 for (intname = daemon->int_names; intname; intname = intname->next)
543 {
Simon Kelley376d48c2013-11-13 13:04:30 +0000544 for (addr = intname->addr; addr; addr = tmp)
Simon Kelley115ac3e2013-05-20 11:28:32 +0100545 {
546 tmp = addr->next;
547 addr->next = spare;
548 spare = addr;
549 }
550
Simon Kelley376d48c2013-11-13 13:04:30 +0000551 intname->addr = NULL;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100552 }
Simon Kelley376d48c2013-11-13 13:04:30 +0000553
554#ifdef HAVE_AUTH
555 /* remove addresses stored against auth_zone subnets, but not
556 ones configured as address literals */
557 for (zone = daemon->auth_zones; zone; zone = zone->next)
558 if (zone->interface_names)
559 {
560 struct addrlist **up;
561 for (up = &zone->subnet, addr = zone->subnet; addr; addr = tmp)
562 {
563 tmp = addr->next;
564 if (addr->flags & ADDRLIST_LITERAL)
565 up = &addr->next;
566 else
567 {
568 *up = addr->next;
569 addr->next = spare;
570 spare = addr;
571 }
572 }
573 }
574#endif
575
Simon Kelley115ac3e2013-05-20 11:28:32 +0100576 param.spare = spare;
577
578#ifdef HAVE_IPV6
579 ret = iface_enumerate(AF_INET6, &param, iface_allowed_v6);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100580#endif
Simon Kelley28866e92011-02-14 20:19:14 +0000581
Simon Kelley115ac3e2013-05-20 11:28:32 +0100582 if (ret)
583 ret = iface_enumerate(AF_INET, &param, iface_allowed_v4);
584
585 errsave = errno;
586 close(param.fd);
587 errno = errsave;
588
589 spare = param.spare;
Simon Kelley397542b2013-09-05 11:27:34 +0100590 active = 0;
591
Simon Kelley115ac3e2013-05-20 11:28:32 +0100592 return ret;
Simon Kelley44a2a312004-03-10 20:04:35 +0000593}
594
Simon Kelley5aabfc72007-08-29 11:24:47 +0100595/* set NONBLOCK bit on fd: See Stevens 16.6 */
Simon Kelley7cebd202006-05-06 14:13:33 +0100596int fix_fd(int fd)
597{
598 int flags;
599
600 if ((flags = fcntl(fd, F_GETFL)) == -1 ||
Simon Kelley5aabfc72007-08-29 11:24:47 +0100601 fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
Simon Kelley7cebd202006-05-06 14:13:33 +0100602 return 0;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100603
Simon Kelley7cebd202006-05-06 14:13:33 +0100604 return 1;
605}
606
Simon Kelley74c95c22011-10-19 09:33:39 +0100607static int make_sock(union mysockaddr *addr, int type, int dienow)
Simon Kelley44a2a312004-03-10 20:04:35 +0000608{
Simon Kelley28866e92011-02-14 20:19:14 +0000609 int family = addr->sa.sa_family;
610 int fd, rc, opt = 1;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100611
Simon Kelley28866e92011-02-14 20:19:14 +0000612 if ((fd = socket(family, type, 0)) == -1)
Simon Kelley316e2732010-01-22 20:16:09 +0000613 {
Simon Kelley28866e92011-02-14 20:19:14 +0000614 int port;
Simon Kelley39f1b8e2012-06-20 20:04:27 +0100615 char *s;
Simon Kelley28866e92011-02-14 20:19:14 +0000616
617 /* No error if the kernel just doesn't support this IP flavour */
618 if (errno == EPROTONOSUPPORT ||
619 errno == EAFNOSUPPORT ||
620 errno == EINVAL)
621 return -1;
622
623 err:
Simon Kelley39f1b8e2012-06-20 20:04:27 +0100624 port = prettyprint_addr(addr, daemon->addrbuff);
625 if (!option_bool(OPT_NOWILD) && !option_bool(OPT_CLEVERBIND))
626 sprintf(daemon->addrbuff, "port %d", port);
627 s = _("failed to create listening socket for %s: %s");
628
Simon Kelley5f11b3e2012-08-16 14:04:05 +0100629 if (fd != -1)
630 close (fd);
Simon Kelley39f1b8e2012-06-20 20:04:27 +0100631
Simon Kelley5f11b3e2012-08-16 14:04:05 +0100632 if (dienow)
633 {
634 /* failure to bind addresses given by --listen-address at this point
635 is OK if we're doing bind-dynamic */
636 if (!option_bool(OPT_CLEVERBIND))
637 die(s, daemon->addrbuff, EC_BADNET);
638 }
639 else
640 my_syslog(LOG_WARNING, s, daemon->addrbuff, strerror(errno));
641
Simon Kelley74c95c22011-10-19 09:33:39 +0100642 return -1;
Simon Kelley28866e92011-02-14 20:19:14 +0000643 }
Simon Kelley5f11b3e2012-08-16 14:04:05 +0100644
Simon Kelley28866e92011-02-14 20:19:14 +0000645 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || !fix_fd(fd))
646 goto err;
647
648#ifdef HAVE_IPV6
Simon Kelleyc72daea2012-01-05 21:33:27 +0000649 if (family == AF_INET6 && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)) == -1)
Simon Kelley28866e92011-02-14 20:19:14 +0000650 goto err;
651#endif
652
Simon Kelley74c95c22011-10-19 09:33:39 +0100653 if ((rc = bind(fd, (struct sockaddr *)addr, sa_len(addr))) == -1)
Simon Kelley28866e92011-02-14 20:19:14 +0000654 goto err;
655
656 if (type == SOCK_STREAM)
657 {
658 if (listen(fd, 5) == -1)
659 goto err;
660 }
661 else if (!option_bool(OPT_NOWILD))
662 {
663 if (family == AF_INET)
664 {
665#if defined(HAVE_LINUX_NETWORK)
Simon Kelleyc72daea2012-01-05 21:33:27 +0000666 if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) == -1)
Simon Kelley28866e92011-02-14 20:19:14 +0000667 goto err;
668#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
669 if (setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt)) == -1 ||
670 setsockopt(fd, IPPROTO_IP, IP_RECVIF, &opt, sizeof(opt)) == -1)
671 goto err;
672#endif
673 }
674#ifdef HAVE_IPV6
Simon Kelleyc72daea2012-01-05 21:33:27 +0000675 else if (!set_ipv6pktinfo(fd))
676 goto err;
Simon Kelley316e2732010-01-22 20:16:09 +0000677#endif
Simon Kelley28866e92011-02-14 20:19:14 +0000678 }
Simon Kelleyc72daea2012-01-05 21:33:27 +0000679
Simon Kelley28866e92011-02-14 20:19:14 +0000680 return fd;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100681}
Simon Kelleyc72daea2012-01-05 21:33:27 +0000682
683#ifdef HAVE_IPV6
684int set_ipv6pktinfo(int fd)
685{
686 int opt = 1;
687
688 /* The API changed around Linux 2.6.14 but the old ABI is still supported:
689 handle all combinations of headers and kernel.
690 OpenWrt note that this fixes the problem addressed by your very broken patch. */
691 daemon->v6pktinfo = IPV6_PKTINFO;
692
693#ifdef IPV6_RECVPKTINFO
694 if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &opt, sizeof(opt)) != -1)
695 return 1;
696# ifdef IPV6_2292PKTINFO
697 else if (errno == ENOPROTOOPT && setsockopt(fd, IPPROTO_IPV6, IPV6_2292PKTINFO, &opt, sizeof(opt)) != -1)
698 {
699 daemon->v6pktinfo = IPV6_2292PKTINFO;
700 return 1;
701 }
702# endif
703#else
704 if (setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &opt, sizeof(opt)) != -1)
705 return 1;
706#endif
707
708 return 0;
709}
710#endif
Simon Kelley22ce5502013-01-22 13:53:04 +0000711
712
713/* Find the interface on which a TCP connection arrived, if possible, or zero otherwise. */
714int tcp_interface(int fd, int af)
715{
716 int if_index = 0;
717
718#ifdef HAVE_LINUX_NETWORK
719 int opt = 1;
720 struct cmsghdr *cmptr;
721 struct msghdr msg;
722
723 /* use mshdr do that the CMSDG_* macros are available */
724 msg.msg_control = daemon->packet;
725 msg.msg_controllen = daemon->packet_buff_sz;
726
727 /* we overwrote the buffer... */
728 daemon->srv_save = NULL;
729
730 if (af == AF_INET)
731 {
732 if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) != -1 &&
733 getsockopt(fd, IPPROTO_IP, IP_PKTOPTIONS, msg.msg_control, (socklen_t *)&msg.msg_controllen) != -1)
734 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
735 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
736 {
737 union {
738 unsigned char *c;
739 struct in_pktinfo *p;
740 } p;
741
742 p.c = CMSG_DATA(cmptr);
743 if_index = p.p->ipi_ifindex;
744 }
745 }
746#ifdef HAVE_IPV6
747 else
748 {
749 /* Only the RFC-2292 API has the ability to find the interface for TCP connections,
750 it was removed in RFC-3542 !!!!
751
752 Fortunately, Linux kept the 2292 ABI when it moved to 3542. The following code always
753 uses the old ABI, and should work with pre- and post-3542 kernel headers */
754
755#ifdef IPV6_2292PKTOPTIONS
756# define PKTOPTIONS IPV6_2292PKTOPTIONS
757#else
758# define PKTOPTIONS IPV6_PKTOPTIONS
759#endif
760
761 if (set_ipv6pktinfo(fd) &&
762 getsockopt(fd, IPPROTO_IPV6, PKTOPTIONS, msg.msg_control, (socklen_t *)&msg.msg_controllen) != -1)
763 {
764 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
765 if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
766 {
767 union {
768 unsigned char *c;
769 struct in6_pktinfo *p;
770 } p;
771 p.c = CMSG_DATA(cmptr);
772
773 if_index = p.p->ipi6_ifindex;
774 }
775 }
776 }
777#endif /* IPV6 */
778#endif /* Linux */
779
780 return if_index;
781}
Simon Kelley28866e92011-02-14 20:19:14 +0000782
Simon Kelley74c95c22011-10-19 09:33:39 +0100783static struct listener *create_listeners(union mysockaddr *addr, int do_tftp, int dienow)
Simon Kelley28866e92011-02-14 20:19:14 +0000784{
785 struct listener *l = NULL;
786 int fd = -1, tcpfd = -1, tftpfd = -1;
787
Vladislav Grishenko408c3682013-09-24 16:18:49 +0100788 (void)do_tftp;
789
Simon Kelley28866e92011-02-14 20:19:14 +0000790 if (daemon->port != 0)
791 {
Simon Kelley74c95c22011-10-19 09:33:39 +0100792 fd = make_sock(addr, SOCK_DGRAM, dienow);
793 tcpfd = make_sock(addr, SOCK_STREAM, dienow);
Simon Kelley28866e92011-02-14 20:19:14 +0000794 }
795
796#ifdef HAVE_TFTP
797 if (do_tftp)
798 {
799 if (addr->sa.sa_family == AF_INET)
800 {
801 /* port must be restored to DNS port for TCP code */
802 short save = addr->in.sin_port;
803 addr->in.sin_port = htons(TFTP_PORT);
Simon Kelley74c95c22011-10-19 09:33:39 +0100804 tftpfd = make_sock(addr, SOCK_DGRAM, dienow);
Simon Kelley28866e92011-02-14 20:19:14 +0000805 addr->in.sin_port = save;
806 }
807# ifdef HAVE_IPV6
808 else
809 {
810 short save = addr->in6.sin6_port;
811 addr->in6.sin6_port = htons(TFTP_PORT);
Simon Kelley74c95c22011-10-19 09:33:39 +0100812 tftpfd = make_sock(addr, SOCK_DGRAM, dienow);
Simon Kelley28866e92011-02-14 20:19:14 +0000813 addr->in6.sin6_port = save;
814 }
815# endif
816 }
Simon Kelley44a2a312004-03-10 20:04:35 +0000817#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100818
Simon Kelley28866e92011-02-14 20:19:14 +0000819 if (fd != -1 || tcpfd != -1 || tftpfd != -1)
820 {
821 l = safe_malloc(sizeof(struct listener));
822 l->next = NULL;
823 l->family = addr->sa.sa_family;
824 l->fd = fd;
825 l->tcpfd = tcpfd;
826 l->tftpfd = tftpfd;
827 }
828
829 return l;
830}
831
Simon Kelley74c95c22011-10-19 09:33:39 +0100832void create_wildcard_listeners(void)
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100833{
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100834 union mysockaddr addr;
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100835 struct listener *l, *l6;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100836
Simon Kelley849a8352006-06-09 21:02:31 +0100837 memset(&addr, 0, sizeof(addr));
Simon Kelley28866e92011-02-14 20:19:14 +0000838#ifdef HAVE_SOCKADDR_SA_LEN
839 addr.in.sin_len = sizeof(addr.in);
840#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100841 addr.in.sin_family = AF_INET;
842 addr.in.sin_addr.s_addr = INADDR_ANY;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100843 addr.in.sin_port = htons(daemon->port);
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100844
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100845 l = create_listeners(&addr, !!option_bool(OPT_TFTP), 1);
Simon Kelley28866e92011-02-14 20:19:14 +0000846
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100847#ifdef HAVE_IPV6
Simon Kelley28866e92011-02-14 20:19:14 +0000848 memset(&addr, 0, sizeof(addr));
849# ifdef HAVE_SOCKADDR_SA_LEN
850 addr.in6.sin6_len = sizeof(addr.in6);
851# endif
852 addr.in6.sin6_family = AF_INET6;
853 addr.in6.sin6_addr = in6addr_any;
854 addr.in6.sin6_port = htons(daemon->port);
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100855
856 l6 = create_listeners(&addr, !!option_bool(OPT_TFTP), 1);
Simon Kelley28866e92011-02-14 20:19:14 +0000857 if (l)
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100858 l->next = l6;
Simon Kelley28866e92011-02-14 20:19:14 +0000859 else
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100860 l = l6;
Simon Kelley832af0b2007-01-21 20:01:28 +0000861#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100862
Simon Kelley74c95c22011-10-19 09:33:39 +0100863 daemon->listeners = l;
Simon Kelley44a2a312004-03-10 20:04:35 +0000864}
865
Simon Kelley74c95c22011-10-19 09:33:39 +0100866void create_bound_listeners(int dienow)
Simon Kelley44a2a312004-03-10 20:04:35 +0000867{
Simon Kelley74c95c22011-10-19 09:33:39 +0100868 struct listener *new;
Simon Kelley44a2a312004-03-10 20:04:35 +0000869 struct irec *iface;
Simon Kelley52d4abf2012-03-21 21:39:48 +0000870 struct iname *if_tmp;
Simon Kelley73a08a22009-02-05 20:28:08 +0000871
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100872 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelley74c95c22011-10-19 09:33:39 +0100873 if (!iface->done && !iface->dad &&
874 (new = create_listeners(&iface->addr, iface->tftp_ok, dienow)))
Simon Kelley28866e92011-02-14 20:19:14 +0000875 {
876 new->iface = iface;
Simon Kelley74c95c22011-10-19 09:33:39 +0100877 new->next = daemon->listeners;
878 daemon->listeners = new;
879 iface->done = 1;
Simon Kelley28866e92011-02-14 20:19:14 +0000880 }
Simon Kelley52d4abf2012-03-21 21:39:48 +0000881
882 /* Check for --listen-address options that haven't been used because there's
883 no interface with a matching address. These may be valid: eg it's possible
884 to listen on 127.0.1.1 even if the loopback interface is 127.0.0.1
885
Simon Kelley5f11b3e2012-08-16 14:04:05 +0100886 If the address isn't valid the bind() will fail and we'll die()
887 (except in bind-dynamic mode, when we'll complain but keep trying.)
Simon Kelley52d4abf2012-03-21 21:39:48 +0000888
889 The resulting listeners have the ->iface field NULL, and this has to be
890 handled by the DNS and TFTP code. It disables --localise-queries processing
891 (no netmask) and some MTU login the tftp code. */
892
893 for (if_tmp = daemon->if_addrs; if_tmp; if_tmp = if_tmp->next)
894 if (!if_tmp->used &&
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100895 (new = create_listeners(&if_tmp->addr, !!option_bool(OPT_TFTP), dienow)))
Simon Kelley52d4abf2012-03-21 21:39:48 +0000896 {
897 new->iface = NULL;
898 new->next = daemon->listeners;
899 daemon->listeners = new;
900 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000901}
902
Simon Kelleydc27e142013-10-16 13:09:53 +0100903/* In --bind-interfaces, the only access control is the addresses we're listening on.
904 There's nothing to avoid a query to the address of an internal interface arriving via
905 an external interface where we don't want to accept queries, except that in the usual
906 case the addresses of internal interfaces are RFC1918. When bind-interfaces in use,
907 and we listen on an address that looks like it's probably globally routeable, shout.
908
909 The fix is to use --bind-dynamic, which actually checks the arrival interface too.
910 Tough if your platform doesn't support this.
911*/
912
913void warn_bound_listeners(void)
914{
915 struct irec *iface;
916 int advice = 0;
917
918 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelleyf7029f52013-11-21 15:09:09 +0000919 if (!iface->dns_auth)
Simon Kelleydc27e142013-10-16 13:09:53 +0100920 {
921 int warn = 0;
922 if (iface->addr.sa.sa_family == AF_INET)
923 {
924 if (!private_net(iface->addr.in.sin_addr, 1))
925 {
926 inet_ntop(AF_INET, &iface->addr.in.sin_addr, daemon->addrbuff, ADDRSTRLEN);
927 warn = 1;
928 }
929 }
930#ifdef HAVE_IPV6
931 else
932 {
933 if (!IN6_IS_ADDR_LINKLOCAL(&iface->addr.in6.sin6_addr) &&
934 !IN6_IS_ADDR_SITELOCAL(&iface->addr.in6.sin6_addr) &&
935 !IN6_IS_ADDR_ULA(&iface->addr.in6.sin6_addr) &&
936 !IN6_IS_ADDR_LOOPBACK(&iface->addr.in6.sin6_addr))
937 {
938 inet_ntop(AF_INET6, &iface->addr.in6.sin6_addr, daemon->addrbuff, ADDRSTRLEN);
939 warn = 1;
940 }
941 }
942#endif
943 if (warn)
944 {
945 iface->warned = advice = 1;
946 my_syslog(LOG_WARNING,
Simon Kelleyf7029f52013-11-21 15:09:09 +0000947 _("LOUD WARNING: listening on %s may accept requests via interfaces other than %s"),
Simon Kelleydc27e142013-10-16 13:09:53 +0100948 daemon->addrbuff, iface->name);
949 }
950 }
951
952 if (advice)
Simon Kelleyf7029f52013-11-21 15:09:09 +0000953 my_syslog(LOG_WARNING, _("LOUD WARNING: use --bind-dynamic rather than --bind-interfaces to avoid DNS amplification attacks via these interface(s)"));
Simon Kelleydc27e142013-10-16 13:09:53 +0100954}
955
Simon Kelleyf7029f52013-11-21 15:09:09 +0000956void warn_int_names(void)
957{
958 struct interface_name *intname;
959
960 for (intname = daemon->int_names; intname; intname = intname->next)
961 if (!intname->addr)
962 my_syslog(LOG_WARNING, _("warning: no addresses found for interface %s"), intname->intr);
963}
964
Simon Kelley74c95c22011-10-19 09:33:39 +0100965int is_dad_listeners(void)
966{
967 struct irec *iface;
968
969 if (option_bool(OPT_NOWILD))
970 for (iface = daemon->interfaces; iface; iface = iface->next)
971 if (iface->dad && !iface->done)
972 return 1;
973
974 return 0;
975}
Simon Kelley5d162f22012-12-20 14:55:46 +0000976
977#ifdef HAVE_DHCP6
978void join_multicast(int dienow)
979{
980 struct irec *iface, *tmp;
981
982 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelley19624462012-12-28 11:18:09 +0000983 if (iface->addr.sa.sa_family == AF_INET6 && iface->dhcp_ok && !iface->multicast_done)
Simon Kelley5d162f22012-12-20 14:55:46 +0000984 {
985 /* There's an irec per address but we only want to join for multicast
986 once per interface. Weed out duplicates. */
987 for (tmp = daemon->interfaces; tmp; tmp = tmp->next)
988 if (tmp->multicast_done && tmp->index == iface->index)
989 break;
990
991 iface->multicast_done = 1;
992
993 if (!tmp)
994 {
995 struct ipv6_mreq mreq;
996 int err = 0;
997
998 mreq.ipv6mr_interface = iface->index;
999
1000 inet_pton(AF_INET6, ALL_RELAY_AGENTS_AND_SERVERS, &mreq.ipv6mr_multiaddr);
1001
Simon Kelleyff7eea22013-09-04 18:01:38 +01001002 if ((daemon->doing_dhcp6 || daemon->relay6) &&
Simon Kelley5d162f22012-12-20 14:55:46 +00001003 setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
1004 err = 1;
1005
1006 inet_pton(AF_INET6, ALL_SERVERS, &mreq.ipv6mr_multiaddr);
1007
1008 if (daemon->doing_dhcp6 &&
1009 setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
1010 err = 1;
1011
1012 inet_pton(AF_INET6, ALL_ROUTERS, &mreq.ipv6mr_multiaddr);
1013
1014 if (daemon->doing_ra &&
1015 setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
1016 err = 1;
1017
1018 if (err)
1019 {
1020 char *s = _("interface %s failed to join DHCPv6 multicast group: %s");
1021 if (dienow)
1022 die(s, iface->name, EC_BADNET);
1023 else
1024 my_syslog(LOG_ERR, s, iface->name, strerror(errno));
1025 }
1026 }
1027 }
1028}
1029#endif
1030
Simon Kelley9009d742008-11-14 20:04:27 +00001031/* return a UDP socket bound to a random port, have to cope with straying into
Simon Kelley1a6bca82008-07-11 11:11:42 +01001032 occupied port nos and reserved ones. */
1033int random_sock(int family)
1034{
1035 int fd;
1036
1037 if ((fd = socket(family, SOCK_DGRAM, 0)) != -1)
1038 {
Simon Kelley3927da42008-07-20 15:10:39 +01001039 union mysockaddr addr;
Simon Kelley1ad24ae2008-07-20 20:22:50 +01001040 unsigned int ports_avail = 65536u - (unsigned short)daemon->min_port;
Simon Kelley9009d742008-11-14 20:04:27 +00001041 int tries = ports_avail < 30 ? 3 * ports_avail : 100;
Simon Kelley3927da42008-07-20 15:10:39 +01001042
Simon Kelley1a6bca82008-07-11 11:11:42 +01001043 memset(&addr, 0, sizeof(addr));
Simon Kelley3927da42008-07-20 15:10:39 +01001044 addr.sa.sa_family = family;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001045
Simon Kelley1ad24ae2008-07-20 20:22:50 +01001046 /* don't loop forever if all ports in use. */
1047
Simon Kelley1a6bca82008-07-11 11:11:42 +01001048 if (fix_fd(fd))
Simon Kelley9009d742008-11-14 20:04:27 +00001049 while(tries--)
Simon Kelley1a6bca82008-07-11 11:11:42 +01001050 {
1051 unsigned short port = rand16();
1052
Simon Kelley3927da42008-07-20 15:10:39 +01001053 if (daemon->min_port != 0)
Simon Kelley1ad24ae2008-07-20 20:22:50 +01001054 port = htons(daemon->min_port + (port % ((unsigned short)ports_avail)));
Simon Kelley1a6bca82008-07-11 11:11:42 +01001055
1056 if (family == AF_INET)
1057 {
1058 addr.in.sin_addr.s_addr = INADDR_ANY;
Simon Kelley3927da42008-07-20 15:10:39 +01001059 addr.in.sin_port = port;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001060#ifdef HAVE_SOCKADDR_SA_LEN
1061 addr.in.sin_len = sizeof(struct sockaddr_in);
1062#endif
1063 }
1064#ifdef HAVE_IPV6
1065 else
1066 {
1067 addr.in6.sin6_addr = in6addr_any;
Simon Kelley3927da42008-07-20 15:10:39 +01001068 addr.in6.sin6_port = port;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001069#ifdef HAVE_SOCKADDR_SA_LEN
1070 addr.in6.sin6_len = sizeof(struct sockaddr_in6);
1071#endif
1072 }
1073#endif
1074
1075 if (bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == 0)
1076 return fd;
1077
1078 if (errno != EADDRINUSE && errno != EACCES)
1079 break;
1080 }
1081
1082 close(fd);
1083 }
1084
1085 return -1;
1086}
1087
1088
Simon Kelley824af852008-02-12 20:43:05 +00001089int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp)
1090{
1091 union mysockaddr addr_copy = *addr;
1092
1093 /* cannot set source _port_ for TCP connections. */
1094 if (is_tcp)
1095 {
1096 if (addr_copy.sa.sa_family == AF_INET)
1097 addr_copy.in.sin_port = 0;
1098#ifdef HAVE_IPV6
1099 else
1100 addr_copy.in6.sin6_port = 0;
1101#endif
1102 }
1103
1104 if (bind(fd, (struct sockaddr *)&addr_copy, sa_len(&addr_copy)) == -1)
1105 return 0;
1106
1107#if defined(SO_BINDTODEVICE)
Simon Kelley73a08a22009-02-05 20:28:08 +00001108 if (intname[0] != 0 &&
Simon Kelley316e2732010-01-22 20:16:09 +00001109 setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, intname, IF_NAMESIZE) == -1)
Simon Kelley824af852008-02-12 20:43:05 +00001110 return 0;
1111#endif
1112
1113 return 1;
1114}
1115
1116static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001117{
1118 struct serverfd *sfd;
Simon Kelley824af852008-02-12 20:43:05 +00001119 int errsave;
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001120
Simon Kelley1a6bca82008-07-11 11:11:42 +01001121 /* when using random ports, servers which would otherwise use
1122 the INADDR_ANY/port0 socket have sfd set to NULL */
Simon Kelley73a08a22009-02-05 20:28:08 +00001123 if (!daemon->osport && intname[0] == 0)
Simon Kelley1a6bca82008-07-11 11:11:42 +01001124 {
1125 errno = 0;
1126
1127 if (addr->sa.sa_family == AF_INET &&
1128 addr->in.sin_addr.s_addr == INADDR_ANY &&
1129 addr->in.sin_port == htons(0))
1130 return NULL;
1131
1132#ifdef HAVE_IPV6
1133 if (addr->sa.sa_family == AF_INET6 &&
1134 memcmp(&addr->in6.sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0 &&
1135 addr->in6.sin6_port == htons(0))
1136 return NULL;
1137#endif
1138 }
1139
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001140 /* may have a suitable one already */
Simon Kelley824af852008-02-12 20:43:05 +00001141 for (sfd = daemon->sfds; sfd; sfd = sfd->next )
1142 if (sockaddr_isequal(&sfd->source_addr, addr) &&
1143 strcmp(intname, sfd->interface) == 0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001144 return sfd;
1145
1146 /* need to make a new one. */
1147 errno = ENOMEM; /* in case malloc fails. */
Simon Kelley5aabfc72007-08-29 11:24:47 +01001148 if (!(sfd = whine_malloc(sizeof(struct serverfd))))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001149 return NULL;
1150
1151 if ((sfd->fd = socket(addr->sa.sa_family, SOCK_DGRAM, 0)) == -1)
1152 {
1153 free(sfd);
1154 return NULL;
1155 }
1156
Simon Kelley824af852008-02-12 20:43:05 +00001157 if (!local_bind(sfd->fd, addr, intname, 0) || !fix_fd(sfd->fd))
1158 {
1159 errsave = errno; /* save error from bind. */
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001160 close(sfd->fd);
1161 free(sfd);
1162 errno = errsave;
1163 return NULL;
1164 }
Simon Kelley824af852008-02-12 20:43:05 +00001165
1166 strcpy(sfd->interface, intname);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001167 sfd->source_addr = *addr;
Simon Kelley824af852008-02-12 20:43:05 +00001168 sfd->next = daemon->sfds;
1169 daemon->sfds = sfd;
1170 return sfd;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001171}
1172
Simon Kelley824af852008-02-12 20:43:05 +00001173/* create upstream sockets during startup, before root is dropped which may be needed
1174 this allows query_port to be a low port and interface binding */
1175void pre_allocate_sfds(void)
1176{
1177 struct server *srv;
1178
1179 if (daemon->query_port != 0)
1180 {
1181 union mysockaddr addr;
1182 memset(&addr, 0, sizeof(addr));
1183 addr.in.sin_family = AF_INET;
1184 addr.in.sin_addr.s_addr = INADDR_ANY;
1185 addr.in.sin_port = htons(daemon->query_port);
1186#ifdef HAVE_SOCKADDR_SA_LEN
1187 addr.in.sin_len = sizeof(struct sockaddr_in);
1188#endif
1189 allocate_sfd(&addr, "");
1190#ifdef HAVE_IPV6
1191 memset(&addr, 0, sizeof(addr));
1192 addr.in6.sin6_family = AF_INET6;
1193 addr.in6.sin6_addr = in6addr_any;
1194 addr.in6.sin6_port = htons(daemon->query_port);
1195#ifdef HAVE_SOCKADDR_SA_LEN
1196 addr.in6.sin6_len = sizeof(struct sockaddr_in6);
1197#endif
1198 allocate_sfd(&addr, "");
1199#endif
1200 }
1201
1202 for (srv = daemon->servers; srv; srv = srv->next)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001203 if (!(srv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)) &&
Simon Kelley824af852008-02-12 20:43:05 +00001204 !allocate_sfd(&srv->source_addr, srv->interface) &&
Simon Kelley1a6bca82008-07-11 11:11:42 +01001205 errno != 0 &&
Simon Kelley28866e92011-02-14 20:19:14 +00001206 option_bool(OPT_NOWILD))
Simon Kelley824af852008-02-12 20:43:05 +00001207 {
Simon Kelley316e2732010-01-22 20:16:09 +00001208 prettyprint_addr(&srv->source_addr, daemon->namebuff);
Simon Kelley73a08a22009-02-05 20:28:08 +00001209 if (srv->interface[0] != 0)
Simon Kelley824af852008-02-12 20:43:05 +00001210 {
1211 strcat(daemon->namebuff, " ");
1212 strcat(daemon->namebuff, srv->interface);
1213 }
1214 die(_("failed to bind server socket for %s: %s"),
1215 daemon->namebuff, EC_BADNET);
1216 }
1217}
1218
1219
Simon Kelley5aabfc72007-08-29 11:24:47 +01001220void check_servers(void)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001221{
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001222 struct irec *iface;
Simon Kelley3be34542004-09-11 19:12:13 +01001223 struct server *new, *tmp, *ret = NULL;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001224 int port = 0;
1225
Simon Kelley316e2732010-01-22 20:16:09 +00001226 /* interface may be new since startup */
Simon Kelley28866e92011-02-14 20:19:14 +00001227 if (!option_bool(OPT_NOWILD))
Simon Kelley115ac3e2013-05-20 11:28:32 +01001228 enumerate_interfaces(0);
Simon Kelley316e2732010-01-22 20:16:09 +00001229
Simon Kelley3be34542004-09-11 19:12:13 +01001230 for (new = daemon->servers; new; new = tmp)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001231 {
1232 tmp = new->next;
1233
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001234 if (!(new->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001235 {
Simon Kelley3d8df262005-08-29 12:19:27 +01001236 port = prettyprint_addr(&new->addr, daemon->namebuff);
1237
Simon Kelley16972692006-10-16 20:04:18 +01001238 /* 0.0.0.0 is nothing, the stack treats it like 127.0.0.1 */
1239 if (new->addr.sa.sa_family == AF_INET &&
1240 new->addr.in.sin_addr.s_addr == 0)
1241 {
1242 free(new);
1243 continue;
1244 }
1245
Simon Kelley3d8df262005-08-29 12:19:27 +01001246 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001247 if (sockaddr_isequal(&new->addr, &iface->addr))
1248 break;
1249 if (iface)
1250 {
Simon Kelleyf2621c72007-04-29 19:47:21 +01001251 my_syslog(LOG_WARNING, _("ignoring nameserver %s - local interface"), daemon->namebuff);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001252 free(new);
1253 continue;
1254 }
1255
1256 /* Do we need a socket set? */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001257 if (!new->sfd &&
1258 !(new->sfd = allocate_sfd(&new->source_addr, new->interface)) &&
1259 errno != 0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001260 {
Simon Kelleyf2621c72007-04-29 19:47:21 +01001261 my_syslog(LOG_WARNING,
1262 _("ignoring nameserver %s - cannot make/bind socket: %s"),
1263 daemon->namebuff, strerror(errno));
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001264 free(new);
1265 continue;
1266 }
1267 }
1268
1269 /* reverse order - gets it right. */
1270 new->next = ret;
1271 ret = new;
1272
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001273 if (!(new->flags & SERV_NO_REBIND))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001274 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001275 if (new->flags & (SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_USE_RESOLV))
1276 {
1277 char *s1, *s2;
1278 if (!(new->flags & SERV_HAS_DOMAIN))
1279 s1 = _("unqualified"), s2 = _("names");
1280 else if (strlen(new->domain) == 0)
1281 s1 = _("default"), s2 = "";
1282 else
1283 s1 = _("domain"), s2 = new->domain;
1284
1285 if (new->flags & SERV_NO_ADDR)
1286 my_syslog(LOG_INFO, _("using local addresses only for %s %s"), s1, s2);
1287 else if (new->flags & SERV_USE_RESOLV)
1288 my_syslog(LOG_INFO, _("using standard nameservers for %s %s"), s1, s2);
1289 else if (!(new->flags & SERV_LITERAL_ADDRESS))
1290 my_syslog(LOG_INFO, _("using nameserver %s#%d for %s %s"), daemon->namebuff, port, s1, s2);
1291 }
1292 else if (new->interface[0] != 0)
1293 my_syslog(LOG_INFO, _("using nameserver %s#%d(via %s)"), daemon->namebuff, port, new->interface);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001294 else
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001295 my_syslog(LOG_INFO, _("using nameserver %s#%d"), daemon->namebuff, port);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001296 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001297 }
1298
Simon Kelley3be34542004-09-11 19:12:13 +01001299 daemon->servers = ret;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001300}
Simon Kelley849a8352006-06-09 21:02:31 +01001301
1302/* Return zero if no servers found, in that case we keep polling.
1303 This is a protection against an update-time/write race on resolv.conf */
Simon Kelley5aabfc72007-08-29 11:24:47 +01001304int reload_servers(char *fname)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001305{
1306 FILE *f;
1307 char *line;
1308 struct server *old_servers = NULL;
1309 struct server *new_servers = NULL;
Simon Kelley849a8352006-06-09 21:02:31 +01001310 struct server *serv;
1311 int gotone = 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001312
Simon Kelley849a8352006-06-09 21:02:31 +01001313 /* buff happens to be MAXDNAME long... */
1314 if (!(f = fopen(fname, "r")))
1315 {
Simon Kelleyf2621c72007-04-29 19:47:21 +01001316 my_syslog(LOG_ERR, _("failed to read %s: %s"), fname, strerror(errno));
Simon Kelley849a8352006-06-09 21:02:31 +01001317 return 0;
1318 }
1319
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001320 /* move old servers to free list - we can reuse the memory
1321 and not risk malloc if there are the same or fewer new servers.
1322 Servers which were specced on the command line go to the new list. */
Simon Kelley849a8352006-06-09 21:02:31 +01001323 for (serv = daemon->servers; serv;)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001324 {
1325 struct server *tmp = serv->next;
1326 if (serv->flags & SERV_FROM_RESOLV)
1327 {
1328 serv->next = old_servers;
Simon Kelley849a8352006-06-09 21:02:31 +01001329 old_servers = serv;
1330 /* forward table rules reference servers, so have to blow them away */
Simon Kelley5aabfc72007-08-29 11:24:47 +01001331 server_gone(serv);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001332 }
1333 else
1334 {
1335 serv->next = new_servers;
1336 new_servers = serv;
1337 }
1338 serv = tmp;
1339 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001340
Simon Kelley849a8352006-06-09 21:02:31 +01001341 while ((line = fgets(daemon->namebuff, MAXDNAME, f)))
1342 {
1343 union mysockaddr addr, source_addr;
1344 char *token = strtok(line, " \t\n\r");
1345
Simon Kelley5aabfc72007-08-29 11:24:47 +01001346 if (!token)
1347 continue;
1348 if (strcmp(token, "nameserver") != 0 && strcmp(token, "server") != 0)
Simon Kelley849a8352006-06-09 21:02:31 +01001349 continue;
1350 if (!(token = strtok(NULL, " \t\n\r")))
1351 continue;
1352
1353 memset(&addr, 0, sizeof(addr));
1354 memset(&source_addr, 0, sizeof(source_addr));
1355
1356 if ((addr.in.sin_addr.s_addr = inet_addr(token)) != (in_addr_t) -1)
1357 {
1358#ifdef HAVE_SOCKADDR_SA_LEN
1359 source_addr.in.sin_len = addr.in.sin_len = sizeof(source_addr.in);
1360#endif
1361 source_addr.in.sin_family = addr.in.sin_family = AF_INET;
1362 addr.in.sin_port = htons(NAMESERVER_PORT);
1363 source_addr.in.sin_addr.s_addr = INADDR_ANY;
1364 source_addr.in.sin_port = htons(daemon->query_port);
1365 }
1366#ifdef HAVE_IPV6
Simon Kelley7de060b2011-08-26 17:24:52 +01001367 else
1368 {
1369 int scope_index = 0;
1370 char *scope_id = strchr(token, '%');
1371
1372 if (scope_id)
1373 {
1374 *(scope_id++) = 0;
1375 scope_index = if_nametoindex(scope_id);
1376 }
1377
1378 if (inet_pton(AF_INET6, token, &addr.in6.sin6_addr) > 0)
1379 {
Simon Kelley849a8352006-06-09 21:02:31 +01001380#ifdef HAVE_SOCKADDR_SA_LEN
Simon Kelley7de060b2011-08-26 17:24:52 +01001381 source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(source_addr.in6);
Simon Kelley849a8352006-06-09 21:02:31 +01001382#endif
Simon Kelley7de060b2011-08-26 17:24:52 +01001383 source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6;
1384 source_addr.in6.sin6_flowinfo = addr.in6.sin6_flowinfo = 0;
1385 addr.in6.sin6_port = htons(NAMESERVER_PORT);
1386 addr.in6.sin6_scope_id = scope_index;
1387 source_addr.in6.sin6_addr = in6addr_any;
1388 source_addr.in6.sin6_port = htons(daemon->query_port);
1389 source_addr.in6.sin6_scope_id = 0;
1390 }
1391 else
1392 continue;
Simon Kelley849a8352006-06-09 21:02:31 +01001393 }
Simon Kelley7de060b2011-08-26 17:24:52 +01001394#else /* IPV6 */
Simon Kelley849a8352006-06-09 21:02:31 +01001395 else
1396 continue;
Simon Kelley7de060b2011-08-26 17:24:52 +01001397#endif
1398
Simon Kelley849a8352006-06-09 21:02:31 +01001399 if (old_servers)
1400 {
1401 serv = old_servers;
1402 old_servers = old_servers->next;
1403 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001404 else if (!(serv = whine_malloc(sizeof (struct server))))
Simon Kelley849a8352006-06-09 21:02:31 +01001405 continue;
1406
1407 /* this list is reverse ordered:
1408 it gets reversed again in check_servers */
1409 serv->next = new_servers;
1410 new_servers = serv;
1411 serv->addr = addr;
1412 serv->source_addr = source_addr;
1413 serv->domain = NULL;
Simon Kelley824af852008-02-12 20:43:05 +00001414 serv->interface[0] = 0;
Simon Kelley849a8352006-06-09 21:02:31 +01001415 serv->sfd = NULL;
1416 serv->flags = SERV_FROM_RESOLV;
Simon Kelley824af852008-02-12 20:43:05 +00001417 serv->queries = serv->failed_queries = 0;
Simon Kelley849a8352006-06-09 21:02:31 +01001418 gotone = 1;
1419 }
1420
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001421 /* Free any memory not used. */
Simon Kelley849a8352006-06-09 21:02:31 +01001422 while (old_servers)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001423 {
1424 struct server *tmp = old_servers->next;
1425 free(old_servers);
1426 old_servers = tmp;
1427 }
1428
Simon Kelley3be34542004-09-11 19:12:13 +01001429 daemon->servers = new_servers;
Simon Kelley849a8352006-06-09 21:02:31 +01001430 fclose(f);
1431
1432 return gotone;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001433}
1434
1435
1436
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001437
1438
1439