blob: 303ae50745474dcc6883c3ec9e17a389b9f8ad47 [file] [log] [blame]
Simon Kelleyc49778d2016-01-06 18:52:33 +00001/* dnsmasq is Copyright (c) 2000-2016 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 Kelley7622fc02009-06-04 20:32:05 +010019#ifdef HAVE_LINUX_NETWORK
20
21int indextoname(int fd, int index, char *name)
22{
23 struct ifreq ifr;
24
25 if (index == 0)
26 return 0;
27
28 ifr.ifr_ifindex = index;
29 if (ioctl(fd, SIOCGIFNAME, &ifr) == -1)
30 return 0;
31
32 strncpy(name, ifr.ifr_name, IF_NAMESIZE);
33
34 return 1;
35}
36
Simon Kelley28866e92011-02-14 20:19:14 +000037
38#elif defined(HAVE_SOLARIS_NETWORK)
39
40#include <zone.h>
41#include <alloca.h>
42#ifndef LIFC_UNDER_IPMP
43# define LIFC_UNDER_IPMP 0
44#endif
45
46int indextoname(int fd, int index, char *name)
47{
48 int64_t lifc_flags;
49 struct lifnum lifn;
50 int numifs, bufsize, i;
51 struct lifconf lifc;
52 struct lifreq *lifrp;
53
54 if (index == 0)
55 return 0;
56
57 if (getzoneid() == GLOBAL_ZONEID)
58 {
59 if (!if_indextoname(index, name))
60 return 0;
61 return 1;
62 }
63
64 lifc_flags = LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES | LIFC_UNDER_IPMP;
65 lifn.lifn_family = AF_UNSPEC;
66 lifn.lifn_flags = lifc_flags;
67 if (ioctl(fd, SIOCGLIFNUM, &lifn) < 0)
68 return 0;
69
70 numifs = lifn.lifn_count;
71 bufsize = numifs * sizeof(struct lifreq);
72
73 lifc.lifc_family = AF_UNSPEC;
74 lifc.lifc_flags = lifc_flags;
75 lifc.lifc_len = bufsize;
76 lifc.lifc_buf = alloca(bufsize);
77
78 if (ioctl(fd, SIOCGLIFCONF, &lifc) < 0)
79 return 0;
80
81 lifrp = lifc.lifc_req;
82 for (i = lifc.lifc_len / sizeof(struct lifreq); i; i--, lifrp++)
83 {
84 struct lifreq lifr;
85 strncpy(lifr.lifr_name, lifrp->lifr_name, IF_NAMESIZE);
86 if (ioctl(fd, SIOCGLIFINDEX, &lifr) < 0)
87 return 0;
88
89 if (lifr.lifr_index == index) {
90 strncpy(name, lifr.lifr_name, IF_NAMESIZE);
91 return 1;
92 }
93 }
94 return 0;
95}
96
97
Simon Kelley7622fc02009-06-04 20:32:05 +010098#else
99
100int indextoname(int fd, int index, char *name)
101{
Simon Kelley115ac3e2013-05-20 11:28:32 +0100102 (void)fd;
103
Simon Kelley7622fc02009-06-04 20:32:05 +0100104 if (index == 0 || !if_indextoname(index, name))
105 return 0;
106
107 return 1;
108}
109
110#endif
111
Simon Kelley4f7b3042012-11-28 21:27:02 +0000112int iface_check(int family, struct all_addr *addr, char *name, int *auth)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000113{
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000114 struct iname *tmp;
Simon Kelleyedf0bde2013-07-29 17:21:48 +0100115 int ret = 1, match_addr = 0;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100116
Simon Kelley309331f2006-04-22 15:05:01 +0100117 /* Note: have to check all and not bail out early, so that we set the
Simon Kelley89500e32013-09-20 16:29:20 +0100118 "used" flags.
119
120 May be called with family == AF_LOCALto check interface by name only. */
Simon Kelley429798f2012-12-10 20:45:53 +0000121
Simon Kelley4f7b3042012-11-28 21:27:02 +0000122 if (auth)
Simon Kelley429798f2012-12-10 20:45:53 +0000123 *auth = 0;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100124
Simon Kelleyc72daea2012-01-05 21:33:27 +0000125 if (daemon->if_names || daemon->if_addrs)
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100126 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100127 ret = 0;
128
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100129 for (tmp = daemon->if_names; tmp; tmp = tmp->next)
Simon Kelley49333cb2013-03-15 20:30:51 +0000130 if (tmp->name && wildcard_match(tmp->name, name))
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100131 ret = tmp->used = 1;
132
Simon Kelley429798f2012-12-10 20:45:53 +0000133 if (addr)
134 for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
135 if (tmp->addr.sa.sa_family == family)
136 {
137 if (family == AF_INET &&
138 tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
Simon Kelleyedf0bde2013-07-29 17:21:48 +0100139 ret = match_addr = tmp->used = 1;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100140#ifdef HAVE_IPV6
Simon Kelley429798f2012-12-10 20:45:53 +0000141 else if (family == AF_INET6 &&
142 IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr,
143 &addr->addr.addr6))
Simon Kelleyedf0bde2013-07-29 17:21:48 +0100144 ret = match_addr = tmp->used = 1;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100145#endif
Simon Kelley429798f2012-12-10 20:45:53 +0000146 }
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100147 }
148
Simon Kelleyedf0bde2013-07-29 17:21:48 +0100149 if (!match_addr)
150 for (tmp = daemon->if_except; tmp; tmp = tmp->next)
151 if (tmp->name && wildcard_match(tmp->name, name))
152 ret = 0;
Simon Kelleyc72daea2012-01-05 21:33:27 +0000153
Simon Kelley429798f2012-12-10 20:45:53 +0000154
155 for (tmp = daemon->authinterface; tmp; tmp = tmp->next)
156 if (tmp->name)
157 {
Simon Kelleyf25e6c62013-11-17 12:23:42 +0000158 if (strcmp(tmp->name, name) == 0 &&
159 (tmp->addr.sa.sa_family == 0 || tmp->addr.sa.sa_family == family))
Simon Kelley429798f2012-12-10 20:45:53 +0000160 break;
161 }
162 else if (addr && tmp->addr.sa.sa_family == AF_INET && family == AF_INET &&
163 tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
164 break;
165#ifdef HAVE_IPV6
166 else if (addr && tmp->addr.sa.sa_family == AF_INET6 && family == AF_INET6 &&
167 IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, &addr->addr.addr6))
168 break;
169#endif
170
171 if (tmp && auth)
172 {
173 *auth = 1;
174 ret = 1;
175 }
176
Simon Kelley309331f2006-04-22 15:05:01 +0100177 return ret;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100178}
Simon Kelleye25db1f2013-01-29 22:10:26 +0000179
180
181/* Fix for problem that the kernel sometimes reports the loopback inerface as the
182 arrival interface when a packet originates locally, even when sent to address of
183 an interface other than the loopback. Accept packet if it arrived via a loopback
184 interface, even when we're not accepting packets that way, as long as the destination
185 address is one we're believing. Interface list must be up-to-date before calling. */
186int loopback_exception(int fd, int family, struct all_addr *addr, char *name)
187{
188 struct ifreq ifr;
189 struct irec *iface;
190
191 strncpy(ifr.ifr_name, name, IF_NAMESIZE);
192 if (ioctl(fd, SIOCGIFFLAGS, &ifr) != -1 &&
193 ifr.ifr_flags & IFF_LOOPBACK)
194 {
195 for (iface = daemon->interfaces; iface; iface = iface->next)
196 if (iface->addr.sa.sa_family == family)
197 {
198 if (family == AF_INET)
199 {
200 if (iface->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
201 return 1;
202 }
203#ifdef HAVE_IPV6
204 else if (IN6_ARE_ADDR_EQUAL(&iface->addr.in6.sin6_addr, &addr->addr.addr6))
205 return 1;
206#endif
207
208 }
209 }
210 return 0;
211}
212
Simon Kelley3f2873d2013-05-14 11:28:47 +0100213/* If we're configured with something like --interface=eth0:0 then we'll listen correctly
214 on the relevant address, but the name of the arrival interface, derived from the
215 index won't match the config. Check that we found an interface address for the arrival
216 interface: daemon->interfaces must be up-to-date. */
217int label_exception(int index, int family, struct all_addr *addr)
218{
219 struct irec *iface;
220
221 /* labels only supported on IPv4 addresses. */
222 if (family != AF_INET)
223 return 0;
224
225 for (iface = daemon->interfaces; iface; iface = iface->next)
226 if (iface->index == index && iface->addr.sa.sa_family == AF_INET &&
227 iface->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
228 return 1;
229
230 return 0;
231}
232
Simon Kelley115ac3e2013-05-20 11:28:32 +0100233struct iface_param {
234 struct addrlist *spare;
235 int fd;
236};
237
238static int iface_allowed(struct iface_param *param, int if_index, char *label,
Simon Kelley47669362014-12-17 12:41:56 +0000239 union mysockaddr *addr, struct in_addr netmask, int prefixlen, int iface_flags)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100240{
241 struct irec *iface;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100242 int mtu = 0, loopback;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100243 struct ifreq ifr;
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100244 int tftp_ok = !!option_bool(OPT_TFTP);
Simon Kelley9380ba72012-04-16 14:41:56 +0100245 int dhcp_ok = 1;
Simon Kelley4f7b3042012-11-28 21:27:02 +0000246 int auth_dns = 0;
Simon Kelley91543f42013-09-23 12:41:20 +0100247#if defined(HAVE_DHCP) || defined(HAVE_TFTP)
Simon Kelley832af0b2007-01-21 20:01:28 +0000248 struct iname *tmp;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100249#endif
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100250
Vladislav Grishenko3b195962013-11-26 11:08:21 +0000251 (void)prefixlen;
252
Simon Kelley115ac3e2013-05-20 11:28:32 +0100253 if (!indextoname(param->fd, if_index, ifr.ifr_name) ||
254 ioctl(param->fd, SIOCGIFFLAGS, &ifr) == -1)
255 return 0;
Simon Kelley1f15b812009-10-13 17:49:32 +0100256
257 loopback = ifr.ifr_flags & IFF_LOOPBACK;
Simon Kelley9380ba72012-04-16 14:41:56 +0100258
259 if (loopback)
Simon Kelley3f2873d2013-05-14 11:28:47 +0100260 dhcp_ok = 0;
261
Simon Kelley115ac3e2013-05-20 11:28:32 +0100262 if (ioctl(param->fd, SIOCGIFMTU, &ifr) != -1)
Simon Kelley1f15b812009-10-13 17:49:32 +0100263 mtu = ifr.ifr_mtu;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100264
Simon Kelley115ac3e2013-05-20 11:28:32 +0100265 if (!label)
266 label = ifr.ifr_name;
Simon Kelleyc8a80482014-03-05 14:29:54 +0000267
268 /* maintain a list of all addresses on all interfaces for --local-service option */
269 if (option_bool(OPT_LOCAL_SERVICE))
270 {
271 struct addrlist *al;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100272
Simon Kelleyc8a80482014-03-05 14:29:54 +0000273 if (param->spare)
274 {
275 al = param->spare;
276 param->spare = al->next;
277 }
278 else
279 al = whine_malloc(sizeof(struct addrlist));
280
281 if (al)
282 {
283 al->next = daemon->interface_addrs;
284 daemon->interface_addrs = al;
285 al->prefixlen = prefixlen;
286
287 if (addr->sa.sa_family == AF_INET)
288 {
289 al->addr.addr.addr4 = addr->in.sin_addr;
290 al->flags = 0;
291 }
292#ifdef HAVE_IPV6
293 else
294 {
295 al->addr.addr.addr6 = addr->in6.sin6_addr;
296 al->flags = ADDRLIST_IPV6;
297 }
298#endif
299 }
300 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000301
Simon Kelley115ac3e2013-05-20 11:28:32 +0100302#ifdef HAVE_IPV6
303 if (addr->sa.sa_family != AF_INET6 || !IN6_IS_ADDR_LINKLOCAL(&addr->in6.sin6_addr))
304#endif
305 {
306 struct interface_name *int_name;
307 struct addrlist *al;
Simon Kelley376d48c2013-11-13 13:04:30 +0000308#ifdef HAVE_AUTH
309 struct auth_zone *zone;
310 struct auth_name_list *name;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100311
Simon Kelley376d48c2013-11-13 13:04:30 +0000312 /* Find subnets in auth_zones */
313 for (zone = daemon->auth_zones; zone; zone = zone->next)
314 for (name = zone->interface_names; name; name = name->next)
315 if (wildcard_match(name->name, label))
316 {
317 if (addr->sa.sa_family == AF_INET && (name->flags & AUTH4))
318 {
319 if (param->spare)
320 {
321 al = param->spare;
322 param->spare = al->next;
323 }
324 else
325 al = whine_malloc(sizeof(struct addrlist));
326
327 if (al)
328 {
329 al->next = zone->subnet;
330 zone->subnet = al;
331 al->prefixlen = prefixlen;
332 al->addr.addr.addr4 = addr->in.sin_addr;
333 al->flags = 0;
334 }
335 }
336
337#ifdef HAVE_IPV6
338 if (addr->sa.sa_family == AF_INET6 && (name->flags & AUTH6))
339 {
340 if (param->spare)
341 {
342 al = param->spare;
343 param->spare = al->next;
344 }
345 else
346 al = whine_malloc(sizeof(struct addrlist));
347
348 if (al)
349 {
350 al->next = zone->subnet;
351 zone->subnet = al;
Vladislav Grishenko3b195962013-11-26 11:08:21 +0000352 al->prefixlen = prefixlen;
353 al->addr.addr.addr6 = addr->in6.sin6_addr;
Simon Kelley376d48c2013-11-13 13:04:30 +0000354 al->flags = ADDRLIST_IPV6;
355 }
356 }
357#endif
358
359 }
360#endif
361
362 /* Update addresses from interface_names. These are a set independent
363 of the set we're listening on. */
Simon Kelley115ac3e2013-05-20 11:28:32 +0100364 for (int_name = daemon->int_names; int_name; int_name = int_name->next)
Simon Kelleyf7029f52013-11-21 15:09:09 +0000365 if (strncmp(label, int_name->intr, IF_NAMESIZE) == 0 &&
366 (addr->sa.sa_family == int_name->family || int_name->family == 0))
Simon Kelley115ac3e2013-05-20 11:28:32 +0100367 {
368 if (param->spare)
369 {
370 al = param->spare;
371 param->spare = al->next;
372 }
373 else
374 al = whine_malloc(sizeof(struct addrlist));
375
376 if (al)
377 {
Simon Kelley376d48c2013-11-13 13:04:30 +0000378 al->next = int_name->addr;
379 int_name->addr = al;
380
Simon Kelley115ac3e2013-05-20 11:28:32 +0100381 if (addr->sa.sa_family == AF_INET)
382 {
383 al->addr.addr.addr4 = addr->in.sin_addr;
Simon Kelley376d48c2013-11-13 13:04:30 +0000384 al->flags = 0;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100385 }
386#ifdef HAVE_IPV6
387 else
388 {
389 al->addr.addr.addr6 = addr->in6.sin6_addr;
Simon Kelley376d48c2013-11-13 13:04:30 +0000390 al->flags = ADDRLIST_IPV6;
Simon Kelley47669362014-12-17 12:41:56 +0000391 /* Privacy addresses and addresses still undergoing DAD and deprecated addresses
392 don't appear in forward queries, but will in reverse ones. */
393 if (!(iface_flags & IFACE_PERMANENT) || (iface_flags & (IFACE_DEPRECATED | IFACE_TENTATIVE)))
394 al->flags |= ADDRLIST_REVONLY;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100395 }
396#endif
397 }
398 }
399 }
400
401 /* check whether the interface IP has been added already
402 we call this routine multiple times. */
403 for (iface = daemon->interfaces; iface; iface = iface->next)
404 if (sockaddr_isequal(&iface->addr, addr))
405 {
Simon Kelley47669362014-12-17 12:41:56 +0000406 iface->dad = !!(iface_flags & IFACE_TENTATIVE);
Simon Kelley08619212013-12-02 14:43:48 +0000407 iface->found = 1; /* for garbage collection */
Simon Kelley115ac3e2013-05-20 11:28:32 +0100408 return 1;
409 }
410
411 /* If we are restricting the set of interfaces to use, make
Simon Kelley59353a62004-11-21 19:34:28 +0000412 sure that loopback interfaces are in that set. */
Simon Kelley1f15b812009-10-13 17:49:32 +0100413 if (daemon->if_names && loopback)
Simon Kelley59353a62004-11-21 19:34:28 +0000414 {
415 struct iname *lo;
416 for (lo = daemon->if_names; lo; lo = lo->next)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100417 if (lo->name && strcmp(lo->name, ifr.ifr_name) == 0)
Simon Kelley4ce4f372012-06-14 11:50:45 +0100418 break;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100419
Simon Kelley38365ff2013-02-05 14:35:54 +0000420 if (!lo && (lo = whine_malloc(sizeof(struct iname))))
Simon Kelley59353a62004-11-21 19:34:28 +0000421 {
Simon Kelley38365ff2013-02-05 14:35:54 +0000422 if ((lo->name = whine_malloc(strlen(ifr.ifr_name)+1)))
423 {
424 strcpy(lo->name, ifr.ifr_name);
425 lo->used = 1;
426 lo->next = daemon->if_names;
427 daemon->if_names = lo;
428 }
429 else
430 free(lo);
Simon Kelley59353a62004-11-21 19:34:28 +0000431 }
432 }
433
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100434 if (addr->sa.sa_family == AF_INET &&
Simon Kelley3f2873d2013-05-14 11:28:47 +0100435 !iface_check(AF_INET, (struct all_addr *)&addr->in.sin_addr, label, &auth_dns))
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100436 return 1;
Simon Kelley4f7b3042012-11-28 21:27:02 +0000437
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100438#ifdef HAVE_IPV6
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100439 if (addr->sa.sa_family == AF_INET6 &&
Simon Kelley3f2873d2013-05-14 11:28:47 +0100440 !iface_check(AF_INET6, (struct all_addr *)&addr->in6.sin6_addr, label, &auth_dns))
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100441 return 1;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100442#endif
Simon Kelley4f7b3042012-11-28 21:27:02 +0000443
444#ifdef HAVE_DHCP
445 /* No DHCP where we're doing auth DNS. */
446 if (auth_dns)
447 {
448 tftp_ok = 0;
449 dhcp_ok = 0;
450 }
451 else
452 for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
Simon Kelley49333cb2013-03-15 20:30:51 +0000453 if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
Simon Kelley4f7b3042012-11-28 21:27:02 +0000454 {
455 tftp_ok = 0;
456 dhcp_ok = 0;
457 }
458#endif
459
Simon Kelley2937f8a2013-07-29 19:49:07 +0100460
Simon Kelley91543f42013-09-23 12:41:20 +0100461#ifdef HAVE_TFTP
Simon Kelley2937f8a2013-07-29 19:49:07 +0100462 if (daemon->tftp_interfaces)
463 {
464 /* dedicated tftp interface list */
465 tftp_ok = 0;
466 for (tmp = daemon->tftp_interfaces; tmp; tmp = tmp->next)
467 if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
468 tftp_ok = 1;
469 }
Simon Kelley91543f42013-09-23 12:41:20 +0100470#endif
Simon Kelley2937f8a2013-07-29 19:49:07 +0100471
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100472 /* add to list */
Simon Kelley5aabfc72007-08-29 11:24:47 +0100473 if ((iface = whine_malloc(sizeof(struct irec))))
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100474 {
475 iface->addr = *addr;
476 iface->netmask = netmask;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100477 iface->tftp_ok = tftp_ok;
Simon Kelley9380ba72012-04-16 14:41:56 +0100478 iface->dhcp_ok = dhcp_ok;
Simon Kelley4f7b3042012-11-28 21:27:02 +0000479 iface->dns_auth = auth_dns;
Simon Kelley1f15b812009-10-13 17:49:32 +0100480 iface->mtu = mtu;
Simon Kelley47669362014-12-17 12:41:56 +0000481 iface->dad = !!(iface_flags & IFACE_TENTATIVE);
Simon Kelley08619212013-12-02 14:43:48 +0000482 iface->found = 1;
Simon Kelleydc27e142013-10-16 13:09:53 +0100483 iface->done = iface->multicast_done = iface->warned = 0;
Simon Kelley5d162f22012-12-20 14:55:46 +0000484 iface->index = if_index;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100485 if ((iface->name = whine_malloc(strlen(ifr.ifr_name)+1)))
Simon Kelley6f13e532012-04-17 14:25:06 +0100486 {
487 strcpy(iface->name, ifr.ifr_name);
Simon Kelley115ac3e2013-05-20 11:28:32 +0100488 iface->next = daemon->interfaces;
489 daemon->interfaces = iface;
Simon Kelley6f13e532012-04-17 14:25:06 +0100490 return 1;
491 }
492 free(iface);
Simon Kelley5d162f22012-12-20 14:55:46 +0000493
Simon Kelley44a2a312004-03-10 20:04:35 +0000494 }
495
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100496 errno = ENOMEM;
497 return 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000498}
499
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100500#ifdef HAVE_IPV6
Simon Kelleyc72daea2012-01-05 21:33:27 +0000501static int iface_allowed_v6(struct in6_addr *local, int prefix,
Simon Kelleybad7b872012-12-20 22:00:39 +0000502 int scope, int if_index, int flags,
Simon Kelley1f776932012-12-16 19:46:08 +0000503 int preferred, int valid, void *vparam)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000504{
Simon Kelley59353a62004-11-21 19:34:28 +0000505 union mysockaddr addr;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100506 struct in_addr netmask; /* dummy */
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100507 netmask.s_addr = 0;
Simon Kelley52b92f42012-01-22 16:05:15 +0000508
Simon Kelley52b92f42012-01-22 16:05:15 +0000509 (void)scope; /* warning */
Simon Kelley1f776932012-12-16 19:46:08 +0000510 (void)preferred;
511 (void)valid;
Simon Kelley44a2a312004-03-10 20:04:35 +0000512
Simon Kelley849a8352006-06-09 21:02:31 +0100513 memset(&addr, 0, sizeof(addr));
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000514#ifdef HAVE_SOCKADDR_SA_LEN
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100515 addr.in6.sin6_len = sizeof(addr.in6);
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000516#endif
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100517 addr.in6.sin6_family = AF_INET6;
518 addr.in6.sin6_addr = *local;
519 addr.in6.sin6_port = htons(daemon->port);
Simon Kelley62ab3cc2013-12-03 11:53:53 +0000520 /* FreeBSD insists this is zero for non-linklocal addresses */
521 if (IN6_IS_ADDR_LINKLOCAL(local))
522 addr.in6.sin6_scope_id = if_index;
523 else
524 addr.in6.sin6_scope_id = 0;
Simon Kelley1ee9be42013-12-09 16:50:19 +0000525
Simon Kelley47669362014-12-17 12:41:56 +0000526 return iface_allowed((struct iface_param *)vparam, if_index, NULL, &addr, netmask, prefix, flags);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100527}
528#endif
Simon Kelley59353a62004-11-21 19:34:28 +0000529
Simon Kelley3f2873d2013-05-14 11:28:47 +0100530static int iface_allowed_v4(struct in_addr local, int if_index, char *label,
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100531 struct in_addr netmask, struct in_addr broadcast, void *vparam)
532{
533 union mysockaddr addr;
Simon Kelley376d48c2013-11-13 13:04:30 +0000534 int prefix, bit;
Simon Kelley849a8352006-06-09 21:02:31 +0100535
536 memset(&addr, 0, sizeof(addr));
Simon Kelley1ab84e22004-01-29 16:48:35 +0000537#ifdef HAVE_SOCKADDR_SA_LEN
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100538 addr.in.sin_len = sizeof(addr.in);
Simon Kelley1ab84e22004-01-29 16:48:35 +0000539#endif
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100540 addr.in.sin_family = AF_INET;
541 addr.in.sin_addr = broadcast; /* warning */
542 addr.in.sin_addr = local;
543 addr.in.sin_port = htons(daemon->port);
Simon Kelley44a2a312004-03-10 20:04:35 +0000544
Simon Kelley376d48c2013-11-13 13:04:30 +0000545 /* determine prefix length from netmask */
546 for (prefix = 32, bit = 1; (bit & ntohl(netmask.s_addr)) == 0 && prefix != 0; bit = bit << 1, prefix--);
547
548 return iface_allowed((struct iface_param *)vparam, if_index, label, &addr, netmask, prefix, 0);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100549}
550
Simon Kelley115ac3e2013-05-20 11:28:32 +0100551int enumerate_interfaces(int reset)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100552{
Simon Kelley115ac3e2013-05-20 11:28:32 +0100553 static struct addrlist *spare = NULL;
Simon Kelleya0358e52014-06-07 13:38:48 +0100554 static int done = 0;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100555 struct iface_param param;
556 int errsave, ret = 1;
557 struct addrlist *addr, *tmp;
558 struct interface_name *intname;
Simon Kelley08619212013-12-02 14:43:48 +0000559 struct irec *iface;
Simon Kelley376d48c2013-11-13 13:04:30 +0000560#ifdef HAVE_AUTH
561 struct auth_zone *zone;
562#endif
563
Simon Kelley76dd75d2013-05-23 10:04:25 +0100564 /* Do this max once per select cycle - also inhibits netlink socket use
565 in TCP child processes. */
Simon Kelley397542b2013-09-05 11:27:34 +0100566
Simon Kelley115ac3e2013-05-20 11:28:32 +0100567 if (reset)
568 {
569 done = 0;
570 return 1;
571 }
572
Simon Kelleya0358e52014-06-07 13:38:48 +0100573 if (done)
Simon Kelley115ac3e2013-05-20 11:28:32 +0100574 return 1;
575
576 done = 1;
577
578 if ((param.fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
579 return 0;
580
Simon Kelley08619212013-12-02 14:43:48 +0000581 /* Mark interfaces for garbage collection */
582 for (iface = daemon->interfaces; iface; iface = iface->next)
583 iface->found = 0;
584
Simon Kelley115ac3e2013-05-20 11:28:32 +0100585 /* remove addresses stored against interface_names */
586 for (intname = daemon->int_names; intname; intname = intname->next)
587 {
Simon Kelley376d48c2013-11-13 13:04:30 +0000588 for (addr = intname->addr; addr; addr = tmp)
Simon Kelley115ac3e2013-05-20 11:28:32 +0100589 {
590 tmp = addr->next;
591 addr->next = spare;
592 spare = addr;
593 }
594
Simon Kelley376d48c2013-11-13 13:04:30 +0000595 intname->addr = NULL;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100596 }
Simon Kelley376d48c2013-11-13 13:04:30 +0000597
Simon Kelleyc8a80482014-03-05 14:29:54 +0000598 /* Remove list of addresses of local interfaces */
599 for (addr = daemon->interface_addrs; addr; addr = tmp)
600 {
601 tmp = addr->next;
602 addr->next = spare;
603 spare = addr;
604 }
605 daemon->interface_addrs = NULL;
606
Simon Kelley376d48c2013-11-13 13:04:30 +0000607#ifdef HAVE_AUTH
608 /* remove addresses stored against auth_zone subnets, but not
609 ones configured as address literals */
610 for (zone = daemon->auth_zones; zone; zone = zone->next)
611 if (zone->interface_names)
612 {
613 struct addrlist **up;
614 for (up = &zone->subnet, addr = zone->subnet; addr; addr = tmp)
615 {
616 tmp = addr->next;
617 if (addr->flags & ADDRLIST_LITERAL)
618 up = &addr->next;
619 else
620 {
621 *up = addr->next;
622 addr->next = spare;
623 spare = addr;
624 }
625 }
626 }
627#endif
628
Simon Kelley115ac3e2013-05-20 11:28:32 +0100629 param.spare = spare;
630
631#ifdef HAVE_IPV6
632 ret = iface_enumerate(AF_INET6, &param, iface_allowed_v6);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100633#endif
Simon Kelley28866e92011-02-14 20:19:14 +0000634
Simon Kelley115ac3e2013-05-20 11:28:32 +0100635 if (ret)
636 ret = iface_enumerate(AF_INET, &param, iface_allowed_v4);
637
638 errsave = errno;
639 close(param.fd);
Simon Kelley08619212013-12-02 14:43:48 +0000640
641 if (option_bool(OPT_CLEVERBIND))
642 {
643 /* Garbage-collect listeners listening on addresses that no longer exist.
644 Does nothing when not binding interfaces or for listeners on localhost,
645 since the ->iface field is NULL. Note that this needs the protections
646 against re-entrancy, hence it's here. It also means there's a possibility,
647 in OPT_CLEVERBIND mode, that at listener will just disappear after
648 a call to enumerate_interfaces, this is checked OK on all calls. */
649 struct listener *l, *tmp, **up;
650
651 for (up = &daemon->listeners, l = daemon->listeners; l; l = tmp)
652 {
653 tmp = l->next;
654
655 if (!l->iface || l->iface->found)
656 up = &l->next;
657 else
658 {
659 *up = l->next;
660
661 /* In case it ever returns */
662 l->iface->done = 0;
663
664 if (l->fd != -1)
665 close(l->fd);
666 if (l->tcpfd != -1)
667 close(l->tcpfd);
668 if (l->tftpfd != -1)
669 close(l->tftpfd);
670
671 free(l);
672 }
673 }
674 }
675
Simon Kelley115ac3e2013-05-20 11:28:32 +0100676 errno = errsave;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100677 spare = param.spare;
Simon Kelleya0358e52014-06-07 13:38:48 +0100678
Simon Kelley115ac3e2013-05-20 11:28:32 +0100679 return ret;
Simon Kelley44a2a312004-03-10 20:04:35 +0000680}
681
Simon Kelley5aabfc72007-08-29 11:24:47 +0100682/* set NONBLOCK bit on fd: See Stevens 16.6 */
Simon Kelley7cebd202006-05-06 14:13:33 +0100683int fix_fd(int fd)
684{
685 int flags;
686
687 if ((flags = fcntl(fd, F_GETFL)) == -1 ||
Simon Kelley5aabfc72007-08-29 11:24:47 +0100688 fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
Simon Kelley7cebd202006-05-06 14:13:33 +0100689 return 0;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100690
Simon Kelley7cebd202006-05-06 14:13:33 +0100691 return 1;
692}
693
Simon Kelley74c95c22011-10-19 09:33:39 +0100694static int make_sock(union mysockaddr *addr, int type, int dienow)
Simon Kelley44a2a312004-03-10 20:04:35 +0000695{
Simon Kelley28866e92011-02-14 20:19:14 +0000696 int family = addr->sa.sa_family;
697 int fd, rc, opt = 1;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100698
Simon Kelley28866e92011-02-14 20:19:14 +0000699 if ((fd = socket(family, type, 0)) == -1)
Simon Kelley316e2732010-01-22 20:16:09 +0000700 {
Matthias Andree71aaa5a2013-12-03 11:20:45 +0000701 int port, errsav;
Simon Kelley39f1b8e2012-06-20 20:04:27 +0100702 char *s;
Simon Kelley28866e92011-02-14 20:19:14 +0000703
704 /* No error if the kernel just doesn't support this IP flavour */
705 if (errno == EPROTONOSUPPORT ||
706 errno == EAFNOSUPPORT ||
707 errno == EINVAL)
708 return -1;
709
710 err:
Matthias Andree71aaa5a2013-12-03 11:20:45 +0000711 errsav = errno;
Simon Kelley39f1b8e2012-06-20 20:04:27 +0100712 port = prettyprint_addr(addr, daemon->addrbuff);
713 if (!option_bool(OPT_NOWILD) && !option_bool(OPT_CLEVERBIND))
714 sprintf(daemon->addrbuff, "port %d", port);
715 s = _("failed to create listening socket for %s: %s");
716
Simon Kelley5f11b3e2012-08-16 14:04:05 +0100717 if (fd != -1)
Matthias Andree71aaa5a2013-12-03 11:20:45 +0000718 close (fd);
719
720 errno = errsav;
Simon Kelley1ee9be42013-12-09 16:50:19 +0000721
Simon Kelley5f11b3e2012-08-16 14:04:05 +0100722 if (dienow)
723 {
724 /* failure to bind addresses given by --listen-address at this point
725 is OK if we're doing bind-dynamic */
726 if (!option_bool(OPT_CLEVERBIND))
727 die(s, daemon->addrbuff, EC_BADNET);
728 }
729 else
730 my_syslog(LOG_WARNING, s, daemon->addrbuff, strerror(errno));
731
Simon Kelley74c95c22011-10-19 09:33:39 +0100732 return -1;
Simon Kelley28866e92011-02-14 20:19:14 +0000733 }
Simon Kelley5f11b3e2012-08-16 14:04:05 +0100734
Simon Kelley28866e92011-02-14 20:19:14 +0000735 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || !fix_fd(fd))
736 goto err;
737
738#ifdef HAVE_IPV6
Simon Kelleyc72daea2012-01-05 21:33:27 +0000739 if (family == AF_INET6 && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)) == -1)
Simon Kelley28866e92011-02-14 20:19:14 +0000740 goto err;
741#endif
742
Simon Kelley74c95c22011-10-19 09:33:39 +0100743 if ((rc = bind(fd, (struct sockaddr *)addr, sa_len(addr))) == -1)
Simon Kelley28866e92011-02-14 20:19:14 +0000744 goto err;
745
746 if (type == SOCK_STREAM)
747 {
748 if (listen(fd, 5) == -1)
749 goto err;
750 }
Simon Kelley2329bef2013-12-03 13:41:16 +0000751 else if (family == AF_INET)
Simon Kelley28866e92011-02-14 20:19:14 +0000752 {
Simon Kelley2329bef2013-12-03 13:41:16 +0000753 if (!option_bool(OPT_NOWILD))
Simon Kelley28866e92011-02-14 20:19:14 +0000754 {
755#if defined(HAVE_LINUX_NETWORK)
Simon Kelleyc72daea2012-01-05 21:33:27 +0000756 if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) == -1)
Simon Kelley28866e92011-02-14 20:19:14 +0000757 goto err;
758#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
759 if (setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt)) == -1 ||
760 setsockopt(fd, IPPROTO_IP, IP_RECVIF, &opt, sizeof(opt)) == -1)
761 goto err;
762#endif
763 }
Simon Kelley28866e92011-02-14 20:19:14 +0000764 }
Simon Kelley2329bef2013-12-03 13:41:16 +0000765#ifdef HAVE_IPV6
766 else if (!set_ipv6pktinfo(fd))
767 goto err;
768#endif
Simon Kelleyc72daea2012-01-05 21:33:27 +0000769
Simon Kelley28866e92011-02-14 20:19:14 +0000770 return fd;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100771}
Simon Kelleyc72daea2012-01-05 21:33:27 +0000772
773#ifdef HAVE_IPV6
774int set_ipv6pktinfo(int fd)
775{
776 int opt = 1;
777
778 /* The API changed around Linux 2.6.14 but the old ABI is still supported:
779 handle all combinations of headers and kernel.
780 OpenWrt note that this fixes the problem addressed by your very broken patch. */
781 daemon->v6pktinfo = IPV6_PKTINFO;
782
783#ifdef IPV6_RECVPKTINFO
784 if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &opt, sizeof(opt)) != -1)
785 return 1;
786# ifdef IPV6_2292PKTINFO
787 else if (errno == ENOPROTOOPT && setsockopt(fd, IPPROTO_IPV6, IPV6_2292PKTINFO, &opt, sizeof(opt)) != -1)
788 {
789 daemon->v6pktinfo = IPV6_2292PKTINFO;
790 return 1;
791 }
792# endif
793#else
794 if (setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &opt, sizeof(opt)) != -1)
795 return 1;
796#endif
797
798 return 0;
799}
800#endif
Simon Kelley22ce5502013-01-22 13:53:04 +0000801
802
803/* Find the interface on which a TCP connection arrived, if possible, or zero otherwise. */
804int tcp_interface(int fd, int af)
805{
806 int if_index = 0;
807
808#ifdef HAVE_LINUX_NETWORK
809 int opt = 1;
810 struct cmsghdr *cmptr;
811 struct msghdr msg;
812
813 /* use mshdr do that the CMSDG_* macros are available */
814 msg.msg_control = daemon->packet;
815 msg.msg_controllen = daemon->packet_buff_sz;
816
817 /* we overwrote the buffer... */
818 daemon->srv_save = NULL;
819
820 if (af == AF_INET)
821 {
822 if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) != -1 &&
823 getsockopt(fd, IPPROTO_IP, IP_PKTOPTIONS, msg.msg_control, (socklen_t *)&msg.msg_controllen) != -1)
824 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
825 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
826 {
827 union {
828 unsigned char *c;
829 struct in_pktinfo *p;
830 } p;
831
832 p.c = CMSG_DATA(cmptr);
833 if_index = p.p->ipi_ifindex;
834 }
835 }
836#ifdef HAVE_IPV6
837 else
838 {
839 /* Only the RFC-2292 API has the ability to find the interface for TCP connections,
840 it was removed in RFC-3542 !!!!
841
842 Fortunately, Linux kept the 2292 ABI when it moved to 3542. The following code always
843 uses the old ABI, and should work with pre- and post-3542 kernel headers */
844
845#ifdef IPV6_2292PKTOPTIONS
846# define PKTOPTIONS IPV6_2292PKTOPTIONS
847#else
848# define PKTOPTIONS IPV6_PKTOPTIONS
849#endif
850
851 if (set_ipv6pktinfo(fd) &&
852 getsockopt(fd, IPPROTO_IPV6, PKTOPTIONS, msg.msg_control, (socklen_t *)&msg.msg_controllen) != -1)
853 {
854 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
855 if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
856 {
857 union {
858 unsigned char *c;
859 struct in6_pktinfo *p;
860 } p;
861 p.c = CMSG_DATA(cmptr);
862
863 if_index = p.p->ipi6_ifindex;
864 }
865 }
866 }
867#endif /* IPV6 */
868#endif /* Linux */
869
870 return if_index;
871}
Simon Kelley28866e92011-02-14 20:19:14 +0000872
Simon Kelley74c95c22011-10-19 09:33:39 +0100873static struct listener *create_listeners(union mysockaddr *addr, int do_tftp, int dienow)
Simon Kelley28866e92011-02-14 20:19:14 +0000874{
875 struct listener *l = NULL;
876 int fd = -1, tcpfd = -1, tftpfd = -1;
877
Vladislav Grishenko408c3682013-09-24 16:18:49 +0100878 (void)do_tftp;
879
Simon Kelley28866e92011-02-14 20:19:14 +0000880 if (daemon->port != 0)
881 {
Simon Kelley74c95c22011-10-19 09:33:39 +0100882 fd = make_sock(addr, SOCK_DGRAM, dienow);
883 tcpfd = make_sock(addr, SOCK_STREAM, dienow);
Simon Kelley28866e92011-02-14 20:19:14 +0000884 }
885
886#ifdef HAVE_TFTP
887 if (do_tftp)
888 {
889 if (addr->sa.sa_family == AF_INET)
890 {
891 /* port must be restored to DNS port for TCP code */
892 short save = addr->in.sin_port;
893 addr->in.sin_port = htons(TFTP_PORT);
Simon Kelley74c95c22011-10-19 09:33:39 +0100894 tftpfd = make_sock(addr, SOCK_DGRAM, dienow);
Simon Kelley28866e92011-02-14 20:19:14 +0000895 addr->in.sin_port = save;
896 }
897# ifdef HAVE_IPV6
898 else
899 {
900 short save = addr->in6.sin6_port;
901 addr->in6.sin6_port = htons(TFTP_PORT);
Simon Kelley74c95c22011-10-19 09:33:39 +0100902 tftpfd = make_sock(addr, SOCK_DGRAM, dienow);
Simon Kelley28866e92011-02-14 20:19:14 +0000903 addr->in6.sin6_port = save;
904 }
905# endif
906 }
Simon Kelley44a2a312004-03-10 20:04:35 +0000907#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100908
Simon Kelley28866e92011-02-14 20:19:14 +0000909 if (fd != -1 || tcpfd != -1 || tftpfd != -1)
910 {
911 l = safe_malloc(sizeof(struct listener));
912 l->next = NULL;
913 l->family = addr->sa.sa_family;
914 l->fd = fd;
915 l->tcpfd = tcpfd;
Simon Kelley08619212013-12-02 14:43:48 +0000916 l->tftpfd = tftpfd;
917 l->iface = NULL;
Simon Kelley28866e92011-02-14 20:19:14 +0000918 }
919
920 return l;
921}
922
Simon Kelley74c95c22011-10-19 09:33:39 +0100923void create_wildcard_listeners(void)
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100924{
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100925 union mysockaddr addr;
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100926 struct listener *l, *l6;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100927
Simon Kelley849a8352006-06-09 21:02:31 +0100928 memset(&addr, 0, sizeof(addr));
Simon Kelley28866e92011-02-14 20:19:14 +0000929#ifdef HAVE_SOCKADDR_SA_LEN
930 addr.in.sin_len = sizeof(addr.in);
931#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100932 addr.in.sin_family = AF_INET;
933 addr.in.sin_addr.s_addr = INADDR_ANY;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100934 addr.in.sin_port = htons(daemon->port);
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100935
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100936 l = create_listeners(&addr, !!option_bool(OPT_TFTP), 1);
Simon Kelley28866e92011-02-14 20:19:14 +0000937
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100938#ifdef HAVE_IPV6
Simon Kelley28866e92011-02-14 20:19:14 +0000939 memset(&addr, 0, sizeof(addr));
940# ifdef HAVE_SOCKADDR_SA_LEN
941 addr.in6.sin6_len = sizeof(addr.in6);
942# endif
943 addr.in6.sin6_family = AF_INET6;
944 addr.in6.sin6_addr = in6addr_any;
945 addr.in6.sin6_port = htons(daemon->port);
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100946
947 l6 = create_listeners(&addr, !!option_bool(OPT_TFTP), 1);
Simon Kelley28866e92011-02-14 20:19:14 +0000948 if (l)
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100949 l->next = l6;
Simon Kelley28866e92011-02-14 20:19:14 +0000950 else
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100951 l = l6;
Simon Kelley832af0b2007-01-21 20:01:28 +0000952#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100953
Simon Kelley74c95c22011-10-19 09:33:39 +0100954 daemon->listeners = l;
Simon Kelley44a2a312004-03-10 20:04:35 +0000955}
956
Simon Kelley74c95c22011-10-19 09:33:39 +0100957void create_bound_listeners(int dienow)
Simon Kelley44a2a312004-03-10 20:04:35 +0000958{
Simon Kelley74c95c22011-10-19 09:33:39 +0100959 struct listener *new;
Simon Kelley44a2a312004-03-10 20:04:35 +0000960 struct irec *iface;
Simon Kelley52d4abf2012-03-21 21:39:48 +0000961 struct iname *if_tmp;
Simon Kelley73a08a22009-02-05 20:28:08 +0000962
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100963 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelley08619212013-12-02 14:43:48 +0000964 if (!iface->done && !iface->dad && iface->found &&
Simon Kelley74c95c22011-10-19 09:33:39 +0100965 (new = create_listeners(&iface->addr, iface->tftp_ok, dienow)))
Simon Kelley28866e92011-02-14 20:19:14 +0000966 {
967 new->iface = iface;
Simon Kelley74c95c22011-10-19 09:33:39 +0100968 new->next = daemon->listeners;
969 daemon->listeners = new;
970 iface->done = 1;
Simon Kelley28866e92011-02-14 20:19:14 +0000971 }
Simon Kelley52d4abf2012-03-21 21:39:48 +0000972
973 /* Check for --listen-address options that haven't been used because there's
974 no interface with a matching address. These may be valid: eg it's possible
975 to listen on 127.0.1.1 even if the loopback interface is 127.0.0.1
976
Simon Kelley5f11b3e2012-08-16 14:04:05 +0100977 If the address isn't valid the bind() will fail and we'll die()
978 (except in bind-dynamic mode, when we'll complain but keep trying.)
Simon Kelley52d4abf2012-03-21 21:39:48 +0000979
980 The resulting listeners have the ->iface field NULL, and this has to be
981 handled by the DNS and TFTP code. It disables --localise-queries processing
982 (no netmask) and some MTU login the tftp code. */
983
984 for (if_tmp = daemon->if_addrs; if_tmp; if_tmp = if_tmp->next)
985 if (!if_tmp->used &&
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100986 (new = create_listeners(&if_tmp->addr, !!option_bool(OPT_TFTP), dienow)))
Simon Kelley52d4abf2012-03-21 21:39:48 +0000987 {
Simon Kelley52d4abf2012-03-21 21:39:48 +0000988 new->next = daemon->listeners;
989 daemon->listeners = new;
990 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000991}
992
Simon Kelleydc27e142013-10-16 13:09:53 +0100993/* In --bind-interfaces, the only access control is the addresses we're listening on.
994 There's nothing to avoid a query to the address of an internal interface arriving via
995 an external interface where we don't want to accept queries, except that in the usual
996 case the addresses of internal interfaces are RFC1918. When bind-interfaces in use,
997 and we listen on an address that looks like it's probably globally routeable, shout.
998
999 The fix is to use --bind-dynamic, which actually checks the arrival interface too.
1000 Tough if your platform doesn't support this.
Simon Kelley2329bef2013-12-03 13:41:16 +00001001
1002 Note that checking the arrival interface is supported in the standard IPv6 API and
1003 always done, so we don't warn about any IPv6 addresses here.
Simon Kelleydc27e142013-10-16 13:09:53 +01001004*/
1005
1006void warn_bound_listeners(void)
1007{
1008 struct irec *iface;
1009 int advice = 0;
1010
1011 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelleyf7029f52013-11-21 15:09:09 +00001012 if (!iface->dns_auth)
Simon Kelleydc27e142013-10-16 13:09:53 +01001013 {
Simon Kelleydc27e142013-10-16 13:09:53 +01001014 if (iface->addr.sa.sa_family == AF_INET)
1015 {
1016 if (!private_net(iface->addr.in.sin_addr, 1))
1017 {
1018 inet_ntop(AF_INET, &iface->addr.in.sin_addr, daemon->addrbuff, ADDRSTRLEN);
Simon Kelley2329bef2013-12-03 13:41:16 +00001019 iface->warned = advice = 1;
1020 my_syslog(LOG_WARNING,
1021 _("LOUD WARNING: listening on %s may accept requests via interfaces other than %s"),
1022 daemon->addrbuff, iface->name);
Simon Kelleydc27e142013-10-16 13:09:53 +01001023 }
1024 }
Simon Kelleydc27e142013-10-16 13:09:53 +01001025 }
1026
1027 if (advice)
Simon Kelleyf7029f52013-11-21 15:09:09 +00001028 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 +01001029}
1030
Simon Kelleyf7029f52013-11-21 15:09:09 +00001031void warn_int_names(void)
1032{
1033 struct interface_name *intname;
1034
1035 for (intname = daemon->int_names; intname; intname = intname->next)
1036 if (!intname->addr)
1037 my_syslog(LOG_WARNING, _("warning: no addresses found for interface %s"), intname->intr);
1038}
1039
Simon Kelley74c95c22011-10-19 09:33:39 +01001040int is_dad_listeners(void)
1041{
1042 struct irec *iface;
1043
1044 if (option_bool(OPT_NOWILD))
1045 for (iface = daemon->interfaces; iface; iface = iface->next)
1046 if (iface->dad && !iface->done)
1047 return 1;
1048
1049 return 0;
1050}
Simon Kelley5d162f22012-12-20 14:55:46 +00001051
1052#ifdef HAVE_DHCP6
1053void join_multicast(int dienow)
1054{
1055 struct irec *iface, *tmp;
1056
1057 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelley19624462012-12-28 11:18:09 +00001058 if (iface->addr.sa.sa_family == AF_INET6 && iface->dhcp_ok && !iface->multicast_done)
Simon Kelley5d162f22012-12-20 14:55:46 +00001059 {
1060 /* There's an irec per address but we only want to join for multicast
1061 once per interface. Weed out duplicates. */
1062 for (tmp = daemon->interfaces; tmp; tmp = tmp->next)
1063 if (tmp->multicast_done && tmp->index == iface->index)
1064 break;
1065
1066 iface->multicast_done = 1;
1067
1068 if (!tmp)
1069 {
1070 struct ipv6_mreq mreq;
1071 int err = 0;
1072
1073 mreq.ipv6mr_interface = iface->index;
1074
1075 inet_pton(AF_INET6, ALL_RELAY_AGENTS_AND_SERVERS, &mreq.ipv6mr_multiaddr);
1076
Simon Kelleyff7eea22013-09-04 18:01:38 +01001077 if ((daemon->doing_dhcp6 || daemon->relay6) &&
Simon Kelley5d162f22012-12-20 14:55:46 +00001078 setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
Simon Kelley9cdcfe92015-08-26 22:38:08 +01001079 err = errno;
Simon Kelley5d162f22012-12-20 14:55:46 +00001080
1081 inet_pton(AF_INET6, ALL_SERVERS, &mreq.ipv6mr_multiaddr);
1082
1083 if (daemon->doing_dhcp6 &&
1084 setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
Simon Kelley9cdcfe92015-08-26 22:38:08 +01001085 err = errno;
Simon Kelley5d162f22012-12-20 14:55:46 +00001086
1087 inet_pton(AF_INET6, ALL_ROUTERS, &mreq.ipv6mr_multiaddr);
1088
1089 if (daemon->doing_ra &&
1090 setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
Simon Kelley9cdcfe92015-08-26 22:38:08 +01001091 err = errno;
Simon Kelley5d162f22012-12-20 14:55:46 +00001092
1093 if (err)
1094 {
1095 char *s = _("interface %s failed to join DHCPv6 multicast group: %s");
Simon Kelley9cdcfe92015-08-26 22:38:08 +01001096 errno = err;
1097
1098#ifdef HAVE_LINUX_NETWORK
1099 if (errno == ENOMEM)
1100 my_syslog(LOG_ERR, _("try increasing /proc/sys/net/core/optmem_max"));
1101#endif
1102
Simon Kelley5d162f22012-12-20 14:55:46 +00001103 if (dienow)
1104 die(s, iface->name, EC_BADNET);
1105 else
1106 my_syslog(LOG_ERR, s, iface->name, strerror(errno));
1107 }
1108 }
1109 }
1110}
1111#endif
1112
Simon Kelley9009d742008-11-14 20:04:27 +00001113/* return a UDP socket bound to a random port, have to cope with straying into
Simon Kelley1a6bca82008-07-11 11:11:42 +01001114 occupied port nos and reserved ones. */
1115int random_sock(int family)
1116{
1117 int fd;
1118
1119 if ((fd = socket(family, SOCK_DGRAM, 0)) != -1)
1120 {
Simon Kelley3927da42008-07-20 15:10:39 +01001121 union mysockaddr addr;
Simon Kelley1ad24ae2008-07-20 20:22:50 +01001122 unsigned int ports_avail = 65536u - (unsigned short)daemon->min_port;
Simon Kelley9009d742008-11-14 20:04:27 +00001123 int tries = ports_avail < 30 ? 3 * ports_avail : 100;
Simon Kelley3927da42008-07-20 15:10:39 +01001124
Simon Kelley1a6bca82008-07-11 11:11:42 +01001125 memset(&addr, 0, sizeof(addr));
Simon Kelley3927da42008-07-20 15:10:39 +01001126 addr.sa.sa_family = family;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001127
Simon Kelley1ad24ae2008-07-20 20:22:50 +01001128 /* don't loop forever if all ports in use. */
1129
Simon Kelley1a6bca82008-07-11 11:11:42 +01001130 if (fix_fd(fd))
Simon Kelley9009d742008-11-14 20:04:27 +00001131 while(tries--)
Simon Kelley1a6bca82008-07-11 11:11:42 +01001132 {
1133 unsigned short port = rand16();
1134
Simon Kelley3927da42008-07-20 15:10:39 +01001135 if (daemon->min_port != 0)
Simon Kelley1ad24ae2008-07-20 20:22:50 +01001136 port = htons(daemon->min_port + (port % ((unsigned short)ports_avail)));
Simon Kelley1a6bca82008-07-11 11:11:42 +01001137
1138 if (family == AF_INET)
1139 {
1140 addr.in.sin_addr.s_addr = INADDR_ANY;
Simon Kelley3927da42008-07-20 15:10:39 +01001141 addr.in.sin_port = port;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001142#ifdef HAVE_SOCKADDR_SA_LEN
1143 addr.in.sin_len = sizeof(struct sockaddr_in);
1144#endif
1145 }
1146#ifdef HAVE_IPV6
1147 else
1148 {
1149 addr.in6.sin6_addr = in6addr_any;
Simon Kelley3927da42008-07-20 15:10:39 +01001150 addr.in6.sin6_port = port;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001151#ifdef HAVE_SOCKADDR_SA_LEN
1152 addr.in6.sin6_len = sizeof(struct sockaddr_in6);
1153#endif
1154 }
1155#endif
1156
1157 if (bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == 0)
1158 return fd;
1159
1160 if (errno != EADDRINUSE && errno != EACCES)
1161 break;
1162 }
1163
1164 close(fd);
1165 }
1166
1167 return -1;
1168}
1169
1170
Simon Kelley824af852008-02-12 20:43:05 +00001171int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp)
1172{
1173 union mysockaddr addr_copy = *addr;
1174
1175 /* cannot set source _port_ for TCP connections. */
1176 if (is_tcp)
1177 {
1178 if (addr_copy.sa.sa_family == AF_INET)
1179 addr_copy.in.sin_port = 0;
1180#ifdef HAVE_IPV6
1181 else
1182 addr_copy.in6.sin6_port = 0;
1183#endif
1184 }
1185
1186 if (bind(fd, (struct sockaddr *)&addr_copy, sa_len(&addr_copy)) == -1)
1187 return 0;
1188
1189#if defined(SO_BINDTODEVICE)
Simon Kelley73a08a22009-02-05 20:28:08 +00001190 if (intname[0] != 0 &&
Simon Kelley316e2732010-01-22 20:16:09 +00001191 setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, intname, IF_NAMESIZE) == -1)
Simon Kelley824af852008-02-12 20:43:05 +00001192 return 0;
1193#endif
1194
1195 return 1;
1196}
1197
1198static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001199{
1200 struct serverfd *sfd;
Simon Kelley824af852008-02-12 20:43:05 +00001201 int errsave;
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001202
Simon Kelley1a6bca82008-07-11 11:11:42 +01001203 /* when using random ports, servers which would otherwise use
1204 the INADDR_ANY/port0 socket have sfd set to NULL */
Simon Kelley73a08a22009-02-05 20:28:08 +00001205 if (!daemon->osport && intname[0] == 0)
Simon Kelley1a6bca82008-07-11 11:11:42 +01001206 {
1207 errno = 0;
1208
1209 if (addr->sa.sa_family == AF_INET &&
1210 addr->in.sin_addr.s_addr == INADDR_ANY &&
1211 addr->in.sin_port == htons(0))
1212 return NULL;
1213
1214#ifdef HAVE_IPV6
1215 if (addr->sa.sa_family == AF_INET6 &&
1216 memcmp(&addr->in6.sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0 &&
1217 addr->in6.sin6_port == htons(0))
1218 return NULL;
1219#endif
1220 }
1221
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001222 /* may have a suitable one already */
Simon Kelley824af852008-02-12 20:43:05 +00001223 for (sfd = daemon->sfds; sfd; sfd = sfd->next )
1224 if (sockaddr_isequal(&sfd->source_addr, addr) &&
1225 strcmp(intname, sfd->interface) == 0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001226 return sfd;
1227
1228 /* need to make a new one. */
1229 errno = ENOMEM; /* in case malloc fails. */
Simon Kelley5aabfc72007-08-29 11:24:47 +01001230 if (!(sfd = whine_malloc(sizeof(struct serverfd))))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001231 return NULL;
1232
1233 if ((sfd->fd = socket(addr->sa.sa_family, SOCK_DGRAM, 0)) == -1)
1234 {
1235 free(sfd);
1236 return NULL;
1237 }
1238
Simon Kelley824af852008-02-12 20:43:05 +00001239 if (!local_bind(sfd->fd, addr, intname, 0) || !fix_fd(sfd->fd))
1240 {
1241 errsave = errno; /* save error from bind. */
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001242 close(sfd->fd);
1243 free(sfd);
1244 errno = errsave;
1245 return NULL;
1246 }
Simon Kelley824af852008-02-12 20:43:05 +00001247
1248 strcpy(sfd->interface, intname);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001249 sfd->source_addr = *addr;
Simon Kelley824af852008-02-12 20:43:05 +00001250 sfd->next = daemon->sfds;
1251 daemon->sfds = sfd;
1252 return sfd;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001253}
1254
Simon Kelley824af852008-02-12 20:43:05 +00001255/* create upstream sockets during startup, before root is dropped which may be needed
1256 this allows query_port to be a low port and interface binding */
1257void pre_allocate_sfds(void)
1258{
1259 struct server *srv;
1260
1261 if (daemon->query_port != 0)
1262 {
1263 union mysockaddr addr;
1264 memset(&addr, 0, sizeof(addr));
1265 addr.in.sin_family = AF_INET;
1266 addr.in.sin_addr.s_addr = INADDR_ANY;
1267 addr.in.sin_port = htons(daemon->query_port);
1268#ifdef HAVE_SOCKADDR_SA_LEN
1269 addr.in.sin_len = sizeof(struct sockaddr_in);
1270#endif
1271 allocate_sfd(&addr, "");
1272#ifdef HAVE_IPV6
1273 memset(&addr, 0, sizeof(addr));
1274 addr.in6.sin6_family = AF_INET6;
1275 addr.in6.sin6_addr = in6addr_any;
1276 addr.in6.sin6_port = htons(daemon->query_port);
1277#ifdef HAVE_SOCKADDR_SA_LEN
1278 addr.in6.sin6_len = sizeof(struct sockaddr_in6);
1279#endif
1280 allocate_sfd(&addr, "");
1281#endif
1282 }
1283
1284 for (srv = daemon->servers; srv; srv = srv->next)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001285 if (!(srv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)) &&
Simon Kelley824af852008-02-12 20:43:05 +00001286 !allocate_sfd(&srv->source_addr, srv->interface) &&
Simon Kelley1a6bca82008-07-11 11:11:42 +01001287 errno != 0 &&
Simon Kelley28866e92011-02-14 20:19:14 +00001288 option_bool(OPT_NOWILD))
Simon Kelley824af852008-02-12 20:43:05 +00001289 {
Simon Kelley316e2732010-01-22 20:16:09 +00001290 prettyprint_addr(&srv->source_addr, daemon->namebuff);
Simon Kelley73a08a22009-02-05 20:28:08 +00001291 if (srv->interface[0] != 0)
Simon Kelley824af852008-02-12 20:43:05 +00001292 {
1293 strcat(daemon->namebuff, " ");
1294 strcat(daemon->namebuff, srv->interface);
1295 }
1296 die(_("failed to bind server socket for %s: %s"),
1297 daemon->namebuff, EC_BADNET);
1298 }
1299}
1300
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001301void mark_servers(int flag)
1302{
1303 struct server *serv;
1304
1305 /* mark everything with argument flag */
1306 for (serv = daemon->servers; serv; serv = serv->next)
Simon Kelley40766e52014-07-29 16:52:00 +01001307 {
1308 if (serv->flags & flag)
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001309 serv->flags |= SERV_MARK;
1310#ifdef HAVE_LOOP
Simon Kelley40766e52014-07-29 16:52:00 +01001311 /* Give looped servers another chance */
1312 serv->flags &= ~SERV_LOOP;
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001313#endif
Simon Kelley40766e52014-07-29 16:52:00 +01001314 }
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001315}
1316
1317void cleanup_servers(void)
1318{
1319 struct server *serv, *tmp, **up;
1320
1321 /* unlink and free anything still marked. */
1322 for (serv = daemon->servers, up = &daemon->servers; serv; serv = tmp)
1323 {
1324 tmp = serv->next;
1325 if (serv->flags & SERV_MARK)
1326 {
1327 server_gone(serv);
1328 *up = serv->next;
1329 if (serv->domain)
1330 free(serv->domain);
1331 free(serv);
1332 }
1333 else
1334 up = &serv->next;
1335 }
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001336
1337#ifdef HAVE_LOOP
1338 /* Now we have a new set of servers, test for loops. */
1339 loop_send_probes();
1340#endif
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001341}
1342
1343void add_update_server(int flags,
1344 union mysockaddr *addr,
1345 union mysockaddr *source_addr,
1346 const char *interface,
1347 const char *domain)
1348{
Simon Kelley7b1eae42014-02-20 13:43:28 +00001349 struct server *serv, *next = NULL;
1350 char *domain_str = NULL;
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001351
1352 /* See if there is a suitable candidate, and unmark */
1353 for (serv = daemon->servers; serv; serv = serv->next)
1354 if (serv->flags & SERV_MARK)
1355 {
1356 if (domain)
1357 {
1358 if (!(serv->flags & SERV_HAS_DOMAIN) || !hostname_isequal(domain, serv->domain))
1359 continue;
1360 }
1361 else
1362 {
1363 if (serv->flags & SERV_HAS_DOMAIN)
1364 continue;
1365 }
1366
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001367 break;
1368 }
Simon Kelley7b1eae42014-02-20 13:43:28 +00001369
1370 if (serv)
1371 {
1372 domain_str = serv->domain;
1373 next = serv->next;
1374 }
1375 else if ((serv = whine_malloc(sizeof (struct server))))
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001376 {
1377 /* Not found, create a new one. */
Simon Kelley7b1eae42014-02-20 13:43:28 +00001378 if (domain && !(domain_str = whine_malloc(strlen(domain)+1)))
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001379 {
1380 free(serv);
1381 serv = NULL;
1382 }
1383 else
1384 {
1385 struct server *s;
1386 /* Add to the end of the chain, for order */
1387 if (!daemon->servers)
1388 daemon->servers = serv;
1389 else
1390 {
1391 for (s = daemon->servers; s->next; s = s->next);
1392 s->next = serv;
1393 }
1394 if (domain)
Simon Kelley7b1eae42014-02-20 13:43:28 +00001395 strcpy(domain_str, domain);
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001396 }
1397 }
1398
1399 if (serv)
1400 {
Simon Kelley7b1eae42014-02-20 13:43:28 +00001401 memset(serv, 0, sizeof(struct server));
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001402 serv->flags = flags;
Simon Kelley7b1eae42014-02-20 13:43:28 +00001403 serv->domain = domain_str;
1404 serv->next = next;
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001405 serv->queries = serv->failed_queries = 0;
Simon Kelleya77cec82015-05-08 16:25:38 +01001406 serv->edns_pktsz = daemon->edns_pktsz;
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001407#ifdef HAVE_LOOP
1408 serv->uid = rand32();
1409#endif
1410
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001411 if (domain)
1412 serv->flags |= SERV_HAS_DOMAIN;
1413
1414 if (interface)
Simon Kelley7b1eae42014-02-20 13:43:28 +00001415 strcpy(serv->interface, interface);
1416 if (addr)
1417 serv->addr = *addr;
1418 if (source_addr)
1419 serv->source_addr = *source_addr;
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001420 }
1421}
Simon Kelley824af852008-02-12 20:43:05 +00001422
Simon Kelley5aabfc72007-08-29 11:24:47 +01001423void check_servers(void)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001424{
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001425 struct irec *iface;
Simon Kelley7bcca002014-02-19 17:45:17 +00001426 struct server *serv;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001427 int port = 0;
1428
Simon Kelley316e2732010-01-22 20:16:09 +00001429 /* interface may be new since startup */
Simon Kelley28866e92011-02-14 20:19:14 +00001430 if (!option_bool(OPT_NOWILD))
Simon Kelley115ac3e2013-05-20 11:28:32 +01001431 enumerate_interfaces(0);
Simon Kelley316e2732010-01-22 20:16:09 +00001432
Simon Kelley367341f2016-01-12 15:58:23 +00001433#ifdef HAVE_DNSSEC
1434 /* Disable DNSSEC validation when using server=/domain/.... servers
1435 unless there's a configured trust anchor. */
1436 for (serv = daemon->servers; serv; serv = serv->next)
1437 serv->flags |= SERV_DO_DNSSEC;
1438#endif
1439
Simon Kelley7bcca002014-02-19 17:45:17 +00001440 for (serv = daemon->servers; serv; serv = serv->next)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001441 {
Simon Kelley367341f2016-01-12 15:58:23 +00001442 if (!(serv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001443 {
Simon Kelley367341f2016-01-12 15:58:23 +00001444#ifdef HAVE_DNSSEC
1445 if (option_bool(OPT_DNSSEC_VALID) && (serv->flags & SERV_HAS_DOMAIN))
1446 {
1447 struct ds_config *ds;
1448 char *domain = serv->domain;
Simon Kelley3d8df262005-08-29 12:19:27 +01001449
Simon Kelley367341f2016-01-12 15:58:23 +00001450 /* .example.com is valid */
1451 while (*domain == '.')
1452 domain++;
1453
1454 for (ds = daemon->ds; ds; ds = ds->next)
1455 if (ds->name[0] != 0 && hostname_isequal(domain, ds->name))
1456 break;
1457
1458 if (!ds)
1459 serv->flags &= ~SERV_DO_DNSSEC;
1460 }
1461#endif
1462
1463 port = prettyprint_addr(&serv->addr, daemon->namebuff);
1464
Simon Kelley16972692006-10-16 20:04:18 +01001465 /* 0.0.0.0 is nothing, the stack treats it like 127.0.0.1 */
Simon Kelley7bcca002014-02-19 17:45:17 +00001466 if (serv->addr.sa.sa_family == AF_INET &&
1467 serv->addr.in.sin_addr.s_addr == 0)
Simon Kelley16972692006-10-16 20:04:18 +01001468 {
Simon Kelley7bcca002014-02-19 17:45:17 +00001469 serv->flags |= SERV_MARK;
Simon Kelley16972692006-10-16 20:04:18 +01001470 continue;
1471 }
1472
Simon Kelley3d8df262005-08-29 12:19:27 +01001473 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelley7bcca002014-02-19 17:45:17 +00001474 if (sockaddr_isequal(&serv->addr, &iface->addr))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001475 break;
1476 if (iface)
1477 {
Simon Kelleyf2621c72007-04-29 19:47:21 +01001478 my_syslog(LOG_WARNING, _("ignoring nameserver %s - local interface"), daemon->namebuff);
Simon Kelley7bcca002014-02-19 17:45:17 +00001479 serv->flags |= SERV_MARK;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001480 continue;
1481 }
1482
1483 /* Do we need a socket set? */
Simon Kelley7bcca002014-02-19 17:45:17 +00001484 if (!serv->sfd &&
1485 !(serv->sfd = allocate_sfd(&serv->source_addr, serv->interface)) &&
Simon Kelley1a6bca82008-07-11 11:11:42 +01001486 errno != 0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001487 {
Simon Kelleyf2621c72007-04-29 19:47:21 +01001488 my_syslog(LOG_WARNING,
1489 _("ignoring nameserver %s - cannot make/bind socket: %s"),
1490 daemon->namebuff, strerror(errno));
Simon Kelley7bcca002014-02-19 17:45:17 +00001491 serv->flags |= SERV_MARK;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001492 continue;
1493 }
1494 }
1495
Simon Kelley979fe862015-03-19 22:50:22 +00001496 if (!(serv->flags & SERV_NO_REBIND) && !(serv->flags & SERV_LITERAL_ADDRESS))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001497 {
Simon Kelley7bcca002014-02-19 17:45:17 +00001498 if (serv->flags & (SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_USE_RESOLV))
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001499 {
Simon Kelley367341f2016-01-12 15:58:23 +00001500 char *s1, *s2, *s3 = "";
1501#ifdef HAVE_DNSSEC
1502 if (option_bool(OPT_DNSSEC_VALID) && !(serv->flags & SERV_DO_DNSSEC))
1503 s3 = _("(no DNSSEC)");
1504#endif
Simon Kelley7bcca002014-02-19 17:45:17 +00001505 if (!(serv->flags & SERV_HAS_DOMAIN))
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001506 s1 = _("unqualified"), s2 = _("names");
Simon Kelley7bcca002014-02-19 17:45:17 +00001507 else if (strlen(serv->domain) == 0)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001508 s1 = _("default"), s2 = "";
1509 else
Simon Kelley7bcca002014-02-19 17:45:17 +00001510 s1 = _("domain"), s2 = serv->domain;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001511
Simon Kelley7bcca002014-02-19 17:45:17 +00001512 if (serv->flags & SERV_NO_ADDR)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001513 my_syslog(LOG_INFO, _("using local addresses only for %s %s"), s1, s2);
Simon Kelley7bcca002014-02-19 17:45:17 +00001514 else if (serv->flags & SERV_USE_RESOLV)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001515 my_syslog(LOG_INFO, _("using standard nameservers for %s %s"), s1, s2);
Simon Kelley979fe862015-03-19 22:50:22 +00001516 else
Simon Kelley367341f2016-01-12 15:58:23 +00001517 my_syslog(LOG_INFO, _("using nameserver %s#%d for %s %s %s"), daemon->namebuff, port, s1, s2, s3);
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001518 }
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001519#ifdef HAVE_LOOP
1520 else if (serv->flags & SERV_LOOP)
1521 my_syslog(LOG_INFO, _("NOT using nameserver %s#%d - query loop detected"), daemon->namebuff, port);
1522#endif
Simon Kelley7bcca002014-02-19 17:45:17 +00001523 else if (serv->interface[0] != 0)
1524 my_syslog(LOG_INFO, _("using nameserver %s#%d(via %s)"), daemon->namebuff, port, serv->interface);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001525 else
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001526 my_syslog(LOG_INFO, _("using nameserver %s#%d"), daemon->namebuff, port);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001527 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001528 }
Simon Kelley7bcca002014-02-19 17:45:17 +00001529
1530 cleanup_servers();
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001531}
Simon Kelley849a8352006-06-09 21:02:31 +01001532
1533/* Return zero if no servers found, in that case we keep polling.
1534 This is a protection against an update-time/write race on resolv.conf */
Simon Kelley5aabfc72007-08-29 11:24:47 +01001535int reload_servers(char *fname)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001536{
1537 FILE *f;
1538 char *line;
Simon Kelley849a8352006-06-09 21:02:31 +01001539 int gotone = 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001540
Simon Kelley849a8352006-06-09 21:02:31 +01001541 /* buff happens to be MAXDNAME long... */
1542 if (!(f = fopen(fname, "r")))
1543 {
Simon Kelleyf2621c72007-04-29 19:47:21 +01001544 my_syslog(LOG_ERR, _("failed to read %s: %s"), fname, strerror(errno));
Simon Kelley849a8352006-06-09 21:02:31 +01001545 return 0;
1546 }
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001547
1548 mark_servers(SERV_FROM_RESOLV);
1549
Simon Kelley849a8352006-06-09 21:02:31 +01001550 while ((line = fgets(daemon->namebuff, MAXDNAME, f)))
1551 {
1552 union mysockaddr addr, source_addr;
1553 char *token = strtok(line, " \t\n\r");
1554
Simon Kelley5aabfc72007-08-29 11:24:47 +01001555 if (!token)
1556 continue;
1557 if (strcmp(token, "nameserver") != 0 && strcmp(token, "server") != 0)
Simon Kelley849a8352006-06-09 21:02:31 +01001558 continue;
1559 if (!(token = strtok(NULL, " \t\n\r")))
1560 continue;
1561
1562 memset(&addr, 0, sizeof(addr));
1563 memset(&source_addr, 0, sizeof(source_addr));
1564
1565 if ((addr.in.sin_addr.s_addr = inet_addr(token)) != (in_addr_t) -1)
1566 {
1567#ifdef HAVE_SOCKADDR_SA_LEN
1568 source_addr.in.sin_len = addr.in.sin_len = sizeof(source_addr.in);
1569#endif
1570 source_addr.in.sin_family = addr.in.sin_family = AF_INET;
1571 addr.in.sin_port = htons(NAMESERVER_PORT);
1572 source_addr.in.sin_addr.s_addr = INADDR_ANY;
1573 source_addr.in.sin_port = htons(daemon->query_port);
1574 }
1575#ifdef HAVE_IPV6
Simon Kelley7de060b2011-08-26 17:24:52 +01001576 else
1577 {
1578 int scope_index = 0;
1579 char *scope_id = strchr(token, '%');
1580
1581 if (scope_id)
1582 {
1583 *(scope_id++) = 0;
1584 scope_index = if_nametoindex(scope_id);
1585 }
1586
1587 if (inet_pton(AF_INET6, token, &addr.in6.sin6_addr) > 0)
1588 {
Simon Kelley849a8352006-06-09 21:02:31 +01001589#ifdef HAVE_SOCKADDR_SA_LEN
Simon Kelley7de060b2011-08-26 17:24:52 +01001590 source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(source_addr.in6);
Simon Kelley849a8352006-06-09 21:02:31 +01001591#endif
Simon Kelley7de060b2011-08-26 17:24:52 +01001592 source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6;
1593 source_addr.in6.sin6_flowinfo = addr.in6.sin6_flowinfo = 0;
1594 addr.in6.sin6_port = htons(NAMESERVER_PORT);
1595 addr.in6.sin6_scope_id = scope_index;
1596 source_addr.in6.sin6_addr = in6addr_any;
1597 source_addr.in6.sin6_port = htons(daemon->query_port);
1598 source_addr.in6.sin6_scope_id = 0;
1599 }
1600 else
1601 continue;
Simon Kelley849a8352006-06-09 21:02:31 +01001602 }
Simon Kelley7de060b2011-08-26 17:24:52 +01001603#else /* IPV6 */
Simon Kelley849a8352006-06-09 21:02:31 +01001604 else
1605 continue;
Simon Kelley7de060b2011-08-26 17:24:52 +01001606#endif
1607
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001608 add_update_server(SERV_FROM_RESOLV, &addr, &source_addr, NULL, NULL);
Simon Kelley849a8352006-06-09 21:02:31 +01001609 gotone = 1;
1610 }
1611
Simon Kelley849a8352006-06-09 21:02:31 +01001612 fclose(f);
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001613 cleanup_servers();
Simon Kelley849a8352006-06-09 21:02:31 +01001614
1615 return gotone;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001616}
1617
Simon Kelley1ee9be42013-12-09 16:50:19 +00001618/* Called when addresses are added or deleted from an interface */
1619void newaddress(time_t now)
1620{
1621 (void)now;
1622
Simon Kelley89b12ed2014-03-06 13:27:57 +00001623 if (option_bool(OPT_CLEVERBIND) || option_bool(OPT_LOCAL_SERVICE) ||
1624 daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
Simon Kelley1ee9be42013-12-09 16:50:19 +00001625 enumerate_interfaces(0);
1626
1627 if (option_bool(OPT_CLEVERBIND))
1628 create_bound_listeners(0);
1629
1630#ifdef HAVE_DHCP6
1631 if (daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
1632 join_multicast(0);
1633
1634 if (daemon->doing_dhcp6 || daemon->doing_ra)
1635 dhcp_construct_contexts(now);
1636
1637 if (daemon->doing_dhcp6)
1638 lease_find_interfaces(now);
1639#endif
1640}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001641
1642
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001643
1644
1645