blob: 770558a0a07f814efec22b8c620cd02306bc42f7 [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
Josh Soref730c6742017-02-06 16:14:04 +0000181/* Fix for problem that the kernel sometimes reports the loopback interface as the
Simon Kelleye25db1f2013-01-29 22:10:26 +0000182 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 Kelleyb8ac4662016-03-10 18:40:53 +0000535
536 (void)broadcast; /* warning */
Simon Kelley849a8352006-06-09 21:02:31 +0100537
538 memset(&addr, 0, sizeof(addr));
Simon Kelley1ab84e22004-01-29 16:48:35 +0000539#ifdef HAVE_SOCKADDR_SA_LEN
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100540 addr.in.sin_len = sizeof(addr.in);
Simon Kelley1ab84e22004-01-29 16:48:35 +0000541#endif
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100542 addr.in.sin_family = AF_INET;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100543 addr.in.sin_addr = local;
544 addr.in.sin_port = htons(daemon->port);
Simon Kelley44a2a312004-03-10 20:04:35 +0000545
Simon Kelley376d48c2013-11-13 13:04:30 +0000546 /* determine prefix length from netmask */
547 for (prefix = 32, bit = 1; (bit & ntohl(netmask.s_addr)) == 0 && prefix != 0; bit = bit << 1, prefix--);
548
549 return iface_allowed((struct iface_param *)vparam, if_index, label, &addr, netmask, prefix, 0);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100550}
551
Simon Kelley115ac3e2013-05-20 11:28:32 +0100552int enumerate_interfaces(int reset)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100553{
Simon Kelley115ac3e2013-05-20 11:28:32 +0100554 static struct addrlist *spare = NULL;
Simon Kelleya0358e52014-06-07 13:38:48 +0100555 static int done = 0;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100556 struct iface_param param;
557 int errsave, ret = 1;
558 struct addrlist *addr, *tmp;
559 struct interface_name *intname;
Simon Kelley08619212013-12-02 14:43:48 +0000560 struct irec *iface;
Simon Kelley376d48c2013-11-13 13:04:30 +0000561#ifdef HAVE_AUTH
562 struct auth_zone *zone;
563#endif
564
Simon Kelley76dd75d2013-05-23 10:04:25 +0100565 /* Do this max once per select cycle - also inhibits netlink socket use
566 in TCP child processes. */
Simon Kelley397542b2013-09-05 11:27:34 +0100567
Simon Kelley115ac3e2013-05-20 11:28:32 +0100568 if (reset)
569 {
570 done = 0;
571 return 1;
572 }
573
Simon Kelleya0358e52014-06-07 13:38:48 +0100574 if (done)
Simon Kelley115ac3e2013-05-20 11:28:32 +0100575 return 1;
576
577 done = 1;
578
579 if ((param.fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
580 return 0;
581
Simon Kelley08619212013-12-02 14:43:48 +0000582 /* Mark interfaces for garbage collection */
583 for (iface = daemon->interfaces; iface; iface = iface->next)
584 iface->found = 0;
585
Simon Kelley115ac3e2013-05-20 11:28:32 +0100586 /* remove addresses stored against interface_names */
587 for (intname = daemon->int_names; intname; intname = intname->next)
588 {
Simon Kelley376d48c2013-11-13 13:04:30 +0000589 for (addr = intname->addr; addr; addr = tmp)
Simon Kelley115ac3e2013-05-20 11:28:32 +0100590 {
591 tmp = addr->next;
592 addr->next = spare;
593 spare = addr;
594 }
595
Simon Kelley376d48c2013-11-13 13:04:30 +0000596 intname->addr = NULL;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100597 }
Simon Kelley376d48c2013-11-13 13:04:30 +0000598
Simon Kelleyc8a80482014-03-05 14:29:54 +0000599 /* Remove list of addresses of local interfaces */
600 for (addr = daemon->interface_addrs; addr; addr = tmp)
601 {
602 tmp = addr->next;
603 addr->next = spare;
604 spare = addr;
605 }
606 daemon->interface_addrs = NULL;
607
Simon Kelley376d48c2013-11-13 13:04:30 +0000608#ifdef HAVE_AUTH
609 /* remove addresses stored against auth_zone subnets, but not
610 ones configured as address literals */
611 for (zone = daemon->auth_zones; zone; zone = zone->next)
612 if (zone->interface_names)
613 {
614 struct addrlist **up;
615 for (up = &zone->subnet, addr = zone->subnet; addr; addr = tmp)
616 {
617 tmp = addr->next;
618 if (addr->flags & ADDRLIST_LITERAL)
619 up = &addr->next;
620 else
621 {
622 *up = addr->next;
623 addr->next = spare;
624 spare = addr;
625 }
626 }
627 }
628#endif
629
Simon Kelley115ac3e2013-05-20 11:28:32 +0100630 param.spare = spare;
631
632#ifdef HAVE_IPV6
633 ret = iface_enumerate(AF_INET6, &param, iface_allowed_v6);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100634#endif
Simon Kelley28866e92011-02-14 20:19:14 +0000635
Simon Kelley115ac3e2013-05-20 11:28:32 +0100636 if (ret)
637 ret = iface_enumerate(AF_INET, &param, iface_allowed_v4);
638
639 errsave = errno;
640 close(param.fd);
Simon Kelley08619212013-12-02 14:43:48 +0000641
642 if (option_bool(OPT_CLEVERBIND))
643 {
644 /* Garbage-collect listeners listening on addresses that no longer exist.
645 Does nothing when not binding interfaces or for listeners on localhost,
646 since the ->iface field is NULL. Note that this needs the protections
Josh Soref730c6742017-02-06 16:14:04 +0000647 against reentrancy, hence it's here. It also means there's a possibility,
Simon Kelley08619212013-12-02 14:43:48 +0000648 in OPT_CLEVERBIND mode, that at listener will just disappear after
649 a call to enumerate_interfaces, this is checked OK on all calls. */
650 struct listener *l, *tmp, **up;
651
652 for (up = &daemon->listeners, l = daemon->listeners; l; l = tmp)
653 {
654 tmp = l->next;
655
656 if (!l->iface || l->iface->found)
657 up = &l->next;
658 else
659 {
660 *up = l->next;
661
662 /* In case it ever returns */
663 l->iface->done = 0;
664
665 if (l->fd != -1)
666 close(l->fd);
667 if (l->tcpfd != -1)
668 close(l->tcpfd);
669 if (l->tftpfd != -1)
670 close(l->tftpfd);
671
672 free(l);
673 }
674 }
675 }
676
Simon Kelley115ac3e2013-05-20 11:28:32 +0100677 errno = errsave;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100678 spare = param.spare;
Simon Kelleya0358e52014-06-07 13:38:48 +0100679
Simon Kelley115ac3e2013-05-20 11:28:32 +0100680 return ret;
Simon Kelley44a2a312004-03-10 20:04:35 +0000681}
682
Simon Kelley5aabfc72007-08-29 11:24:47 +0100683/* set NONBLOCK bit on fd: See Stevens 16.6 */
Simon Kelley7cebd202006-05-06 14:13:33 +0100684int fix_fd(int fd)
685{
686 int flags;
687
688 if ((flags = fcntl(fd, F_GETFL)) == -1 ||
Simon Kelley5aabfc72007-08-29 11:24:47 +0100689 fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
Simon Kelley7cebd202006-05-06 14:13:33 +0100690 return 0;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100691
Simon Kelley7cebd202006-05-06 14:13:33 +0100692 return 1;
693}
694
Simon Kelley74c95c22011-10-19 09:33:39 +0100695static int make_sock(union mysockaddr *addr, int type, int dienow)
Simon Kelley44a2a312004-03-10 20:04:35 +0000696{
Simon Kelley28866e92011-02-14 20:19:14 +0000697 int family = addr->sa.sa_family;
698 int fd, rc, opt = 1;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100699
Simon Kelley28866e92011-02-14 20:19:14 +0000700 if ((fd = socket(family, type, 0)) == -1)
Simon Kelley316e2732010-01-22 20:16:09 +0000701 {
Josh Soref730c6742017-02-06 16:14:04 +0000702 int port, errsave;
Simon Kelley39f1b8e2012-06-20 20:04:27 +0100703 char *s;
Simon Kelley28866e92011-02-14 20:19:14 +0000704
705 /* No error if the kernel just doesn't support this IP flavour */
706 if (errno == EPROTONOSUPPORT ||
707 errno == EAFNOSUPPORT ||
708 errno == EINVAL)
709 return -1;
710
711 err:
Josh Soref730c6742017-02-06 16:14:04 +0000712 errsave = errno;
Simon Kelley39f1b8e2012-06-20 20:04:27 +0100713 port = prettyprint_addr(addr, daemon->addrbuff);
714 if (!option_bool(OPT_NOWILD) && !option_bool(OPT_CLEVERBIND))
715 sprintf(daemon->addrbuff, "port %d", port);
716 s = _("failed to create listening socket for %s: %s");
717
Simon Kelley5f11b3e2012-08-16 14:04:05 +0100718 if (fd != -1)
Matthias Andree71aaa5a2013-12-03 11:20:45 +0000719 close (fd);
720
Josh Soref730c6742017-02-06 16:14:04 +0000721 errno = errsave;
Simon Kelley1ee9be42013-12-09 16:50:19 +0000722
Simon Kelley5f11b3e2012-08-16 14:04:05 +0100723 if (dienow)
724 {
725 /* failure to bind addresses given by --listen-address at this point
726 is OK if we're doing bind-dynamic */
727 if (!option_bool(OPT_CLEVERBIND))
728 die(s, daemon->addrbuff, EC_BADNET);
729 }
730 else
731 my_syslog(LOG_WARNING, s, daemon->addrbuff, strerror(errno));
732
Simon Kelley74c95c22011-10-19 09:33:39 +0100733 return -1;
Simon Kelley28866e92011-02-14 20:19:14 +0000734 }
Simon Kelley5f11b3e2012-08-16 14:04:05 +0100735
Simon Kelley28866e92011-02-14 20:19:14 +0000736 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || !fix_fd(fd))
737 goto err;
738
739#ifdef HAVE_IPV6
Simon Kelleyc72daea2012-01-05 21:33:27 +0000740 if (family == AF_INET6 && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)) == -1)
Simon Kelley28866e92011-02-14 20:19:14 +0000741 goto err;
742#endif
743
Simon Kelley74c95c22011-10-19 09:33:39 +0100744 if ((rc = bind(fd, (struct sockaddr *)addr, sa_len(addr))) == -1)
Simon Kelley28866e92011-02-14 20:19:14 +0000745 goto err;
746
747 if (type == SOCK_STREAM)
748 {
Simon Kelley09b768e2016-12-22 22:16:58 +0000749 if (listen(fd, TCP_BACKLOG) == -1)
Simon Kelley28866e92011-02-14 20:19:14 +0000750 goto err;
751 }
Simon Kelley2329bef2013-12-03 13:41:16 +0000752 else if (family == AF_INET)
Simon Kelley28866e92011-02-14 20:19:14 +0000753 {
Simon Kelley2329bef2013-12-03 13:41:16 +0000754 if (!option_bool(OPT_NOWILD))
Simon Kelley28866e92011-02-14 20:19:14 +0000755 {
756#if defined(HAVE_LINUX_NETWORK)
Simon Kelleyc72daea2012-01-05 21:33:27 +0000757 if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) == -1)
Simon Kelley28866e92011-02-14 20:19:14 +0000758 goto err;
759#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
760 if (setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt)) == -1 ||
761 setsockopt(fd, IPPROTO_IP, IP_RECVIF, &opt, sizeof(opt)) == -1)
762 goto err;
763#endif
764 }
Simon Kelley28866e92011-02-14 20:19:14 +0000765 }
Simon Kelley2329bef2013-12-03 13:41:16 +0000766#ifdef HAVE_IPV6
767 else if (!set_ipv6pktinfo(fd))
768 goto err;
769#endif
Simon Kelleyc72daea2012-01-05 21:33:27 +0000770
Simon Kelley28866e92011-02-14 20:19:14 +0000771 return fd;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100772}
Simon Kelleyc72daea2012-01-05 21:33:27 +0000773
774#ifdef HAVE_IPV6
775int set_ipv6pktinfo(int fd)
776{
777 int opt = 1;
778
779 /* The API changed around Linux 2.6.14 but the old ABI is still supported:
780 handle all combinations of headers and kernel.
781 OpenWrt note that this fixes the problem addressed by your very broken patch. */
782 daemon->v6pktinfo = IPV6_PKTINFO;
783
784#ifdef IPV6_RECVPKTINFO
785 if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &opt, sizeof(opt)) != -1)
786 return 1;
787# ifdef IPV6_2292PKTINFO
788 else if (errno == ENOPROTOOPT && setsockopt(fd, IPPROTO_IPV6, IPV6_2292PKTINFO, &opt, sizeof(opt)) != -1)
789 {
790 daemon->v6pktinfo = IPV6_2292PKTINFO;
791 return 1;
792 }
793# endif
794#else
795 if (setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &opt, sizeof(opt)) != -1)
796 return 1;
797#endif
798
799 return 0;
800}
801#endif
Simon Kelley22ce5502013-01-22 13:53:04 +0000802
803
804/* Find the interface on which a TCP connection arrived, if possible, or zero otherwise. */
805int tcp_interface(int fd, int af)
806{
807 int if_index = 0;
808
809#ifdef HAVE_LINUX_NETWORK
810 int opt = 1;
811 struct cmsghdr *cmptr;
812 struct msghdr msg;
Simon Kelley529b0302016-03-16 19:00:45 +0000813 socklen_t len;
Simon Kelley22ce5502013-01-22 13:53:04 +0000814
Simon Kelley529b0302016-03-16 19:00:45 +0000815 /* use mshdr so that the CMSDG_* macros are available */
Simon Kelley22ce5502013-01-22 13:53:04 +0000816 msg.msg_control = daemon->packet;
Simon Kelley529b0302016-03-16 19:00:45 +0000817 msg.msg_controllen = len = daemon->packet_buff_sz;
Simon Kelley22ce5502013-01-22 13:53:04 +0000818
819 /* we overwrote the buffer... */
820 daemon->srv_save = NULL;
821
822 if (af == AF_INET)
823 {
824 if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) != -1 &&
Simon Kelley529b0302016-03-16 19:00:45 +0000825 getsockopt(fd, IPPROTO_IP, IP_PKTOPTIONS, msg.msg_control, &len) != -1)
826 {
827 msg.msg_controllen = len;
828 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
829 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
830 {
831 union {
832 unsigned char *c;
833 struct in_pktinfo *p;
834 } p;
835
836 p.c = CMSG_DATA(cmptr);
837 if_index = p.p->ipi_ifindex;
838 }
839 }
Simon Kelley22ce5502013-01-22 13:53:04 +0000840 }
841#ifdef HAVE_IPV6
842 else
843 {
844 /* Only the RFC-2292 API has the ability to find the interface for TCP connections,
845 it was removed in RFC-3542 !!!!
846
847 Fortunately, Linux kept the 2292 ABI when it moved to 3542. The following code always
848 uses the old ABI, and should work with pre- and post-3542 kernel headers */
849
850#ifdef IPV6_2292PKTOPTIONS
851# define PKTOPTIONS IPV6_2292PKTOPTIONS
852#else
853# define PKTOPTIONS IPV6_PKTOPTIONS
854#endif
855
856 if (set_ipv6pktinfo(fd) &&
Simon Kelley529b0302016-03-16 19:00:45 +0000857 getsockopt(fd, IPPROTO_IPV6, PKTOPTIONS, msg.msg_control, &len) != -1)
Simon Kelley22ce5502013-01-22 13:53:04 +0000858 {
Simon Kelley529b0302016-03-16 19:00:45 +0000859 msg.msg_controllen = len;
860 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
Simon Kelley22ce5502013-01-22 13:53:04 +0000861 if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
862 {
863 union {
864 unsigned char *c;
865 struct in6_pktinfo *p;
866 } p;
867 p.c = CMSG_DATA(cmptr);
868
869 if_index = p.p->ipi6_ifindex;
870 }
871 }
872 }
873#endif /* IPV6 */
874#endif /* Linux */
875
876 return if_index;
877}
Simon Kelley28866e92011-02-14 20:19:14 +0000878
Simon Kelley74c95c22011-10-19 09:33:39 +0100879static struct listener *create_listeners(union mysockaddr *addr, int do_tftp, int dienow)
Simon Kelley28866e92011-02-14 20:19:14 +0000880{
881 struct listener *l = NULL;
882 int fd = -1, tcpfd = -1, tftpfd = -1;
883
Vladislav Grishenko408c3682013-09-24 16:18:49 +0100884 (void)do_tftp;
885
Simon Kelley28866e92011-02-14 20:19:14 +0000886 if (daemon->port != 0)
887 {
Simon Kelley74c95c22011-10-19 09:33:39 +0100888 fd = make_sock(addr, SOCK_DGRAM, dienow);
889 tcpfd = make_sock(addr, SOCK_STREAM, dienow);
Simon Kelley28866e92011-02-14 20:19:14 +0000890 }
891
892#ifdef HAVE_TFTP
893 if (do_tftp)
894 {
895 if (addr->sa.sa_family == AF_INET)
896 {
897 /* port must be restored to DNS port for TCP code */
898 short save = addr->in.sin_port;
899 addr->in.sin_port = htons(TFTP_PORT);
Simon Kelley74c95c22011-10-19 09:33:39 +0100900 tftpfd = make_sock(addr, SOCK_DGRAM, dienow);
Simon Kelley28866e92011-02-14 20:19:14 +0000901 addr->in.sin_port = save;
902 }
903# ifdef HAVE_IPV6
904 else
905 {
906 short save = addr->in6.sin6_port;
907 addr->in6.sin6_port = htons(TFTP_PORT);
Simon Kelley74c95c22011-10-19 09:33:39 +0100908 tftpfd = make_sock(addr, SOCK_DGRAM, dienow);
Simon Kelley28866e92011-02-14 20:19:14 +0000909 addr->in6.sin6_port = save;
910 }
911# endif
912 }
Simon Kelley44a2a312004-03-10 20:04:35 +0000913#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100914
Simon Kelley28866e92011-02-14 20:19:14 +0000915 if (fd != -1 || tcpfd != -1 || tftpfd != -1)
916 {
917 l = safe_malloc(sizeof(struct listener));
918 l->next = NULL;
919 l->family = addr->sa.sa_family;
920 l->fd = fd;
921 l->tcpfd = tcpfd;
Simon Kelley08619212013-12-02 14:43:48 +0000922 l->tftpfd = tftpfd;
923 l->iface = NULL;
Simon Kelley28866e92011-02-14 20:19:14 +0000924 }
925
926 return l;
927}
928
Simon Kelley74c95c22011-10-19 09:33:39 +0100929void create_wildcard_listeners(void)
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100930{
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100931 union mysockaddr addr;
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100932 struct listener *l, *l6;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100933
Simon Kelley849a8352006-06-09 21:02:31 +0100934 memset(&addr, 0, sizeof(addr));
Simon Kelley28866e92011-02-14 20:19:14 +0000935#ifdef HAVE_SOCKADDR_SA_LEN
936 addr.in.sin_len = sizeof(addr.in);
937#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100938 addr.in.sin_family = AF_INET;
939 addr.in.sin_addr.s_addr = INADDR_ANY;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100940 addr.in.sin_port = htons(daemon->port);
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100941
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100942 l = create_listeners(&addr, !!option_bool(OPT_TFTP), 1);
Simon Kelley28866e92011-02-14 20:19:14 +0000943
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100944#ifdef HAVE_IPV6
Simon Kelley28866e92011-02-14 20:19:14 +0000945 memset(&addr, 0, sizeof(addr));
946# ifdef HAVE_SOCKADDR_SA_LEN
947 addr.in6.sin6_len = sizeof(addr.in6);
948# endif
949 addr.in6.sin6_family = AF_INET6;
950 addr.in6.sin6_addr = in6addr_any;
951 addr.in6.sin6_port = htons(daemon->port);
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100952
953 l6 = create_listeners(&addr, !!option_bool(OPT_TFTP), 1);
Simon Kelley28866e92011-02-14 20:19:14 +0000954 if (l)
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100955 l->next = l6;
Simon Kelley28866e92011-02-14 20:19:14 +0000956 else
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100957 l = l6;
Simon Kelley832af0b2007-01-21 20:01:28 +0000958#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100959
Simon Kelley74c95c22011-10-19 09:33:39 +0100960 daemon->listeners = l;
Simon Kelley44a2a312004-03-10 20:04:35 +0000961}
962
Simon Kelley74c95c22011-10-19 09:33:39 +0100963void create_bound_listeners(int dienow)
Simon Kelley44a2a312004-03-10 20:04:35 +0000964{
Simon Kelley74c95c22011-10-19 09:33:39 +0100965 struct listener *new;
Simon Kelley44a2a312004-03-10 20:04:35 +0000966 struct irec *iface;
Simon Kelley52d4abf2012-03-21 21:39:48 +0000967 struct iname *if_tmp;
Simon Kelley73a08a22009-02-05 20:28:08 +0000968
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100969 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelley08619212013-12-02 14:43:48 +0000970 if (!iface->done && !iface->dad && iface->found &&
Simon Kelley74c95c22011-10-19 09:33:39 +0100971 (new = create_listeners(&iface->addr, iface->tftp_ok, dienow)))
Simon Kelley28866e92011-02-14 20:19:14 +0000972 {
973 new->iface = iface;
Simon Kelley74c95c22011-10-19 09:33:39 +0100974 new->next = daemon->listeners;
975 daemon->listeners = new;
976 iface->done = 1;
Simon Kelley28866e92011-02-14 20:19:14 +0000977 }
Simon Kelley52d4abf2012-03-21 21:39:48 +0000978
979 /* Check for --listen-address options that haven't been used because there's
980 no interface with a matching address. These may be valid: eg it's possible
981 to listen on 127.0.1.1 even if the loopback interface is 127.0.0.1
982
Simon Kelley5f11b3e2012-08-16 14:04:05 +0100983 If the address isn't valid the bind() will fail and we'll die()
984 (except in bind-dynamic mode, when we'll complain but keep trying.)
Simon Kelley52d4abf2012-03-21 21:39:48 +0000985
986 The resulting listeners have the ->iface field NULL, and this has to be
987 handled by the DNS and TFTP code. It disables --localise-queries processing
988 (no netmask) and some MTU login the tftp code. */
989
990 for (if_tmp = daemon->if_addrs; if_tmp; if_tmp = if_tmp->next)
991 if (!if_tmp->used &&
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100992 (new = create_listeners(&if_tmp->addr, !!option_bool(OPT_TFTP), dienow)))
Simon Kelley52d4abf2012-03-21 21:39:48 +0000993 {
Simon Kelley52d4abf2012-03-21 21:39:48 +0000994 new->next = daemon->listeners;
995 daemon->listeners = new;
996 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000997}
998
Simon Kelleydc27e142013-10-16 13:09:53 +0100999/* In --bind-interfaces, the only access control is the addresses we're listening on.
1000 There's nothing to avoid a query to the address of an internal interface arriving via
1001 an external interface where we don't want to accept queries, except that in the usual
1002 case the addresses of internal interfaces are RFC1918. When bind-interfaces in use,
1003 and we listen on an address that looks like it's probably globally routeable, shout.
1004
1005 The fix is to use --bind-dynamic, which actually checks the arrival interface too.
1006 Tough if your platform doesn't support this.
Simon Kelley2329bef2013-12-03 13:41:16 +00001007
1008 Note that checking the arrival interface is supported in the standard IPv6 API and
1009 always done, so we don't warn about any IPv6 addresses here.
Simon Kelleydc27e142013-10-16 13:09:53 +01001010*/
1011
1012void warn_bound_listeners(void)
1013{
1014 struct irec *iface;
1015 int advice = 0;
1016
1017 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelleyf7029f52013-11-21 15:09:09 +00001018 if (!iface->dns_auth)
Simon Kelleydc27e142013-10-16 13:09:53 +01001019 {
Simon Kelleydc27e142013-10-16 13:09:53 +01001020 if (iface->addr.sa.sa_family == AF_INET)
1021 {
1022 if (!private_net(iface->addr.in.sin_addr, 1))
1023 {
1024 inet_ntop(AF_INET, &iface->addr.in.sin_addr, daemon->addrbuff, ADDRSTRLEN);
Simon Kelley2329bef2013-12-03 13:41:16 +00001025 iface->warned = advice = 1;
1026 my_syslog(LOG_WARNING,
1027 _("LOUD WARNING: listening on %s may accept requests via interfaces other than %s"),
1028 daemon->addrbuff, iface->name);
Simon Kelleydc27e142013-10-16 13:09:53 +01001029 }
1030 }
Simon Kelleydc27e142013-10-16 13:09:53 +01001031 }
1032
1033 if (advice)
Simon Kelleyf7029f52013-11-21 15:09:09 +00001034 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 +01001035}
1036
Simon Kelleyf7029f52013-11-21 15:09:09 +00001037void warn_int_names(void)
1038{
1039 struct interface_name *intname;
1040
1041 for (intname = daemon->int_names; intname; intname = intname->next)
1042 if (!intname->addr)
1043 my_syslog(LOG_WARNING, _("warning: no addresses found for interface %s"), intname->intr);
1044}
1045
Simon Kelley74c95c22011-10-19 09:33:39 +01001046int is_dad_listeners(void)
1047{
1048 struct irec *iface;
1049
1050 if (option_bool(OPT_NOWILD))
1051 for (iface = daemon->interfaces; iface; iface = iface->next)
1052 if (iface->dad && !iface->done)
1053 return 1;
1054
1055 return 0;
1056}
Simon Kelley5d162f22012-12-20 14:55:46 +00001057
1058#ifdef HAVE_DHCP6
1059void join_multicast(int dienow)
1060{
1061 struct irec *iface, *tmp;
1062
1063 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelley19624462012-12-28 11:18:09 +00001064 if (iface->addr.sa.sa_family == AF_INET6 && iface->dhcp_ok && !iface->multicast_done)
Simon Kelley5d162f22012-12-20 14:55:46 +00001065 {
1066 /* There's an irec per address but we only want to join for multicast
1067 once per interface. Weed out duplicates. */
1068 for (tmp = daemon->interfaces; tmp; tmp = tmp->next)
1069 if (tmp->multicast_done && tmp->index == iface->index)
1070 break;
1071
1072 iface->multicast_done = 1;
1073
1074 if (!tmp)
1075 {
1076 struct ipv6_mreq mreq;
1077 int err = 0;
1078
1079 mreq.ipv6mr_interface = iface->index;
1080
1081 inet_pton(AF_INET6, ALL_RELAY_AGENTS_AND_SERVERS, &mreq.ipv6mr_multiaddr);
1082
Simon Kelleyff7eea22013-09-04 18:01:38 +01001083 if ((daemon->doing_dhcp6 || daemon->relay6) &&
Simon Kelley5d162f22012-12-20 14:55:46 +00001084 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_SERVERS, &mreq.ipv6mr_multiaddr);
1088
1089 if (daemon->doing_dhcp6 &&
1090 setsockopt(daemon->dhcp6fd, 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 inet_pton(AF_INET6, ALL_ROUTERS, &mreq.ipv6mr_multiaddr);
1094
1095 if (daemon->doing_ra &&
1096 setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
Simon Kelley9cdcfe92015-08-26 22:38:08 +01001097 err = errno;
Simon Kelley5d162f22012-12-20 14:55:46 +00001098
1099 if (err)
1100 {
1101 char *s = _("interface %s failed to join DHCPv6 multicast group: %s");
Simon Kelley9cdcfe92015-08-26 22:38:08 +01001102 errno = err;
1103
1104#ifdef HAVE_LINUX_NETWORK
1105 if (errno == ENOMEM)
1106 my_syslog(LOG_ERR, _("try increasing /proc/sys/net/core/optmem_max"));
1107#endif
1108
Simon Kelley5d162f22012-12-20 14:55:46 +00001109 if (dienow)
1110 die(s, iface->name, EC_BADNET);
1111 else
1112 my_syslog(LOG_ERR, s, iface->name, strerror(errno));
1113 }
1114 }
1115 }
1116}
1117#endif
1118
Simon Kelley9009d742008-11-14 20:04:27 +00001119/* return a UDP socket bound to a random port, have to cope with straying into
Simon Kelley1a6bca82008-07-11 11:11:42 +01001120 occupied port nos and reserved ones. */
1121int random_sock(int family)
1122{
1123 int fd;
1124
1125 if ((fd = socket(family, SOCK_DGRAM, 0)) != -1)
1126 {
Simon Kelley3927da42008-07-20 15:10:39 +01001127 union mysockaddr addr;
Hans Dedecker926332a2016-01-23 10:48:12 +00001128 unsigned int ports_avail = ((unsigned short)daemon->max_port - (unsigned short)daemon->min_port) + 1;
Simon Kelley9009d742008-11-14 20:04:27 +00001129 int tries = ports_avail < 30 ? 3 * ports_avail : 100;
Simon Kelley3927da42008-07-20 15:10:39 +01001130
Simon Kelley1a6bca82008-07-11 11:11:42 +01001131 memset(&addr, 0, sizeof(addr));
Simon Kelley3927da42008-07-20 15:10:39 +01001132 addr.sa.sa_family = family;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001133
Simon Kelley1ad24ae2008-07-20 20:22:50 +01001134 /* don't loop forever if all ports in use. */
1135
Simon Kelley1a6bca82008-07-11 11:11:42 +01001136 if (fix_fd(fd))
Simon Kelley9009d742008-11-14 20:04:27 +00001137 while(tries--)
Simon Kelley1a6bca82008-07-11 11:11:42 +01001138 {
1139 unsigned short port = rand16();
1140
Hans Dedecker926332a2016-01-23 10:48:12 +00001141 if (daemon->min_port != 0 || daemon->max_port != MAX_PORT)
1142 port = htons(daemon->min_port + (port % ((unsigned short)ports_avail)));
Simon Kelley1a6bca82008-07-11 11:11:42 +01001143
1144 if (family == AF_INET)
1145 {
1146 addr.in.sin_addr.s_addr = INADDR_ANY;
Simon Kelley3927da42008-07-20 15:10:39 +01001147 addr.in.sin_port = port;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001148#ifdef HAVE_SOCKADDR_SA_LEN
1149 addr.in.sin_len = sizeof(struct sockaddr_in);
1150#endif
1151 }
1152#ifdef HAVE_IPV6
1153 else
1154 {
1155 addr.in6.sin6_addr = in6addr_any;
Simon Kelley3927da42008-07-20 15:10:39 +01001156 addr.in6.sin6_port = port;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001157#ifdef HAVE_SOCKADDR_SA_LEN
1158 addr.in6.sin6_len = sizeof(struct sockaddr_in6);
1159#endif
1160 }
1161#endif
1162
1163 if (bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == 0)
1164 return fd;
1165
1166 if (errno != EADDRINUSE && errno != EACCES)
1167 break;
1168 }
1169
1170 close(fd);
1171 }
1172
1173 return -1;
1174}
1175
1176
Simon Kelley824af852008-02-12 20:43:05 +00001177int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp)
1178{
1179 union mysockaddr addr_copy = *addr;
1180
1181 /* cannot set source _port_ for TCP connections. */
1182 if (is_tcp)
1183 {
1184 if (addr_copy.sa.sa_family == AF_INET)
1185 addr_copy.in.sin_port = 0;
1186#ifdef HAVE_IPV6
1187 else
1188 addr_copy.in6.sin6_port = 0;
1189#endif
1190 }
1191
1192 if (bind(fd, (struct sockaddr *)&addr_copy, sa_len(&addr_copy)) == -1)
1193 return 0;
1194
1195#if defined(SO_BINDTODEVICE)
Simon Kelley73a08a22009-02-05 20:28:08 +00001196 if (intname[0] != 0 &&
Simon Kelley316e2732010-01-22 20:16:09 +00001197 setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, intname, IF_NAMESIZE) == -1)
Simon Kelley824af852008-02-12 20:43:05 +00001198 return 0;
1199#endif
1200
1201 return 1;
1202}
1203
1204static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001205{
1206 struct serverfd *sfd;
Beniamino Galvani2675f202016-08-28 20:44:05 +01001207 unsigned int ifindex = 0;
Simon Kelley824af852008-02-12 20:43:05 +00001208 int errsave;
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001209
Simon Kelley1a6bca82008-07-11 11:11:42 +01001210 /* when using random ports, servers which would otherwise use
1211 the INADDR_ANY/port0 socket have sfd set to NULL */
Simon Kelley73a08a22009-02-05 20:28:08 +00001212 if (!daemon->osport && intname[0] == 0)
Simon Kelley1a6bca82008-07-11 11:11:42 +01001213 {
1214 errno = 0;
1215
1216 if (addr->sa.sa_family == AF_INET &&
1217 addr->in.sin_addr.s_addr == INADDR_ANY &&
1218 addr->in.sin_port == htons(0))
1219 return NULL;
1220
1221#ifdef HAVE_IPV6
1222 if (addr->sa.sa_family == AF_INET6 &&
1223 memcmp(&addr->in6.sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0 &&
1224 addr->in6.sin6_port == htons(0))
1225 return NULL;
1226#endif
1227 }
Beniamino Galvani2675f202016-08-28 20:44:05 +01001228
1229 if (intname && strlen(intname) != 0)
1230 ifindex = if_nametoindex(intname); /* index == 0 when not binding to an interface */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001231
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001232 /* may have a suitable one already */
Simon Kelley824af852008-02-12 20:43:05 +00001233 for (sfd = daemon->sfds; sfd; sfd = sfd->next )
1234 if (sockaddr_isequal(&sfd->source_addr, addr) &&
Beniamino Galvani2675f202016-08-28 20:44:05 +01001235 strcmp(intname, sfd->interface) == 0 &&
1236 ifindex == sfd->ifindex)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001237 return sfd;
1238
1239 /* need to make a new one. */
1240 errno = ENOMEM; /* in case malloc fails. */
Simon Kelley5aabfc72007-08-29 11:24:47 +01001241 if (!(sfd = whine_malloc(sizeof(struct serverfd))))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001242 return NULL;
1243
1244 if ((sfd->fd = socket(addr->sa.sa_family, SOCK_DGRAM, 0)) == -1)
1245 {
1246 free(sfd);
1247 return NULL;
1248 }
1249
Simon Kelley824af852008-02-12 20:43:05 +00001250 if (!local_bind(sfd->fd, addr, intname, 0) || !fix_fd(sfd->fd))
1251 {
1252 errsave = errno; /* save error from bind. */
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001253 close(sfd->fd);
1254 free(sfd);
1255 errno = errsave;
1256 return NULL;
1257 }
Beniamino Galvani2675f202016-08-28 20:44:05 +01001258
Simon Kelley824af852008-02-12 20:43:05 +00001259 strcpy(sfd->interface, intname);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001260 sfd->source_addr = *addr;
Simon Kelley824af852008-02-12 20:43:05 +00001261 sfd->next = daemon->sfds;
Beniamino Galvani2675f202016-08-28 20:44:05 +01001262 sfd->ifindex = ifindex;
Simon Kelley824af852008-02-12 20:43:05 +00001263 daemon->sfds = sfd;
Beniamino Galvani2675f202016-08-28 20:44:05 +01001264
Simon Kelley824af852008-02-12 20:43:05 +00001265 return sfd;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001266}
1267
Simon Kelley824af852008-02-12 20:43:05 +00001268/* create upstream sockets during startup, before root is dropped which may be needed
1269 this allows query_port to be a low port and interface binding */
1270void pre_allocate_sfds(void)
1271{
1272 struct server *srv;
1273
1274 if (daemon->query_port != 0)
1275 {
1276 union mysockaddr addr;
1277 memset(&addr, 0, sizeof(addr));
1278 addr.in.sin_family = AF_INET;
1279 addr.in.sin_addr.s_addr = INADDR_ANY;
1280 addr.in.sin_port = htons(daemon->query_port);
1281#ifdef HAVE_SOCKADDR_SA_LEN
1282 addr.in.sin_len = sizeof(struct sockaddr_in);
1283#endif
1284 allocate_sfd(&addr, "");
1285#ifdef HAVE_IPV6
1286 memset(&addr, 0, sizeof(addr));
1287 addr.in6.sin6_family = AF_INET6;
1288 addr.in6.sin6_addr = in6addr_any;
1289 addr.in6.sin6_port = htons(daemon->query_port);
1290#ifdef HAVE_SOCKADDR_SA_LEN
1291 addr.in6.sin6_len = sizeof(struct sockaddr_in6);
1292#endif
1293 allocate_sfd(&addr, "");
1294#endif
1295 }
1296
1297 for (srv = daemon->servers; srv; srv = srv->next)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001298 if (!(srv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)) &&
Simon Kelley824af852008-02-12 20:43:05 +00001299 !allocate_sfd(&srv->source_addr, srv->interface) &&
Simon Kelley1a6bca82008-07-11 11:11:42 +01001300 errno != 0 &&
Simon Kelley28866e92011-02-14 20:19:14 +00001301 option_bool(OPT_NOWILD))
Simon Kelley824af852008-02-12 20:43:05 +00001302 {
Simon Kelley316e2732010-01-22 20:16:09 +00001303 prettyprint_addr(&srv->source_addr, daemon->namebuff);
Simon Kelley73a08a22009-02-05 20:28:08 +00001304 if (srv->interface[0] != 0)
Simon Kelley824af852008-02-12 20:43:05 +00001305 {
1306 strcat(daemon->namebuff, " ");
1307 strcat(daemon->namebuff, srv->interface);
1308 }
1309 die(_("failed to bind server socket for %s: %s"),
1310 daemon->namebuff, EC_BADNET);
1311 }
1312}
1313
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001314void mark_servers(int flag)
1315{
1316 struct server *serv;
1317
1318 /* mark everything with argument flag */
1319 for (serv = daemon->servers; serv; serv = serv->next)
Simon Kelley40766e52014-07-29 16:52:00 +01001320 {
1321 if (serv->flags & flag)
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001322 serv->flags |= SERV_MARK;
1323#ifdef HAVE_LOOP
Simon Kelley40766e52014-07-29 16:52:00 +01001324 /* Give looped servers another chance */
1325 serv->flags &= ~SERV_LOOP;
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001326#endif
Simon Kelley40766e52014-07-29 16:52:00 +01001327 }
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001328}
1329
1330void cleanup_servers(void)
1331{
1332 struct server *serv, *tmp, **up;
1333
1334 /* unlink and free anything still marked. */
1335 for (serv = daemon->servers, up = &daemon->servers; serv; serv = tmp)
1336 {
1337 tmp = serv->next;
1338 if (serv->flags & SERV_MARK)
1339 {
1340 server_gone(serv);
1341 *up = serv->next;
1342 if (serv->domain)
1343 free(serv->domain);
1344 free(serv);
1345 }
1346 else
1347 up = &serv->next;
1348 }
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001349
1350#ifdef HAVE_LOOP
1351 /* Now we have a new set of servers, test for loops. */
1352 loop_send_probes();
1353#endif
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001354}
1355
1356void add_update_server(int flags,
1357 union mysockaddr *addr,
1358 union mysockaddr *source_addr,
1359 const char *interface,
1360 const char *domain)
1361{
Simon Kelley7b1eae42014-02-20 13:43:28 +00001362 struct server *serv, *next = NULL;
1363 char *domain_str = NULL;
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001364
1365 /* See if there is a suitable candidate, and unmark */
1366 for (serv = daemon->servers; serv; serv = serv->next)
1367 if (serv->flags & SERV_MARK)
1368 {
1369 if (domain)
1370 {
1371 if (!(serv->flags & SERV_HAS_DOMAIN) || !hostname_isequal(domain, serv->domain))
1372 continue;
1373 }
1374 else
1375 {
1376 if (serv->flags & SERV_HAS_DOMAIN)
1377 continue;
1378 }
1379
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001380 break;
1381 }
Simon Kelley7b1eae42014-02-20 13:43:28 +00001382
1383 if (serv)
1384 {
1385 domain_str = serv->domain;
1386 next = serv->next;
1387 }
1388 else if ((serv = whine_malloc(sizeof (struct server))))
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001389 {
1390 /* Not found, create a new one. */
Simon Kelley7b1eae42014-02-20 13:43:28 +00001391 if (domain && !(domain_str = whine_malloc(strlen(domain)+1)))
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001392 {
1393 free(serv);
1394 serv = NULL;
1395 }
1396 else
1397 {
1398 struct server *s;
1399 /* Add to the end of the chain, for order */
1400 if (!daemon->servers)
1401 daemon->servers = serv;
1402 else
1403 {
1404 for (s = daemon->servers; s->next; s = s->next);
1405 s->next = serv;
1406 }
1407 if (domain)
Simon Kelley7b1eae42014-02-20 13:43:28 +00001408 strcpy(domain_str, domain);
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001409 }
1410 }
1411
1412 if (serv)
1413 {
Simon Kelley7b1eae42014-02-20 13:43:28 +00001414 memset(serv, 0, sizeof(struct server));
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001415 serv->flags = flags;
Simon Kelley7b1eae42014-02-20 13:43:28 +00001416 serv->domain = domain_str;
1417 serv->next = next;
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001418 serv->queries = serv->failed_queries = 0;
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001419#ifdef HAVE_LOOP
1420 serv->uid = rand32();
1421#endif
1422
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001423 if (domain)
1424 serv->flags |= SERV_HAS_DOMAIN;
1425
1426 if (interface)
Simon Kelley7b1eae42014-02-20 13:43:28 +00001427 strcpy(serv->interface, interface);
1428 if (addr)
1429 serv->addr = *addr;
1430 if (source_addr)
1431 serv->source_addr = *source_addr;
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001432 }
1433}
Simon Kelley824af852008-02-12 20:43:05 +00001434
Simon Kelley5aabfc72007-08-29 11:24:47 +01001435void check_servers(void)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001436{
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001437 struct irec *iface;
Simon Kelley7bcca002014-02-19 17:45:17 +00001438 struct server *serv;
Beniamino Galvani2675f202016-08-28 20:44:05 +01001439 struct serverfd *sfd, *tmp, **up;
Simon Kelleyb9702602016-05-03 22:34:06 +01001440 int port = 0, count;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001441
Simon Kelley316e2732010-01-22 20:16:09 +00001442 /* interface may be new since startup */
Simon Kelley28866e92011-02-14 20:19:14 +00001443 if (!option_bool(OPT_NOWILD))
Simon Kelley115ac3e2013-05-20 11:28:32 +01001444 enumerate_interfaces(0);
Simon Kelley316e2732010-01-22 20:16:09 +00001445
Beniamino Galvani2675f202016-08-28 20:44:05 +01001446 for (sfd = daemon->sfds; sfd; sfd = sfd->next)
1447 sfd->used = 0;
1448
Simon Kelley367341f2016-01-12 15:58:23 +00001449#ifdef HAVE_DNSSEC
1450 /* Disable DNSSEC validation when using server=/domain/.... servers
1451 unless there's a configured trust anchor. */
1452 for (serv = daemon->servers; serv; serv = serv->next)
1453 serv->flags |= SERV_DO_DNSSEC;
1454#endif
1455
Simon Kelleyb9702602016-05-03 22:34:06 +01001456 for (count = 0, serv = daemon->servers; serv; serv = serv->next)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001457 {
Simon Kelley367341f2016-01-12 15:58:23 +00001458 if (!(serv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001459 {
Simon Kelley14ffa072016-04-25 16:36:44 +01001460 /* Init edns_pktsz for newly created server records. */
1461 if (serv->edns_pktsz == 0)
1462 serv->edns_pktsz = daemon->edns_pktsz;
1463
Simon Kelley367341f2016-01-12 15:58:23 +00001464#ifdef HAVE_DNSSEC
Simon Kelley92be34a2016-01-16 18:39:54 +00001465 if (option_bool(OPT_DNSSEC_VALID))
1466 {
1467 if (serv->flags & SERV_HAS_DOMAIN)
1468 {
1469 struct ds_config *ds;
1470 char *domain = serv->domain;
1471
1472 /* .example.com is valid */
1473 while (*domain == '.')
1474 domain++;
1475
1476 for (ds = daemon->ds; ds; ds = ds->next)
1477 if (ds->name[0] != 0 && hostname_isequal(domain, ds->name))
1478 break;
1479
1480 if (!ds)
1481 serv->flags &= ~SERV_DO_DNSSEC;
1482 }
1483 else if (serv->flags & SERV_FOR_NODOTS)
Simon Kelley367341f2016-01-12 15:58:23 +00001484 serv->flags &= ~SERV_DO_DNSSEC;
1485 }
1486#endif
1487
1488 port = prettyprint_addr(&serv->addr, daemon->namebuff);
1489
Simon Kelley16972692006-10-16 20:04:18 +01001490 /* 0.0.0.0 is nothing, the stack treats it like 127.0.0.1 */
Simon Kelley7bcca002014-02-19 17:45:17 +00001491 if (serv->addr.sa.sa_family == AF_INET &&
1492 serv->addr.in.sin_addr.s_addr == 0)
Simon Kelley16972692006-10-16 20:04:18 +01001493 {
Simon Kelley7bcca002014-02-19 17:45:17 +00001494 serv->flags |= SERV_MARK;
Simon Kelley16972692006-10-16 20:04:18 +01001495 continue;
1496 }
1497
Simon Kelley3d8df262005-08-29 12:19:27 +01001498 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelley7bcca002014-02-19 17:45:17 +00001499 if (sockaddr_isequal(&serv->addr, &iface->addr))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001500 break;
1501 if (iface)
1502 {
Simon Kelleyf2621c72007-04-29 19:47:21 +01001503 my_syslog(LOG_WARNING, _("ignoring nameserver %s - local interface"), daemon->namebuff);
Simon Kelley7bcca002014-02-19 17:45:17 +00001504 serv->flags |= SERV_MARK;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001505 continue;
1506 }
1507
1508 /* Do we need a socket set? */
Simon Kelley7bcca002014-02-19 17:45:17 +00001509 if (!serv->sfd &&
1510 !(serv->sfd = allocate_sfd(&serv->source_addr, serv->interface)) &&
Simon Kelley1a6bca82008-07-11 11:11:42 +01001511 errno != 0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001512 {
Simon Kelleyf2621c72007-04-29 19:47:21 +01001513 my_syslog(LOG_WARNING,
1514 _("ignoring nameserver %s - cannot make/bind socket: %s"),
1515 daemon->namebuff, strerror(errno));
Simon Kelley7bcca002014-02-19 17:45:17 +00001516 serv->flags |= SERV_MARK;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001517 continue;
1518 }
Simon Kelley16800ea2016-08-30 23:07:06 +01001519
1520 if (serv->sfd)
1521 serv->sfd->used = 1;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001522 }
1523
Simon Kelley979fe862015-03-19 22:50:22 +00001524 if (!(serv->flags & SERV_NO_REBIND) && !(serv->flags & SERV_LITERAL_ADDRESS))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001525 {
Simon Kelleyb9702602016-05-03 22:34:06 +01001526 if (++count > SERVERS_LOGGED)
1527 continue;
1528
Simon Kelley7bcca002014-02-19 17:45:17 +00001529 if (serv->flags & (SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_USE_RESOLV))
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001530 {
Simon Kelley367341f2016-01-12 15:58:23 +00001531 char *s1, *s2, *s3 = "";
1532#ifdef HAVE_DNSSEC
1533 if (option_bool(OPT_DNSSEC_VALID) && !(serv->flags & SERV_DO_DNSSEC))
1534 s3 = _("(no DNSSEC)");
1535#endif
Simon Kelley7bcca002014-02-19 17:45:17 +00001536 if (!(serv->flags & SERV_HAS_DOMAIN))
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001537 s1 = _("unqualified"), s2 = _("names");
Simon Kelley7bcca002014-02-19 17:45:17 +00001538 else if (strlen(serv->domain) == 0)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001539 s1 = _("default"), s2 = "";
1540 else
Simon Kelley7bcca002014-02-19 17:45:17 +00001541 s1 = _("domain"), s2 = serv->domain;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001542
Simon Kelley7bcca002014-02-19 17:45:17 +00001543 if (serv->flags & SERV_NO_ADDR)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001544 my_syslog(LOG_INFO, _("using local addresses only for %s %s"), s1, s2);
Simon Kelley7bcca002014-02-19 17:45:17 +00001545 else if (serv->flags & SERV_USE_RESOLV)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001546 my_syslog(LOG_INFO, _("using standard nameservers for %s %s"), s1, s2);
Simon Kelley979fe862015-03-19 22:50:22 +00001547 else
Simon Kelley367341f2016-01-12 15:58:23 +00001548 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 +01001549 }
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001550#ifdef HAVE_LOOP
1551 else if (serv->flags & SERV_LOOP)
1552 my_syslog(LOG_INFO, _("NOT using nameserver %s#%d - query loop detected"), daemon->namebuff, port);
1553#endif
Simon Kelley7bcca002014-02-19 17:45:17 +00001554 else if (serv->interface[0] != 0)
1555 my_syslog(LOG_INFO, _("using nameserver %s#%d(via %s)"), daemon->namebuff, port, serv->interface);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001556 else
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001557 my_syslog(LOG_INFO, _("using nameserver %s#%d"), daemon->namebuff, port);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001558 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001559 }
Simon Kelleyb9702602016-05-03 22:34:06 +01001560
1561 if (count - 1 > SERVERS_LOGGED)
1562 my_syslog(LOG_INFO, _("using %d more nameservers"), count - SERVERS_LOGGED - 1);
Simon Kelley7bcca002014-02-19 17:45:17 +00001563
Beniamino Galvani2675f202016-08-28 20:44:05 +01001564 /* Remove unused sfds */
1565 for (sfd = daemon->sfds, up = &daemon->sfds; sfd; sfd = tmp)
1566 {
1567 tmp = sfd->next;
1568 if (!sfd->used)
1569 {
1570 *up = sfd->next;
1571 close(sfd->fd);
1572 free(sfd);
1573 }
1574 else
1575 up = &sfd->next;
1576 }
1577
Simon Kelley7bcca002014-02-19 17:45:17 +00001578 cleanup_servers();
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001579}
Simon Kelley849a8352006-06-09 21:02:31 +01001580
1581/* Return zero if no servers found, in that case we keep polling.
1582 This is a protection against an update-time/write race on resolv.conf */
Simon Kelley5aabfc72007-08-29 11:24:47 +01001583int reload_servers(char *fname)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001584{
1585 FILE *f;
1586 char *line;
Simon Kelley849a8352006-06-09 21:02:31 +01001587 int gotone = 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001588
Simon Kelley849a8352006-06-09 21:02:31 +01001589 /* buff happens to be MAXDNAME long... */
1590 if (!(f = fopen(fname, "r")))
1591 {
Simon Kelleyf2621c72007-04-29 19:47:21 +01001592 my_syslog(LOG_ERR, _("failed to read %s: %s"), fname, strerror(errno));
Simon Kelley849a8352006-06-09 21:02:31 +01001593 return 0;
1594 }
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001595
1596 mark_servers(SERV_FROM_RESOLV);
1597
Simon Kelley849a8352006-06-09 21:02:31 +01001598 while ((line = fgets(daemon->namebuff, MAXDNAME, f)))
1599 {
1600 union mysockaddr addr, source_addr;
1601 char *token = strtok(line, " \t\n\r");
1602
Simon Kelley5aabfc72007-08-29 11:24:47 +01001603 if (!token)
1604 continue;
1605 if (strcmp(token, "nameserver") != 0 && strcmp(token, "server") != 0)
Simon Kelley849a8352006-06-09 21:02:31 +01001606 continue;
1607 if (!(token = strtok(NULL, " \t\n\r")))
1608 continue;
1609
1610 memset(&addr, 0, sizeof(addr));
1611 memset(&source_addr, 0, sizeof(source_addr));
1612
1613 if ((addr.in.sin_addr.s_addr = inet_addr(token)) != (in_addr_t) -1)
1614 {
1615#ifdef HAVE_SOCKADDR_SA_LEN
1616 source_addr.in.sin_len = addr.in.sin_len = sizeof(source_addr.in);
1617#endif
1618 source_addr.in.sin_family = addr.in.sin_family = AF_INET;
1619 addr.in.sin_port = htons(NAMESERVER_PORT);
1620 source_addr.in.sin_addr.s_addr = INADDR_ANY;
1621 source_addr.in.sin_port = htons(daemon->query_port);
1622 }
1623#ifdef HAVE_IPV6
Simon Kelley7de060b2011-08-26 17:24:52 +01001624 else
1625 {
1626 int scope_index = 0;
1627 char *scope_id = strchr(token, '%');
1628
1629 if (scope_id)
1630 {
1631 *(scope_id++) = 0;
1632 scope_index = if_nametoindex(scope_id);
1633 }
1634
1635 if (inet_pton(AF_INET6, token, &addr.in6.sin6_addr) > 0)
1636 {
Simon Kelley849a8352006-06-09 21:02:31 +01001637#ifdef HAVE_SOCKADDR_SA_LEN
Simon Kelley7de060b2011-08-26 17:24:52 +01001638 source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(source_addr.in6);
Simon Kelley849a8352006-06-09 21:02:31 +01001639#endif
Simon Kelley7de060b2011-08-26 17:24:52 +01001640 source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6;
1641 source_addr.in6.sin6_flowinfo = addr.in6.sin6_flowinfo = 0;
1642 addr.in6.sin6_port = htons(NAMESERVER_PORT);
1643 addr.in6.sin6_scope_id = scope_index;
1644 source_addr.in6.sin6_addr = in6addr_any;
1645 source_addr.in6.sin6_port = htons(daemon->query_port);
1646 source_addr.in6.sin6_scope_id = 0;
1647 }
1648 else
1649 continue;
Simon Kelley849a8352006-06-09 21:02:31 +01001650 }
Simon Kelley7de060b2011-08-26 17:24:52 +01001651#else /* IPV6 */
Simon Kelley849a8352006-06-09 21:02:31 +01001652 else
1653 continue;
Simon Kelley7de060b2011-08-26 17:24:52 +01001654#endif
1655
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001656 add_update_server(SERV_FROM_RESOLV, &addr, &source_addr, NULL, NULL);
Simon Kelley849a8352006-06-09 21:02:31 +01001657 gotone = 1;
1658 }
1659
Simon Kelley849a8352006-06-09 21:02:31 +01001660 fclose(f);
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001661 cleanup_servers();
Simon Kelley849a8352006-06-09 21:02:31 +01001662
1663 return gotone;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001664}
1665
Simon Kelley1ee9be42013-12-09 16:50:19 +00001666/* Called when addresses are added or deleted from an interface */
1667void newaddress(time_t now)
1668{
1669 (void)now;
1670
Simon Kelley89b12ed2014-03-06 13:27:57 +00001671 if (option_bool(OPT_CLEVERBIND) || option_bool(OPT_LOCAL_SERVICE) ||
1672 daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
Simon Kelley1ee9be42013-12-09 16:50:19 +00001673 enumerate_interfaces(0);
1674
1675 if (option_bool(OPT_CLEVERBIND))
1676 create_bound_listeners(0);
1677
1678#ifdef HAVE_DHCP6
1679 if (daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
1680 join_multicast(0);
1681
1682 if (daemon->doing_dhcp6 || daemon->doing_ra)
1683 dhcp_construct_contexts(now);
1684
1685 if (daemon->doing_dhcp6)
1686 lease_find_interfaces(now);
1687#endif
1688}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001689
1690
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001691
1692
1693