blob: 6cf15a98bb8c950ff9516fe75cff3a965e4d6f52 [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;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100235 int mtu = 0, 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 (ioctl(param->fd, SIOCGIFMTU, &ifr) != -1)
Simon Kelley1f15b812009-10-13 17:49:32 +0100257 mtu = ifr.ifr_mtu;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100258
Simon Kelley115ac3e2013-05-20 11:28:32 +0100259 if (!label)
260 label = ifr.ifr_name;
Petr Menšíkad59f272017-03-17 17:22:19 +0000261 else
262 is_label = strcmp(label, ifr.ifr_name);
Simon Kelleyc8a80482014-03-05 14:29:54 +0000263
264 /* maintain a list of all addresses on all interfaces for --local-service option */
265 if (option_bool(OPT_LOCAL_SERVICE))
266 {
267 struct addrlist *al;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100268
Simon Kelleyc8a80482014-03-05 14:29:54 +0000269 if (param->spare)
270 {
271 al = param->spare;
272 param->spare = al->next;
273 }
274 else
275 al = whine_malloc(sizeof(struct addrlist));
276
277 if (al)
278 {
279 al->next = daemon->interface_addrs;
280 daemon->interface_addrs = al;
281 al->prefixlen = prefixlen;
282
283 if (addr->sa.sa_family == AF_INET)
284 {
Simon Kelleycc921df2019-01-02 22:48:59 +0000285 al->addr.addr4 = addr->in.sin_addr;
Simon Kelleyc8a80482014-03-05 14:29:54 +0000286 al->flags = 0;
287 }
Simon Kelleyc8a80482014-03-05 14:29:54 +0000288 else
289 {
Simon Kelleycc921df2019-01-02 22:48:59 +0000290 al->addr.addr6 = addr->in6.sin6_addr;
Simon Kelleyc8a80482014-03-05 14:29:54 +0000291 al->flags = ADDRLIST_IPV6;
292 }
Simon Kelleyc8a80482014-03-05 14:29:54 +0000293 }
294 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000295
Simon Kelley115ac3e2013-05-20 11:28:32 +0100296 if (addr->sa.sa_family != AF_INET6 || !IN6_IS_ADDR_LINKLOCAL(&addr->in6.sin6_addr))
Simon Kelley115ac3e2013-05-20 11:28:32 +0100297 {
298 struct interface_name *int_name;
299 struct addrlist *al;
Simon Kelley376d48c2013-11-13 13:04:30 +0000300#ifdef HAVE_AUTH
301 struct auth_zone *zone;
302 struct auth_name_list *name;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100303
Simon Kelley376d48c2013-11-13 13:04:30 +0000304 /* Find subnets in auth_zones */
305 for (zone = daemon->auth_zones; zone; zone = zone->next)
306 for (name = zone->interface_names; name; name = name->next)
307 if (wildcard_match(name->name, label))
308 {
309 if (addr->sa.sa_family == AF_INET && (name->flags & AUTH4))
310 {
311 if (param->spare)
312 {
313 al = param->spare;
314 param->spare = al->next;
315 }
316 else
317 al = whine_malloc(sizeof(struct addrlist));
318
319 if (al)
320 {
321 al->next = zone->subnet;
322 zone->subnet = al;
323 al->prefixlen = prefixlen;
Simon Kelleycc921df2019-01-02 22:48:59 +0000324 al->addr.addr4 = addr->in.sin_addr;
Simon Kelley376d48c2013-11-13 13:04:30 +0000325 al->flags = 0;
326 }
327 }
328
Simon Kelley376d48c2013-11-13 13:04:30 +0000329 if (addr->sa.sa_family == AF_INET6 && (name->flags & AUTH6))
330 {
331 if (param->spare)
332 {
333 al = param->spare;
334 param->spare = al->next;
335 }
336 else
337 al = whine_malloc(sizeof(struct addrlist));
338
339 if (al)
340 {
341 al->next = zone->subnet;
342 zone->subnet = al;
Vladislav Grishenko3b195962013-11-26 11:08:21 +0000343 al->prefixlen = prefixlen;
Simon Kelleycc921df2019-01-02 22:48:59 +0000344 al->addr.addr6 = addr->in6.sin6_addr;
Simon Kelley376d48c2013-11-13 13:04:30 +0000345 al->flags = ADDRLIST_IPV6;
346 }
347 }
Simon Kelley376d48c2013-11-13 13:04:30 +0000348 }
349#endif
350
351 /* Update addresses from interface_names. These are a set independent
352 of the set we're listening on. */
Simon Kelley115ac3e2013-05-20 11:28:32 +0100353 for (int_name = daemon->int_names; int_name; int_name = int_name->next)
Simon Kelleyf7029f52013-11-21 15:09:09 +0000354 if (strncmp(label, int_name->intr, IF_NAMESIZE) == 0 &&
355 (addr->sa.sa_family == int_name->family || int_name->family == 0))
Simon Kelley115ac3e2013-05-20 11:28:32 +0100356 {
357 if (param->spare)
358 {
359 al = param->spare;
360 param->spare = al->next;
361 }
362 else
363 al = whine_malloc(sizeof(struct addrlist));
364
365 if (al)
366 {
Simon Kelley376d48c2013-11-13 13:04:30 +0000367 al->next = int_name->addr;
368 int_name->addr = al;
369
Simon Kelley115ac3e2013-05-20 11:28:32 +0100370 if (addr->sa.sa_family == AF_INET)
371 {
Simon Kelleycc921df2019-01-02 22:48:59 +0000372 al->addr.addr4 = addr->in.sin_addr;
Simon Kelley376d48c2013-11-13 13:04:30 +0000373 al->flags = 0;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100374 }
Simon Kelley115ac3e2013-05-20 11:28:32 +0100375 else
376 {
Simon Kelleycc921df2019-01-02 22:48:59 +0000377 al->addr.addr6 = addr->in6.sin6_addr;
Simon Kelley376d48c2013-11-13 13:04:30 +0000378 al->flags = ADDRLIST_IPV6;
Simon Kelley47669362014-12-17 12:41:56 +0000379 /* Privacy addresses and addresses still undergoing DAD and deprecated addresses
380 don't appear in forward queries, but will in reverse ones. */
381 if (!(iface_flags & IFACE_PERMANENT) || (iface_flags & (IFACE_DEPRECATED | IFACE_TENTATIVE)))
382 al->flags |= ADDRLIST_REVONLY;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100383 }
Simon Kelley115ac3e2013-05-20 11:28:32 +0100384 }
385 }
386 }
387
388 /* check whether the interface IP has been added already
389 we call this routine multiple times. */
390 for (iface = daemon->interfaces; iface; iface = iface->next)
Petr Mensik951a2212019-07-03 17:02:16 +0200391 if (sockaddr_isequal(&iface->addr, addr) && iface->index == if_index)
Simon Kelley115ac3e2013-05-20 11:28:32 +0100392 {
Simon Kelley47669362014-12-17 12:41:56 +0000393 iface->dad = !!(iface_flags & IFACE_TENTATIVE);
Simon Kelley08619212013-12-02 14:43:48 +0000394 iface->found = 1; /* for garbage collection */
Petr Mensik951a2212019-07-03 17:02:16 +0200395 iface->netmask = netmask;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100396 return 1;
397 }
398
399 /* If we are restricting the set of interfaces to use, make
Simon Kelley59353a62004-11-21 19:34:28 +0000400 sure that loopback interfaces are in that set. */
Simon Kelley1f15b812009-10-13 17:49:32 +0100401 if (daemon->if_names && loopback)
Simon Kelley59353a62004-11-21 19:34:28 +0000402 {
403 struct iname *lo;
404 for (lo = daemon->if_names; lo; lo = lo->next)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100405 if (lo->name && strcmp(lo->name, ifr.ifr_name) == 0)
Simon Kelley4ce4f372012-06-14 11:50:45 +0100406 break;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100407
Simon Kelley38365ff2013-02-05 14:35:54 +0000408 if (!lo && (lo = whine_malloc(sizeof(struct iname))))
Simon Kelley59353a62004-11-21 19:34:28 +0000409 {
Simon Kelley38365ff2013-02-05 14:35:54 +0000410 if ((lo->name = whine_malloc(strlen(ifr.ifr_name)+1)))
411 {
412 strcpy(lo->name, ifr.ifr_name);
413 lo->used = 1;
414 lo->next = daemon->if_names;
415 daemon->if_names = lo;
416 }
417 else
418 free(lo);
Simon Kelley59353a62004-11-21 19:34:28 +0000419 }
420 }
421
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100422 if (addr->sa.sa_family == AF_INET &&
Simon Kelleycc921df2019-01-02 22:48:59 +0000423 !iface_check(AF_INET, (union all_addr *)&addr->in.sin_addr, label, &auth_dns))
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100424 return 1;
Simon Kelley4f7b3042012-11-28 21:27:02 +0000425
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100426 if (addr->sa.sa_family == AF_INET6 &&
Simon Kelleycc921df2019-01-02 22:48:59 +0000427 !iface_check(AF_INET6, (union all_addr *)&addr->in6.sin6_addr, label, &auth_dns))
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100428 return 1;
Simon Kelley4f7b3042012-11-28 21:27:02 +0000429
430#ifdef HAVE_DHCP
431 /* No DHCP where we're doing auth DNS. */
432 if (auth_dns)
433 {
434 tftp_ok = 0;
435 dhcp_ok = 0;
436 }
437 else
438 for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
Simon Kelley49333cb2013-03-15 20:30:51 +0000439 if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
Simon Kelley4f7b3042012-11-28 21:27:02 +0000440 {
441 tftp_ok = 0;
442 dhcp_ok = 0;
443 }
444#endif
445
Simon Kelley2937f8a2013-07-29 19:49:07 +0100446
Simon Kelley91543f42013-09-23 12:41:20 +0100447#ifdef HAVE_TFTP
Simon Kelley2937f8a2013-07-29 19:49:07 +0100448 if (daemon->tftp_interfaces)
449 {
450 /* dedicated tftp interface list */
451 tftp_ok = 0;
452 for (tmp = daemon->tftp_interfaces; tmp; tmp = tmp->next)
453 if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
454 tftp_ok = 1;
455 }
Simon Kelley91543f42013-09-23 12:41:20 +0100456#endif
Simon Kelley2937f8a2013-07-29 19:49:07 +0100457
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100458 /* add to list */
Simon Kelley5aabfc72007-08-29 11:24:47 +0100459 if ((iface = whine_malloc(sizeof(struct irec))))
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100460 {
461 iface->addr = *addr;
462 iface->netmask = netmask;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100463 iface->tftp_ok = tftp_ok;
Simon Kelley9380ba72012-04-16 14:41:56 +0100464 iface->dhcp_ok = dhcp_ok;
Simon Kelley4f7b3042012-11-28 21:27:02 +0000465 iface->dns_auth = auth_dns;
Simon Kelley1f15b812009-10-13 17:49:32 +0100466 iface->mtu = mtu;
Simon Kelley47669362014-12-17 12:41:56 +0000467 iface->dad = !!(iface_flags & IFACE_TENTATIVE);
Simon Kelley08619212013-12-02 14:43:48 +0000468 iface->found = 1;
Simon Kelleydc27e142013-10-16 13:09:53 +0100469 iface->done = iface->multicast_done = iface->warned = 0;
Simon Kelley5d162f22012-12-20 14:55:46 +0000470 iface->index = if_index;
Petr Menšíkad59f272017-03-17 17:22:19 +0000471 iface->label = is_label;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100472 if ((iface->name = whine_malloc(strlen(ifr.ifr_name)+1)))
Simon Kelley6f13e532012-04-17 14:25:06 +0100473 {
474 strcpy(iface->name, ifr.ifr_name);
Simon Kelley115ac3e2013-05-20 11:28:32 +0100475 iface->next = daemon->interfaces;
476 daemon->interfaces = iface;
Simon Kelley6f13e532012-04-17 14:25:06 +0100477 return 1;
478 }
479 free(iface);
Simon Kelley5d162f22012-12-20 14:55:46 +0000480
Simon Kelley44a2a312004-03-10 20:04:35 +0000481 }
482
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100483 errno = ENOMEM;
484 return 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000485}
486
Simon Kelleyc72daea2012-01-05 21:33:27 +0000487static int iface_allowed_v6(struct in6_addr *local, int prefix,
Simon Kelleybad7b872012-12-20 22:00:39 +0000488 int scope, int if_index, int flags,
Simon Kelley1f776932012-12-16 19:46:08 +0000489 int preferred, int valid, void *vparam)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000490{
Simon Kelley59353a62004-11-21 19:34:28 +0000491 union mysockaddr addr;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100492 struct in_addr netmask; /* dummy */
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100493 netmask.s_addr = 0;
Simon Kelley52b92f42012-01-22 16:05:15 +0000494
Simon Kelley52b92f42012-01-22 16:05:15 +0000495 (void)scope; /* warning */
Simon Kelley1f776932012-12-16 19:46:08 +0000496 (void)preferred;
497 (void)valid;
Simon Kelley44a2a312004-03-10 20:04:35 +0000498
Simon Kelley849a8352006-06-09 21:02:31 +0100499 memset(&addr, 0, sizeof(addr));
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000500#ifdef HAVE_SOCKADDR_SA_LEN
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100501 addr.in6.sin6_len = sizeof(addr.in6);
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000502#endif
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100503 addr.in6.sin6_family = AF_INET6;
504 addr.in6.sin6_addr = *local;
505 addr.in6.sin6_port = htons(daemon->port);
Simon Kelley62ab3cc2013-12-03 11:53:53 +0000506 /* FreeBSD insists this is zero for non-linklocal addresses */
507 if (IN6_IS_ADDR_LINKLOCAL(local))
508 addr.in6.sin6_scope_id = if_index;
509 else
510 addr.in6.sin6_scope_id = 0;
Simon Kelley1ee9be42013-12-09 16:50:19 +0000511
Simon Kelley47669362014-12-17 12:41:56 +0000512 return iface_allowed((struct iface_param *)vparam, if_index, NULL, &addr, netmask, prefix, flags);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100513}
Simon Kelley59353a62004-11-21 19:34:28 +0000514
Simon Kelley3f2873d2013-05-14 11:28:47 +0100515static int iface_allowed_v4(struct in_addr local, int if_index, char *label,
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100516 struct in_addr netmask, struct in_addr broadcast, void *vparam)
517{
518 union mysockaddr addr;
Simon Kelley376d48c2013-11-13 13:04:30 +0000519 int prefix, bit;
Simon Kelleyb8ac4662016-03-10 18:40:53 +0000520
521 (void)broadcast; /* warning */
Simon Kelley849a8352006-06-09 21:02:31 +0100522
523 memset(&addr, 0, sizeof(addr));
Simon Kelley1ab84e22004-01-29 16:48:35 +0000524#ifdef HAVE_SOCKADDR_SA_LEN
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100525 addr.in.sin_len = sizeof(addr.in);
Simon Kelley1ab84e22004-01-29 16:48:35 +0000526#endif
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100527 addr.in.sin_family = AF_INET;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100528 addr.in.sin_addr = local;
529 addr.in.sin_port = htons(daemon->port);
Simon Kelley44a2a312004-03-10 20:04:35 +0000530
Simon Kelley376d48c2013-11-13 13:04:30 +0000531 /* determine prefix length from netmask */
532 for (prefix = 32, bit = 1; (bit & ntohl(netmask.s_addr)) == 0 && prefix != 0; bit = bit << 1, prefix--);
533
534 return iface_allowed((struct iface_param *)vparam, if_index, label, &addr, netmask, prefix, 0);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100535}
Petr Mensik60a3ae12019-07-09 14:05:59 +0200536
537/*
538 * Clean old interfaces no longer found.
539 */
540static void clean_interfaces()
541{
542 struct irec *iface;
543 struct irec **up = &daemon->interfaces;
544
545 for (iface = *up; iface; iface = *up)
546 {
547 if (!iface->found && !iface->done)
548 {
549 *up = iface->next;
550 free(iface->name);
551 free(iface);
552 }
553 else
554 {
555 up = &iface->next;
556 }
557 }
558}
559
Petr Menšík49bdf1e2019-07-15 17:13:12 +0200560/** Release listener if no other interface needs it.
561 *
562 * @return 1 if released, 0 if still required
563 */
564static int release_listener(struct listener *l)
565{
566 if (l->used > 1)
567 {
568 struct irec *iface;
569 for (iface = daemon->interfaces; iface; iface = iface->next)
570 if (iface->done && sockaddr_isequal(&l->addr, &iface->addr))
571 {
572 if (iface->found)
573 {
574 /* update listener to point to active interface instead */
575 if (!l->iface->found)
576 l->iface = iface;
577 }
578 else
579 {
580 l->used--;
581 iface->done = 0;
582 }
583 }
584
585 /* Someone is still using this listener, skip its deletion */
586 if (l->used > 0)
587 return 0;
588 }
589
590 if (l->iface->done)
591 {
592 int port;
593
594 port = prettyprint_addr(&l->iface->addr, daemon->addrbuff);
595 my_syslog(LOG_DEBUG, _("stopped listening on %s(#%d): %s port %d"),
596 l->iface->name, l->iface->index, daemon->addrbuff, port);
597 /* In case it ever returns */
598 l->iface->done = 0;
599 }
600
601 if (l->fd != -1)
602 close(l->fd);
603 if (l->tcpfd != -1)
604 close(l->tcpfd);
605 if (l->tftpfd != -1)
606 close(l->tftpfd);
607
608 free(l);
609 return 1;
610}
611
Simon Kelley115ac3e2013-05-20 11:28:32 +0100612int enumerate_interfaces(int reset)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100613{
Simon Kelley115ac3e2013-05-20 11:28:32 +0100614 static struct addrlist *spare = NULL;
Simon Kelleya0358e52014-06-07 13:38:48 +0100615 static int done = 0;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100616 struct iface_param param;
617 int errsave, ret = 1;
618 struct addrlist *addr, *tmp;
619 struct interface_name *intname;
Simon Kelley08619212013-12-02 14:43:48 +0000620 struct irec *iface;
Simon Kelley376d48c2013-11-13 13:04:30 +0000621#ifdef HAVE_AUTH
622 struct auth_zone *zone;
623#endif
624
Simon Kelley76dd75d2013-05-23 10:04:25 +0100625 /* Do this max once per select cycle - also inhibits netlink socket use
626 in TCP child processes. */
Simon Kelley397542b2013-09-05 11:27:34 +0100627
Simon Kelley115ac3e2013-05-20 11:28:32 +0100628 if (reset)
629 {
630 done = 0;
631 return 1;
632 }
633
Simon Kelleya0358e52014-06-07 13:38:48 +0100634 if (done)
Simon Kelley115ac3e2013-05-20 11:28:32 +0100635 return 1;
636
637 done = 1;
638
639 if ((param.fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
640 return 0;
641
Simon Kelley08619212013-12-02 14:43:48 +0000642 /* Mark interfaces for garbage collection */
643 for (iface = daemon->interfaces; iface; iface = iface->next)
644 iface->found = 0;
645
Simon Kelley115ac3e2013-05-20 11:28:32 +0100646 /* remove addresses stored against interface_names */
647 for (intname = daemon->int_names; intname; intname = intname->next)
648 {
Simon Kelley376d48c2013-11-13 13:04:30 +0000649 for (addr = intname->addr; addr; addr = tmp)
Simon Kelley115ac3e2013-05-20 11:28:32 +0100650 {
651 tmp = addr->next;
652 addr->next = spare;
653 spare = addr;
654 }
655
Simon Kelley376d48c2013-11-13 13:04:30 +0000656 intname->addr = NULL;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100657 }
Simon Kelley376d48c2013-11-13 13:04:30 +0000658
Simon Kelleyc8a80482014-03-05 14:29:54 +0000659 /* Remove list of addresses of local interfaces */
660 for (addr = daemon->interface_addrs; addr; addr = tmp)
661 {
662 tmp = addr->next;
663 addr->next = spare;
664 spare = addr;
665 }
666 daemon->interface_addrs = NULL;
667
Simon Kelley376d48c2013-11-13 13:04:30 +0000668#ifdef HAVE_AUTH
669 /* remove addresses stored against auth_zone subnets, but not
670 ones configured as address literals */
671 for (zone = daemon->auth_zones; zone; zone = zone->next)
672 if (zone->interface_names)
673 {
674 struct addrlist **up;
675 for (up = &zone->subnet, addr = zone->subnet; addr; addr = tmp)
676 {
677 tmp = addr->next;
678 if (addr->flags & ADDRLIST_LITERAL)
679 up = &addr->next;
680 else
681 {
682 *up = addr->next;
683 addr->next = spare;
684 spare = addr;
685 }
686 }
687 }
688#endif
689
Simon Kelley115ac3e2013-05-20 11:28:32 +0100690 param.spare = spare;
691
Simon Kelley115ac3e2013-05-20 11:28:32 +0100692 ret = iface_enumerate(AF_INET6, &param, iface_allowed_v6);
Simon Kelley28866e92011-02-14 20:19:14 +0000693
Simon Kelley115ac3e2013-05-20 11:28:32 +0100694 if (ret)
695 ret = iface_enumerate(AF_INET, &param, iface_allowed_v4);
696
697 errsave = errno;
698 close(param.fd);
Simon Kelley08619212013-12-02 14:43:48 +0000699
700 if (option_bool(OPT_CLEVERBIND))
701 {
702 /* Garbage-collect listeners listening on addresses that no longer exist.
703 Does nothing when not binding interfaces or for listeners on localhost,
704 since the ->iface field is NULL. Note that this needs the protections
Josh Soref730c6742017-02-06 16:14:04 +0000705 against reentrancy, hence it's here. It also means there's a possibility,
Simon Kelley08619212013-12-02 14:43:48 +0000706 in OPT_CLEVERBIND mode, that at listener will just disappear after
707 a call to enumerate_interfaces, this is checked OK on all calls. */
708 struct listener *l, *tmp, **up;
Petr Mensik60a3ae12019-07-09 14:05:59 +0200709 int freed = 0;
Simon Kelley08619212013-12-02 14:43:48 +0000710
711 for (up = &daemon->listeners, l = daemon->listeners; l; l = tmp)
712 {
713 tmp = l->next;
714
715 if (!l->iface || l->iface->found)
716 up = &l->next;
Petr Menšík49bdf1e2019-07-15 17:13:12 +0200717 else if (release_listener(l))
Simon Kelley08619212013-12-02 14:43:48 +0000718 {
Petr Menšík49bdf1e2019-07-15 17:13:12 +0200719 *up = tmp;
Simon Kelley619000a2020-04-29 00:09:58 +0100720 freed = 1;
Simon Kelley08619212013-12-02 14:43:48 +0000721 }
722 }
Petr Mensik60a3ae12019-07-09 14:05:59 +0200723
724 if (freed)
725 clean_interfaces();
Simon Kelley08619212013-12-02 14:43:48 +0000726 }
Petr Mensik60a3ae12019-07-09 14:05:59 +0200727
Simon Kelley115ac3e2013-05-20 11:28:32 +0100728 errno = errsave;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100729 spare = param.spare;
Simon Kelleya0358e52014-06-07 13:38:48 +0100730
Simon Kelley115ac3e2013-05-20 11:28:32 +0100731 return ret;
Simon Kelley44a2a312004-03-10 20:04:35 +0000732}
733
Simon Kelley5aabfc72007-08-29 11:24:47 +0100734/* set NONBLOCK bit on fd: See Stevens 16.6 */
Simon Kelley7cebd202006-05-06 14:13:33 +0100735int fix_fd(int fd)
736{
737 int flags;
738
739 if ((flags = fcntl(fd, F_GETFL)) == -1 ||
Simon Kelley5aabfc72007-08-29 11:24:47 +0100740 fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
Simon Kelley7cebd202006-05-06 14:13:33 +0100741 return 0;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100742
Simon Kelley7cebd202006-05-06 14:13:33 +0100743 return 1;
744}
745
Simon Kelley74c95c22011-10-19 09:33:39 +0100746static int make_sock(union mysockaddr *addr, int type, int dienow)
Simon Kelley44a2a312004-03-10 20:04:35 +0000747{
Simon Kelley28866e92011-02-14 20:19:14 +0000748 int family = addr->sa.sa_family;
749 int fd, rc, opt = 1;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100750
Simon Kelley28866e92011-02-14 20:19:14 +0000751 if ((fd = socket(family, type, 0)) == -1)
Simon Kelley316e2732010-01-22 20:16:09 +0000752 {
Josh Soref730c6742017-02-06 16:14:04 +0000753 int port, errsave;
Simon Kelley39f1b8e2012-06-20 20:04:27 +0100754 char *s;
Simon Kelley28866e92011-02-14 20:19:14 +0000755
756 /* No error if the kernel just doesn't support this IP flavour */
757 if (errno == EPROTONOSUPPORT ||
758 errno == EAFNOSUPPORT ||
759 errno == EINVAL)
760 return -1;
761
762 err:
Josh Soref730c6742017-02-06 16:14:04 +0000763 errsave = errno;
Simon Kelley39f1b8e2012-06-20 20:04:27 +0100764 port = prettyprint_addr(addr, daemon->addrbuff);
765 if (!option_bool(OPT_NOWILD) && !option_bool(OPT_CLEVERBIND))
766 sprintf(daemon->addrbuff, "port %d", port);
767 s = _("failed to create listening socket for %s: %s");
768
Simon Kelley5f11b3e2012-08-16 14:04:05 +0100769 if (fd != -1)
Matthias Andree71aaa5a2013-12-03 11:20:45 +0000770 close (fd);
771
Josh Soref730c6742017-02-06 16:14:04 +0000772 errno = errsave;
Simon Kelley1ee9be42013-12-09 16:50:19 +0000773
Simon Kelley5f11b3e2012-08-16 14:04:05 +0100774 if (dienow)
775 {
776 /* failure to bind addresses given by --listen-address at this point
777 is OK if we're doing bind-dynamic */
778 if (!option_bool(OPT_CLEVERBIND))
779 die(s, daemon->addrbuff, EC_BADNET);
780 }
781 else
782 my_syslog(LOG_WARNING, s, daemon->addrbuff, strerror(errno));
783
Simon Kelley74c95c22011-10-19 09:33:39 +0100784 return -1;
Simon Kelley28866e92011-02-14 20:19:14 +0000785 }
Simon Kelley5f11b3e2012-08-16 14:04:05 +0100786
Simon Kelley28866e92011-02-14 20:19:14 +0000787 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || !fix_fd(fd))
788 goto err;
789
Simon Kelleyc72daea2012-01-05 21:33:27 +0000790 if (family == AF_INET6 && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)) == -1)
Simon Kelley28866e92011-02-14 20:19:14 +0000791 goto err;
Simon Kelley28866e92011-02-14 20:19:14 +0000792
Simon Kelley74c95c22011-10-19 09:33:39 +0100793 if ((rc = bind(fd, (struct sockaddr *)addr, sa_len(addr))) == -1)
Simon Kelley28866e92011-02-14 20:19:14 +0000794 goto err;
795
796 if (type == SOCK_STREAM)
797 {
Simon Kelley608aa9f2019-03-10 22:44:15 +0000798#ifdef TCP_FASTOPEN
799 int qlen = 5;
Matthias Andreee39c4842020-03-05 15:58:31 +0000800 setsockopt(fd, IPPROTO_TCP, TCP_FASTOPEN, &qlen, sizeof(qlen));
Simon Kelley608aa9f2019-03-10 22:44:15 +0000801#endif
802
Simon Kelley09b768e2016-12-22 22:16:58 +0000803 if (listen(fd, TCP_BACKLOG) == -1)
Simon Kelley28866e92011-02-14 20:19:14 +0000804 goto err;
805 }
Simon Kelley2329bef2013-12-03 13:41:16 +0000806 else if (family == AF_INET)
Simon Kelley28866e92011-02-14 20:19:14 +0000807 {
Simon Kelley2329bef2013-12-03 13:41:16 +0000808 if (!option_bool(OPT_NOWILD))
Simon Kelley28866e92011-02-14 20:19:14 +0000809 {
810#if defined(HAVE_LINUX_NETWORK)
Simon Kelleyc72daea2012-01-05 21:33:27 +0000811 if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) == -1)
Simon Kelley28866e92011-02-14 20:19:14 +0000812 goto err;
813#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
814 if (setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt)) == -1 ||
815 setsockopt(fd, IPPROTO_IP, IP_RECVIF, &opt, sizeof(opt)) == -1)
816 goto err;
817#endif
818 }
Simon Kelley28866e92011-02-14 20:19:14 +0000819 }
Simon Kelley2329bef2013-12-03 13:41:16 +0000820 else if (!set_ipv6pktinfo(fd))
821 goto err;
Simon Kelleyc72daea2012-01-05 21:33:27 +0000822
Simon Kelley28866e92011-02-14 20:19:14 +0000823 return fd;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100824}
Simon Kelleyc72daea2012-01-05 21:33:27 +0000825
Simon Kelleyc72daea2012-01-05 21:33:27 +0000826int set_ipv6pktinfo(int fd)
827{
828 int opt = 1;
829
830 /* The API changed around Linux 2.6.14 but the old ABI is still supported:
831 handle all combinations of headers and kernel.
832 OpenWrt note that this fixes the problem addressed by your very broken patch. */
833 daemon->v6pktinfo = IPV6_PKTINFO;
834
835#ifdef IPV6_RECVPKTINFO
836 if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &opt, sizeof(opt)) != -1)
837 return 1;
838# ifdef IPV6_2292PKTINFO
839 else if (errno == ENOPROTOOPT && setsockopt(fd, IPPROTO_IPV6, IPV6_2292PKTINFO, &opt, sizeof(opt)) != -1)
840 {
841 daemon->v6pktinfo = IPV6_2292PKTINFO;
842 return 1;
843 }
844# endif
845#else
846 if (setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &opt, sizeof(opt)) != -1)
847 return 1;
848#endif
849
850 return 0;
851}
Simon Kelley22ce5502013-01-22 13:53:04 +0000852
853
854/* Find the interface on which a TCP connection arrived, if possible, or zero otherwise. */
855int tcp_interface(int fd, int af)
856{
Kevin Darbyshire-Bryant70c50ef2020-03-06 10:31:15 +0000857 (void)fd; /* suppress potential unused warning */
858 (void)af; /* suppress potential unused warning */
Simon Kelley22ce5502013-01-22 13:53:04 +0000859 int if_index = 0;
860
861#ifdef HAVE_LINUX_NETWORK
862 int opt = 1;
863 struct cmsghdr *cmptr;
864 struct msghdr msg;
Simon Kelley529b0302016-03-16 19:00:45 +0000865 socklen_t len;
Simon Kelley22ce5502013-01-22 13:53:04 +0000866
Simon Kelley529b0302016-03-16 19:00:45 +0000867 /* use mshdr so that the CMSDG_* macros are available */
Simon Kelley22ce5502013-01-22 13:53:04 +0000868 msg.msg_control = daemon->packet;
Simon Kelley529b0302016-03-16 19:00:45 +0000869 msg.msg_controllen = len = daemon->packet_buff_sz;
Simon Kelley22ce5502013-01-22 13:53:04 +0000870
871 /* we overwrote the buffer... */
872 daemon->srv_save = NULL;
873
874 if (af == AF_INET)
875 {
876 if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) != -1 &&
Simon Kelley529b0302016-03-16 19:00:45 +0000877 getsockopt(fd, IPPROTO_IP, IP_PKTOPTIONS, msg.msg_control, &len) != -1)
878 {
879 msg.msg_controllen = len;
880 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
881 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
882 {
883 union {
884 unsigned char *c;
885 struct in_pktinfo *p;
886 } p;
887
888 p.c = CMSG_DATA(cmptr);
889 if_index = p.p->ipi_ifindex;
890 }
891 }
Simon Kelley22ce5502013-01-22 13:53:04 +0000892 }
Simon Kelley22ce5502013-01-22 13:53:04 +0000893 else
894 {
895 /* Only the RFC-2292 API has the ability to find the interface for TCP connections,
896 it was removed in RFC-3542 !!!!
897
898 Fortunately, Linux kept the 2292 ABI when it moved to 3542. The following code always
899 uses the old ABI, and should work with pre- and post-3542 kernel headers */
900
901#ifdef IPV6_2292PKTOPTIONS
902# define PKTOPTIONS IPV6_2292PKTOPTIONS
903#else
904# define PKTOPTIONS IPV6_PKTOPTIONS
905#endif
906
907 if (set_ipv6pktinfo(fd) &&
Simon Kelley529b0302016-03-16 19:00:45 +0000908 getsockopt(fd, IPPROTO_IPV6, PKTOPTIONS, msg.msg_control, &len) != -1)
Simon Kelley22ce5502013-01-22 13:53:04 +0000909 {
Simon Kelley529b0302016-03-16 19:00:45 +0000910 msg.msg_controllen = len;
911 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
Simon Kelley22ce5502013-01-22 13:53:04 +0000912 if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
913 {
914 union {
915 unsigned char *c;
916 struct in6_pktinfo *p;
917 } p;
918 p.c = CMSG_DATA(cmptr);
919
920 if_index = p.p->ipi6_ifindex;
921 }
922 }
923 }
Simon Kelley22ce5502013-01-22 13:53:04 +0000924#endif /* Linux */
925
926 return if_index;
927}
Simon Kelley28866e92011-02-14 20:19:14 +0000928
Simon Kelley74c95c22011-10-19 09:33:39 +0100929static struct listener *create_listeners(union mysockaddr *addr, int do_tftp, int dienow)
Simon Kelley28866e92011-02-14 20:19:14 +0000930{
931 struct listener *l = NULL;
932 int fd = -1, tcpfd = -1, tftpfd = -1;
933
Vladislav Grishenko408c3682013-09-24 16:18:49 +0100934 (void)do_tftp;
935
Simon Kelley28866e92011-02-14 20:19:14 +0000936 if (daemon->port != 0)
937 {
Simon Kelley74c95c22011-10-19 09:33:39 +0100938 fd = make_sock(addr, SOCK_DGRAM, dienow);
939 tcpfd = make_sock(addr, SOCK_STREAM, dienow);
Simon Kelley28866e92011-02-14 20:19:14 +0000940 }
941
942#ifdef HAVE_TFTP
943 if (do_tftp)
944 {
945 if (addr->sa.sa_family == AF_INET)
946 {
947 /* port must be restored to DNS port for TCP code */
948 short save = addr->in.sin_port;
949 addr->in.sin_port = htons(TFTP_PORT);
Simon Kelley74c95c22011-10-19 09:33:39 +0100950 tftpfd = make_sock(addr, SOCK_DGRAM, dienow);
Simon Kelley28866e92011-02-14 20:19:14 +0000951 addr->in.sin_port = save;
952 }
Simon Kelley28866e92011-02-14 20:19:14 +0000953 else
954 {
955 short save = addr->in6.sin6_port;
956 addr->in6.sin6_port = htons(TFTP_PORT);
Simon Kelley74c95c22011-10-19 09:33:39 +0100957 tftpfd = make_sock(addr, SOCK_DGRAM, dienow);
Simon Kelley28866e92011-02-14 20:19:14 +0000958 addr->in6.sin6_port = save;
959 }
Simon Kelley28866e92011-02-14 20:19:14 +0000960 }
Simon Kelley44a2a312004-03-10 20:04:35 +0000961#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100962
Simon Kelley28866e92011-02-14 20:19:14 +0000963 if (fd != -1 || tcpfd != -1 || tftpfd != -1)
964 {
965 l = safe_malloc(sizeof(struct listener));
966 l->next = NULL;
Simon Kelley28866e92011-02-14 20:19:14 +0000967 l->fd = fd;
968 l->tcpfd = tcpfd;
Petr Menšík49bdf1e2019-07-15 17:13:12 +0200969 l->tftpfd = tftpfd;
970 l->addr = *addr;
971 l->used = 1;
Simon Kelley08619212013-12-02 14:43:48 +0000972 l->iface = NULL;
Simon Kelley28866e92011-02-14 20:19:14 +0000973 }
974
975 return l;
976}
977
Simon Kelley74c95c22011-10-19 09:33:39 +0100978void create_wildcard_listeners(void)
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100979{
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100980 union mysockaddr addr;
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100981 struct listener *l, *l6;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100982
Simon Kelley849a8352006-06-09 21:02:31 +0100983 memset(&addr, 0, sizeof(addr));
Simon Kelley28866e92011-02-14 20:19:14 +0000984#ifdef HAVE_SOCKADDR_SA_LEN
985 addr.in.sin_len = sizeof(addr.in);
986#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100987 addr.in.sin_family = AF_INET;
988 addr.in.sin_addr.s_addr = INADDR_ANY;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100989 addr.in.sin_port = htons(daemon->port);
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100990
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100991 l = create_listeners(&addr, !!option_bool(OPT_TFTP), 1);
Simon Kelley28866e92011-02-14 20:19:14 +0000992
Simon Kelley28866e92011-02-14 20:19:14 +0000993 memset(&addr, 0, sizeof(addr));
Simon Kelleyee875042018-10-23 22:10:17 +0100994#ifdef HAVE_SOCKADDR_SA_LEN
Simon Kelley28866e92011-02-14 20:19:14 +0000995 addr.in6.sin6_len = sizeof(addr.in6);
Simon Kelleyee875042018-10-23 22:10:17 +0100996#endif
Simon Kelley28866e92011-02-14 20:19:14 +0000997 addr.in6.sin6_family = AF_INET6;
998 addr.in6.sin6_addr = in6addr_any;
999 addr.in6.sin6_port = htons(daemon->port);
Simon Kelley8bc4cec2012-07-03 21:04:11 +01001000
1001 l6 = create_listeners(&addr, !!option_bool(OPT_TFTP), 1);
Simon Kelley28866e92011-02-14 20:19:14 +00001002 if (l)
Simon Kelley8bc4cec2012-07-03 21:04:11 +01001003 l->next = l6;
Simon Kelley28866e92011-02-14 20:19:14 +00001004 else
Simon Kelley8bc4cec2012-07-03 21:04:11 +01001005 l = l6;
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001006
Simon Kelley74c95c22011-10-19 09:33:39 +01001007 daemon->listeners = l;
Simon Kelley44a2a312004-03-10 20:04:35 +00001008}
1009
Petr Menšík49bdf1e2019-07-15 17:13:12 +02001010static struct listener *find_listener(union mysockaddr *addr)
1011{
1012 struct listener *l;
1013 for (l = daemon->listeners; l; l = l->next)
1014 if (sockaddr_isequal(&l->addr, addr))
1015 return l;
1016 return NULL;
1017}
1018
Simon Kelley74c95c22011-10-19 09:33:39 +01001019void create_bound_listeners(int dienow)
Simon Kelley44a2a312004-03-10 20:04:35 +00001020{
Simon Kelley74c95c22011-10-19 09:33:39 +01001021 struct listener *new;
Simon Kelley44a2a312004-03-10 20:04:35 +00001022 struct irec *iface;
Simon Kelley52d4abf2012-03-21 21:39:48 +00001023 struct iname *if_tmp;
Petr Menšík49bdf1e2019-07-15 17:13:12 +02001024 struct listener *existing;
Simon Kelley73a08a22009-02-05 20:28:08 +00001025
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001026 for (iface = daemon->interfaces; iface; iface = iface->next)
Petr Menšík49bdf1e2019-07-15 17:13:12 +02001027 if (!iface->done && !iface->dad && iface->found)
Simon Kelley28866e92011-02-14 20:19:14 +00001028 {
Petr Menšík49bdf1e2019-07-15 17:13:12 +02001029 existing = find_listener(&iface->addr);
1030 if (existing)
1031 {
1032 iface->done = 1;
1033 existing->used++; /* increase usage counter */
1034 }
1035 else if ((new = create_listeners(&iface->addr, iface->tftp_ok, dienow)))
1036 {
Petr Menšík49bdf1e2019-07-15 17:13:12 +02001037 new->iface = iface;
1038 new->next = daemon->listeners;
1039 daemon->listeners = new;
1040 iface->done = 1;
Simon Kelley619000a2020-04-29 00:09:58 +01001041
1042 /* Don't log the initial set of listen addresses created
1043 at startup, since this is happening before the logging
1044 system is initialised and the sign-on printed. */
1045 if (!dienow)
1046 {
1047 int port = prettyprint_addr(&iface->addr, daemon->addrbuff);
1048 my_syslog(LOG_DEBUG, _("listening on %s(#%d): %s port %d"),
1049 iface->name, iface->index, daemon->addrbuff, port);
1050 }
Petr Menšík49bdf1e2019-07-15 17:13:12 +02001051 }
Simon Kelley28866e92011-02-14 20:19:14 +00001052 }
Simon Kelley52d4abf2012-03-21 21:39:48 +00001053
1054 /* Check for --listen-address options that haven't been used because there's
1055 no interface with a matching address. These may be valid: eg it's possible
1056 to listen on 127.0.1.1 even if the loopback interface is 127.0.0.1
1057
Simon Kelley5f11b3e2012-08-16 14:04:05 +01001058 If the address isn't valid the bind() will fail and we'll die()
1059 (except in bind-dynamic mode, when we'll complain but keep trying.)
Simon Kelley52d4abf2012-03-21 21:39:48 +00001060
1061 The resulting listeners have the ->iface field NULL, and this has to be
1062 handled by the DNS and TFTP code. It disables --localise-queries processing
1063 (no netmask) and some MTU login the tftp code. */
1064
1065 for (if_tmp = daemon->if_addrs; if_tmp; if_tmp = if_tmp->next)
1066 if (!if_tmp->used &&
Simon Kelley8bc4cec2012-07-03 21:04:11 +01001067 (new = create_listeners(&if_tmp->addr, !!option_bool(OPT_TFTP), dienow)))
Simon Kelley52d4abf2012-03-21 21:39:48 +00001068 {
Simon Kelley52d4abf2012-03-21 21:39:48 +00001069 new->next = daemon->listeners;
1070 daemon->listeners = new;
Simon Kelley619000a2020-04-29 00:09:58 +01001071
1072 if (!dienow)
1073 {
1074 int port = prettyprint_addr(&if_tmp->addr, daemon->addrbuff);
1075 my_syslog(LOG_DEBUG, _("listening on %s port %d"), daemon->addrbuff, port);
1076 }
Simon Kelley52d4abf2012-03-21 21:39:48 +00001077 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001078}
1079
Simon Kelleydc27e142013-10-16 13:09:53 +01001080/* In --bind-interfaces, the only access control is the addresses we're listening on.
1081 There's nothing to avoid a query to the address of an internal interface arriving via
1082 an external interface where we don't want to accept queries, except that in the usual
1083 case the addresses of internal interfaces are RFC1918. When bind-interfaces in use,
1084 and we listen on an address that looks like it's probably globally routeable, shout.
1085
1086 The fix is to use --bind-dynamic, which actually checks the arrival interface too.
1087 Tough if your platform doesn't support this.
Simon Kelley2329bef2013-12-03 13:41:16 +00001088
1089 Note that checking the arrival interface is supported in the standard IPv6 API and
1090 always done, so we don't warn about any IPv6 addresses here.
Simon Kelleydc27e142013-10-16 13:09:53 +01001091*/
1092
1093void warn_bound_listeners(void)
1094{
1095 struct irec *iface;
1096 int advice = 0;
1097
1098 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelleyf7029f52013-11-21 15:09:09 +00001099 if (!iface->dns_auth)
Simon Kelleydc27e142013-10-16 13:09:53 +01001100 {
Simon Kelleydc27e142013-10-16 13:09:53 +01001101 if (iface->addr.sa.sa_family == AF_INET)
1102 {
1103 if (!private_net(iface->addr.in.sin_addr, 1))
1104 {
1105 inet_ntop(AF_INET, &iface->addr.in.sin_addr, daemon->addrbuff, ADDRSTRLEN);
Simon Kelley2329bef2013-12-03 13:41:16 +00001106 iface->warned = advice = 1;
1107 my_syslog(LOG_WARNING,
1108 _("LOUD WARNING: listening on %s may accept requests via interfaces other than %s"),
1109 daemon->addrbuff, iface->name);
Simon Kelleydc27e142013-10-16 13:09:53 +01001110 }
1111 }
Simon Kelleydc27e142013-10-16 13:09:53 +01001112 }
1113
1114 if (advice)
Simon Kelleyf7029f52013-11-21 15:09:09 +00001115 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 +01001116}
1117
Petr Menšíkad59f272017-03-17 17:22:19 +00001118void warn_wild_labels(void)
1119{
1120 struct irec *iface;
1121
1122 for (iface = daemon->interfaces; iface; iface = iface->next)
1123 if (iface->found && iface->name && iface->label)
1124 my_syslog(LOG_WARNING, _("warning: using interface %s instead"), iface->name);
1125}
1126
Simon Kelleyf7029f52013-11-21 15:09:09 +00001127void warn_int_names(void)
1128{
1129 struct interface_name *intname;
1130
1131 for (intname = daemon->int_names; intname; intname = intname->next)
1132 if (!intname->addr)
1133 my_syslog(LOG_WARNING, _("warning: no addresses found for interface %s"), intname->intr);
1134}
1135
Simon Kelley74c95c22011-10-19 09:33:39 +01001136int is_dad_listeners(void)
1137{
1138 struct irec *iface;
1139
1140 if (option_bool(OPT_NOWILD))
1141 for (iface = daemon->interfaces; iface; iface = iface->next)
1142 if (iface->dad && !iface->done)
1143 return 1;
1144
1145 return 0;
1146}
Simon Kelley5d162f22012-12-20 14:55:46 +00001147
1148#ifdef HAVE_DHCP6
1149void join_multicast(int dienow)
1150{
1151 struct irec *iface, *tmp;
1152
1153 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelley19624462012-12-28 11:18:09 +00001154 if (iface->addr.sa.sa_family == AF_INET6 && iface->dhcp_ok && !iface->multicast_done)
Simon Kelley5d162f22012-12-20 14:55:46 +00001155 {
1156 /* There's an irec per address but we only want to join for multicast
1157 once per interface. Weed out duplicates. */
1158 for (tmp = daemon->interfaces; tmp; tmp = tmp->next)
1159 if (tmp->multicast_done && tmp->index == iface->index)
1160 break;
1161
1162 iface->multicast_done = 1;
1163
1164 if (!tmp)
1165 {
1166 struct ipv6_mreq mreq;
1167 int err = 0;
1168
1169 mreq.ipv6mr_interface = iface->index;
1170
1171 inet_pton(AF_INET6, ALL_RELAY_AGENTS_AND_SERVERS, &mreq.ipv6mr_multiaddr);
1172
Simon Kelleyff7eea22013-09-04 18:01:38 +01001173 if ((daemon->doing_dhcp6 || daemon->relay6) &&
Simon Kelley5d162f22012-12-20 14:55:46 +00001174 setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
Simon Kelley9cdcfe92015-08-26 22:38:08 +01001175 err = errno;
Simon Kelley5d162f22012-12-20 14:55:46 +00001176
1177 inet_pton(AF_INET6, ALL_SERVERS, &mreq.ipv6mr_multiaddr);
1178
1179 if (daemon->doing_dhcp6 &&
1180 setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
Simon Kelley9cdcfe92015-08-26 22:38:08 +01001181 err = errno;
Simon Kelley5d162f22012-12-20 14:55:46 +00001182
1183 inet_pton(AF_INET6, ALL_ROUTERS, &mreq.ipv6mr_multiaddr);
1184
1185 if (daemon->doing_ra &&
1186 setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
Simon Kelley9cdcfe92015-08-26 22:38:08 +01001187 err = errno;
Simon Kelley5d162f22012-12-20 14:55:46 +00001188
1189 if (err)
1190 {
1191 char *s = _("interface %s failed to join DHCPv6 multicast group: %s");
Simon Kelley9cdcfe92015-08-26 22:38:08 +01001192 errno = err;
1193
1194#ifdef HAVE_LINUX_NETWORK
1195 if (errno == ENOMEM)
1196 my_syslog(LOG_ERR, _("try increasing /proc/sys/net/core/optmem_max"));
1197#endif
1198
Simon Kelley5d162f22012-12-20 14:55:46 +00001199 if (dienow)
1200 die(s, iface->name, EC_BADNET);
1201 else
1202 my_syslog(LOG_ERR, s, iface->name, strerror(errno));
1203 }
1204 }
1205 }
1206}
1207#endif
1208
Simon Kelley9009d742008-11-14 20:04:27 +00001209/* return a UDP socket bound to a random port, have to cope with straying into
Simon Kelley1a6bca82008-07-11 11:11:42 +01001210 occupied port nos and reserved ones. */
1211int random_sock(int family)
1212{
1213 int fd;
1214
1215 if ((fd = socket(family, SOCK_DGRAM, 0)) != -1)
1216 {
Simon Kelley3927da42008-07-20 15:10:39 +01001217 union mysockaddr addr;
Hans Dedecker926332a2016-01-23 10:48:12 +00001218 unsigned int ports_avail = ((unsigned short)daemon->max_port - (unsigned short)daemon->min_port) + 1;
Simon Kelley9009d742008-11-14 20:04:27 +00001219 int tries = ports_avail < 30 ? 3 * ports_avail : 100;
Simon Kelley3927da42008-07-20 15:10:39 +01001220
Simon Kelley1a6bca82008-07-11 11:11:42 +01001221 memset(&addr, 0, sizeof(addr));
Simon Kelley3927da42008-07-20 15:10:39 +01001222 addr.sa.sa_family = family;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001223
Simon Kelley1ad24ae2008-07-20 20:22:50 +01001224 /* don't loop forever if all ports in use. */
1225
Simon Kelley1a6bca82008-07-11 11:11:42 +01001226 if (fix_fd(fd))
Simon Kelley9009d742008-11-14 20:04:27 +00001227 while(tries--)
Simon Kelley1a6bca82008-07-11 11:11:42 +01001228 {
Simon Kelleybaf553d2018-01-29 22:49:27 +00001229 unsigned short port = htons(daemon->min_port + (rand16() % ((unsigned short)ports_avail)));
Simon Kelley1a6bca82008-07-11 11:11:42 +01001230
1231 if (family == AF_INET)
1232 {
1233 addr.in.sin_addr.s_addr = INADDR_ANY;
Simon Kelley3927da42008-07-20 15:10:39 +01001234 addr.in.sin_port = port;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001235#ifdef HAVE_SOCKADDR_SA_LEN
1236 addr.in.sin_len = sizeof(struct sockaddr_in);
1237#endif
1238 }
Simon Kelley1a6bca82008-07-11 11:11:42 +01001239 else
1240 {
1241 addr.in6.sin6_addr = in6addr_any;
Simon Kelley3927da42008-07-20 15:10:39 +01001242 addr.in6.sin6_port = port;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001243#ifdef HAVE_SOCKADDR_SA_LEN
1244 addr.in6.sin6_len = sizeof(struct sockaddr_in6);
1245#endif
1246 }
Simon Kelley1a6bca82008-07-11 11:11:42 +01001247
1248 if (bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == 0)
1249 return fd;
1250
1251 if (errno != EADDRINUSE && errno != EACCES)
1252 break;
1253 }
1254
1255 close(fd);
1256 }
1257
1258 return -1;
1259}
1260
1261
Simon Kelley9d6918d2017-10-13 17:55:09 +01001262int local_bind(int fd, union mysockaddr *addr, char *intname, unsigned int ifindex, int is_tcp)
Simon Kelley824af852008-02-12 20:43:05 +00001263{
1264 union mysockaddr addr_copy = *addr;
Simon Kelleya2a7e042020-12-12 23:26:45 +00001265 unsigned short port;
1266 int tries = 1, done = 0;
1267 unsigned int ports_avail = ((unsigned short)daemon->max_port - (unsigned short)daemon->min_port) + 1;
1268
1269 if (addr_copy.sa.sa_family == AF_INET)
1270 port = addr_copy.in.sin_port;
1271 else
1272 port = addr_copy.in6.sin6_port;
Simon Kelley824af852008-02-12 20:43:05 +00001273
1274 /* cannot set source _port_ for TCP connections. */
1275 if (is_tcp)
Simon Kelleya2a7e042020-12-12 23:26:45 +00001276 port = 0;
1277
1278 /* Bind a random port within the range given by min-port and max-port */
1279 if (port == 0)
Simon Kelley824af852008-02-12 20:43:05 +00001280 {
Simon Kelleya2a7e042020-12-12 23:26:45 +00001281 tries = ports_avail < 30 ? 3 * ports_avail : 100;
1282 port = htons(daemon->min_port + (rand16() % ((unsigned short)ports_avail)));
Simon Kelley824af852008-02-12 20:43:05 +00001283 }
1284
Simon Kelleya2a7e042020-12-12 23:26:45 +00001285 while (tries--)
1286 {
1287 if (addr_copy.sa.sa_family == AF_INET)
1288 addr_copy.in.sin_port = port;
1289 else
1290 addr_copy.in6.sin6_port = port;
1291
1292 if (bind(fd, (struct sockaddr *)&addr_copy, sa_len(&addr_copy)) != -1)
1293 {
1294 done = 1;
1295 break;
1296 }
1297
1298 if (errno != EADDRINUSE && errno != EACCES)
1299 return 0;
1300
1301 port = htons(daemon->min_port + (rand16() % ((unsigned short)ports_avail)));
1302 }
1303
1304 if (!done)
Simon Kelley824af852008-02-12 20:43:05 +00001305 return 0;
Simon Kelley9d6918d2017-10-13 17:55:09 +01001306
1307 if (!is_tcp && ifindex > 0)
1308 {
1309#if defined(IP_UNICAST_IF)
1310 if (addr_copy.sa.sa_family == AF_INET)
1311 {
1312 uint32_t ifindex_opt = htonl(ifindex);
1313 return setsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex_opt, sizeof(ifindex_opt)) == 0;
1314 }
1315#endif
Simon Kelleyee875042018-10-23 22:10:17 +01001316#if defined (IPV6_UNICAST_IF)
Simon Kelley9d6918d2017-10-13 17:55:09 +01001317 if (addr_copy.sa.sa_family == AF_INET6)
1318 {
1319 uint32_t ifindex_opt = htonl(ifindex);
1320 return setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_IF, &ifindex_opt, sizeof(ifindex_opt)) == 0;
1321 }
1322#endif
1323 }
1324
Kevin Darbyshire-Bryant70c50ef2020-03-06 10:31:15 +00001325 (void)intname; /* suppress potential unused warning */
Simon Kelley824af852008-02-12 20:43:05 +00001326#if defined(SO_BINDTODEVICE)
Simon Kelley73a08a22009-02-05 20:28:08 +00001327 if (intname[0] != 0 &&
Simon Kelley316e2732010-01-22 20:16:09 +00001328 setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, intname, IF_NAMESIZE) == -1)
Simon Kelley824af852008-02-12 20:43:05 +00001329 return 0;
1330#endif
1331
1332 return 1;
1333}
1334
1335static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001336{
1337 struct serverfd *sfd;
Beniamino Galvani2675f202016-08-28 20:44:05 +01001338 unsigned int ifindex = 0;
Simon Kelley824af852008-02-12 20:43:05 +00001339 int errsave;
Simon Kelleye83915d2018-04-10 21:27:26 +01001340 int opt = 1;
1341
Simon Kelley1a6bca82008-07-11 11:11:42 +01001342 /* when using random ports, servers which would otherwise use
1343 the INADDR_ANY/port0 socket have sfd set to NULL */
Simon Kelley73a08a22009-02-05 20:28:08 +00001344 if (!daemon->osport && intname[0] == 0)
Simon Kelley1a6bca82008-07-11 11:11:42 +01001345 {
1346 errno = 0;
1347
1348 if (addr->sa.sa_family == AF_INET &&
1349 addr->in.sin_addr.s_addr == INADDR_ANY &&
1350 addr->in.sin_port == htons(0))
1351 return NULL;
1352
Simon Kelley1a6bca82008-07-11 11:11:42 +01001353 if (addr->sa.sa_family == AF_INET6 &&
1354 memcmp(&addr->in6.sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0 &&
1355 addr->in6.sin6_port == htons(0))
1356 return NULL;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001357 }
Beniamino Galvani2675f202016-08-28 20:44:05 +01001358
1359 if (intname && strlen(intname) != 0)
1360 ifindex = if_nametoindex(intname); /* index == 0 when not binding to an interface */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001361
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001362 /* may have a suitable one already */
Simon Kelley824af852008-02-12 20:43:05 +00001363 for (sfd = daemon->sfds; sfd; sfd = sfd->next )
1364 if (sockaddr_isequal(&sfd->source_addr, addr) &&
Beniamino Galvani2675f202016-08-28 20:44:05 +01001365 strcmp(intname, sfd->interface) == 0 &&
1366 ifindex == sfd->ifindex)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001367 return sfd;
1368
1369 /* need to make a new one. */
1370 errno = ENOMEM; /* in case malloc fails. */
Simon Kelley5aabfc72007-08-29 11:24:47 +01001371 if (!(sfd = whine_malloc(sizeof(struct serverfd))))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001372 return NULL;
1373
1374 if ((sfd->fd = socket(addr->sa.sa_family, SOCK_DGRAM, 0)) == -1)
1375 {
1376 free(sfd);
1377 return NULL;
1378 }
Simon Kelleye83915d2018-04-10 21:27:26 +01001379
1380 if ((addr->sa.sa_family == AF_INET6 && setsockopt(sfd->fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)) == -1) ||
1381 !local_bind(sfd->fd, addr, intname, ifindex, 0) || !fix_fd(sfd->fd))
Simon Kelley824af852008-02-12 20:43:05 +00001382 {
Simon Kelleye83915d2018-04-10 21:27:26 +01001383 errsave = errno; /* save error from bind/setsockopt. */
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001384 close(sfd->fd);
1385 free(sfd);
1386 errno = errsave;
1387 return NULL;
1388 }
Beniamino Galvani2675f202016-08-28 20:44:05 +01001389
Petr Menšík47b45b22018-08-15 18:17:00 +02001390 safe_strncpy(sfd->interface, intname, sizeof(sfd->interface));
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001391 sfd->source_addr = *addr;
Simon Kelley824af852008-02-12 20:43:05 +00001392 sfd->next = daemon->sfds;
Beniamino Galvani2675f202016-08-28 20:44:05 +01001393 sfd->ifindex = ifindex;
Simon Kelley4441cf72018-04-10 21:39:54 +01001394 sfd->preallocated = 0;
Simon Kelley824af852008-02-12 20:43:05 +00001395 daemon->sfds = sfd;
Beniamino Galvani2675f202016-08-28 20:44:05 +01001396
Simon Kelley824af852008-02-12 20:43:05 +00001397 return sfd;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001398}
1399
Simon Kelley824af852008-02-12 20:43:05 +00001400/* create upstream sockets during startup, before root is dropped which may be needed
1401 this allows query_port to be a low port and interface binding */
1402void pre_allocate_sfds(void)
1403{
1404 struct server *srv;
Simon Kelley4441cf72018-04-10 21:39:54 +01001405 struct serverfd *sfd;
Simon Kelley824af852008-02-12 20:43:05 +00001406
1407 if (daemon->query_port != 0)
1408 {
1409 union mysockaddr addr;
1410 memset(&addr, 0, sizeof(addr));
1411 addr.in.sin_family = AF_INET;
1412 addr.in.sin_addr.s_addr = INADDR_ANY;
1413 addr.in.sin_port = htons(daemon->query_port);
1414#ifdef HAVE_SOCKADDR_SA_LEN
1415 addr.in.sin_len = sizeof(struct sockaddr_in);
1416#endif
Simon Kelley4441cf72018-04-10 21:39:54 +01001417 if ((sfd = allocate_sfd(&addr, "")))
1418 sfd->preallocated = 1;
Simon Kelleyee875042018-10-23 22:10:17 +01001419
Simon Kelley824af852008-02-12 20:43:05 +00001420 memset(&addr, 0, sizeof(addr));
1421 addr.in6.sin6_family = AF_INET6;
1422 addr.in6.sin6_addr = in6addr_any;
1423 addr.in6.sin6_port = htons(daemon->query_port);
1424#ifdef HAVE_SOCKADDR_SA_LEN
1425 addr.in6.sin6_len = sizeof(struct sockaddr_in6);
1426#endif
Simon Kelley4441cf72018-04-10 21:39:54 +01001427 if ((sfd = allocate_sfd(&addr, "")))
1428 sfd->preallocated = 1;
Simon Kelley824af852008-02-12 20:43:05 +00001429 }
1430
1431 for (srv = daemon->servers; srv; srv = srv->next)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001432 if (!(srv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)) &&
Simon Kelley824af852008-02-12 20:43:05 +00001433 !allocate_sfd(&srv->source_addr, srv->interface) &&
Simon Kelley1a6bca82008-07-11 11:11:42 +01001434 errno != 0 &&
Simon Kelley28866e92011-02-14 20:19:14 +00001435 option_bool(OPT_NOWILD))
Simon Kelley824af852008-02-12 20:43:05 +00001436 {
Petr Mensik51cdd1a2019-07-04 20:28:08 +02001437 (void)prettyprint_addr(&srv->source_addr, daemon->namebuff);
Simon Kelley73a08a22009-02-05 20:28:08 +00001438 if (srv->interface[0] != 0)
Simon Kelley824af852008-02-12 20:43:05 +00001439 {
1440 strcat(daemon->namebuff, " ");
1441 strcat(daemon->namebuff, srv->interface);
1442 }
1443 die(_("failed to bind server socket for %s: %s"),
1444 daemon->namebuff, EC_BADNET);
1445 }
1446}
1447
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001448void mark_servers(int flag)
1449{
1450 struct server *serv;
1451
1452 /* mark everything with argument flag */
1453 for (serv = daemon->servers; serv; serv = serv->next)
Simon Kelley40766e52014-07-29 16:52:00 +01001454 {
1455 if (serv->flags & flag)
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001456 serv->flags |= SERV_MARK;
1457#ifdef HAVE_LOOP
Simon Kelley40766e52014-07-29 16:52:00 +01001458 /* Give looped servers another chance */
1459 serv->flags &= ~SERV_LOOP;
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001460#endif
Simon Kelley40766e52014-07-29 16:52:00 +01001461 }
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001462}
1463
1464void cleanup_servers(void)
1465{
1466 struct server *serv, *tmp, **up;
1467
1468 /* unlink and free anything still marked. */
1469 for (serv = daemon->servers, up = &daemon->servers; serv; serv = tmp)
1470 {
1471 tmp = serv->next;
1472 if (serv->flags & SERV_MARK)
1473 {
1474 server_gone(serv);
1475 *up = serv->next;
1476 if (serv->domain)
1477 free(serv->domain);
1478 free(serv);
1479 }
1480 else
1481 up = &serv->next;
1482 }
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001483
1484#ifdef HAVE_LOOP
1485 /* Now we have a new set of servers, test for loops. */
1486 loop_send_probes();
1487#endif
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001488}
1489
1490void add_update_server(int flags,
1491 union mysockaddr *addr,
1492 union mysockaddr *source_addr,
1493 const char *interface,
1494 const char *domain)
1495{
Simon Kelley7b1eae42014-02-20 13:43:28 +00001496 struct server *serv, *next = NULL;
1497 char *domain_str = NULL;
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001498
1499 /* See if there is a suitable candidate, and unmark */
1500 for (serv = daemon->servers; serv; serv = serv->next)
1501 if (serv->flags & SERV_MARK)
1502 {
1503 if (domain)
1504 {
1505 if (!(serv->flags & SERV_HAS_DOMAIN) || !hostname_isequal(domain, serv->domain))
1506 continue;
1507 }
1508 else
1509 {
1510 if (serv->flags & SERV_HAS_DOMAIN)
1511 continue;
1512 }
1513
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001514 break;
1515 }
Simon Kelley7b1eae42014-02-20 13:43:28 +00001516
1517 if (serv)
1518 {
1519 domain_str = serv->domain;
1520 next = serv->next;
1521 }
1522 else if ((serv = whine_malloc(sizeof (struct server))))
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001523 {
1524 /* Not found, create a new one. */
Simon Kelley7b1eae42014-02-20 13:43:28 +00001525 if (domain && !(domain_str = whine_malloc(strlen(domain)+1)))
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001526 {
1527 free(serv);
1528 serv = NULL;
1529 }
1530 else
1531 {
1532 struct server *s;
1533 /* Add to the end of the chain, for order */
1534 if (!daemon->servers)
1535 daemon->servers = serv;
1536 else
1537 {
1538 for (s = daemon->servers; s->next; s = s->next);
1539 s->next = serv;
1540 }
1541 if (domain)
Simon Kelley7b1eae42014-02-20 13:43:28 +00001542 strcpy(domain_str, domain);
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001543 }
1544 }
1545
1546 if (serv)
1547 {
Simon Kelley7b1eae42014-02-20 13:43:28 +00001548 memset(serv, 0, sizeof(struct server));
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001549 serv->flags = flags;
Simon Kelley7b1eae42014-02-20 13:43:28 +00001550 serv->domain = domain_str;
1551 serv->next = next;
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001552 serv->queries = serv->failed_queries = 0;
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001553#ifdef HAVE_LOOP
1554 serv->uid = rand32();
1555#endif
1556
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001557 if (domain)
1558 serv->flags |= SERV_HAS_DOMAIN;
1559
1560 if (interface)
Petr Menšík47b45b22018-08-15 18:17:00 +02001561 safe_strncpy(serv->interface, interface, sizeof(serv->interface));
Simon Kelley7b1eae42014-02-20 13:43:28 +00001562 if (addr)
1563 serv->addr = *addr;
1564 if (source_addr)
1565 serv->source_addr = *source_addr;
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001566 }
1567}
Simon Kelley824af852008-02-12 20:43:05 +00001568
Simon Kelley5aabfc72007-08-29 11:24:47 +01001569void check_servers(void)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001570{
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001571 struct irec *iface;
Simon Kelley7bcca002014-02-19 17:45:17 +00001572 struct server *serv;
Beniamino Galvani2675f202016-08-28 20:44:05 +01001573 struct serverfd *sfd, *tmp, **up;
Simon Kelleyb9702602016-05-03 22:34:06 +01001574 int port = 0, count;
Hannu Nyman3e2496f2017-02-11 13:44:08 +00001575 int locals = 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001576
Simon Kelley316e2732010-01-22 20:16:09 +00001577 /* interface may be new since startup */
Simon Kelley28866e92011-02-14 20:19:14 +00001578 if (!option_bool(OPT_NOWILD))
Simon Kelley115ac3e2013-05-20 11:28:32 +01001579 enumerate_interfaces(0);
Simon Kelley4441cf72018-04-10 21:39:54 +01001580
1581 /* don't garbage collect pre-allocated sfds. */
Beniamino Galvani2675f202016-08-28 20:44:05 +01001582 for (sfd = daemon->sfds; sfd; sfd = sfd->next)
Simon Kelley4441cf72018-04-10 21:39:54 +01001583 sfd->used = sfd->preallocated;
Beniamino Galvani2675f202016-08-28 20:44:05 +01001584
Simon Kelleyb9702602016-05-03 22:34:06 +01001585 for (count = 0, serv = daemon->servers; serv; serv = serv->next)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001586 {
Simon Kelley367341f2016-01-12 15:58:23 +00001587 if (!(serv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001588 {
Simon Kelley14ffa072016-04-25 16:36:44 +01001589 /* Init edns_pktsz for newly created server records. */
1590 if (serv->edns_pktsz == 0)
1591 serv->edns_pktsz = daemon->edns_pktsz;
1592
Simon Kelley367341f2016-01-12 15:58:23 +00001593#ifdef HAVE_DNSSEC
Simon Kelley92be34a2016-01-16 18:39:54 +00001594 if (option_bool(OPT_DNSSEC_VALID))
1595 {
Simon Kelleya49c5c22017-10-10 22:04:59 +01001596 if (!(serv->flags & SERV_FOR_NODOTS))
1597 serv->flags |= SERV_DO_DNSSEC;
1598
1599 /* Disable DNSSEC validation when using server=/domain/.... servers
1600 unless there's a configured trust anchor. */
Simon Kelley92be34a2016-01-16 18:39:54 +00001601 if (serv->flags & SERV_HAS_DOMAIN)
1602 {
1603 struct ds_config *ds;
1604 char *domain = serv->domain;
1605
1606 /* .example.com is valid */
1607 while (*domain == '.')
1608 domain++;
1609
1610 for (ds = daemon->ds; ds; ds = ds->next)
1611 if (ds->name[0] != 0 && hostname_isequal(domain, ds->name))
1612 break;
1613
1614 if (!ds)
1615 serv->flags &= ~SERV_DO_DNSSEC;
1616 }
Simon Kelley367341f2016-01-12 15:58:23 +00001617 }
1618#endif
1619
1620 port = prettyprint_addr(&serv->addr, daemon->namebuff);
1621
Simon Kelley16972692006-10-16 20:04:18 +01001622 /* 0.0.0.0 is nothing, the stack treats it like 127.0.0.1 */
Simon Kelley7bcca002014-02-19 17:45:17 +00001623 if (serv->addr.sa.sa_family == AF_INET &&
1624 serv->addr.in.sin_addr.s_addr == 0)
Simon Kelley16972692006-10-16 20:04:18 +01001625 {
Simon Kelley7bcca002014-02-19 17:45:17 +00001626 serv->flags |= SERV_MARK;
Simon Kelley16972692006-10-16 20:04:18 +01001627 continue;
1628 }
1629
Simon Kelley3d8df262005-08-29 12:19:27 +01001630 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelley7bcca002014-02-19 17:45:17 +00001631 if (sockaddr_isequal(&serv->addr, &iface->addr))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001632 break;
1633 if (iface)
1634 {
Simon Kelleyf2621c72007-04-29 19:47:21 +01001635 my_syslog(LOG_WARNING, _("ignoring nameserver %s - local interface"), daemon->namebuff);
Simon Kelley7bcca002014-02-19 17:45:17 +00001636 serv->flags |= SERV_MARK;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001637 continue;
1638 }
1639
1640 /* Do we need a socket set? */
Simon Kelley7bcca002014-02-19 17:45:17 +00001641 if (!serv->sfd &&
1642 !(serv->sfd = allocate_sfd(&serv->source_addr, serv->interface)) &&
Simon Kelley1a6bca82008-07-11 11:11:42 +01001643 errno != 0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001644 {
Simon Kelleyf2621c72007-04-29 19:47:21 +01001645 my_syslog(LOG_WARNING,
1646 _("ignoring nameserver %s - cannot make/bind socket: %s"),
1647 daemon->namebuff, strerror(errno));
Simon Kelley7bcca002014-02-19 17:45:17 +00001648 serv->flags |= SERV_MARK;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001649 continue;
1650 }
Simon Kelley16800ea2016-08-30 23:07:06 +01001651
1652 if (serv->sfd)
1653 serv->sfd->used = 1;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001654 }
1655
Simon Kelley979fe862015-03-19 22:50:22 +00001656 if (!(serv->flags & SERV_NO_REBIND) && !(serv->flags & SERV_LITERAL_ADDRESS))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001657 {
Simon Kelleyb9702602016-05-03 22:34:06 +01001658 if (++count > SERVERS_LOGGED)
1659 continue;
1660
Simon Kelley7bcca002014-02-19 17:45:17 +00001661 if (serv->flags & (SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_USE_RESOLV))
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001662 {
Simon Kelley367341f2016-01-12 15:58:23 +00001663 char *s1, *s2, *s3 = "";
1664#ifdef HAVE_DNSSEC
1665 if (option_bool(OPT_DNSSEC_VALID) && !(serv->flags & SERV_DO_DNSSEC))
1666 s3 = _("(no DNSSEC)");
1667#endif
Simon Kelley7bcca002014-02-19 17:45:17 +00001668 if (!(serv->flags & SERV_HAS_DOMAIN))
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001669 s1 = _("unqualified"), s2 = _("names");
Simon Kelleyd9603ef2020-01-26 18:13:35 +00001670 else if (strlen(serv->domain) == 0)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001671 s1 = _("default"), s2 = "";
1672 else
Simon Kelley7bcca002014-02-19 17:45:17 +00001673 s1 = _("domain"), s2 = serv->domain;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001674
Simon Kelley7bcca002014-02-19 17:45:17 +00001675 if (serv->flags & SERV_NO_ADDR)
Hannu Nyman3e2496f2017-02-11 13:44:08 +00001676 {
1677 count--;
1678 if (++locals <= LOCALS_LOGGED)
Simon Kelley8bd28a82019-03-01 15:00:12 +00001679 my_syslog(LOG_INFO, _("using only locally-known addresses for %s %s"), s1, s2);
Hannu Nyman3e2496f2017-02-11 13:44:08 +00001680 }
Simon Kelley7bcca002014-02-19 17:45:17 +00001681 else if (serv->flags & SERV_USE_RESOLV)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001682 my_syslog(LOG_INFO, _("using standard nameservers for %s %s"), s1, s2);
Simon Kelley979fe862015-03-19 22:50:22 +00001683 else
Simon Kelley367341f2016-01-12 15:58:23 +00001684 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 +01001685 }
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001686#ifdef HAVE_LOOP
1687 else if (serv->flags & SERV_LOOP)
1688 my_syslog(LOG_INFO, _("NOT using nameserver %s#%d - query loop detected"), daemon->namebuff, port);
1689#endif
Simon Kelley7bcca002014-02-19 17:45:17 +00001690 else if (serv->interface[0] != 0)
1691 my_syslog(LOG_INFO, _("using nameserver %s#%d(via %s)"), daemon->namebuff, port, serv->interface);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001692 else
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001693 my_syslog(LOG_INFO, _("using nameserver %s#%d"), daemon->namebuff, port);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001694 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001695 }
Simon Kelleyb9702602016-05-03 22:34:06 +01001696
Hannu Nyman3e2496f2017-02-11 13:44:08 +00001697 if (locals > LOCALS_LOGGED)
1698 my_syslog(LOG_INFO, _("using %d more local addresses"), locals - LOCALS_LOGGED);
Simon Kelleyb9702602016-05-03 22:34:06 +01001699 if (count - 1 > SERVERS_LOGGED)
1700 my_syslog(LOG_INFO, _("using %d more nameservers"), count - SERVERS_LOGGED - 1);
Simon Kelley7bcca002014-02-19 17:45:17 +00001701
Beniamino Galvani2675f202016-08-28 20:44:05 +01001702 /* Remove unused sfds */
1703 for (sfd = daemon->sfds, up = &daemon->sfds; sfd; sfd = tmp)
1704 {
1705 tmp = sfd->next;
1706 if (!sfd->used)
1707 {
1708 *up = sfd->next;
1709 close(sfd->fd);
1710 free(sfd);
1711 }
1712 else
1713 up = &sfd->next;
1714 }
1715
Simon Kelley7bcca002014-02-19 17:45:17 +00001716 cleanup_servers();
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001717}
Simon Kelley849a8352006-06-09 21:02:31 +01001718
1719/* Return zero if no servers found, in that case we keep polling.
1720 This is a protection against an update-time/write race on resolv.conf */
Simon Kelley5aabfc72007-08-29 11:24:47 +01001721int reload_servers(char *fname)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001722{
1723 FILE *f;
1724 char *line;
Simon Kelley849a8352006-06-09 21:02:31 +01001725 int gotone = 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001726
Simon Kelley849a8352006-06-09 21:02:31 +01001727 /* buff happens to be MAXDNAME long... */
1728 if (!(f = fopen(fname, "r")))
1729 {
Simon Kelleyf2621c72007-04-29 19:47:21 +01001730 my_syslog(LOG_ERR, _("failed to read %s: %s"), fname, strerror(errno));
Simon Kelley849a8352006-06-09 21:02:31 +01001731 return 0;
1732 }
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001733
1734 mark_servers(SERV_FROM_RESOLV);
1735
Simon Kelley849a8352006-06-09 21:02:31 +01001736 while ((line = fgets(daemon->namebuff, MAXDNAME, f)))
1737 {
1738 union mysockaddr addr, source_addr;
1739 char *token = strtok(line, " \t\n\r");
1740
Simon Kelley5aabfc72007-08-29 11:24:47 +01001741 if (!token)
1742 continue;
1743 if (strcmp(token, "nameserver") != 0 && strcmp(token, "server") != 0)
Simon Kelley849a8352006-06-09 21:02:31 +01001744 continue;
1745 if (!(token = strtok(NULL, " \t\n\r")))
1746 continue;
1747
1748 memset(&addr, 0, sizeof(addr));
1749 memset(&source_addr, 0, sizeof(source_addr));
1750
1751 if ((addr.in.sin_addr.s_addr = inet_addr(token)) != (in_addr_t) -1)
1752 {
1753#ifdef HAVE_SOCKADDR_SA_LEN
1754 source_addr.in.sin_len = addr.in.sin_len = sizeof(source_addr.in);
1755#endif
1756 source_addr.in.sin_family = addr.in.sin_family = AF_INET;
1757 addr.in.sin_port = htons(NAMESERVER_PORT);
1758 source_addr.in.sin_addr.s_addr = INADDR_ANY;
1759 source_addr.in.sin_port = htons(daemon->query_port);
1760 }
Simon Kelley7de060b2011-08-26 17:24:52 +01001761 else
1762 {
1763 int scope_index = 0;
1764 char *scope_id = strchr(token, '%');
1765
1766 if (scope_id)
1767 {
1768 *(scope_id++) = 0;
1769 scope_index = if_nametoindex(scope_id);
1770 }
1771
1772 if (inet_pton(AF_INET6, token, &addr.in6.sin6_addr) > 0)
1773 {
Simon Kelley849a8352006-06-09 21:02:31 +01001774#ifdef HAVE_SOCKADDR_SA_LEN
Simon Kelley7de060b2011-08-26 17:24:52 +01001775 source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(source_addr.in6);
Simon Kelley849a8352006-06-09 21:02:31 +01001776#endif
Simon Kelley7de060b2011-08-26 17:24:52 +01001777 source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6;
1778 source_addr.in6.sin6_flowinfo = addr.in6.sin6_flowinfo = 0;
1779 addr.in6.sin6_port = htons(NAMESERVER_PORT);
1780 addr.in6.sin6_scope_id = scope_index;
1781 source_addr.in6.sin6_addr = in6addr_any;
1782 source_addr.in6.sin6_port = htons(daemon->query_port);
1783 source_addr.in6.sin6_scope_id = 0;
1784 }
1785 else
1786 continue;
Simon Kelley849a8352006-06-09 21:02:31 +01001787 }
Simon Kelley7de060b2011-08-26 17:24:52 +01001788
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001789 add_update_server(SERV_FROM_RESOLV, &addr, &source_addr, NULL, NULL);
Simon Kelley849a8352006-06-09 21:02:31 +01001790 gotone = 1;
1791 }
1792
Simon Kelley849a8352006-06-09 21:02:31 +01001793 fclose(f);
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001794 cleanup_servers();
Simon Kelley849a8352006-06-09 21:02:31 +01001795
1796 return gotone;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001797}
1798
Simon Kelley1ee9be42013-12-09 16:50:19 +00001799/* Called when addresses are added or deleted from an interface */
1800void newaddress(time_t now)
1801{
1802 (void)now;
1803
Simon Kelley89b12ed2014-03-06 13:27:57 +00001804 if (option_bool(OPT_CLEVERBIND) || option_bool(OPT_LOCAL_SERVICE) ||
1805 daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
Simon Kelley1ee9be42013-12-09 16:50:19 +00001806 enumerate_interfaces(0);
1807
1808 if (option_bool(OPT_CLEVERBIND))
1809 create_bound_listeners(0);
1810
1811#ifdef HAVE_DHCP6
1812 if (daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
1813 join_multicast(0);
1814
1815 if (daemon->doing_dhcp6 || daemon->doing_ra)
1816 dhcp_construct_contexts(now);
1817
1818 if (daemon->doing_dhcp6)
1819 lease_find_interfaces(now);
1820#endif
1821}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001822
1823
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001824
1825
1826