blob: 3600250bed30a1b47bf043f423c252fd543a557e [file] [log] [blame]
Simon Kelleyc8e8f5c2021-01-24 21:59:37 +00001/* dnsmasq is Copyright (c) 2000-2021 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
Petr Menšík47b45b22018-08-15 18:17:00 +020032 safe_strncpy(name, ifr.ifr_name, IF_NAMESIZE);
Simon Kelley7622fc02009-06-04 20:32:05 +010033
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;
Petr Menšík47b45b22018-08-15 18:17:00 +020085 safe_strncpy(lifr.lifr_name, lifrp->lifr_name, IF_NAMESIZE);
Simon Kelley28866e92011-02-14 20:19:14 +000086 if (ioctl(fd, SIOCGLIFINDEX, &lifr) < 0)
87 return 0;
88
89 if (lifr.lifr_index == index) {
Petr Menšík47b45b22018-08-15 18:17:00 +020090 safe_strncpy(name, lifr.lifr_name, IF_NAMESIZE);
Simon Kelley28866e92011-02-14 20:19:14 +000091 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 Kelleycc921df2019-01-02 22:48:59 +0000112int iface_check(int family, union 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 &&
Simon Kelleycc921df2019-01-02 22:48:59 +0000138 tmp->addr.in.sin_addr.s_addr == addr->addr4.s_addr)
Simon Kelleyedf0bde2013-07-29 17:21:48 +0100139 ret = match_addr = tmp->used = 1;
Simon Kelley429798f2012-12-10 20:45:53 +0000140 else if (family == AF_INET6 &&
141 IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr,
Simon Kelleycc921df2019-01-02 22:48:59 +0000142 &addr->addr6))
Simon Kelleyedf0bde2013-07-29 17:21:48 +0100143 ret = match_addr = tmp->used = 1;
Simon Kelley429798f2012-12-10 20:45:53 +0000144 }
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100145 }
146
Simon Kelleyedf0bde2013-07-29 17:21:48 +0100147 if (!match_addr)
148 for (tmp = daemon->if_except; tmp; tmp = tmp->next)
149 if (tmp->name && wildcard_match(tmp->name, name))
150 ret = 0;
Simon Kelleyc72daea2012-01-05 21:33:27 +0000151
Simon Kelley429798f2012-12-10 20:45:53 +0000152
153 for (tmp = daemon->authinterface; tmp; tmp = tmp->next)
154 if (tmp->name)
155 {
Simon Kelleyf25e6c62013-11-17 12:23:42 +0000156 if (strcmp(tmp->name, name) == 0 &&
157 (tmp->addr.sa.sa_family == 0 || tmp->addr.sa.sa_family == family))
Simon Kelley429798f2012-12-10 20:45:53 +0000158 break;
159 }
160 else if (addr && tmp->addr.sa.sa_family == AF_INET && family == AF_INET &&
Simon Kelleycc921df2019-01-02 22:48:59 +0000161 tmp->addr.in.sin_addr.s_addr == addr->addr4.s_addr)
Simon Kelley429798f2012-12-10 20:45:53 +0000162 break;
Simon Kelley429798f2012-12-10 20:45:53 +0000163 else if (addr && tmp->addr.sa.sa_family == AF_INET6 && family == AF_INET6 &&
Simon Kelleycc921df2019-01-02 22:48:59 +0000164 IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, &addr->addr6))
Simon Kelley429798f2012-12-10 20:45:53 +0000165 break;
Simon Kelley429798f2012-12-10 20:45:53 +0000166
167 if (tmp && auth)
168 {
169 *auth = 1;
170 ret = 1;
171 }
172
Simon Kelley309331f2006-04-22 15:05:01 +0100173 return ret;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100174}
Simon Kelleye25db1f2013-01-29 22:10:26 +0000175
176
Josh Soref730c6742017-02-06 16:14:04 +0000177/* Fix for problem that the kernel sometimes reports the loopback interface as the
Simon Kelleye25db1f2013-01-29 22:10:26 +0000178 arrival interface when a packet originates locally, even when sent to address of
179 an interface other than the loopback. Accept packet if it arrived via a loopback
180 interface, even when we're not accepting packets that way, as long as the destination
181 address is one we're believing. Interface list must be up-to-date before calling. */
Simon Kelleycc921df2019-01-02 22:48:59 +0000182int loopback_exception(int fd, int family, union all_addr *addr, char *name)
Simon Kelleye25db1f2013-01-29 22:10:26 +0000183{
184 struct ifreq ifr;
185 struct irec *iface;
186
Petr Menšík47b45b22018-08-15 18:17:00 +0200187 safe_strncpy(ifr.ifr_name, name, IF_NAMESIZE);
Simon Kelleye25db1f2013-01-29 22:10:26 +0000188 if (ioctl(fd, SIOCGIFFLAGS, &ifr) != -1 &&
189 ifr.ifr_flags & IFF_LOOPBACK)
190 {
191 for (iface = daemon->interfaces; iface; iface = iface->next)
192 if (iface->addr.sa.sa_family == family)
193 {
194 if (family == AF_INET)
195 {
Simon Kelleycc921df2019-01-02 22:48:59 +0000196 if (iface->addr.in.sin_addr.s_addr == addr->addr4.s_addr)
Simon Kelleye25db1f2013-01-29 22:10:26 +0000197 return 1;
198 }
Simon Kelleycc921df2019-01-02 22:48:59 +0000199 else if (IN6_ARE_ADDR_EQUAL(&iface->addr.in6.sin6_addr, &addr->addr6))
Simon Kelleye25db1f2013-01-29 22:10:26 +0000200 return 1;
Simon Kelleye25db1f2013-01-29 22:10:26 +0000201 }
202 }
203 return 0;
204}
205
Simon Kelley3f2873d2013-05-14 11:28:47 +0100206/* If we're configured with something like --interface=eth0:0 then we'll listen correctly
207 on the relevant address, but the name of the arrival interface, derived from the
208 index won't match the config. Check that we found an interface address for the arrival
209 interface: daemon->interfaces must be up-to-date. */
Simon Kelleycc921df2019-01-02 22:48:59 +0000210int label_exception(int index, int family, union all_addr *addr)
Simon Kelley3f2873d2013-05-14 11:28:47 +0100211{
212 struct irec *iface;
213
214 /* labels only supported on IPv4 addresses. */
215 if (family != AF_INET)
216 return 0;
217
218 for (iface = daemon->interfaces; iface; iface = iface->next)
219 if (iface->index == index && iface->addr.sa.sa_family == AF_INET &&
Simon Kelleycc921df2019-01-02 22:48:59 +0000220 iface->addr.in.sin_addr.s_addr == addr->addr4.s_addr)
Simon Kelley3f2873d2013-05-14 11:28:47 +0100221 return 1;
222
223 return 0;
224}
225
Simon Kelley115ac3e2013-05-20 11:28:32 +0100226struct iface_param {
227 struct addrlist *spare;
228 int fd;
229};
230
231static int iface_allowed(struct iface_param *param, int if_index, char *label,
Simon Kelley47669362014-12-17 12:41:56 +0000232 union mysockaddr *addr, struct in_addr netmask, int prefixlen, int iface_flags)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100233{
234 struct irec *iface;
Petr Menšíka8c14742021-03-02 21:38:02 +0000235 int loopback;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100236 struct ifreq ifr;
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100237 int tftp_ok = !!option_bool(OPT_TFTP);
Simon Kelley9380ba72012-04-16 14:41:56 +0100238 int dhcp_ok = 1;
Simon Kelley4f7b3042012-11-28 21:27:02 +0000239 int auth_dns = 0;
Petr Menšíkad59f272017-03-17 17:22:19 +0000240 int is_label = 0;
Simon Kelley91543f42013-09-23 12:41:20 +0100241#if defined(HAVE_DHCP) || defined(HAVE_TFTP)
Simon Kelley832af0b2007-01-21 20:01:28 +0000242 struct iname *tmp;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100243#endif
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100244
Vladislav Grishenko3b195962013-11-26 11:08:21 +0000245 (void)prefixlen;
246
Simon Kelley115ac3e2013-05-20 11:28:32 +0100247 if (!indextoname(param->fd, if_index, ifr.ifr_name) ||
248 ioctl(param->fd, SIOCGIFFLAGS, &ifr) == -1)
249 return 0;
Simon Kelley1f15b812009-10-13 17:49:32 +0100250
251 loopback = ifr.ifr_flags & IFF_LOOPBACK;
Simon Kelley9380ba72012-04-16 14:41:56 +0100252
253 if (loopback)
Simon Kelley3f2873d2013-05-14 11:28:47 +0100254 dhcp_ok = 0;
255
Simon Kelley115ac3e2013-05-20 11:28:32 +0100256 if (!label)
257 label = ifr.ifr_name;
Petr Menšíkad59f272017-03-17 17:22:19 +0000258 else
259 is_label = strcmp(label, ifr.ifr_name);
Simon Kelleyc8a80482014-03-05 14:29:54 +0000260
261 /* maintain a list of all addresses on all interfaces for --local-service option */
262 if (option_bool(OPT_LOCAL_SERVICE))
263 {
264 struct addrlist *al;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100265
Simon Kelleyc8a80482014-03-05 14:29:54 +0000266 if (param->spare)
267 {
268 al = param->spare;
269 param->spare = al->next;
270 }
271 else
272 al = whine_malloc(sizeof(struct addrlist));
273
274 if (al)
275 {
276 al->next = daemon->interface_addrs;
277 daemon->interface_addrs = al;
278 al->prefixlen = prefixlen;
279
280 if (addr->sa.sa_family == AF_INET)
281 {
Simon Kelleycc921df2019-01-02 22:48:59 +0000282 al->addr.addr4 = addr->in.sin_addr;
Simon Kelleyc8a80482014-03-05 14:29:54 +0000283 al->flags = 0;
284 }
Simon Kelleyc8a80482014-03-05 14:29:54 +0000285 else
286 {
Simon Kelleycc921df2019-01-02 22:48:59 +0000287 al->addr.addr6 = addr->in6.sin6_addr;
Simon Kelleyc8a80482014-03-05 14:29:54 +0000288 al->flags = ADDRLIST_IPV6;
289 }
Simon Kelleyc8a80482014-03-05 14:29:54 +0000290 }
291 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000292
Simon Kelley115ac3e2013-05-20 11:28:32 +0100293 if (addr->sa.sa_family != AF_INET6 || !IN6_IS_ADDR_LINKLOCAL(&addr->in6.sin6_addr))
Simon Kelley115ac3e2013-05-20 11:28:32 +0100294 {
295 struct interface_name *int_name;
296 struct addrlist *al;
Simon Kelley376d48c2013-11-13 13:04:30 +0000297#ifdef HAVE_AUTH
298 struct auth_zone *zone;
299 struct auth_name_list *name;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100300
Simon Kelley376d48c2013-11-13 13:04:30 +0000301 /* Find subnets in auth_zones */
302 for (zone = daemon->auth_zones; zone; zone = zone->next)
303 for (name = zone->interface_names; name; name = name->next)
304 if (wildcard_match(name->name, label))
305 {
306 if (addr->sa.sa_family == AF_INET && (name->flags & AUTH4))
307 {
308 if (param->spare)
309 {
310 al = param->spare;
311 param->spare = al->next;
312 }
313 else
314 al = whine_malloc(sizeof(struct addrlist));
315
316 if (al)
317 {
318 al->next = zone->subnet;
319 zone->subnet = al;
320 al->prefixlen = prefixlen;
Simon Kelleycc921df2019-01-02 22:48:59 +0000321 al->addr.addr4 = addr->in.sin_addr;
Simon Kelley376d48c2013-11-13 13:04:30 +0000322 al->flags = 0;
323 }
324 }
325
Simon Kelley376d48c2013-11-13 13:04:30 +0000326 if (addr->sa.sa_family == AF_INET6 && (name->flags & AUTH6))
327 {
328 if (param->spare)
329 {
330 al = param->spare;
331 param->spare = al->next;
332 }
333 else
334 al = whine_malloc(sizeof(struct addrlist));
335
336 if (al)
337 {
338 al->next = zone->subnet;
339 zone->subnet = al;
Vladislav Grishenko3b195962013-11-26 11:08:21 +0000340 al->prefixlen = prefixlen;
Simon Kelleycc921df2019-01-02 22:48:59 +0000341 al->addr.addr6 = addr->in6.sin6_addr;
Simon Kelley376d48c2013-11-13 13:04:30 +0000342 al->flags = ADDRLIST_IPV6;
343 }
344 }
Simon Kelley376d48c2013-11-13 13:04:30 +0000345 }
346#endif
347
348 /* Update addresses from interface_names. These are a set independent
349 of the set we're listening on. */
Simon Kelley115ac3e2013-05-20 11:28:32 +0100350 for (int_name = daemon->int_names; int_name; int_name = int_name->next)
Simon Kelleyb7cf7542021-03-04 16:54:14 +0000351 if (strncmp(label, int_name->intr, IF_NAMESIZE) == 0)
Simon Kelley115ac3e2013-05-20 11:28:32 +0100352 {
Simon Kelleyb7cf7542021-03-04 16:54:14 +0000353 struct addrlist *lp;
354
355 al = NULL;
356
357 if (addr->sa.sa_family == AF_INET && (int_name->flags & (IN4 | INP4)))
Simon Kelley115ac3e2013-05-20 11:28:32 +0100358 {
Simon Kelleyb7cf7542021-03-04 16:54:14 +0000359 struct in_addr newaddr = addr->in.sin_addr;
360
361 if (int_name->flags & INP4)
362 {
363 if (netmask.s_addr == 0xffff)
364 continue;
365
366 newaddr.s_addr = (addr->in.sin_addr.s_addr & netmask.s_addr) |
367 (int_name->proto4.s_addr & ~netmask.s_addr);
368 }
369
370 /* check for duplicates. */
371 for (lp = int_name->addr; lp; lp = lp->next)
372 if (lp->flags == 0 && lp->addr.addr4.s_addr == newaddr.s_addr)
373 break;
374
375 if (!lp)
376 {
377 if (param->spare)
378 {
379 al = param->spare;
380 param->spare = al->next;
381 }
382 else
383 al = whine_malloc(sizeof(struct addrlist));
384
385 if (al)
386 {
387 al->flags = 0;
388 al->addr.addr4 = newaddr;
389 }
390 }
Simon Kelley115ac3e2013-05-20 11:28:32 +0100391 }
Simon Kelleyb7cf7542021-03-04 16:54:14 +0000392
393 if (addr->sa.sa_family == AF_INET6 && (int_name->flags & (IN6 | INP6)))
394 {
395 struct in6_addr newaddr = addr->in6.sin6_addr;
396
397 if (int_name->flags & INP6)
398 {
399 int i;
400
401 /* No sense in doing /128. */
402 if (prefixlen == 128)
403 continue;
404
405 for (i = 0; i < 16; i++)
406 {
407 int bits = ((i+1)*8) - prefixlen;
408
409 if (bits >= 8)
410 newaddr.s6_addr[i] = int_name->proto6.s6_addr[i];
411 else if (bits >= 0)
412 {
413 unsigned char mask = 0xff << bits;
414 newaddr.s6_addr[i] =
415 (addr->in6.sin6_addr.s6_addr[i] & mask) |
416 (int_name->proto6.s6_addr[i] & ~mask);
417 }
418 }
419 }
420
421 /* check for duplicates. */
422 for (lp = int_name->addr; lp; lp = lp->next)
423 if ((lp->flags & ADDRLIST_IPV6) &&
424 IN6_ARE_ADDR_EQUAL(&lp->addr.addr6, &newaddr))
425 break;
426
427 if (!lp)
428 {
429 if (param->spare)
430 {
431 al = param->spare;
432 param->spare = al->next;
433 }
434 else
435 al = whine_malloc(sizeof(struct addrlist));
436
437 if (al)
438 {
439 al->flags = ADDRLIST_IPV6;
440 al->addr.addr6 = newaddr;
441
442 /* Privacy addresses and addresses still undergoing DAD and deprecated addresses
443 don't appear in forward queries, but will in reverse ones. */
444 if (!(iface_flags & IFACE_PERMANENT) || (iface_flags & (IFACE_DEPRECATED | IFACE_TENTATIVE)))
445 al->flags |= ADDRLIST_REVONLY;
446 }
447 }
448 }
Simon Kelley115ac3e2013-05-20 11:28:32 +0100449
450 if (al)
451 {
Simon Kelley376d48c2013-11-13 13:04:30 +0000452 al->next = int_name->addr;
453 int_name->addr = al;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100454 }
455 }
456 }
457
458 /* check whether the interface IP has been added already
459 we call this routine multiple times. */
460 for (iface = daemon->interfaces; iface; iface = iface->next)
Petr Mensik951a2212019-07-03 17:02:16 +0200461 if (sockaddr_isequal(&iface->addr, addr) && iface->index == if_index)
Simon Kelley115ac3e2013-05-20 11:28:32 +0100462 {
Simon Kelley47669362014-12-17 12:41:56 +0000463 iface->dad = !!(iface_flags & IFACE_TENTATIVE);
Simon Kelley08619212013-12-02 14:43:48 +0000464 iface->found = 1; /* for garbage collection */
Petr Mensik951a2212019-07-03 17:02:16 +0200465 iface->netmask = netmask;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100466 return 1;
467 }
468
469 /* If we are restricting the set of interfaces to use, make
Simon Kelley59353a62004-11-21 19:34:28 +0000470 sure that loopback interfaces are in that set. */
Simon Kelley1f15b812009-10-13 17:49:32 +0100471 if (daemon->if_names && loopback)
Simon Kelley59353a62004-11-21 19:34:28 +0000472 {
473 struct iname *lo;
474 for (lo = daemon->if_names; lo; lo = lo->next)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100475 if (lo->name && strcmp(lo->name, ifr.ifr_name) == 0)
Simon Kelley4ce4f372012-06-14 11:50:45 +0100476 break;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100477
Simon Kelley38365ff2013-02-05 14:35:54 +0000478 if (!lo && (lo = whine_malloc(sizeof(struct iname))))
Simon Kelley59353a62004-11-21 19:34:28 +0000479 {
Simon Kelley38365ff2013-02-05 14:35:54 +0000480 if ((lo->name = whine_malloc(strlen(ifr.ifr_name)+1)))
481 {
482 strcpy(lo->name, ifr.ifr_name);
483 lo->used = 1;
484 lo->next = daemon->if_names;
485 daemon->if_names = lo;
486 }
487 else
488 free(lo);
Simon Kelley59353a62004-11-21 19:34:28 +0000489 }
490 }
491
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100492 if (addr->sa.sa_family == AF_INET &&
Simon Kelleycc921df2019-01-02 22:48:59 +0000493 !iface_check(AF_INET, (union all_addr *)&addr->in.sin_addr, label, &auth_dns))
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100494 return 1;
Simon Kelley4f7b3042012-11-28 21:27:02 +0000495
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100496 if (addr->sa.sa_family == AF_INET6 &&
Simon Kelleycc921df2019-01-02 22:48:59 +0000497 !iface_check(AF_INET6, (union all_addr *)&addr->in6.sin6_addr, label, &auth_dns))
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100498 return 1;
Simon Kelley4f7b3042012-11-28 21:27:02 +0000499
500#ifdef HAVE_DHCP
501 /* No DHCP where we're doing auth DNS. */
502 if (auth_dns)
503 {
504 tftp_ok = 0;
505 dhcp_ok = 0;
506 }
507 else
508 for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
Simon Kelley49333cb2013-03-15 20:30:51 +0000509 if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
Simon Kelley4f7b3042012-11-28 21:27:02 +0000510 {
511 tftp_ok = 0;
512 dhcp_ok = 0;
513 }
514#endif
515
Simon Kelley2937f8a2013-07-29 19:49:07 +0100516
Simon Kelley91543f42013-09-23 12:41:20 +0100517#ifdef HAVE_TFTP
Simon Kelley2937f8a2013-07-29 19:49:07 +0100518 if (daemon->tftp_interfaces)
519 {
520 /* dedicated tftp interface list */
521 tftp_ok = 0;
522 for (tmp = daemon->tftp_interfaces; tmp; tmp = tmp->next)
523 if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
524 tftp_ok = 1;
525 }
Simon Kelley91543f42013-09-23 12:41:20 +0100526#endif
Simon Kelley2937f8a2013-07-29 19:49:07 +0100527
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100528 /* add to list */
Simon Kelley5aabfc72007-08-29 11:24:47 +0100529 if ((iface = whine_malloc(sizeof(struct irec))))
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100530 {
Petr Menšíka8c14742021-03-02 21:38:02 +0000531 int mtu = 0;
532
533 if (ioctl(param->fd, SIOCGIFMTU, &ifr) != -1)
534 mtu = ifr.ifr_mtu;
535
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100536 iface->addr = *addr;
537 iface->netmask = netmask;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100538 iface->tftp_ok = tftp_ok;
Simon Kelley9380ba72012-04-16 14:41:56 +0100539 iface->dhcp_ok = dhcp_ok;
Simon Kelley4f7b3042012-11-28 21:27:02 +0000540 iface->dns_auth = auth_dns;
Simon Kelley1f15b812009-10-13 17:49:32 +0100541 iface->mtu = mtu;
Simon Kelley47669362014-12-17 12:41:56 +0000542 iface->dad = !!(iface_flags & IFACE_TENTATIVE);
Simon Kelley08619212013-12-02 14:43:48 +0000543 iface->found = 1;
Simon Kelleydc27e142013-10-16 13:09:53 +0100544 iface->done = iface->multicast_done = iface->warned = 0;
Simon Kelley5d162f22012-12-20 14:55:46 +0000545 iface->index = if_index;
Petr Menšíkad59f272017-03-17 17:22:19 +0000546 iface->label = is_label;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100547 if ((iface->name = whine_malloc(strlen(ifr.ifr_name)+1)))
Simon Kelley6f13e532012-04-17 14:25:06 +0100548 {
549 strcpy(iface->name, ifr.ifr_name);
Simon Kelley115ac3e2013-05-20 11:28:32 +0100550 iface->next = daemon->interfaces;
551 daemon->interfaces = iface;
Simon Kelley6f13e532012-04-17 14:25:06 +0100552 return 1;
553 }
554 free(iface);
Simon Kelley5d162f22012-12-20 14:55:46 +0000555
Simon Kelley44a2a312004-03-10 20:04:35 +0000556 }
557
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100558 errno = ENOMEM;
559 return 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000560}
561
Simon Kelleyc72daea2012-01-05 21:33:27 +0000562static int iface_allowed_v6(struct in6_addr *local, int prefix,
Simon Kelleybad7b872012-12-20 22:00:39 +0000563 int scope, int if_index, int flags,
Simon Kelley1f776932012-12-16 19:46:08 +0000564 int preferred, int valid, void *vparam)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000565{
Simon Kelley59353a62004-11-21 19:34:28 +0000566 union mysockaddr addr;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100567 struct in_addr netmask; /* dummy */
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100568 netmask.s_addr = 0;
Simon Kelley52b92f42012-01-22 16:05:15 +0000569
Simon Kelley52b92f42012-01-22 16:05:15 +0000570 (void)scope; /* warning */
Simon Kelley1f776932012-12-16 19:46:08 +0000571 (void)preferred;
572 (void)valid;
Simon Kelley44a2a312004-03-10 20:04:35 +0000573
Simon Kelley849a8352006-06-09 21:02:31 +0100574 memset(&addr, 0, sizeof(addr));
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000575#ifdef HAVE_SOCKADDR_SA_LEN
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100576 addr.in6.sin6_len = sizeof(addr.in6);
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000577#endif
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100578 addr.in6.sin6_family = AF_INET6;
579 addr.in6.sin6_addr = *local;
580 addr.in6.sin6_port = htons(daemon->port);
Simon Kelley62ab3cc2013-12-03 11:53:53 +0000581 /* FreeBSD insists this is zero for non-linklocal addresses */
582 if (IN6_IS_ADDR_LINKLOCAL(local))
583 addr.in6.sin6_scope_id = if_index;
584 else
585 addr.in6.sin6_scope_id = 0;
Simon Kelley1ee9be42013-12-09 16:50:19 +0000586
Simon Kelley47669362014-12-17 12:41:56 +0000587 return iface_allowed((struct iface_param *)vparam, if_index, NULL, &addr, netmask, prefix, flags);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100588}
Simon Kelley59353a62004-11-21 19:34:28 +0000589
Simon Kelley3f2873d2013-05-14 11:28:47 +0100590static int iface_allowed_v4(struct in_addr local, int if_index, char *label,
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100591 struct in_addr netmask, struct in_addr broadcast, void *vparam)
592{
593 union mysockaddr addr;
Simon Kelley376d48c2013-11-13 13:04:30 +0000594 int prefix, bit;
Simon Kelleyb8ac4662016-03-10 18:40:53 +0000595
596 (void)broadcast; /* warning */
Simon Kelley849a8352006-06-09 21:02:31 +0100597
598 memset(&addr, 0, sizeof(addr));
Simon Kelley1ab84e22004-01-29 16:48:35 +0000599#ifdef HAVE_SOCKADDR_SA_LEN
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100600 addr.in.sin_len = sizeof(addr.in);
Simon Kelley1ab84e22004-01-29 16:48:35 +0000601#endif
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100602 addr.in.sin_family = AF_INET;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100603 addr.in.sin_addr = local;
604 addr.in.sin_port = htons(daemon->port);
Simon Kelley44a2a312004-03-10 20:04:35 +0000605
Simon Kelley376d48c2013-11-13 13:04:30 +0000606 /* determine prefix length from netmask */
607 for (prefix = 32, bit = 1; (bit & ntohl(netmask.s_addr)) == 0 && prefix != 0; bit = bit << 1, prefix--);
608
609 return iface_allowed((struct iface_param *)vparam, if_index, label, &addr, netmask, prefix, 0);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100610}
Petr Mensik60a3ae12019-07-09 14:05:59 +0200611
612/*
613 * Clean old interfaces no longer found.
614 */
615static void clean_interfaces()
616{
617 struct irec *iface;
618 struct irec **up = &daemon->interfaces;
619
620 for (iface = *up; iface; iface = *up)
621 {
622 if (!iface->found && !iface->done)
623 {
624 *up = iface->next;
625 free(iface->name);
626 free(iface);
627 }
628 else
629 {
630 up = &iface->next;
631 }
632 }
633}
634
Petr Menšík49bdf1e2019-07-15 17:13:12 +0200635/** Release listener if no other interface needs it.
636 *
637 * @return 1 if released, 0 if still required
638 */
639static int release_listener(struct listener *l)
640{
641 if (l->used > 1)
642 {
643 struct irec *iface;
644 for (iface = daemon->interfaces; iface; iface = iface->next)
645 if (iface->done && sockaddr_isequal(&l->addr, &iface->addr))
646 {
647 if (iface->found)
648 {
649 /* update listener to point to active interface instead */
650 if (!l->iface->found)
651 l->iface = iface;
652 }
653 else
654 {
655 l->used--;
656 iface->done = 0;
657 }
658 }
659
660 /* Someone is still using this listener, skip its deletion */
661 if (l->used > 0)
662 return 0;
663 }
664
665 if (l->iface->done)
666 {
667 int port;
668
669 port = prettyprint_addr(&l->iface->addr, daemon->addrbuff);
Simon Kelley4c30e962021-03-12 22:09:14 +0000670 my_syslog(LOG_DEBUG|MS_DEBUG, _("stopped listening on %s(#%d): %s port %d"),
Petr Menšík49bdf1e2019-07-15 17:13:12 +0200671 l->iface->name, l->iface->index, daemon->addrbuff, port);
672 /* In case it ever returns */
673 l->iface->done = 0;
674 }
675
676 if (l->fd != -1)
677 close(l->fd);
678 if (l->tcpfd != -1)
679 close(l->tcpfd);
680 if (l->tftpfd != -1)
681 close(l->tftpfd);
682
683 free(l);
684 return 1;
685}
686
Simon Kelley115ac3e2013-05-20 11:28:32 +0100687int enumerate_interfaces(int reset)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100688{
Simon Kelley115ac3e2013-05-20 11:28:32 +0100689 static struct addrlist *spare = NULL;
Simon Kelleya0358e52014-06-07 13:38:48 +0100690 static int done = 0;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100691 struct iface_param param;
692 int errsave, ret = 1;
693 struct addrlist *addr, *tmp;
694 struct interface_name *intname;
Simon Kelley08619212013-12-02 14:43:48 +0000695 struct irec *iface;
Simon Kelley376d48c2013-11-13 13:04:30 +0000696#ifdef HAVE_AUTH
697 struct auth_zone *zone;
698#endif
Simon Kelley74d4fcd2021-03-15 21:59:51 +0000699 struct server *serv;
700
Simon Kelley76dd75d2013-05-23 10:04:25 +0100701 /* Do this max once per select cycle - also inhibits netlink socket use
702 in TCP child processes. */
Simon Kelley397542b2013-09-05 11:27:34 +0100703
Simon Kelley115ac3e2013-05-20 11:28:32 +0100704 if (reset)
705 {
706 done = 0;
707 return 1;
708 }
709
Simon Kelleya0358e52014-06-07 13:38:48 +0100710 if (done)
Simon Kelley115ac3e2013-05-20 11:28:32 +0100711 return 1;
712
713 done = 1;
714
715 if ((param.fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
716 return 0;
Petr Menšík4c0aecc2021-03-02 18:21:32 +0000717
Simon Kelley74d4fcd2021-03-15 21:59:51 +0000718 /* iface indexes can change when interfaces are created/destroyed.
719 We use them in the main forwarding control path, when the path
720 to a server is specified by an interface, so cache them.
721 Update the cache here. */
722 for (serv = daemon->servers; serv; serv = serv->next)
Simon Kelley1de6bbc2021-03-19 22:24:08 +0000723 if (serv->interface[0] != 0)
Simon Kelley74d4fcd2021-03-15 21:59:51 +0000724 {
Simon Kelley1de6bbc2021-03-19 22:24:08 +0000725#ifdef HAVE_LINUX_NETWORK
726 struct ifreq ifr;
727
728 safe_strncpy(ifr.ifr_name, serv->interface, IF_NAMESIZE);
729 if (ioctl(param.fd, SIOCGIFINDEX, &ifr) != -1)
730 serv->ifindex = ifr.ifr_ifindex;
731#else
732 serv->ifindex = if_nametoindex(serv->interface);
733#endif
Simon Kelley74d4fcd2021-03-15 21:59:51 +0000734 }
735
Petr Menšík4c0aecc2021-03-02 18:21:32 +0000736again:
Simon Kelley08619212013-12-02 14:43:48 +0000737 /* Mark interfaces for garbage collection */
738 for (iface = daemon->interfaces; iface; iface = iface->next)
739 iface->found = 0;
740
Simon Kelley115ac3e2013-05-20 11:28:32 +0100741 /* remove addresses stored against interface_names */
742 for (intname = daemon->int_names; intname; intname = intname->next)
743 {
Simon Kelley376d48c2013-11-13 13:04:30 +0000744 for (addr = intname->addr; addr; addr = tmp)
Simon Kelley115ac3e2013-05-20 11:28:32 +0100745 {
746 tmp = addr->next;
747 addr->next = spare;
748 spare = addr;
749 }
750
Simon Kelley376d48c2013-11-13 13:04:30 +0000751 intname->addr = NULL;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100752 }
Simon Kelley376d48c2013-11-13 13:04:30 +0000753
Simon Kelleyc8a80482014-03-05 14:29:54 +0000754 /* Remove list of addresses of local interfaces */
755 for (addr = daemon->interface_addrs; addr; addr = tmp)
756 {
757 tmp = addr->next;
758 addr->next = spare;
759 spare = addr;
760 }
761 daemon->interface_addrs = NULL;
762
Simon Kelley376d48c2013-11-13 13:04:30 +0000763#ifdef HAVE_AUTH
764 /* remove addresses stored against auth_zone subnets, but not
765 ones configured as address literals */
766 for (zone = daemon->auth_zones; zone; zone = zone->next)
767 if (zone->interface_names)
768 {
769 struct addrlist **up;
770 for (up = &zone->subnet, addr = zone->subnet; addr; addr = tmp)
771 {
772 tmp = addr->next;
773 if (addr->flags & ADDRLIST_LITERAL)
774 up = &addr->next;
775 else
776 {
777 *up = addr->next;
778 addr->next = spare;
779 spare = addr;
780 }
781 }
782 }
783#endif
784
Simon Kelley115ac3e2013-05-20 11:28:32 +0100785 param.spare = spare;
786
Simon Kelley115ac3e2013-05-20 11:28:32 +0100787 ret = iface_enumerate(AF_INET6, &param, iface_allowed_v6);
Petr Menšík4c0aecc2021-03-02 18:21:32 +0000788 if (ret < 0)
789 goto again;
790 else if (ret)
791 {
792 ret = iface_enumerate(AF_INET, &param, iface_allowed_v4);
793 if (ret < 0)
794 goto again;
795 }
Simon Kelley115ac3e2013-05-20 11:28:32 +0100796
797 errsave = errno;
798 close(param.fd);
Simon Kelley08619212013-12-02 14:43:48 +0000799
800 if (option_bool(OPT_CLEVERBIND))
801 {
802 /* Garbage-collect listeners listening on addresses that no longer exist.
803 Does nothing when not binding interfaces or for listeners on localhost,
804 since the ->iface field is NULL. Note that this needs the protections
Josh Soref730c6742017-02-06 16:14:04 +0000805 against reentrancy, hence it's here. It also means there's a possibility,
Simon Kelley08619212013-12-02 14:43:48 +0000806 in OPT_CLEVERBIND mode, that at listener will just disappear after
807 a call to enumerate_interfaces, this is checked OK on all calls. */
808 struct listener *l, *tmp, **up;
Petr Mensik60a3ae12019-07-09 14:05:59 +0200809 int freed = 0;
Simon Kelley08619212013-12-02 14:43:48 +0000810
811 for (up = &daemon->listeners, l = daemon->listeners; l; l = tmp)
812 {
813 tmp = l->next;
814
815 if (!l->iface || l->iface->found)
816 up = &l->next;
Petr Menšík49bdf1e2019-07-15 17:13:12 +0200817 else if (release_listener(l))
Simon Kelley08619212013-12-02 14:43:48 +0000818 {
Petr Menšík49bdf1e2019-07-15 17:13:12 +0200819 *up = tmp;
Simon Kelley619000a2020-04-29 00:09:58 +0100820 freed = 1;
Simon Kelley08619212013-12-02 14:43:48 +0000821 }
822 }
Petr Mensik60a3ae12019-07-09 14:05:59 +0200823
824 if (freed)
825 clean_interfaces();
Simon Kelley08619212013-12-02 14:43:48 +0000826 }
Petr Mensik60a3ae12019-07-09 14:05:59 +0200827
Simon Kelley115ac3e2013-05-20 11:28:32 +0100828 errno = errsave;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100829 spare = param.spare;
Simon Kelley74d4fcd2021-03-15 21:59:51 +0000830
Simon Kelley115ac3e2013-05-20 11:28:32 +0100831 return ret;
Simon Kelley44a2a312004-03-10 20:04:35 +0000832}
833
Simon Kelley5aabfc72007-08-29 11:24:47 +0100834/* set NONBLOCK bit on fd: See Stevens 16.6 */
Simon Kelley7cebd202006-05-06 14:13:33 +0100835int fix_fd(int fd)
836{
837 int flags;
838
839 if ((flags = fcntl(fd, F_GETFL)) == -1 ||
Simon Kelley5aabfc72007-08-29 11:24:47 +0100840 fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
Simon Kelley7cebd202006-05-06 14:13:33 +0100841 return 0;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100842
Simon Kelley7cebd202006-05-06 14:13:33 +0100843 return 1;
844}
845
Simon Kelley74c95c22011-10-19 09:33:39 +0100846static int make_sock(union mysockaddr *addr, int type, int dienow)
Simon Kelley44a2a312004-03-10 20:04:35 +0000847{
Simon Kelley28866e92011-02-14 20:19:14 +0000848 int family = addr->sa.sa_family;
849 int fd, rc, opt = 1;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100850
Simon Kelley28866e92011-02-14 20:19:14 +0000851 if ((fd = socket(family, type, 0)) == -1)
Simon Kelley316e2732010-01-22 20:16:09 +0000852 {
Josh Soref730c6742017-02-06 16:14:04 +0000853 int port, errsave;
Simon Kelley39f1b8e2012-06-20 20:04:27 +0100854 char *s;
Simon Kelley28866e92011-02-14 20:19:14 +0000855
856 /* No error if the kernel just doesn't support this IP flavour */
857 if (errno == EPROTONOSUPPORT ||
858 errno == EAFNOSUPPORT ||
859 errno == EINVAL)
860 return -1;
861
862 err:
Josh Soref730c6742017-02-06 16:14:04 +0000863 errsave = errno;
Simon Kelley39f1b8e2012-06-20 20:04:27 +0100864 port = prettyprint_addr(addr, daemon->addrbuff);
865 if (!option_bool(OPT_NOWILD) && !option_bool(OPT_CLEVERBIND))
866 sprintf(daemon->addrbuff, "port %d", port);
867 s = _("failed to create listening socket for %s: %s");
868
Simon Kelley5f11b3e2012-08-16 14:04:05 +0100869 if (fd != -1)
Matthias Andree71aaa5a2013-12-03 11:20:45 +0000870 close (fd);
871
Josh Soref730c6742017-02-06 16:14:04 +0000872 errno = errsave;
Simon Kelley1ee9be42013-12-09 16:50:19 +0000873
Simon Kelley5f11b3e2012-08-16 14:04:05 +0100874 if (dienow)
875 {
876 /* failure to bind addresses given by --listen-address at this point
877 is OK if we're doing bind-dynamic */
878 if (!option_bool(OPT_CLEVERBIND))
879 die(s, daemon->addrbuff, EC_BADNET);
880 }
881 else
882 my_syslog(LOG_WARNING, s, daemon->addrbuff, strerror(errno));
883
Simon Kelley74c95c22011-10-19 09:33:39 +0100884 return -1;
Simon Kelley28866e92011-02-14 20:19:14 +0000885 }
Simon Kelley5f11b3e2012-08-16 14:04:05 +0100886
Simon Kelley28866e92011-02-14 20:19:14 +0000887 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || !fix_fd(fd))
888 goto err;
889
Simon Kelleyc72daea2012-01-05 21:33:27 +0000890 if (family == AF_INET6 && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)) == -1)
Simon Kelley28866e92011-02-14 20:19:14 +0000891 goto err;
Simon Kelley28866e92011-02-14 20:19:14 +0000892
Simon Kelley74c95c22011-10-19 09:33:39 +0100893 if ((rc = bind(fd, (struct sockaddr *)addr, sa_len(addr))) == -1)
Simon Kelley28866e92011-02-14 20:19:14 +0000894 goto err;
895
896 if (type == SOCK_STREAM)
897 {
Simon Kelley608aa9f2019-03-10 22:44:15 +0000898#ifdef TCP_FASTOPEN
899 int qlen = 5;
Matthias Andreee39c4842020-03-05 15:58:31 +0000900 setsockopt(fd, IPPROTO_TCP, TCP_FASTOPEN, &qlen, sizeof(qlen));
Simon Kelley608aa9f2019-03-10 22:44:15 +0000901#endif
902
Simon Kelley09b768e2016-12-22 22:16:58 +0000903 if (listen(fd, TCP_BACKLOG) == -1)
Simon Kelley28866e92011-02-14 20:19:14 +0000904 goto err;
905 }
Simon Kelley2329bef2013-12-03 13:41:16 +0000906 else if (family == AF_INET)
Simon Kelley28866e92011-02-14 20:19:14 +0000907 {
Simon Kelley2329bef2013-12-03 13:41:16 +0000908 if (!option_bool(OPT_NOWILD))
Simon Kelley28866e92011-02-14 20:19:14 +0000909 {
910#if defined(HAVE_LINUX_NETWORK)
Simon Kelleyc72daea2012-01-05 21:33:27 +0000911 if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) == -1)
Simon Kelley28866e92011-02-14 20:19:14 +0000912 goto err;
913#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
914 if (setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt)) == -1 ||
915 setsockopt(fd, IPPROTO_IP, IP_RECVIF, &opt, sizeof(opt)) == -1)
916 goto err;
917#endif
918 }
Simon Kelley28866e92011-02-14 20:19:14 +0000919 }
Simon Kelley2329bef2013-12-03 13:41:16 +0000920 else if (!set_ipv6pktinfo(fd))
921 goto err;
Simon Kelleyc72daea2012-01-05 21:33:27 +0000922
Simon Kelley28866e92011-02-14 20:19:14 +0000923 return fd;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100924}
Simon Kelleyc72daea2012-01-05 21:33:27 +0000925
Simon Kelleyc72daea2012-01-05 21:33:27 +0000926int set_ipv6pktinfo(int fd)
927{
928 int opt = 1;
929
930 /* The API changed around Linux 2.6.14 but the old ABI is still supported:
931 handle all combinations of headers and kernel.
932 OpenWrt note that this fixes the problem addressed by your very broken patch. */
933 daemon->v6pktinfo = IPV6_PKTINFO;
934
935#ifdef IPV6_RECVPKTINFO
936 if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &opt, sizeof(opt)) != -1)
937 return 1;
938# ifdef IPV6_2292PKTINFO
939 else if (errno == ENOPROTOOPT && setsockopt(fd, IPPROTO_IPV6, IPV6_2292PKTINFO, &opt, sizeof(opt)) != -1)
940 {
941 daemon->v6pktinfo = IPV6_2292PKTINFO;
942 return 1;
943 }
944# endif
945#else
946 if (setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &opt, sizeof(opt)) != -1)
947 return 1;
948#endif
949
950 return 0;
951}
Simon Kelley22ce5502013-01-22 13:53:04 +0000952
953
954/* Find the interface on which a TCP connection arrived, if possible, or zero otherwise. */
955int tcp_interface(int fd, int af)
956{
Kevin Darbyshire-Bryant70c50ef2020-03-06 10:31:15 +0000957 (void)fd; /* suppress potential unused warning */
958 (void)af; /* suppress potential unused warning */
Simon Kelley22ce5502013-01-22 13:53:04 +0000959 int if_index = 0;
960
961#ifdef HAVE_LINUX_NETWORK
962 int opt = 1;
963 struct cmsghdr *cmptr;
964 struct msghdr msg;
Simon Kelley529b0302016-03-16 19:00:45 +0000965 socklen_t len;
Simon Kelley22ce5502013-01-22 13:53:04 +0000966
Simon Kelley529b0302016-03-16 19:00:45 +0000967 /* use mshdr so that the CMSDG_* macros are available */
Simon Kelley22ce5502013-01-22 13:53:04 +0000968 msg.msg_control = daemon->packet;
Simon Kelley529b0302016-03-16 19:00:45 +0000969 msg.msg_controllen = len = daemon->packet_buff_sz;
Simon Kelley74d4fcd2021-03-15 21:59:51 +0000970
Simon Kelley22ce5502013-01-22 13:53:04 +0000971 /* we overwrote the buffer... */
Simon Kelley74d4fcd2021-03-15 21:59:51 +0000972 daemon->srv_save = NULL;
973
Simon Kelley22ce5502013-01-22 13:53:04 +0000974 if (af == AF_INET)
975 {
976 if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) != -1 &&
Simon Kelley529b0302016-03-16 19:00:45 +0000977 getsockopt(fd, IPPROTO_IP, IP_PKTOPTIONS, msg.msg_control, &len) != -1)
978 {
979 msg.msg_controllen = len;
980 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
981 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
982 {
983 union {
984 unsigned char *c;
985 struct in_pktinfo *p;
986 } p;
987
988 p.c = CMSG_DATA(cmptr);
989 if_index = p.p->ipi_ifindex;
990 }
991 }
Simon Kelley22ce5502013-01-22 13:53:04 +0000992 }
Simon Kelley22ce5502013-01-22 13:53:04 +0000993 else
994 {
995 /* Only the RFC-2292 API has the ability to find the interface for TCP connections,
996 it was removed in RFC-3542 !!!!
997
998 Fortunately, Linux kept the 2292 ABI when it moved to 3542. The following code always
999 uses the old ABI, and should work with pre- and post-3542 kernel headers */
1000
1001#ifdef IPV6_2292PKTOPTIONS
1002# define PKTOPTIONS IPV6_2292PKTOPTIONS
1003#else
1004# define PKTOPTIONS IPV6_PKTOPTIONS
1005#endif
1006
1007 if (set_ipv6pktinfo(fd) &&
Simon Kelley529b0302016-03-16 19:00:45 +00001008 getsockopt(fd, IPPROTO_IPV6, PKTOPTIONS, msg.msg_control, &len) != -1)
Simon Kelley22ce5502013-01-22 13:53:04 +00001009 {
Simon Kelley529b0302016-03-16 19:00:45 +00001010 msg.msg_controllen = len;
1011 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
Simon Kelley22ce5502013-01-22 13:53:04 +00001012 if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
1013 {
1014 union {
1015 unsigned char *c;
1016 struct in6_pktinfo *p;
1017 } p;
1018 p.c = CMSG_DATA(cmptr);
1019
1020 if_index = p.p->ipi6_ifindex;
1021 }
1022 }
1023 }
Simon Kelley22ce5502013-01-22 13:53:04 +00001024#endif /* Linux */
1025
1026 return if_index;
1027}
Simon Kelley28866e92011-02-14 20:19:14 +00001028
Simon Kelley74c95c22011-10-19 09:33:39 +01001029static struct listener *create_listeners(union mysockaddr *addr, int do_tftp, int dienow)
Simon Kelley28866e92011-02-14 20:19:14 +00001030{
1031 struct listener *l = NULL;
1032 int fd = -1, tcpfd = -1, tftpfd = -1;
1033
Vladislav Grishenko408c3682013-09-24 16:18:49 +01001034 (void)do_tftp;
1035
Simon Kelley28866e92011-02-14 20:19:14 +00001036 if (daemon->port != 0)
1037 {
Simon Kelley74c95c22011-10-19 09:33:39 +01001038 fd = make_sock(addr, SOCK_DGRAM, dienow);
1039 tcpfd = make_sock(addr, SOCK_STREAM, dienow);
Simon Kelley28866e92011-02-14 20:19:14 +00001040 }
1041
1042#ifdef HAVE_TFTP
1043 if (do_tftp)
1044 {
1045 if (addr->sa.sa_family == AF_INET)
1046 {
1047 /* port must be restored to DNS port for TCP code */
1048 short save = addr->in.sin_port;
1049 addr->in.sin_port = htons(TFTP_PORT);
Simon Kelley74c95c22011-10-19 09:33:39 +01001050 tftpfd = make_sock(addr, SOCK_DGRAM, dienow);
Simon Kelley28866e92011-02-14 20:19:14 +00001051 addr->in.sin_port = save;
1052 }
Simon Kelley28866e92011-02-14 20:19:14 +00001053 else
1054 {
1055 short save = addr->in6.sin6_port;
1056 addr->in6.sin6_port = htons(TFTP_PORT);
Simon Kelley74c95c22011-10-19 09:33:39 +01001057 tftpfd = make_sock(addr, SOCK_DGRAM, dienow);
Simon Kelley28866e92011-02-14 20:19:14 +00001058 addr->in6.sin6_port = save;
1059 }
Simon Kelley28866e92011-02-14 20:19:14 +00001060 }
Simon Kelley44a2a312004-03-10 20:04:35 +00001061#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001062
Simon Kelley28866e92011-02-14 20:19:14 +00001063 if (fd != -1 || tcpfd != -1 || tftpfd != -1)
1064 {
1065 l = safe_malloc(sizeof(struct listener));
1066 l->next = NULL;
Simon Kelley28866e92011-02-14 20:19:14 +00001067 l->fd = fd;
1068 l->tcpfd = tcpfd;
Petr Menšík49bdf1e2019-07-15 17:13:12 +02001069 l->tftpfd = tftpfd;
1070 l->addr = *addr;
1071 l->used = 1;
Simon Kelley08619212013-12-02 14:43:48 +00001072 l->iface = NULL;
Simon Kelley28866e92011-02-14 20:19:14 +00001073 }
1074
1075 return l;
1076}
1077
Simon Kelley74c95c22011-10-19 09:33:39 +01001078void create_wildcard_listeners(void)
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001079{
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001080 union mysockaddr addr;
Simon Kelley8bc4cec2012-07-03 21:04:11 +01001081 struct listener *l, *l6;
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001082
Simon Kelley849a8352006-06-09 21:02:31 +01001083 memset(&addr, 0, sizeof(addr));
Simon Kelley28866e92011-02-14 20:19:14 +00001084#ifdef HAVE_SOCKADDR_SA_LEN
1085 addr.in.sin_len = sizeof(addr.in);
1086#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001087 addr.in.sin_family = AF_INET;
1088 addr.in.sin_addr.s_addr = INADDR_ANY;
Simon Kelley5aabfc72007-08-29 11:24:47 +01001089 addr.in.sin_port = htons(daemon->port);
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001090
Simon Kelley8bc4cec2012-07-03 21:04:11 +01001091 l = create_listeners(&addr, !!option_bool(OPT_TFTP), 1);
Simon Kelley28866e92011-02-14 20:19:14 +00001092
Simon Kelley28866e92011-02-14 20:19:14 +00001093 memset(&addr, 0, sizeof(addr));
Simon Kelleyee875042018-10-23 22:10:17 +01001094#ifdef HAVE_SOCKADDR_SA_LEN
Simon Kelley28866e92011-02-14 20:19:14 +00001095 addr.in6.sin6_len = sizeof(addr.in6);
Simon Kelleyee875042018-10-23 22:10:17 +01001096#endif
Simon Kelley28866e92011-02-14 20:19:14 +00001097 addr.in6.sin6_family = AF_INET6;
1098 addr.in6.sin6_addr = in6addr_any;
1099 addr.in6.sin6_port = htons(daemon->port);
Simon Kelley8bc4cec2012-07-03 21:04:11 +01001100
1101 l6 = create_listeners(&addr, !!option_bool(OPT_TFTP), 1);
Simon Kelley28866e92011-02-14 20:19:14 +00001102 if (l)
Simon Kelley8bc4cec2012-07-03 21:04:11 +01001103 l->next = l6;
Simon Kelley28866e92011-02-14 20:19:14 +00001104 else
Simon Kelley8bc4cec2012-07-03 21:04:11 +01001105 l = l6;
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001106
Simon Kelley74c95c22011-10-19 09:33:39 +01001107 daemon->listeners = l;
Simon Kelley44a2a312004-03-10 20:04:35 +00001108}
1109
Petr Menšík49bdf1e2019-07-15 17:13:12 +02001110static struct listener *find_listener(union mysockaddr *addr)
1111{
1112 struct listener *l;
1113 for (l = daemon->listeners; l; l = l->next)
1114 if (sockaddr_isequal(&l->addr, addr))
1115 return l;
1116 return NULL;
1117}
1118
Simon Kelley74c95c22011-10-19 09:33:39 +01001119void create_bound_listeners(int dienow)
Simon Kelley44a2a312004-03-10 20:04:35 +00001120{
Simon Kelley74c95c22011-10-19 09:33:39 +01001121 struct listener *new;
Simon Kelley44a2a312004-03-10 20:04:35 +00001122 struct irec *iface;
Simon Kelley52d4abf2012-03-21 21:39:48 +00001123 struct iname *if_tmp;
Petr Menšík49bdf1e2019-07-15 17:13:12 +02001124 struct listener *existing;
Simon Kelley73a08a22009-02-05 20:28:08 +00001125
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001126 for (iface = daemon->interfaces; iface; iface = iface->next)
Petr Menšík49bdf1e2019-07-15 17:13:12 +02001127 if (!iface->done && !iface->dad && iface->found)
Simon Kelley28866e92011-02-14 20:19:14 +00001128 {
Petr Menšík49bdf1e2019-07-15 17:13:12 +02001129 existing = find_listener(&iface->addr);
1130 if (existing)
1131 {
1132 iface->done = 1;
1133 existing->used++; /* increase usage counter */
1134 }
1135 else if ((new = create_listeners(&iface->addr, iface->tftp_ok, dienow)))
1136 {
Petr Menšík49bdf1e2019-07-15 17:13:12 +02001137 new->iface = iface;
1138 new->next = daemon->listeners;
1139 daemon->listeners = new;
1140 iface->done = 1;
Simon Kelley619000a2020-04-29 00:09:58 +01001141
1142 /* Don't log the initial set of listen addresses created
1143 at startup, since this is happening before the logging
1144 system is initialised and the sign-on printed. */
1145 if (!dienow)
1146 {
1147 int port = prettyprint_addr(&iface->addr, daemon->addrbuff);
Simon Kelley4c30e962021-03-12 22:09:14 +00001148 my_syslog(LOG_DEBUG|MS_DEBUG, _("listening on %s(#%d): %s port %d"),
Simon Kelley619000a2020-04-29 00:09:58 +01001149 iface->name, iface->index, daemon->addrbuff, port);
1150 }
Petr Menšík49bdf1e2019-07-15 17:13:12 +02001151 }
Simon Kelley28866e92011-02-14 20:19:14 +00001152 }
Simon Kelley52d4abf2012-03-21 21:39:48 +00001153
1154 /* Check for --listen-address options that haven't been used because there's
1155 no interface with a matching address. These may be valid: eg it's possible
1156 to listen on 127.0.1.1 even if the loopback interface is 127.0.0.1
1157
Simon Kelley5f11b3e2012-08-16 14:04:05 +01001158 If the address isn't valid the bind() will fail and we'll die()
1159 (except in bind-dynamic mode, when we'll complain but keep trying.)
Simon Kelley52d4abf2012-03-21 21:39:48 +00001160
1161 The resulting listeners have the ->iface field NULL, and this has to be
1162 handled by the DNS and TFTP code. It disables --localise-queries processing
1163 (no netmask) and some MTU login the tftp code. */
1164
1165 for (if_tmp = daemon->if_addrs; if_tmp; if_tmp = if_tmp->next)
1166 if (!if_tmp->used &&
Simon Kelley8bc4cec2012-07-03 21:04:11 +01001167 (new = create_listeners(&if_tmp->addr, !!option_bool(OPT_TFTP), dienow)))
Simon Kelley52d4abf2012-03-21 21:39:48 +00001168 {
Simon Kelley52d4abf2012-03-21 21:39:48 +00001169 new->next = daemon->listeners;
1170 daemon->listeners = new;
Simon Kelley619000a2020-04-29 00:09:58 +01001171
1172 if (!dienow)
1173 {
1174 int port = prettyprint_addr(&if_tmp->addr, daemon->addrbuff);
Simon Kelley4c30e962021-03-12 22:09:14 +00001175 my_syslog(LOG_DEBUG|MS_DEBUG, _("listening on %s port %d"), daemon->addrbuff, port);
Simon Kelley619000a2020-04-29 00:09:58 +01001176 }
Simon Kelley52d4abf2012-03-21 21:39:48 +00001177 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001178}
1179
Simon Kelleydc27e142013-10-16 13:09:53 +01001180/* In --bind-interfaces, the only access control is the addresses we're listening on.
1181 There's nothing to avoid a query to the address of an internal interface arriving via
1182 an external interface where we don't want to accept queries, except that in the usual
1183 case the addresses of internal interfaces are RFC1918. When bind-interfaces in use,
1184 and we listen on an address that looks like it's probably globally routeable, shout.
1185
1186 The fix is to use --bind-dynamic, which actually checks the arrival interface too.
1187 Tough if your platform doesn't support this.
Simon Kelley2329bef2013-12-03 13:41:16 +00001188
1189 Note that checking the arrival interface is supported in the standard IPv6 API and
1190 always done, so we don't warn about any IPv6 addresses here.
Simon Kelleydc27e142013-10-16 13:09:53 +01001191*/
1192
1193void warn_bound_listeners(void)
1194{
1195 struct irec *iface;
1196 int advice = 0;
1197
1198 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelleyf7029f52013-11-21 15:09:09 +00001199 if (!iface->dns_auth)
Simon Kelleydc27e142013-10-16 13:09:53 +01001200 {
Simon Kelleydc27e142013-10-16 13:09:53 +01001201 if (iface->addr.sa.sa_family == AF_INET)
1202 {
1203 if (!private_net(iface->addr.in.sin_addr, 1))
1204 {
1205 inet_ntop(AF_INET, &iface->addr.in.sin_addr, daemon->addrbuff, ADDRSTRLEN);
Simon Kelley2329bef2013-12-03 13:41:16 +00001206 iface->warned = advice = 1;
1207 my_syslog(LOG_WARNING,
1208 _("LOUD WARNING: listening on %s may accept requests via interfaces other than %s"),
1209 daemon->addrbuff, iface->name);
Simon Kelleydc27e142013-10-16 13:09:53 +01001210 }
1211 }
Simon Kelleydc27e142013-10-16 13:09:53 +01001212 }
1213
1214 if (advice)
Simon Kelleyf7029f52013-11-21 15:09:09 +00001215 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 +01001216}
1217
Petr Menšíkad59f272017-03-17 17:22:19 +00001218void warn_wild_labels(void)
1219{
1220 struct irec *iface;
1221
1222 for (iface = daemon->interfaces; iface; iface = iface->next)
1223 if (iface->found && iface->name && iface->label)
1224 my_syslog(LOG_WARNING, _("warning: using interface %s instead"), iface->name);
1225}
1226
Simon Kelleyf7029f52013-11-21 15:09:09 +00001227void warn_int_names(void)
1228{
1229 struct interface_name *intname;
1230
1231 for (intname = daemon->int_names; intname; intname = intname->next)
1232 if (!intname->addr)
1233 my_syslog(LOG_WARNING, _("warning: no addresses found for interface %s"), intname->intr);
1234}
1235
Simon Kelley74c95c22011-10-19 09:33:39 +01001236int is_dad_listeners(void)
1237{
1238 struct irec *iface;
1239
1240 if (option_bool(OPT_NOWILD))
1241 for (iface = daemon->interfaces; iface; iface = iface->next)
1242 if (iface->dad && !iface->done)
1243 return 1;
1244
1245 return 0;
1246}
Simon Kelley5d162f22012-12-20 14:55:46 +00001247
1248#ifdef HAVE_DHCP6
1249void join_multicast(int dienow)
1250{
1251 struct irec *iface, *tmp;
1252
1253 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelley19624462012-12-28 11:18:09 +00001254 if (iface->addr.sa.sa_family == AF_INET6 && iface->dhcp_ok && !iface->multicast_done)
Simon Kelley5d162f22012-12-20 14:55:46 +00001255 {
1256 /* There's an irec per address but we only want to join for multicast
1257 once per interface. Weed out duplicates. */
1258 for (tmp = daemon->interfaces; tmp; tmp = tmp->next)
1259 if (tmp->multicast_done && tmp->index == iface->index)
1260 break;
1261
1262 iface->multicast_done = 1;
1263
1264 if (!tmp)
1265 {
1266 struct ipv6_mreq mreq;
1267 int err = 0;
1268
1269 mreq.ipv6mr_interface = iface->index;
1270
1271 inet_pton(AF_INET6, ALL_RELAY_AGENTS_AND_SERVERS, &mreq.ipv6mr_multiaddr);
1272
Simon Kelleyff7eea22013-09-04 18:01:38 +01001273 if ((daemon->doing_dhcp6 || daemon->relay6) &&
Simon Kelley5d162f22012-12-20 14:55:46 +00001274 setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
Simon Kelley9cdcfe92015-08-26 22:38:08 +01001275 err = errno;
Simon Kelley5d162f22012-12-20 14:55:46 +00001276
1277 inet_pton(AF_INET6, ALL_SERVERS, &mreq.ipv6mr_multiaddr);
1278
1279 if (daemon->doing_dhcp6 &&
1280 setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
Simon Kelley9cdcfe92015-08-26 22:38:08 +01001281 err = errno;
Simon Kelley5d162f22012-12-20 14:55:46 +00001282
1283 inet_pton(AF_INET6, ALL_ROUTERS, &mreq.ipv6mr_multiaddr);
1284
1285 if (daemon->doing_ra &&
1286 setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
Simon Kelley9cdcfe92015-08-26 22:38:08 +01001287 err = errno;
Simon Kelley5d162f22012-12-20 14:55:46 +00001288
1289 if (err)
1290 {
1291 char *s = _("interface %s failed to join DHCPv6 multicast group: %s");
Simon Kelley9cdcfe92015-08-26 22:38:08 +01001292 errno = err;
1293
1294#ifdef HAVE_LINUX_NETWORK
1295 if (errno == ENOMEM)
1296 my_syslog(LOG_ERR, _("try increasing /proc/sys/net/core/optmem_max"));
1297#endif
1298
Simon Kelley5d162f22012-12-20 14:55:46 +00001299 if (dienow)
1300 die(s, iface->name, EC_BADNET);
1301 else
1302 my_syslog(LOG_ERR, s, iface->name, strerror(errno));
1303 }
1304 }
1305 }
1306}
1307#endif
1308
Simon Kelley9d6918d2017-10-13 17:55:09 +01001309int local_bind(int fd, union mysockaddr *addr, char *intname, unsigned int ifindex, int is_tcp)
Simon Kelley824af852008-02-12 20:43:05 +00001310{
1311 union mysockaddr addr_copy = *addr;
Simon Kelleya2a7e042020-12-12 23:26:45 +00001312 unsigned short port;
Simon Kelley4a8c0982021-03-26 21:19:39 +00001313 int tries = 1;
1314 unsigned short ports_avail = 1;
1315
Simon Kelleya2a7e042020-12-12 23:26:45 +00001316 if (addr_copy.sa.sa_family == AF_INET)
1317 port = addr_copy.in.sin_port;
1318 else
1319 port = addr_copy.in6.sin6_port;
Simon Kelley824af852008-02-12 20:43:05 +00001320
1321 /* cannot set source _port_ for TCP connections. */
1322 if (is_tcp)
Simon Kelleya2a7e042020-12-12 23:26:45 +00001323 port = 0;
Simon Kelley4a8c0982021-03-26 21:19:39 +00001324 else if (port == 0 && daemon->max_port != 0)
Simon Kelley824af852008-02-12 20:43:05 +00001325 {
Simon Kelley4a8c0982021-03-26 21:19:39 +00001326 /* Bind a random port within the range given by min-port and max-port if either
1327 or both are set. Otherwise use the OS's random ephemeral port allocation by
1328 leaving port == 0 and tries == 1 */
1329 ports_avail = daemon->max_port - daemon->min_port + 1;
Simon Kelleya2a7e042020-12-12 23:26:45 +00001330 tries = ports_avail < 30 ? 3 * ports_avail : 100;
Simon Kelley4a8c0982021-03-26 21:19:39 +00001331 port = htons(daemon->min_port + (rand16() % ports_avail));
Simon Kelley824af852008-02-12 20:43:05 +00001332 }
1333
Simon Kelley4a8c0982021-03-26 21:19:39 +00001334 while (1)
Simon Kelleya2a7e042020-12-12 23:26:45 +00001335 {
Simon Kelley4a8c0982021-03-26 21:19:39 +00001336 /* elide bind() call if it's to port 0, address 0 */
Simon Kelleya2a7e042020-12-12 23:26:45 +00001337 if (addr_copy.sa.sa_family == AF_INET)
Simon Kelleya2a7e042020-12-12 23:26:45 +00001338 {
Simon Kelley4a8c0982021-03-26 21:19:39 +00001339 if (port == 0 && addr_copy.in.sin_addr.s_addr == 0)
1340 break;
1341 addr_copy.in.sin_port = port;
1342 }
1343 else
1344 {
1345 if (port == 0 && IN6_IS_ADDR_UNSPECIFIED(&addr_copy.in6.sin6_addr))
1346 break;
1347 addr_copy.in6.sin6_port = port;
Simon Kelleya2a7e042020-12-12 23:26:45 +00001348 }
1349
Simon Kelley4a8c0982021-03-26 21:19:39 +00001350 if (bind(fd, (struct sockaddr *)&addr_copy, sa_len(&addr_copy)) != -1)
1351 break;
Simon Kelleya2a7e042020-12-12 23:26:45 +00001352
Simon Kelley4a8c0982021-03-26 21:19:39 +00001353 if (errno != EADDRINUSE && errno != EACCES)
1354 return 0;
Simon Kelleya2a7e042020-12-12 23:26:45 +00001355
Simon Kelley4a8c0982021-03-26 21:19:39 +00001356 if (--tries == 0)
1357 return 0;
1358
1359 port = htons(daemon->min_port + (rand16() % ports_avail));
1360 }
Simon Kelley9d6918d2017-10-13 17:55:09 +01001361
1362 if (!is_tcp && ifindex > 0)
1363 {
1364#if defined(IP_UNICAST_IF)
1365 if (addr_copy.sa.sa_family == AF_INET)
1366 {
1367 uint32_t ifindex_opt = htonl(ifindex);
1368 return setsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex_opt, sizeof(ifindex_opt)) == 0;
1369 }
1370#endif
Simon Kelleyee875042018-10-23 22:10:17 +01001371#if defined (IPV6_UNICAST_IF)
Simon Kelley9d6918d2017-10-13 17:55:09 +01001372 if (addr_copy.sa.sa_family == AF_INET6)
1373 {
1374 uint32_t ifindex_opt = htonl(ifindex);
1375 return setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_IF, &ifindex_opt, sizeof(ifindex_opt)) == 0;
1376 }
1377#endif
1378 }
1379
Kevin Darbyshire-Bryant70c50ef2020-03-06 10:31:15 +00001380 (void)intname; /* suppress potential unused warning */
Simon Kelley824af852008-02-12 20:43:05 +00001381#if defined(SO_BINDTODEVICE)
Simon Kelley73a08a22009-02-05 20:28:08 +00001382 if (intname[0] != 0 &&
Simon Kelley316e2732010-01-22 20:16:09 +00001383 setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, intname, IF_NAMESIZE) == -1)
Simon Kelley824af852008-02-12 20:43:05 +00001384 return 0;
1385#endif
1386
1387 return 1;
1388}
1389
Simon Kelley74d4fcd2021-03-15 21:59:51 +00001390static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname, unsigned int ifindex)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001391{
1392 struct serverfd *sfd;
Simon Kelley824af852008-02-12 20:43:05 +00001393 int errsave;
Simon Kelleye83915d2018-04-10 21:27:26 +01001394 int opt = 1;
1395
Simon Kelley1a6bca82008-07-11 11:11:42 +01001396 /* when using random ports, servers which would otherwise use
Simon Kelley74d4fcd2021-03-15 21:59:51 +00001397 the INADDR_ANY/port0 socket have sfd set to NULL, this is
1398 anything without an explictly set source port. */
1399 if (!daemon->osport)
Simon Kelley1a6bca82008-07-11 11:11:42 +01001400 {
1401 errno = 0;
1402
1403 if (addr->sa.sa_family == AF_INET &&
Simon Kelley1a6bca82008-07-11 11:11:42 +01001404 addr->in.sin_port == htons(0))
1405 return NULL;
1406
Simon Kelley1a6bca82008-07-11 11:11:42 +01001407 if (addr->sa.sa_family == AF_INET6 &&
Simon Kelley1a6bca82008-07-11 11:11:42 +01001408 addr->in6.sin6_port == htons(0))
1409 return NULL;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001410 }
Beniamino Galvani2675f202016-08-28 20:44:05 +01001411
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001412 /* may have a suitable one already */
Simon Kelley824af852008-02-12 20:43:05 +00001413 for (sfd = daemon->sfds; sfd; sfd = sfd->next )
Simon Kelley74d4fcd2021-03-15 21:59:51 +00001414 if (ifindex == sfd->ifindex &&
1415 sockaddr_isequal(&sfd->source_addr, addr) &&
1416 strcmp(intname, sfd->interface) == 0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001417 return sfd;
1418
1419 /* need to make a new one. */
1420 errno = ENOMEM; /* in case malloc fails. */
Simon Kelley5aabfc72007-08-29 11:24:47 +01001421 if (!(sfd = whine_malloc(sizeof(struct serverfd))))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001422 return NULL;
1423
1424 if ((sfd->fd = socket(addr->sa.sa_family, SOCK_DGRAM, 0)) == -1)
1425 {
1426 free(sfd);
1427 return NULL;
1428 }
Simon Kelleye83915d2018-04-10 21:27:26 +01001429
1430 if ((addr->sa.sa_family == AF_INET6 && setsockopt(sfd->fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)) == -1) ||
1431 !local_bind(sfd->fd, addr, intname, ifindex, 0) || !fix_fd(sfd->fd))
Simon Kelley824af852008-02-12 20:43:05 +00001432 {
Simon Kelleye83915d2018-04-10 21:27:26 +01001433 errsave = errno; /* save error from bind/setsockopt. */
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001434 close(sfd->fd);
1435 free(sfd);
1436 errno = errsave;
1437 return NULL;
1438 }
Beniamino Galvani2675f202016-08-28 20:44:05 +01001439
Petr Menšík47b45b22018-08-15 18:17:00 +02001440 safe_strncpy(sfd->interface, intname, sizeof(sfd->interface));
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001441 sfd->source_addr = *addr;
Simon Kelley824af852008-02-12 20:43:05 +00001442 sfd->next = daemon->sfds;
Beniamino Galvani2675f202016-08-28 20:44:05 +01001443 sfd->ifindex = ifindex;
Simon Kelley4441cf72018-04-10 21:39:54 +01001444 sfd->preallocated = 0;
Simon Kelley824af852008-02-12 20:43:05 +00001445 daemon->sfds = sfd;
Beniamino Galvani2675f202016-08-28 20:44:05 +01001446
Simon Kelley824af852008-02-12 20:43:05 +00001447 return sfd;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001448}
1449
Simon Kelley824af852008-02-12 20:43:05 +00001450/* create upstream sockets during startup, before root is dropped which may be needed
1451 this allows query_port to be a low port and interface binding */
1452void pre_allocate_sfds(void)
1453{
1454 struct server *srv;
Simon Kelley4441cf72018-04-10 21:39:54 +01001455 struct serverfd *sfd;
Simon Kelley824af852008-02-12 20:43:05 +00001456
1457 if (daemon->query_port != 0)
1458 {
1459 union mysockaddr addr;
1460 memset(&addr, 0, sizeof(addr));
1461 addr.in.sin_family = AF_INET;
1462 addr.in.sin_addr.s_addr = INADDR_ANY;
1463 addr.in.sin_port = htons(daemon->query_port);
1464#ifdef HAVE_SOCKADDR_SA_LEN
1465 addr.in.sin_len = sizeof(struct sockaddr_in);
1466#endif
Simon Kelley74d4fcd2021-03-15 21:59:51 +00001467 if ((sfd = allocate_sfd(&addr, "", 0)))
Simon Kelley4441cf72018-04-10 21:39:54 +01001468 sfd->preallocated = 1;
Simon Kelleyee875042018-10-23 22:10:17 +01001469
Simon Kelley824af852008-02-12 20:43:05 +00001470 memset(&addr, 0, sizeof(addr));
1471 addr.in6.sin6_family = AF_INET6;
1472 addr.in6.sin6_addr = in6addr_any;
1473 addr.in6.sin6_port = htons(daemon->query_port);
1474#ifdef HAVE_SOCKADDR_SA_LEN
1475 addr.in6.sin6_len = sizeof(struct sockaddr_in6);
1476#endif
Simon Kelley74d4fcd2021-03-15 21:59:51 +00001477 if ((sfd = allocate_sfd(&addr, "", 0)))
Simon Kelley4441cf72018-04-10 21:39:54 +01001478 sfd->preallocated = 1;
Simon Kelley824af852008-02-12 20:43:05 +00001479 }
1480
1481 for (srv = daemon->servers; srv; srv = srv->next)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001482 if (!(srv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)) &&
Simon Kelley74d4fcd2021-03-15 21:59:51 +00001483 !allocate_sfd(&srv->source_addr, srv->interface, srv->ifindex) &&
Simon Kelley1a6bca82008-07-11 11:11:42 +01001484 errno != 0 &&
Simon Kelley28866e92011-02-14 20:19:14 +00001485 option_bool(OPT_NOWILD))
Simon Kelley824af852008-02-12 20:43:05 +00001486 {
Petr Mensik51cdd1a2019-07-04 20:28:08 +02001487 (void)prettyprint_addr(&srv->source_addr, daemon->namebuff);
Simon Kelley73a08a22009-02-05 20:28:08 +00001488 if (srv->interface[0] != 0)
Simon Kelley824af852008-02-12 20:43:05 +00001489 {
1490 strcat(daemon->namebuff, " ");
1491 strcat(daemon->namebuff, srv->interface);
1492 }
1493 die(_("failed to bind server socket for %s: %s"),
1494 daemon->namebuff, EC_BADNET);
1495 }
1496}
1497
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001498void mark_servers(int flag)
1499{
1500 struct server *serv;
1501
1502 /* mark everything with argument flag */
1503 for (serv = daemon->servers; serv; serv = serv->next)
Simon Kelley40766e52014-07-29 16:52:00 +01001504 {
1505 if (serv->flags & flag)
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001506 serv->flags |= SERV_MARK;
1507#ifdef HAVE_LOOP
Simon Kelley40766e52014-07-29 16:52:00 +01001508 /* Give looped servers another chance */
1509 serv->flags &= ~SERV_LOOP;
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001510#endif
Simon Kelley40766e52014-07-29 16:52:00 +01001511 }
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001512}
1513
1514void cleanup_servers(void)
1515{
1516 struct server *serv, *tmp, **up;
1517
1518 /* unlink and free anything still marked. */
1519 for (serv = daemon->servers, up = &daemon->servers; serv; serv = tmp)
1520 {
1521 tmp = serv->next;
1522 if (serv->flags & SERV_MARK)
1523 {
1524 server_gone(serv);
1525 *up = serv->next;
1526 if (serv->domain)
1527 free(serv->domain);
1528 free(serv);
1529 }
1530 else
1531 up = &serv->next;
1532 }
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001533
1534#ifdef HAVE_LOOP
1535 /* Now we have a new set of servers, test for loops. */
1536 loop_send_probes();
1537#endif
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001538}
1539
1540void add_update_server(int flags,
1541 union mysockaddr *addr,
1542 union mysockaddr *source_addr,
1543 const char *interface,
1544 const char *domain)
1545{
Simon Kelley7b1eae42014-02-20 13:43:28 +00001546 struct server *serv, *next = NULL;
1547 char *domain_str = NULL;
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001548
1549 /* See if there is a suitable candidate, and unmark */
1550 for (serv = daemon->servers; serv; serv = serv->next)
1551 if (serv->flags & SERV_MARK)
1552 {
1553 if (domain)
1554 {
1555 if (!(serv->flags & SERV_HAS_DOMAIN) || !hostname_isequal(domain, serv->domain))
1556 continue;
1557 }
1558 else
1559 {
1560 if (serv->flags & SERV_HAS_DOMAIN)
1561 continue;
1562 }
1563
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001564 break;
1565 }
Simon Kelley7b1eae42014-02-20 13:43:28 +00001566
1567 if (serv)
1568 {
1569 domain_str = serv->domain;
1570 next = serv->next;
1571 }
1572 else if ((serv = whine_malloc(sizeof (struct server))))
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001573 {
1574 /* Not found, create a new one. */
Simon Kelley7b1eae42014-02-20 13:43:28 +00001575 if (domain && !(domain_str = whine_malloc(strlen(domain)+1)))
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001576 {
1577 free(serv);
1578 serv = NULL;
1579 }
1580 else
1581 {
1582 struct server *s;
1583 /* Add to the end of the chain, for order */
1584 if (!daemon->servers)
1585 daemon->servers = serv;
1586 else
1587 {
1588 for (s = daemon->servers; s->next; s = s->next);
1589 s->next = serv;
1590 }
1591 if (domain)
Simon Kelley7b1eae42014-02-20 13:43:28 +00001592 strcpy(domain_str, domain);
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001593 }
1594 }
1595
1596 if (serv)
1597 {
Simon Kelley7b1eae42014-02-20 13:43:28 +00001598 memset(serv, 0, sizeof(struct server));
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001599 serv->flags = flags;
Simon Kelley7b1eae42014-02-20 13:43:28 +00001600 serv->domain = domain_str;
1601 serv->next = next;
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001602 serv->queries = serv->failed_queries = 0;
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001603#ifdef HAVE_LOOP
1604 serv->uid = rand32();
1605#endif
1606
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001607 if (domain)
1608 serv->flags |= SERV_HAS_DOMAIN;
1609
1610 if (interface)
Petr Menšík47b45b22018-08-15 18:17:00 +02001611 safe_strncpy(serv->interface, interface, sizeof(serv->interface));
Simon Kelley7b1eae42014-02-20 13:43:28 +00001612 if (addr)
1613 serv->addr = *addr;
1614 if (source_addr)
1615 serv->source_addr = *source_addr;
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001616 }
1617}
Simon Kelley824af852008-02-12 20:43:05 +00001618
Simon Kelley5aabfc72007-08-29 11:24:47 +01001619void check_servers(void)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001620{
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001621 struct irec *iface;
Simon Kelley7bcca002014-02-19 17:45:17 +00001622 struct server *serv;
Beniamino Galvani2675f202016-08-28 20:44:05 +01001623 struct serverfd *sfd, *tmp, **up;
Simon Kelleyb9702602016-05-03 22:34:06 +01001624 int port = 0, count;
Hannu Nyman3e2496f2017-02-11 13:44:08 +00001625 int locals = 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001626
Simon Kelley316e2732010-01-22 20:16:09 +00001627 /* interface may be new since startup */
Simon Kelley28866e92011-02-14 20:19:14 +00001628 if (!option_bool(OPT_NOWILD))
Simon Kelley115ac3e2013-05-20 11:28:32 +01001629 enumerate_interfaces(0);
Simon Kelley4441cf72018-04-10 21:39:54 +01001630
1631 /* don't garbage collect pre-allocated sfds. */
Beniamino Galvani2675f202016-08-28 20:44:05 +01001632 for (sfd = daemon->sfds; sfd; sfd = sfd->next)
Simon Kelley4441cf72018-04-10 21:39:54 +01001633 sfd->used = sfd->preallocated;
Beniamino Galvani2675f202016-08-28 20:44:05 +01001634
Simon Kelleyb9702602016-05-03 22:34:06 +01001635 for (count = 0, serv = daemon->servers; serv; serv = serv->next)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001636 {
Simon Kelley367341f2016-01-12 15:58:23 +00001637 if (!(serv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001638 {
Simon Kelley14ffa072016-04-25 16:36:44 +01001639 /* Init edns_pktsz for newly created server records. */
1640 if (serv->edns_pktsz == 0)
1641 serv->edns_pktsz = daemon->edns_pktsz;
1642
Simon Kelley367341f2016-01-12 15:58:23 +00001643#ifdef HAVE_DNSSEC
Simon Kelley92be34a2016-01-16 18:39:54 +00001644 if (option_bool(OPT_DNSSEC_VALID))
1645 {
Simon Kelleya49c5c22017-10-10 22:04:59 +01001646 if (!(serv->flags & SERV_FOR_NODOTS))
1647 serv->flags |= SERV_DO_DNSSEC;
1648
1649 /* Disable DNSSEC validation when using server=/domain/.... servers
1650 unless there's a configured trust anchor. */
Simon Kelley92be34a2016-01-16 18:39:54 +00001651 if (serv->flags & SERV_HAS_DOMAIN)
1652 {
1653 struct ds_config *ds;
1654 char *domain = serv->domain;
1655
1656 /* .example.com is valid */
1657 while (*domain == '.')
1658 domain++;
1659
1660 for (ds = daemon->ds; ds; ds = ds->next)
1661 if (ds->name[0] != 0 && hostname_isequal(domain, ds->name))
1662 break;
1663
1664 if (!ds)
1665 serv->flags &= ~SERV_DO_DNSSEC;
1666 }
Simon Kelley367341f2016-01-12 15:58:23 +00001667 }
1668#endif
1669
1670 port = prettyprint_addr(&serv->addr, daemon->namebuff);
1671
Simon Kelley16972692006-10-16 20:04:18 +01001672 /* 0.0.0.0 is nothing, the stack treats it like 127.0.0.1 */
Simon Kelley7bcca002014-02-19 17:45:17 +00001673 if (serv->addr.sa.sa_family == AF_INET &&
1674 serv->addr.in.sin_addr.s_addr == 0)
Simon Kelley16972692006-10-16 20:04:18 +01001675 {
Simon Kelley7bcca002014-02-19 17:45:17 +00001676 serv->flags |= SERV_MARK;
Simon Kelley16972692006-10-16 20:04:18 +01001677 continue;
1678 }
1679
Simon Kelley3d8df262005-08-29 12:19:27 +01001680 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelley7bcca002014-02-19 17:45:17 +00001681 if (sockaddr_isequal(&serv->addr, &iface->addr))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001682 break;
1683 if (iface)
1684 {
Simon Kelleyf2621c72007-04-29 19:47:21 +01001685 my_syslog(LOG_WARNING, _("ignoring nameserver %s - local interface"), daemon->namebuff);
Simon Kelley7bcca002014-02-19 17:45:17 +00001686 serv->flags |= SERV_MARK;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001687 continue;
1688 }
1689
1690 /* Do we need a socket set? */
Simon Kelley7bcca002014-02-19 17:45:17 +00001691 if (!serv->sfd &&
Simon Kelley74d4fcd2021-03-15 21:59:51 +00001692 !(serv->sfd = allocate_sfd(&serv->source_addr, serv->interface, serv->ifindex)) &&
Simon Kelley1a6bca82008-07-11 11:11:42 +01001693 errno != 0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001694 {
Simon Kelleyf2621c72007-04-29 19:47:21 +01001695 my_syslog(LOG_WARNING,
1696 _("ignoring nameserver %s - cannot make/bind socket: %s"),
1697 daemon->namebuff, strerror(errno));
Simon Kelley7bcca002014-02-19 17:45:17 +00001698 serv->flags |= SERV_MARK;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001699 continue;
1700 }
Simon Kelley16800ea2016-08-30 23:07:06 +01001701
1702 if (serv->sfd)
1703 serv->sfd->used = 1;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001704 }
1705
Simon Kelley979fe862015-03-19 22:50:22 +00001706 if (!(serv->flags & SERV_NO_REBIND) && !(serv->flags & SERV_LITERAL_ADDRESS))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001707 {
Simon Kelleyb9702602016-05-03 22:34:06 +01001708 if (++count > SERVERS_LOGGED)
1709 continue;
1710
Simon Kelley7bcca002014-02-19 17:45:17 +00001711 if (serv->flags & (SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_USE_RESOLV))
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001712 {
Simon Kelley367341f2016-01-12 15:58:23 +00001713 char *s1, *s2, *s3 = "";
1714#ifdef HAVE_DNSSEC
1715 if (option_bool(OPT_DNSSEC_VALID) && !(serv->flags & SERV_DO_DNSSEC))
1716 s3 = _("(no DNSSEC)");
1717#endif
Simon Kelley7bcca002014-02-19 17:45:17 +00001718 if (!(serv->flags & SERV_HAS_DOMAIN))
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001719 s1 = _("unqualified"), s2 = _("names");
Simon Kelleyd9603ef2020-01-26 18:13:35 +00001720 else if (strlen(serv->domain) == 0)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001721 s1 = _("default"), s2 = "";
1722 else
Simon Kelley7bcca002014-02-19 17:45:17 +00001723 s1 = _("domain"), s2 = serv->domain;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001724
Simon Kelley7bcca002014-02-19 17:45:17 +00001725 if (serv->flags & SERV_NO_ADDR)
Hannu Nyman3e2496f2017-02-11 13:44:08 +00001726 {
1727 count--;
1728 if (++locals <= LOCALS_LOGGED)
Simon Kelley8bd28a82019-03-01 15:00:12 +00001729 my_syslog(LOG_INFO, _("using only locally-known addresses for %s %s"), s1, s2);
Hannu Nyman3e2496f2017-02-11 13:44:08 +00001730 }
Simon Kelley7bcca002014-02-19 17:45:17 +00001731 else if (serv->flags & SERV_USE_RESOLV)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001732 my_syslog(LOG_INFO, _("using standard nameservers for %s %s"), s1, s2);
Simon Kelley979fe862015-03-19 22:50:22 +00001733 else
Simon Kelley367341f2016-01-12 15:58:23 +00001734 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 +01001735 }
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001736#ifdef HAVE_LOOP
1737 else if (serv->flags & SERV_LOOP)
1738 my_syslog(LOG_INFO, _("NOT using nameserver %s#%d - query loop detected"), daemon->namebuff, port);
1739#endif
Simon Kelley7bcca002014-02-19 17:45:17 +00001740 else if (serv->interface[0] != 0)
1741 my_syslog(LOG_INFO, _("using nameserver %s#%d(via %s)"), daemon->namebuff, port, serv->interface);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001742 else
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001743 my_syslog(LOG_INFO, _("using nameserver %s#%d"), daemon->namebuff, port);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001744 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001745 }
Simon Kelleyb9702602016-05-03 22:34:06 +01001746
Hannu Nyman3e2496f2017-02-11 13:44:08 +00001747 if (locals > LOCALS_LOGGED)
1748 my_syslog(LOG_INFO, _("using %d more local addresses"), locals - LOCALS_LOGGED);
Simon Kelleyb9702602016-05-03 22:34:06 +01001749 if (count - 1 > SERVERS_LOGGED)
1750 my_syslog(LOG_INFO, _("using %d more nameservers"), count - SERVERS_LOGGED - 1);
Simon Kelley7bcca002014-02-19 17:45:17 +00001751
Beniamino Galvani2675f202016-08-28 20:44:05 +01001752 /* Remove unused sfds */
1753 for (sfd = daemon->sfds, up = &daemon->sfds; sfd; sfd = tmp)
1754 {
1755 tmp = sfd->next;
1756 if (!sfd->used)
1757 {
1758 *up = sfd->next;
1759 close(sfd->fd);
1760 free(sfd);
1761 }
1762 else
1763 up = &sfd->next;
1764 }
1765
Simon Kelley7bcca002014-02-19 17:45:17 +00001766 cleanup_servers();
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001767}
Simon Kelley849a8352006-06-09 21:02:31 +01001768
1769/* Return zero if no servers found, in that case we keep polling.
1770 This is a protection against an update-time/write race on resolv.conf */
Simon Kelley5aabfc72007-08-29 11:24:47 +01001771int reload_servers(char *fname)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001772{
1773 FILE *f;
1774 char *line;
Simon Kelley849a8352006-06-09 21:02:31 +01001775 int gotone = 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001776
Simon Kelley849a8352006-06-09 21:02:31 +01001777 /* buff happens to be MAXDNAME long... */
1778 if (!(f = fopen(fname, "r")))
1779 {
Simon Kelleyf2621c72007-04-29 19:47:21 +01001780 my_syslog(LOG_ERR, _("failed to read %s: %s"), fname, strerror(errno));
Simon Kelley849a8352006-06-09 21:02:31 +01001781 return 0;
1782 }
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001783
1784 mark_servers(SERV_FROM_RESOLV);
1785
Simon Kelley849a8352006-06-09 21:02:31 +01001786 while ((line = fgets(daemon->namebuff, MAXDNAME, f)))
1787 {
1788 union mysockaddr addr, source_addr;
1789 char *token = strtok(line, " \t\n\r");
1790
Simon Kelley5aabfc72007-08-29 11:24:47 +01001791 if (!token)
1792 continue;
1793 if (strcmp(token, "nameserver") != 0 && strcmp(token, "server") != 0)
Simon Kelley849a8352006-06-09 21:02:31 +01001794 continue;
1795 if (!(token = strtok(NULL, " \t\n\r")))
1796 continue;
1797
1798 memset(&addr, 0, sizeof(addr));
1799 memset(&source_addr, 0, sizeof(source_addr));
1800
1801 if ((addr.in.sin_addr.s_addr = inet_addr(token)) != (in_addr_t) -1)
1802 {
1803#ifdef HAVE_SOCKADDR_SA_LEN
1804 source_addr.in.sin_len = addr.in.sin_len = sizeof(source_addr.in);
1805#endif
1806 source_addr.in.sin_family = addr.in.sin_family = AF_INET;
1807 addr.in.sin_port = htons(NAMESERVER_PORT);
1808 source_addr.in.sin_addr.s_addr = INADDR_ANY;
1809 source_addr.in.sin_port = htons(daemon->query_port);
1810 }
Simon Kelley7de060b2011-08-26 17:24:52 +01001811 else
1812 {
1813 int scope_index = 0;
1814 char *scope_id = strchr(token, '%');
1815
1816 if (scope_id)
1817 {
1818 *(scope_id++) = 0;
1819 scope_index = if_nametoindex(scope_id);
1820 }
1821
1822 if (inet_pton(AF_INET6, token, &addr.in6.sin6_addr) > 0)
1823 {
Simon Kelley849a8352006-06-09 21:02:31 +01001824#ifdef HAVE_SOCKADDR_SA_LEN
Simon Kelley7de060b2011-08-26 17:24:52 +01001825 source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(source_addr.in6);
Simon Kelley849a8352006-06-09 21:02:31 +01001826#endif
Simon Kelley7de060b2011-08-26 17:24:52 +01001827 source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6;
1828 source_addr.in6.sin6_flowinfo = addr.in6.sin6_flowinfo = 0;
1829 addr.in6.sin6_port = htons(NAMESERVER_PORT);
1830 addr.in6.sin6_scope_id = scope_index;
1831 source_addr.in6.sin6_addr = in6addr_any;
1832 source_addr.in6.sin6_port = htons(daemon->query_port);
1833 source_addr.in6.sin6_scope_id = 0;
1834 }
1835 else
1836 continue;
Simon Kelley849a8352006-06-09 21:02:31 +01001837 }
Simon Kelley7de060b2011-08-26 17:24:52 +01001838
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001839 add_update_server(SERV_FROM_RESOLV, &addr, &source_addr, NULL, NULL);
Simon Kelley849a8352006-06-09 21:02:31 +01001840 gotone = 1;
1841 }
1842
Simon Kelley849a8352006-06-09 21:02:31 +01001843 fclose(f);
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001844 cleanup_servers();
Simon Kelley849a8352006-06-09 21:02:31 +01001845
1846 return gotone;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001847}
1848
Simon Kelley1ee9be42013-12-09 16:50:19 +00001849/* Called when addresses are added or deleted from an interface */
1850void newaddress(time_t now)
1851{
1852 (void)now;
1853
Simon Kelley89b12ed2014-03-06 13:27:57 +00001854 if (option_bool(OPT_CLEVERBIND) || option_bool(OPT_LOCAL_SERVICE) ||
1855 daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
Simon Kelley1ee9be42013-12-09 16:50:19 +00001856 enumerate_interfaces(0);
1857
1858 if (option_bool(OPT_CLEVERBIND))
1859 create_bound_listeners(0);
1860
1861#ifdef HAVE_DHCP6
1862 if (daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
1863 join_multicast(0);
1864
1865 if (daemon->doing_dhcp6 || daemon->doing_ra)
1866 dhcp_construct_contexts(now);
1867
1868 if (daemon->doing_dhcp6)
1869 lease_find_interfaces(now);
1870#endif
1871}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001872
1873
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001874
1875
1876