blob: 77eb6ade3fe79d7908fd7279378e0b0c0d271e74 [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;
Petr Menšík4c0aecc2021-03-02 18:21:32 +0000641
642again:
Simon Kelley08619212013-12-02 14:43:48 +0000643 /* Mark interfaces for garbage collection */
644 for (iface = daemon->interfaces; iface; iface = iface->next)
645 iface->found = 0;
646
Simon Kelley115ac3e2013-05-20 11:28:32 +0100647 /* remove addresses stored against interface_names */
648 for (intname = daemon->int_names; intname; intname = intname->next)
649 {
Simon Kelley376d48c2013-11-13 13:04:30 +0000650 for (addr = intname->addr; addr; addr = tmp)
Simon Kelley115ac3e2013-05-20 11:28:32 +0100651 {
652 tmp = addr->next;
653 addr->next = spare;
654 spare = addr;
655 }
656
Simon Kelley376d48c2013-11-13 13:04:30 +0000657 intname->addr = NULL;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100658 }
Simon Kelley376d48c2013-11-13 13:04:30 +0000659
Simon Kelleyc8a80482014-03-05 14:29:54 +0000660 /* Remove list of addresses of local interfaces */
661 for (addr = daemon->interface_addrs; addr; addr = tmp)
662 {
663 tmp = addr->next;
664 addr->next = spare;
665 spare = addr;
666 }
667 daemon->interface_addrs = NULL;
668
Simon Kelley376d48c2013-11-13 13:04:30 +0000669#ifdef HAVE_AUTH
670 /* remove addresses stored against auth_zone subnets, but not
671 ones configured as address literals */
672 for (zone = daemon->auth_zones; zone; zone = zone->next)
673 if (zone->interface_names)
674 {
675 struct addrlist **up;
676 for (up = &zone->subnet, addr = zone->subnet; addr; addr = tmp)
677 {
678 tmp = addr->next;
679 if (addr->flags & ADDRLIST_LITERAL)
680 up = &addr->next;
681 else
682 {
683 *up = addr->next;
684 addr->next = spare;
685 spare = addr;
686 }
687 }
688 }
689#endif
690
Simon Kelley115ac3e2013-05-20 11:28:32 +0100691 param.spare = spare;
692
Simon Kelley115ac3e2013-05-20 11:28:32 +0100693 ret = iface_enumerate(AF_INET6, &param, iface_allowed_v6);
Petr Menšík4c0aecc2021-03-02 18:21:32 +0000694 if (ret < 0)
695 goto again;
696 else if (ret)
697 {
698 ret = iface_enumerate(AF_INET, &param, iface_allowed_v4);
699 if (ret < 0)
700 goto again;
701 }
Simon Kelley115ac3e2013-05-20 11:28:32 +0100702
703 errsave = errno;
704 close(param.fd);
Simon Kelley08619212013-12-02 14:43:48 +0000705
706 if (option_bool(OPT_CLEVERBIND))
707 {
708 /* Garbage-collect listeners listening on addresses that no longer exist.
709 Does nothing when not binding interfaces or for listeners on localhost,
710 since the ->iface field is NULL. Note that this needs the protections
Josh Soref730c6742017-02-06 16:14:04 +0000711 against reentrancy, hence it's here. It also means there's a possibility,
Simon Kelley08619212013-12-02 14:43:48 +0000712 in OPT_CLEVERBIND mode, that at listener will just disappear after
713 a call to enumerate_interfaces, this is checked OK on all calls. */
714 struct listener *l, *tmp, **up;
Petr Mensik60a3ae12019-07-09 14:05:59 +0200715 int freed = 0;
Simon Kelley08619212013-12-02 14:43:48 +0000716
717 for (up = &daemon->listeners, l = daemon->listeners; l; l = tmp)
718 {
719 tmp = l->next;
720
721 if (!l->iface || l->iface->found)
722 up = &l->next;
Petr Menšík49bdf1e2019-07-15 17:13:12 +0200723 else if (release_listener(l))
Simon Kelley08619212013-12-02 14:43:48 +0000724 {
Petr Menšík49bdf1e2019-07-15 17:13:12 +0200725 *up = tmp;
Simon Kelley619000a2020-04-29 00:09:58 +0100726 freed = 1;
Simon Kelley08619212013-12-02 14:43:48 +0000727 }
728 }
Petr Mensik60a3ae12019-07-09 14:05:59 +0200729
730 if (freed)
731 clean_interfaces();
Simon Kelley08619212013-12-02 14:43:48 +0000732 }
Petr Mensik60a3ae12019-07-09 14:05:59 +0200733
Simon Kelley115ac3e2013-05-20 11:28:32 +0100734 errno = errsave;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100735 spare = param.spare;
Simon Kelleya0358e52014-06-07 13:38:48 +0100736
Simon Kelley115ac3e2013-05-20 11:28:32 +0100737 return ret;
Simon Kelley44a2a312004-03-10 20:04:35 +0000738}
739
Simon Kelley5aabfc72007-08-29 11:24:47 +0100740/* set NONBLOCK bit on fd: See Stevens 16.6 */
Simon Kelley7cebd202006-05-06 14:13:33 +0100741int fix_fd(int fd)
742{
743 int flags;
744
745 if ((flags = fcntl(fd, F_GETFL)) == -1 ||
Simon Kelley5aabfc72007-08-29 11:24:47 +0100746 fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
Simon Kelley7cebd202006-05-06 14:13:33 +0100747 return 0;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100748
Simon Kelley7cebd202006-05-06 14:13:33 +0100749 return 1;
750}
751
Simon Kelley74c95c22011-10-19 09:33:39 +0100752static int make_sock(union mysockaddr *addr, int type, int dienow)
Simon Kelley44a2a312004-03-10 20:04:35 +0000753{
Simon Kelley28866e92011-02-14 20:19:14 +0000754 int family = addr->sa.sa_family;
755 int fd, rc, opt = 1;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100756
Simon Kelley28866e92011-02-14 20:19:14 +0000757 if ((fd = socket(family, type, 0)) == -1)
Simon Kelley316e2732010-01-22 20:16:09 +0000758 {
Josh Soref730c6742017-02-06 16:14:04 +0000759 int port, errsave;
Simon Kelley39f1b8e2012-06-20 20:04:27 +0100760 char *s;
Simon Kelley28866e92011-02-14 20:19:14 +0000761
762 /* No error if the kernel just doesn't support this IP flavour */
763 if (errno == EPROTONOSUPPORT ||
764 errno == EAFNOSUPPORT ||
765 errno == EINVAL)
766 return -1;
767
768 err:
Josh Soref730c6742017-02-06 16:14:04 +0000769 errsave = errno;
Simon Kelley39f1b8e2012-06-20 20:04:27 +0100770 port = prettyprint_addr(addr, daemon->addrbuff);
771 if (!option_bool(OPT_NOWILD) && !option_bool(OPT_CLEVERBIND))
772 sprintf(daemon->addrbuff, "port %d", port);
773 s = _("failed to create listening socket for %s: %s");
774
Simon Kelley5f11b3e2012-08-16 14:04:05 +0100775 if (fd != -1)
Matthias Andree71aaa5a2013-12-03 11:20:45 +0000776 close (fd);
777
Josh Soref730c6742017-02-06 16:14:04 +0000778 errno = errsave;
Simon Kelley1ee9be42013-12-09 16:50:19 +0000779
Simon Kelley5f11b3e2012-08-16 14:04:05 +0100780 if (dienow)
781 {
782 /* failure to bind addresses given by --listen-address at this point
783 is OK if we're doing bind-dynamic */
784 if (!option_bool(OPT_CLEVERBIND))
785 die(s, daemon->addrbuff, EC_BADNET);
786 }
787 else
788 my_syslog(LOG_WARNING, s, daemon->addrbuff, strerror(errno));
789
Simon Kelley74c95c22011-10-19 09:33:39 +0100790 return -1;
Simon Kelley28866e92011-02-14 20:19:14 +0000791 }
Simon Kelley5f11b3e2012-08-16 14:04:05 +0100792
Simon Kelley28866e92011-02-14 20:19:14 +0000793 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || !fix_fd(fd))
794 goto err;
795
Simon Kelleyc72daea2012-01-05 21:33:27 +0000796 if (family == AF_INET6 && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)) == -1)
Simon Kelley28866e92011-02-14 20:19:14 +0000797 goto err;
Simon Kelley28866e92011-02-14 20:19:14 +0000798
Simon Kelley74c95c22011-10-19 09:33:39 +0100799 if ((rc = bind(fd, (struct sockaddr *)addr, sa_len(addr))) == -1)
Simon Kelley28866e92011-02-14 20:19:14 +0000800 goto err;
801
802 if (type == SOCK_STREAM)
803 {
Simon Kelley608aa9f2019-03-10 22:44:15 +0000804#ifdef TCP_FASTOPEN
805 int qlen = 5;
Matthias Andreee39c4842020-03-05 15:58:31 +0000806 setsockopt(fd, IPPROTO_TCP, TCP_FASTOPEN, &qlen, sizeof(qlen));
Simon Kelley608aa9f2019-03-10 22:44:15 +0000807#endif
808
Simon Kelley09b768e2016-12-22 22:16:58 +0000809 if (listen(fd, TCP_BACKLOG) == -1)
Simon Kelley28866e92011-02-14 20:19:14 +0000810 goto err;
811 }
Simon Kelley2329bef2013-12-03 13:41:16 +0000812 else if (family == AF_INET)
Simon Kelley28866e92011-02-14 20:19:14 +0000813 {
Simon Kelley2329bef2013-12-03 13:41:16 +0000814 if (!option_bool(OPT_NOWILD))
Simon Kelley28866e92011-02-14 20:19:14 +0000815 {
816#if defined(HAVE_LINUX_NETWORK)
Simon Kelleyc72daea2012-01-05 21:33:27 +0000817 if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) == -1)
Simon Kelley28866e92011-02-14 20:19:14 +0000818 goto err;
819#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
820 if (setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt)) == -1 ||
821 setsockopt(fd, IPPROTO_IP, IP_RECVIF, &opt, sizeof(opt)) == -1)
822 goto err;
823#endif
824 }
Simon Kelley28866e92011-02-14 20:19:14 +0000825 }
Simon Kelley2329bef2013-12-03 13:41:16 +0000826 else if (!set_ipv6pktinfo(fd))
827 goto err;
Simon Kelleyc72daea2012-01-05 21:33:27 +0000828
Simon Kelley28866e92011-02-14 20:19:14 +0000829 return fd;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100830}
Simon Kelleyc72daea2012-01-05 21:33:27 +0000831
Simon Kelleyc72daea2012-01-05 21:33:27 +0000832int set_ipv6pktinfo(int fd)
833{
834 int opt = 1;
835
836 /* The API changed around Linux 2.6.14 but the old ABI is still supported:
837 handle all combinations of headers and kernel.
838 OpenWrt note that this fixes the problem addressed by your very broken patch. */
839 daemon->v6pktinfo = IPV6_PKTINFO;
840
841#ifdef IPV6_RECVPKTINFO
842 if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &opt, sizeof(opt)) != -1)
843 return 1;
844# ifdef IPV6_2292PKTINFO
845 else if (errno == ENOPROTOOPT && setsockopt(fd, IPPROTO_IPV6, IPV6_2292PKTINFO, &opt, sizeof(opt)) != -1)
846 {
847 daemon->v6pktinfo = IPV6_2292PKTINFO;
848 return 1;
849 }
850# endif
851#else
852 if (setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &opt, sizeof(opt)) != -1)
853 return 1;
854#endif
855
856 return 0;
857}
Simon Kelley22ce5502013-01-22 13:53:04 +0000858
859
860/* Find the interface on which a TCP connection arrived, if possible, or zero otherwise. */
861int tcp_interface(int fd, int af)
862{
Kevin Darbyshire-Bryant70c50ef2020-03-06 10:31:15 +0000863 (void)fd; /* suppress potential unused warning */
864 (void)af; /* suppress potential unused warning */
Simon Kelley22ce5502013-01-22 13:53:04 +0000865 int if_index = 0;
866
867#ifdef HAVE_LINUX_NETWORK
868 int opt = 1;
869 struct cmsghdr *cmptr;
870 struct msghdr msg;
Simon Kelley529b0302016-03-16 19:00:45 +0000871 socklen_t len;
Simon Kelley22ce5502013-01-22 13:53:04 +0000872
Simon Kelley529b0302016-03-16 19:00:45 +0000873 /* use mshdr so that the CMSDG_* macros are available */
Simon Kelley22ce5502013-01-22 13:53:04 +0000874 msg.msg_control = daemon->packet;
Simon Kelley529b0302016-03-16 19:00:45 +0000875 msg.msg_controllen = len = daemon->packet_buff_sz;
Simon Kelley22ce5502013-01-22 13:53:04 +0000876
877 /* we overwrote the buffer... */
878 daemon->srv_save = NULL;
879
880 if (af == AF_INET)
881 {
882 if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) != -1 &&
Simon Kelley529b0302016-03-16 19:00:45 +0000883 getsockopt(fd, IPPROTO_IP, IP_PKTOPTIONS, msg.msg_control, &len) != -1)
884 {
885 msg.msg_controllen = len;
886 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
887 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
888 {
889 union {
890 unsigned char *c;
891 struct in_pktinfo *p;
892 } p;
893
894 p.c = CMSG_DATA(cmptr);
895 if_index = p.p->ipi_ifindex;
896 }
897 }
Simon Kelley22ce5502013-01-22 13:53:04 +0000898 }
Simon Kelley22ce5502013-01-22 13:53:04 +0000899 else
900 {
901 /* Only the RFC-2292 API has the ability to find the interface for TCP connections,
902 it was removed in RFC-3542 !!!!
903
904 Fortunately, Linux kept the 2292 ABI when it moved to 3542. The following code always
905 uses the old ABI, and should work with pre- and post-3542 kernel headers */
906
907#ifdef IPV6_2292PKTOPTIONS
908# define PKTOPTIONS IPV6_2292PKTOPTIONS
909#else
910# define PKTOPTIONS IPV6_PKTOPTIONS
911#endif
912
913 if (set_ipv6pktinfo(fd) &&
Simon Kelley529b0302016-03-16 19:00:45 +0000914 getsockopt(fd, IPPROTO_IPV6, PKTOPTIONS, msg.msg_control, &len) != -1)
Simon Kelley22ce5502013-01-22 13:53:04 +0000915 {
Simon Kelley529b0302016-03-16 19:00:45 +0000916 msg.msg_controllen = len;
917 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
Simon Kelley22ce5502013-01-22 13:53:04 +0000918 if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
919 {
920 union {
921 unsigned char *c;
922 struct in6_pktinfo *p;
923 } p;
924 p.c = CMSG_DATA(cmptr);
925
926 if_index = p.p->ipi6_ifindex;
927 }
928 }
929 }
Simon Kelley22ce5502013-01-22 13:53:04 +0000930#endif /* Linux */
931
932 return if_index;
933}
Simon Kelley28866e92011-02-14 20:19:14 +0000934
Simon Kelley74c95c22011-10-19 09:33:39 +0100935static struct listener *create_listeners(union mysockaddr *addr, int do_tftp, int dienow)
Simon Kelley28866e92011-02-14 20:19:14 +0000936{
937 struct listener *l = NULL;
938 int fd = -1, tcpfd = -1, tftpfd = -1;
939
Vladislav Grishenko408c3682013-09-24 16:18:49 +0100940 (void)do_tftp;
941
Simon Kelley28866e92011-02-14 20:19:14 +0000942 if (daemon->port != 0)
943 {
Simon Kelley74c95c22011-10-19 09:33:39 +0100944 fd = make_sock(addr, SOCK_DGRAM, dienow);
945 tcpfd = make_sock(addr, SOCK_STREAM, dienow);
Simon Kelley28866e92011-02-14 20:19:14 +0000946 }
947
948#ifdef HAVE_TFTP
949 if (do_tftp)
950 {
951 if (addr->sa.sa_family == AF_INET)
952 {
953 /* port must be restored to DNS port for TCP code */
954 short save = addr->in.sin_port;
955 addr->in.sin_port = htons(TFTP_PORT);
Simon Kelley74c95c22011-10-19 09:33:39 +0100956 tftpfd = make_sock(addr, SOCK_DGRAM, dienow);
Simon Kelley28866e92011-02-14 20:19:14 +0000957 addr->in.sin_port = save;
958 }
Simon Kelley28866e92011-02-14 20:19:14 +0000959 else
960 {
961 short save = addr->in6.sin6_port;
962 addr->in6.sin6_port = htons(TFTP_PORT);
Simon Kelley74c95c22011-10-19 09:33:39 +0100963 tftpfd = make_sock(addr, SOCK_DGRAM, dienow);
Simon Kelley28866e92011-02-14 20:19:14 +0000964 addr->in6.sin6_port = save;
965 }
Simon Kelley28866e92011-02-14 20:19:14 +0000966 }
Simon Kelley44a2a312004-03-10 20:04:35 +0000967#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100968
Simon Kelley28866e92011-02-14 20:19:14 +0000969 if (fd != -1 || tcpfd != -1 || tftpfd != -1)
970 {
971 l = safe_malloc(sizeof(struct listener));
972 l->next = NULL;
Simon Kelley28866e92011-02-14 20:19:14 +0000973 l->fd = fd;
974 l->tcpfd = tcpfd;
Petr Menšík49bdf1e2019-07-15 17:13:12 +0200975 l->tftpfd = tftpfd;
976 l->addr = *addr;
977 l->used = 1;
Simon Kelley08619212013-12-02 14:43:48 +0000978 l->iface = NULL;
Simon Kelley28866e92011-02-14 20:19:14 +0000979 }
980
981 return l;
982}
983
Simon Kelley74c95c22011-10-19 09:33:39 +0100984void create_wildcard_listeners(void)
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100985{
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100986 union mysockaddr addr;
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100987 struct listener *l, *l6;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100988
Simon Kelley849a8352006-06-09 21:02:31 +0100989 memset(&addr, 0, sizeof(addr));
Simon Kelley28866e92011-02-14 20:19:14 +0000990#ifdef HAVE_SOCKADDR_SA_LEN
991 addr.in.sin_len = sizeof(addr.in);
992#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100993 addr.in.sin_family = AF_INET;
994 addr.in.sin_addr.s_addr = INADDR_ANY;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100995 addr.in.sin_port = htons(daemon->port);
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100996
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100997 l = create_listeners(&addr, !!option_bool(OPT_TFTP), 1);
Simon Kelley28866e92011-02-14 20:19:14 +0000998
Simon Kelley28866e92011-02-14 20:19:14 +0000999 memset(&addr, 0, sizeof(addr));
Simon Kelleyee875042018-10-23 22:10:17 +01001000#ifdef HAVE_SOCKADDR_SA_LEN
Simon Kelley28866e92011-02-14 20:19:14 +00001001 addr.in6.sin6_len = sizeof(addr.in6);
Simon Kelleyee875042018-10-23 22:10:17 +01001002#endif
Simon Kelley28866e92011-02-14 20:19:14 +00001003 addr.in6.sin6_family = AF_INET6;
1004 addr.in6.sin6_addr = in6addr_any;
1005 addr.in6.sin6_port = htons(daemon->port);
Simon Kelley8bc4cec2012-07-03 21:04:11 +01001006
1007 l6 = create_listeners(&addr, !!option_bool(OPT_TFTP), 1);
Simon Kelley28866e92011-02-14 20:19:14 +00001008 if (l)
Simon Kelley8bc4cec2012-07-03 21:04:11 +01001009 l->next = l6;
Simon Kelley28866e92011-02-14 20:19:14 +00001010 else
Simon Kelley8bc4cec2012-07-03 21:04:11 +01001011 l = l6;
Simon Kelleyfeba5c12004-07-27 20:28:58 +01001012
Simon Kelley74c95c22011-10-19 09:33:39 +01001013 daemon->listeners = l;
Simon Kelley44a2a312004-03-10 20:04:35 +00001014}
1015
Petr Menšík49bdf1e2019-07-15 17:13:12 +02001016static struct listener *find_listener(union mysockaddr *addr)
1017{
1018 struct listener *l;
1019 for (l = daemon->listeners; l; l = l->next)
1020 if (sockaddr_isequal(&l->addr, addr))
1021 return l;
1022 return NULL;
1023}
1024
Simon Kelley74c95c22011-10-19 09:33:39 +01001025void create_bound_listeners(int dienow)
Simon Kelley44a2a312004-03-10 20:04:35 +00001026{
Simon Kelley74c95c22011-10-19 09:33:39 +01001027 struct listener *new;
Simon Kelley44a2a312004-03-10 20:04:35 +00001028 struct irec *iface;
Simon Kelley52d4abf2012-03-21 21:39:48 +00001029 struct iname *if_tmp;
Petr Menšík49bdf1e2019-07-15 17:13:12 +02001030 struct listener *existing;
Simon Kelley73a08a22009-02-05 20:28:08 +00001031
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001032 for (iface = daemon->interfaces; iface; iface = iface->next)
Petr Menšík49bdf1e2019-07-15 17:13:12 +02001033 if (!iface->done && !iface->dad && iface->found)
Simon Kelley28866e92011-02-14 20:19:14 +00001034 {
Petr Menšík49bdf1e2019-07-15 17:13:12 +02001035 existing = find_listener(&iface->addr);
1036 if (existing)
1037 {
1038 iface->done = 1;
1039 existing->used++; /* increase usage counter */
1040 }
1041 else if ((new = create_listeners(&iface->addr, iface->tftp_ok, dienow)))
1042 {
Petr Menšík49bdf1e2019-07-15 17:13:12 +02001043 new->iface = iface;
1044 new->next = daemon->listeners;
1045 daemon->listeners = new;
1046 iface->done = 1;
Simon Kelley619000a2020-04-29 00:09:58 +01001047
1048 /* Don't log the initial set of listen addresses created
1049 at startup, since this is happening before the logging
1050 system is initialised and the sign-on printed. */
1051 if (!dienow)
1052 {
1053 int port = prettyprint_addr(&iface->addr, daemon->addrbuff);
1054 my_syslog(LOG_DEBUG, _("listening on %s(#%d): %s port %d"),
1055 iface->name, iface->index, daemon->addrbuff, port);
1056 }
Petr Menšík49bdf1e2019-07-15 17:13:12 +02001057 }
Simon Kelley28866e92011-02-14 20:19:14 +00001058 }
Simon Kelley52d4abf2012-03-21 21:39:48 +00001059
1060 /* Check for --listen-address options that haven't been used because there's
1061 no interface with a matching address. These may be valid: eg it's possible
1062 to listen on 127.0.1.1 even if the loopback interface is 127.0.0.1
1063
Simon Kelley5f11b3e2012-08-16 14:04:05 +01001064 If the address isn't valid the bind() will fail and we'll die()
1065 (except in bind-dynamic mode, when we'll complain but keep trying.)
Simon Kelley52d4abf2012-03-21 21:39:48 +00001066
1067 The resulting listeners have the ->iface field NULL, and this has to be
1068 handled by the DNS and TFTP code. It disables --localise-queries processing
1069 (no netmask) and some MTU login the tftp code. */
1070
1071 for (if_tmp = daemon->if_addrs; if_tmp; if_tmp = if_tmp->next)
1072 if (!if_tmp->used &&
Simon Kelley8bc4cec2012-07-03 21:04:11 +01001073 (new = create_listeners(&if_tmp->addr, !!option_bool(OPT_TFTP), dienow)))
Simon Kelley52d4abf2012-03-21 21:39:48 +00001074 {
Simon Kelley52d4abf2012-03-21 21:39:48 +00001075 new->next = daemon->listeners;
1076 daemon->listeners = new;
Simon Kelley619000a2020-04-29 00:09:58 +01001077
1078 if (!dienow)
1079 {
1080 int port = prettyprint_addr(&if_tmp->addr, daemon->addrbuff);
1081 my_syslog(LOG_DEBUG, _("listening on %s port %d"), daemon->addrbuff, port);
1082 }
Simon Kelley52d4abf2012-03-21 21:39:48 +00001083 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001084}
1085
Simon Kelleydc27e142013-10-16 13:09:53 +01001086/* In --bind-interfaces, the only access control is the addresses we're listening on.
1087 There's nothing to avoid a query to the address of an internal interface arriving via
1088 an external interface where we don't want to accept queries, except that in the usual
1089 case the addresses of internal interfaces are RFC1918. When bind-interfaces in use,
1090 and we listen on an address that looks like it's probably globally routeable, shout.
1091
1092 The fix is to use --bind-dynamic, which actually checks the arrival interface too.
1093 Tough if your platform doesn't support this.
Simon Kelley2329bef2013-12-03 13:41:16 +00001094
1095 Note that checking the arrival interface is supported in the standard IPv6 API and
1096 always done, so we don't warn about any IPv6 addresses here.
Simon Kelleydc27e142013-10-16 13:09:53 +01001097*/
1098
1099void warn_bound_listeners(void)
1100{
1101 struct irec *iface;
1102 int advice = 0;
1103
1104 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelleyf7029f52013-11-21 15:09:09 +00001105 if (!iface->dns_auth)
Simon Kelleydc27e142013-10-16 13:09:53 +01001106 {
Simon Kelleydc27e142013-10-16 13:09:53 +01001107 if (iface->addr.sa.sa_family == AF_INET)
1108 {
1109 if (!private_net(iface->addr.in.sin_addr, 1))
1110 {
1111 inet_ntop(AF_INET, &iface->addr.in.sin_addr, daemon->addrbuff, ADDRSTRLEN);
Simon Kelley2329bef2013-12-03 13:41:16 +00001112 iface->warned = advice = 1;
1113 my_syslog(LOG_WARNING,
1114 _("LOUD WARNING: listening on %s may accept requests via interfaces other than %s"),
1115 daemon->addrbuff, iface->name);
Simon Kelleydc27e142013-10-16 13:09:53 +01001116 }
1117 }
Simon Kelleydc27e142013-10-16 13:09:53 +01001118 }
1119
1120 if (advice)
Simon Kelleyf7029f52013-11-21 15:09:09 +00001121 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 +01001122}
1123
Petr Menšíkad59f272017-03-17 17:22:19 +00001124void warn_wild_labels(void)
1125{
1126 struct irec *iface;
1127
1128 for (iface = daemon->interfaces; iface; iface = iface->next)
1129 if (iface->found && iface->name && iface->label)
1130 my_syslog(LOG_WARNING, _("warning: using interface %s instead"), iface->name);
1131}
1132
Simon Kelleyf7029f52013-11-21 15:09:09 +00001133void warn_int_names(void)
1134{
1135 struct interface_name *intname;
1136
1137 for (intname = daemon->int_names; intname; intname = intname->next)
1138 if (!intname->addr)
1139 my_syslog(LOG_WARNING, _("warning: no addresses found for interface %s"), intname->intr);
1140}
1141
Simon Kelley74c95c22011-10-19 09:33:39 +01001142int is_dad_listeners(void)
1143{
1144 struct irec *iface;
1145
1146 if (option_bool(OPT_NOWILD))
1147 for (iface = daemon->interfaces; iface; iface = iface->next)
1148 if (iface->dad && !iface->done)
1149 return 1;
1150
1151 return 0;
1152}
Simon Kelley5d162f22012-12-20 14:55:46 +00001153
1154#ifdef HAVE_DHCP6
1155void join_multicast(int dienow)
1156{
1157 struct irec *iface, *tmp;
1158
1159 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelley19624462012-12-28 11:18:09 +00001160 if (iface->addr.sa.sa_family == AF_INET6 && iface->dhcp_ok && !iface->multicast_done)
Simon Kelley5d162f22012-12-20 14:55:46 +00001161 {
1162 /* There's an irec per address but we only want to join for multicast
1163 once per interface. Weed out duplicates. */
1164 for (tmp = daemon->interfaces; tmp; tmp = tmp->next)
1165 if (tmp->multicast_done && tmp->index == iface->index)
1166 break;
1167
1168 iface->multicast_done = 1;
1169
1170 if (!tmp)
1171 {
1172 struct ipv6_mreq mreq;
1173 int err = 0;
1174
1175 mreq.ipv6mr_interface = iface->index;
1176
1177 inet_pton(AF_INET6, ALL_RELAY_AGENTS_AND_SERVERS, &mreq.ipv6mr_multiaddr);
1178
Simon Kelleyff7eea22013-09-04 18:01:38 +01001179 if ((daemon->doing_dhcp6 || daemon->relay6) &&
Simon Kelley5d162f22012-12-20 14:55:46 +00001180 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_SERVERS, &mreq.ipv6mr_multiaddr);
1184
1185 if (daemon->doing_dhcp6 &&
1186 setsockopt(daemon->dhcp6fd, 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 inet_pton(AF_INET6, ALL_ROUTERS, &mreq.ipv6mr_multiaddr);
1190
1191 if (daemon->doing_ra &&
1192 setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
Simon Kelley9cdcfe92015-08-26 22:38:08 +01001193 err = errno;
Simon Kelley5d162f22012-12-20 14:55:46 +00001194
1195 if (err)
1196 {
1197 char *s = _("interface %s failed to join DHCPv6 multicast group: %s");
Simon Kelley9cdcfe92015-08-26 22:38:08 +01001198 errno = err;
1199
1200#ifdef HAVE_LINUX_NETWORK
1201 if (errno == ENOMEM)
1202 my_syslog(LOG_ERR, _("try increasing /proc/sys/net/core/optmem_max"));
1203#endif
1204
Simon Kelley5d162f22012-12-20 14:55:46 +00001205 if (dienow)
1206 die(s, iface->name, EC_BADNET);
1207 else
1208 my_syslog(LOG_ERR, s, iface->name, strerror(errno));
1209 }
1210 }
1211 }
1212}
1213#endif
1214
Simon Kelley9009d742008-11-14 20:04:27 +00001215/* return a UDP socket bound to a random port, have to cope with straying into
Simon Kelley1a6bca82008-07-11 11:11:42 +01001216 occupied port nos and reserved ones. */
1217int random_sock(int family)
1218{
1219 int fd;
1220
1221 if ((fd = socket(family, SOCK_DGRAM, 0)) != -1)
1222 {
Simon Kelley3927da42008-07-20 15:10:39 +01001223 union mysockaddr addr;
Hans Dedecker926332a2016-01-23 10:48:12 +00001224 unsigned int ports_avail = ((unsigned short)daemon->max_port - (unsigned short)daemon->min_port) + 1;
Simon Kelley9009d742008-11-14 20:04:27 +00001225 int tries = ports_avail < 30 ? 3 * ports_avail : 100;
Simon Kelley3927da42008-07-20 15:10:39 +01001226
Simon Kelley1a6bca82008-07-11 11:11:42 +01001227 memset(&addr, 0, sizeof(addr));
Simon Kelley3927da42008-07-20 15:10:39 +01001228 addr.sa.sa_family = family;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001229
Simon Kelley1ad24ae2008-07-20 20:22:50 +01001230 /* don't loop forever if all ports in use. */
1231
Simon Kelley1a6bca82008-07-11 11:11:42 +01001232 if (fix_fd(fd))
Simon Kelley9009d742008-11-14 20:04:27 +00001233 while(tries--)
Simon Kelley1a6bca82008-07-11 11:11:42 +01001234 {
Simon Kelleybaf553d2018-01-29 22:49:27 +00001235 unsigned short port = htons(daemon->min_port + (rand16() % ((unsigned short)ports_avail)));
Simon Kelley1a6bca82008-07-11 11:11:42 +01001236
1237 if (family == AF_INET)
1238 {
1239 addr.in.sin_addr.s_addr = INADDR_ANY;
Simon Kelley3927da42008-07-20 15:10:39 +01001240 addr.in.sin_port = port;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001241#ifdef HAVE_SOCKADDR_SA_LEN
1242 addr.in.sin_len = sizeof(struct sockaddr_in);
1243#endif
1244 }
Simon Kelley1a6bca82008-07-11 11:11:42 +01001245 else
1246 {
1247 addr.in6.sin6_addr = in6addr_any;
Simon Kelley3927da42008-07-20 15:10:39 +01001248 addr.in6.sin6_port = port;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001249#ifdef HAVE_SOCKADDR_SA_LEN
1250 addr.in6.sin6_len = sizeof(struct sockaddr_in6);
1251#endif
1252 }
Simon Kelley1a6bca82008-07-11 11:11:42 +01001253
1254 if (bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == 0)
1255 return fd;
1256
1257 if (errno != EADDRINUSE && errno != EACCES)
1258 break;
1259 }
1260
1261 close(fd);
1262 }
1263
1264 return -1;
1265}
1266
1267
Simon Kelley9d6918d2017-10-13 17:55:09 +01001268int local_bind(int fd, union mysockaddr *addr, char *intname, unsigned int ifindex, int is_tcp)
Simon Kelley824af852008-02-12 20:43:05 +00001269{
1270 union mysockaddr addr_copy = *addr;
Simon Kelleya2a7e042020-12-12 23:26:45 +00001271 unsigned short port;
1272 int tries = 1, done = 0;
1273 unsigned int ports_avail = ((unsigned short)daemon->max_port - (unsigned short)daemon->min_port) + 1;
1274
1275 if (addr_copy.sa.sa_family == AF_INET)
1276 port = addr_copy.in.sin_port;
1277 else
1278 port = addr_copy.in6.sin6_port;
Simon Kelley824af852008-02-12 20:43:05 +00001279
1280 /* cannot set source _port_ for TCP connections. */
1281 if (is_tcp)
Simon Kelleya2a7e042020-12-12 23:26:45 +00001282 port = 0;
1283
1284 /* Bind a random port within the range given by min-port and max-port */
1285 if (port == 0)
Simon Kelley824af852008-02-12 20:43:05 +00001286 {
Simon Kelleya2a7e042020-12-12 23:26:45 +00001287 tries = ports_avail < 30 ? 3 * ports_avail : 100;
1288 port = htons(daemon->min_port + (rand16() % ((unsigned short)ports_avail)));
Simon Kelley824af852008-02-12 20:43:05 +00001289 }
1290
Simon Kelleya2a7e042020-12-12 23:26:45 +00001291 while (tries--)
1292 {
1293 if (addr_copy.sa.sa_family == AF_INET)
1294 addr_copy.in.sin_port = port;
1295 else
1296 addr_copy.in6.sin6_port = port;
1297
1298 if (bind(fd, (struct sockaddr *)&addr_copy, sa_len(&addr_copy)) != -1)
1299 {
1300 done = 1;
1301 break;
1302 }
1303
1304 if (errno != EADDRINUSE && errno != EACCES)
1305 return 0;
1306
1307 port = htons(daemon->min_port + (rand16() % ((unsigned short)ports_avail)));
1308 }
1309
1310 if (!done)
Simon Kelley824af852008-02-12 20:43:05 +00001311 return 0;
Simon Kelley9d6918d2017-10-13 17:55:09 +01001312
1313 if (!is_tcp && ifindex > 0)
1314 {
1315#if defined(IP_UNICAST_IF)
1316 if (addr_copy.sa.sa_family == AF_INET)
1317 {
1318 uint32_t ifindex_opt = htonl(ifindex);
1319 return setsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex_opt, sizeof(ifindex_opt)) == 0;
1320 }
1321#endif
Simon Kelleyee875042018-10-23 22:10:17 +01001322#if defined (IPV6_UNICAST_IF)
Simon Kelley9d6918d2017-10-13 17:55:09 +01001323 if (addr_copy.sa.sa_family == AF_INET6)
1324 {
1325 uint32_t ifindex_opt = htonl(ifindex);
1326 return setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_IF, &ifindex_opt, sizeof(ifindex_opt)) == 0;
1327 }
1328#endif
1329 }
1330
Kevin Darbyshire-Bryant70c50ef2020-03-06 10:31:15 +00001331 (void)intname; /* suppress potential unused warning */
Simon Kelley824af852008-02-12 20:43:05 +00001332#if defined(SO_BINDTODEVICE)
Simon Kelley73a08a22009-02-05 20:28:08 +00001333 if (intname[0] != 0 &&
Simon Kelley316e2732010-01-22 20:16:09 +00001334 setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, intname, IF_NAMESIZE) == -1)
Simon Kelley824af852008-02-12 20:43:05 +00001335 return 0;
1336#endif
1337
1338 return 1;
1339}
1340
1341static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001342{
1343 struct serverfd *sfd;
Beniamino Galvani2675f202016-08-28 20:44:05 +01001344 unsigned int ifindex = 0;
Simon Kelley824af852008-02-12 20:43:05 +00001345 int errsave;
Simon Kelleye83915d2018-04-10 21:27:26 +01001346 int opt = 1;
1347
Simon Kelley1a6bca82008-07-11 11:11:42 +01001348 /* when using random ports, servers which would otherwise use
1349 the INADDR_ANY/port0 socket have sfd set to NULL */
Simon Kelley73a08a22009-02-05 20:28:08 +00001350 if (!daemon->osport && intname[0] == 0)
Simon Kelley1a6bca82008-07-11 11:11:42 +01001351 {
1352 errno = 0;
1353
1354 if (addr->sa.sa_family == AF_INET &&
1355 addr->in.sin_addr.s_addr == INADDR_ANY &&
1356 addr->in.sin_port == htons(0))
1357 return NULL;
1358
Simon Kelley1a6bca82008-07-11 11:11:42 +01001359 if (addr->sa.sa_family == AF_INET6 &&
1360 memcmp(&addr->in6.sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0 &&
1361 addr->in6.sin6_port == htons(0))
1362 return NULL;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001363 }
Beniamino Galvani2675f202016-08-28 20:44:05 +01001364
1365 if (intname && strlen(intname) != 0)
1366 ifindex = if_nametoindex(intname); /* index == 0 when not binding to an interface */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001367
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001368 /* may have a suitable one already */
Simon Kelley824af852008-02-12 20:43:05 +00001369 for (sfd = daemon->sfds; sfd; sfd = sfd->next )
1370 if (sockaddr_isequal(&sfd->source_addr, addr) &&
Beniamino Galvani2675f202016-08-28 20:44:05 +01001371 strcmp(intname, sfd->interface) == 0 &&
1372 ifindex == sfd->ifindex)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001373 return sfd;
1374
1375 /* need to make a new one. */
1376 errno = ENOMEM; /* in case malloc fails. */
Simon Kelley5aabfc72007-08-29 11:24:47 +01001377 if (!(sfd = whine_malloc(sizeof(struct serverfd))))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001378 return NULL;
1379
1380 if ((sfd->fd = socket(addr->sa.sa_family, SOCK_DGRAM, 0)) == -1)
1381 {
1382 free(sfd);
1383 return NULL;
1384 }
Simon Kelleye83915d2018-04-10 21:27:26 +01001385
1386 if ((addr->sa.sa_family == AF_INET6 && setsockopt(sfd->fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)) == -1) ||
1387 !local_bind(sfd->fd, addr, intname, ifindex, 0) || !fix_fd(sfd->fd))
Simon Kelley824af852008-02-12 20:43:05 +00001388 {
Simon Kelleye83915d2018-04-10 21:27:26 +01001389 errsave = errno; /* save error from bind/setsockopt. */
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001390 close(sfd->fd);
1391 free(sfd);
1392 errno = errsave;
1393 return NULL;
1394 }
Beniamino Galvani2675f202016-08-28 20:44:05 +01001395
Petr Menšík47b45b22018-08-15 18:17:00 +02001396 safe_strncpy(sfd->interface, intname, sizeof(sfd->interface));
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001397 sfd->source_addr = *addr;
Simon Kelley824af852008-02-12 20:43:05 +00001398 sfd->next = daemon->sfds;
Beniamino Galvani2675f202016-08-28 20:44:05 +01001399 sfd->ifindex = ifindex;
Simon Kelley4441cf72018-04-10 21:39:54 +01001400 sfd->preallocated = 0;
Simon Kelley824af852008-02-12 20:43:05 +00001401 daemon->sfds = sfd;
Beniamino Galvani2675f202016-08-28 20:44:05 +01001402
Simon Kelley824af852008-02-12 20:43:05 +00001403 return sfd;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001404}
1405
Simon Kelley824af852008-02-12 20:43:05 +00001406/* create upstream sockets during startup, before root is dropped which may be needed
1407 this allows query_port to be a low port and interface binding */
1408void pre_allocate_sfds(void)
1409{
1410 struct server *srv;
Simon Kelley4441cf72018-04-10 21:39:54 +01001411 struct serverfd *sfd;
Simon Kelley824af852008-02-12 20:43:05 +00001412
1413 if (daemon->query_port != 0)
1414 {
1415 union mysockaddr addr;
1416 memset(&addr, 0, sizeof(addr));
1417 addr.in.sin_family = AF_INET;
1418 addr.in.sin_addr.s_addr = INADDR_ANY;
1419 addr.in.sin_port = htons(daemon->query_port);
1420#ifdef HAVE_SOCKADDR_SA_LEN
1421 addr.in.sin_len = sizeof(struct sockaddr_in);
1422#endif
Simon Kelley4441cf72018-04-10 21:39:54 +01001423 if ((sfd = allocate_sfd(&addr, "")))
1424 sfd->preallocated = 1;
Simon Kelleyee875042018-10-23 22:10:17 +01001425
Simon Kelley824af852008-02-12 20:43:05 +00001426 memset(&addr, 0, sizeof(addr));
1427 addr.in6.sin6_family = AF_INET6;
1428 addr.in6.sin6_addr = in6addr_any;
1429 addr.in6.sin6_port = htons(daemon->query_port);
1430#ifdef HAVE_SOCKADDR_SA_LEN
1431 addr.in6.sin6_len = sizeof(struct sockaddr_in6);
1432#endif
Simon Kelley4441cf72018-04-10 21:39:54 +01001433 if ((sfd = allocate_sfd(&addr, "")))
1434 sfd->preallocated = 1;
Simon Kelley824af852008-02-12 20:43:05 +00001435 }
1436
1437 for (srv = daemon->servers; srv; srv = srv->next)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001438 if (!(srv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)) &&
Simon Kelley824af852008-02-12 20:43:05 +00001439 !allocate_sfd(&srv->source_addr, srv->interface) &&
Simon Kelley1a6bca82008-07-11 11:11:42 +01001440 errno != 0 &&
Simon Kelley28866e92011-02-14 20:19:14 +00001441 option_bool(OPT_NOWILD))
Simon Kelley824af852008-02-12 20:43:05 +00001442 {
Petr Mensik51cdd1a2019-07-04 20:28:08 +02001443 (void)prettyprint_addr(&srv->source_addr, daemon->namebuff);
Simon Kelley73a08a22009-02-05 20:28:08 +00001444 if (srv->interface[0] != 0)
Simon Kelley824af852008-02-12 20:43:05 +00001445 {
1446 strcat(daemon->namebuff, " ");
1447 strcat(daemon->namebuff, srv->interface);
1448 }
1449 die(_("failed to bind server socket for %s: %s"),
1450 daemon->namebuff, EC_BADNET);
1451 }
1452}
1453
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001454void mark_servers(int flag)
1455{
1456 struct server *serv;
1457
1458 /* mark everything with argument flag */
1459 for (serv = daemon->servers; serv; serv = serv->next)
Simon Kelley40766e52014-07-29 16:52:00 +01001460 {
1461 if (serv->flags & flag)
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001462 serv->flags |= SERV_MARK;
1463#ifdef HAVE_LOOP
Simon Kelley40766e52014-07-29 16:52:00 +01001464 /* Give looped servers another chance */
1465 serv->flags &= ~SERV_LOOP;
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001466#endif
Simon Kelley40766e52014-07-29 16:52:00 +01001467 }
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001468}
1469
1470void cleanup_servers(void)
1471{
1472 struct server *serv, *tmp, **up;
1473
1474 /* unlink and free anything still marked. */
1475 for (serv = daemon->servers, up = &daemon->servers; serv; serv = tmp)
1476 {
1477 tmp = serv->next;
1478 if (serv->flags & SERV_MARK)
1479 {
1480 server_gone(serv);
1481 *up = serv->next;
1482 if (serv->domain)
1483 free(serv->domain);
1484 free(serv);
1485 }
1486 else
1487 up = &serv->next;
1488 }
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001489
1490#ifdef HAVE_LOOP
1491 /* Now we have a new set of servers, test for loops. */
1492 loop_send_probes();
1493#endif
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001494}
1495
1496void add_update_server(int flags,
1497 union mysockaddr *addr,
1498 union mysockaddr *source_addr,
1499 const char *interface,
1500 const char *domain)
1501{
Simon Kelley7b1eae42014-02-20 13:43:28 +00001502 struct server *serv, *next = NULL;
1503 char *domain_str = NULL;
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001504
1505 /* See if there is a suitable candidate, and unmark */
1506 for (serv = daemon->servers; serv; serv = serv->next)
1507 if (serv->flags & SERV_MARK)
1508 {
1509 if (domain)
1510 {
1511 if (!(serv->flags & SERV_HAS_DOMAIN) || !hostname_isequal(domain, serv->domain))
1512 continue;
1513 }
1514 else
1515 {
1516 if (serv->flags & SERV_HAS_DOMAIN)
1517 continue;
1518 }
1519
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001520 break;
1521 }
Simon Kelley7b1eae42014-02-20 13:43:28 +00001522
1523 if (serv)
1524 {
1525 domain_str = serv->domain;
1526 next = serv->next;
1527 }
1528 else if ((serv = whine_malloc(sizeof (struct server))))
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001529 {
1530 /* Not found, create a new one. */
Simon Kelley7b1eae42014-02-20 13:43:28 +00001531 if (domain && !(domain_str = whine_malloc(strlen(domain)+1)))
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001532 {
1533 free(serv);
1534 serv = NULL;
1535 }
1536 else
1537 {
1538 struct server *s;
1539 /* Add to the end of the chain, for order */
1540 if (!daemon->servers)
1541 daemon->servers = serv;
1542 else
1543 {
1544 for (s = daemon->servers; s->next; s = s->next);
1545 s->next = serv;
1546 }
1547 if (domain)
Simon Kelley7b1eae42014-02-20 13:43:28 +00001548 strcpy(domain_str, domain);
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001549 }
1550 }
1551
1552 if (serv)
1553 {
Simon Kelley7b1eae42014-02-20 13:43:28 +00001554 memset(serv, 0, sizeof(struct server));
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001555 serv->flags = flags;
Simon Kelley7b1eae42014-02-20 13:43:28 +00001556 serv->domain = domain_str;
1557 serv->next = next;
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001558 serv->queries = serv->failed_queries = 0;
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001559#ifdef HAVE_LOOP
1560 serv->uid = rand32();
1561#endif
1562
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001563 if (domain)
1564 serv->flags |= SERV_HAS_DOMAIN;
1565
1566 if (interface)
Petr Menšík47b45b22018-08-15 18:17:00 +02001567 safe_strncpy(serv->interface, interface, sizeof(serv->interface));
Simon Kelley7b1eae42014-02-20 13:43:28 +00001568 if (addr)
1569 serv->addr = *addr;
1570 if (source_addr)
1571 serv->source_addr = *source_addr;
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001572 }
1573}
Simon Kelley824af852008-02-12 20:43:05 +00001574
Simon Kelley5aabfc72007-08-29 11:24:47 +01001575void check_servers(void)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001576{
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001577 struct irec *iface;
Simon Kelley7bcca002014-02-19 17:45:17 +00001578 struct server *serv;
Beniamino Galvani2675f202016-08-28 20:44:05 +01001579 struct serverfd *sfd, *tmp, **up;
Simon Kelleyb9702602016-05-03 22:34:06 +01001580 int port = 0, count;
Hannu Nyman3e2496f2017-02-11 13:44:08 +00001581 int locals = 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001582
Simon Kelley316e2732010-01-22 20:16:09 +00001583 /* interface may be new since startup */
Simon Kelley28866e92011-02-14 20:19:14 +00001584 if (!option_bool(OPT_NOWILD))
Simon Kelley115ac3e2013-05-20 11:28:32 +01001585 enumerate_interfaces(0);
Simon Kelley4441cf72018-04-10 21:39:54 +01001586
1587 /* don't garbage collect pre-allocated sfds. */
Beniamino Galvani2675f202016-08-28 20:44:05 +01001588 for (sfd = daemon->sfds; sfd; sfd = sfd->next)
Simon Kelley4441cf72018-04-10 21:39:54 +01001589 sfd->used = sfd->preallocated;
Beniamino Galvani2675f202016-08-28 20:44:05 +01001590
Simon Kelleyb9702602016-05-03 22:34:06 +01001591 for (count = 0, serv = daemon->servers; serv; serv = serv->next)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001592 {
Simon Kelley367341f2016-01-12 15:58:23 +00001593 if (!(serv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001594 {
Simon Kelley14ffa072016-04-25 16:36:44 +01001595 /* Init edns_pktsz for newly created server records. */
1596 if (serv->edns_pktsz == 0)
1597 serv->edns_pktsz = daemon->edns_pktsz;
1598
Simon Kelley367341f2016-01-12 15:58:23 +00001599#ifdef HAVE_DNSSEC
Simon Kelley92be34a2016-01-16 18:39:54 +00001600 if (option_bool(OPT_DNSSEC_VALID))
1601 {
Simon Kelleya49c5c22017-10-10 22:04:59 +01001602 if (!(serv->flags & SERV_FOR_NODOTS))
1603 serv->flags |= SERV_DO_DNSSEC;
1604
1605 /* Disable DNSSEC validation when using server=/domain/.... servers
1606 unless there's a configured trust anchor. */
Simon Kelley92be34a2016-01-16 18:39:54 +00001607 if (serv->flags & SERV_HAS_DOMAIN)
1608 {
1609 struct ds_config *ds;
1610 char *domain = serv->domain;
1611
1612 /* .example.com is valid */
1613 while (*domain == '.')
1614 domain++;
1615
1616 for (ds = daemon->ds; ds; ds = ds->next)
1617 if (ds->name[0] != 0 && hostname_isequal(domain, ds->name))
1618 break;
1619
1620 if (!ds)
1621 serv->flags &= ~SERV_DO_DNSSEC;
1622 }
Simon Kelley367341f2016-01-12 15:58:23 +00001623 }
1624#endif
1625
1626 port = prettyprint_addr(&serv->addr, daemon->namebuff);
1627
Simon Kelley16972692006-10-16 20:04:18 +01001628 /* 0.0.0.0 is nothing, the stack treats it like 127.0.0.1 */
Simon Kelley7bcca002014-02-19 17:45:17 +00001629 if (serv->addr.sa.sa_family == AF_INET &&
1630 serv->addr.in.sin_addr.s_addr == 0)
Simon Kelley16972692006-10-16 20:04:18 +01001631 {
Simon Kelley7bcca002014-02-19 17:45:17 +00001632 serv->flags |= SERV_MARK;
Simon Kelley16972692006-10-16 20:04:18 +01001633 continue;
1634 }
1635
Simon Kelley3d8df262005-08-29 12:19:27 +01001636 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelley7bcca002014-02-19 17:45:17 +00001637 if (sockaddr_isequal(&serv->addr, &iface->addr))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001638 break;
1639 if (iface)
1640 {
Simon Kelleyf2621c72007-04-29 19:47:21 +01001641 my_syslog(LOG_WARNING, _("ignoring nameserver %s - local interface"), daemon->namebuff);
Simon Kelley7bcca002014-02-19 17:45:17 +00001642 serv->flags |= SERV_MARK;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001643 continue;
1644 }
1645
1646 /* Do we need a socket set? */
Simon Kelley7bcca002014-02-19 17:45:17 +00001647 if (!serv->sfd &&
1648 !(serv->sfd = allocate_sfd(&serv->source_addr, serv->interface)) &&
Simon Kelley1a6bca82008-07-11 11:11:42 +01001649 errno != 0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001650 {
Simon Kelleyf2621c72007-04-29 19:47:21 +01001651 my_syslog(LOG_WARNING,
1652 _("ignoring nameserver %s - cannot make/bind socket: %s"),
1653 daemon->namebuff, strerror(errno));
Simon Kelley7bcca002014-02-19 17:45:17 +00001654 serv->flags |= SERV_MARK;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001655 continue;
1656 }
Simon Kelley16800ea2016-08-30 23:07:06 +01001657
1658 if (serv->sfd)
1659 serv->sfd->used = 1;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001660 }
1661
Simon Kelley979fe862015-03-19 22:50:22 +00001662 if (!(serv->flags & SERV_NO_REBIND) && !(serv->flags & SERV_LITERAL_ADDRESS))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001663 {
Simon Kelleyb9702602016-05-03 22:34:06 +01001664 if (++count > SERVERS_LOGGED)
1665 continue;
1666
Simon Kelley7bcca002014-02-19 17:45:17 +00001667 if (serv->flags & (SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_USE_RESOLV))
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001668 {
Simon Kelley367341f2016-01-12 15:58:23 +00001669 char *s1, *s2, *s3 = "";
1670#ifdef HAVE_DNSSEC
1671 if (option_bool(OPT_DNSSEC_VALID) && !(serv->flags & SERV_DO_DNSSEC))
1672 s3 = _("(no DNSSEC)");
1673#endif
Simon Kelley7bcca002014-02-19 17:45:17 +00001674 if (!(serv->flags & SERV_HAS_DOMAIN))
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001675 s1 = _("unqualified"), s2 = _("names");
Simon Kelleyd9603ef2020-01-26 18:13:35 +00001676 else if (strlen(serv->domain) == 0)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001677 s1 = _("default"), s2 = "";
1678 else
Simon Kelley7bcca002014-02-19 17:45:17 +00001679 s1 = _("domain"), s2 = serv->domain;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001680
Simon Kelley7bcca002014-02-19 17:45:17 +00001681 if (serv->flags & SERV_NO_ADDR)
Hannu Nyman3e2496f2017-02-11 13:44:08 +00001682 {
1683 count--;
1684 if (++locals <= LOCALS_LOGGED)
Simon Kelley8bd28a82019-03-01 15:00:12 +00001685 my_syslog(LOG_INFO, _("using only locally-known addresses for %s %s"), s1, s2);
Hannu Nyman3e2496f2017-02-11 13:44:08 +00001686 }
Simon Kelley7bcca002014-02-19 17:45:17 +00001687 else if (serv->flags & SERV_USE_RESOLV)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001688 my_syslog(LOG_INFO, _("using standard nameservers for %s %s"), s1, s2);
Simon Kelley979fe862015-03-19 22:50:22 +00001689 else
Simon Kelley367341f2016-01-12 15:58:23 +00001690 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 +01001691 }
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001692#ifdef HAVE_LOOP
1693 else if (serv->flags & SERV_LOOP)
1694 my_syslog(LOG_INFO, _("NOT using nameserver %s#%d - query loop detected"), daemon->namebuff, port);
1695#endif
Simon Kelley7bcca002014-02-19 17:45:17 +00001696 else if (serv->interface[0] != 0)
1697 my_syslog(LOG_INFO, _("using nameserver %s#%d(via %s)"), daemon->namebuff, port, serv->interface);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001698 else
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001699 my_syslog(LOG_INFO, _("using nameserver %s#%d"), daemon->namebuff, port);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001700 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001701 }
Simon Kelleyb9702602016-05-03 22:34:06 +01001702
Hannu Nyman3e2496f2017-02-11 13:44:08 +00001703 if (locals > LOCALS_LOGGED)
1704 my_syslog(LOG_INFO, _("using %d more local addresses"), locals - LOCALS_LOGGED);
Simon Kelleyb9702602016-05-03 22:34:06 +01001705 if (count - 1 > SERVERS_LOGGED)
1706 my_syslog(LOG_INFO, _("using %d more nameservers"), count - SERVERS_LOGGED - 1);
Simon Kelley7bcca002014-02-19 17:45:17 +00001707
Beniamino Galvani2675f202016-08-28 20:44:05 +01001708 /* Remove unused sfds */
1709 for (sfd = daemon->sfds, up = &daemon->sfds; sfd; sfd = tmp)
1710 {
1711 tmp = sfd->next;
1712 if (!sfd->used)
1713 {
1714 *up = sfd->next;
1715 close(sfd->fd);
1716 free(sfd);
1717 }
1718 else
1719 up = &sfd->next;
1720 }
1721
Simon Kelley7bcca002014-02-19 17:45:17 +00001722 cleanup_servers();
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001723}
Simon Kelley849a8352006-06-09 21:02:31 +01001724
1725/* Return zero if no servers found, in that case we keep polling.
1726 This is a protection against an update-time/write race on resolv.conf */
Simon Kelley5aabfc72007-08-29 11:24:47 +01001727int reload_servers(char *fname)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001728{
1729 FILE *f;
1730 char *line;
Simon Kelley849a8352006-06-09 21:02:31 +01001731 int gotone = 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001732
Simon Kelley849a8352006-06-09 21:02:31 +01001733 /* buff happens to be MAXDNAME long... */
1734 if (!(f = fopen(fname, "r")))
1735 {
Simon Kelleyf2621c72007-04-29 19:47:21 +01001736 my_syslog(LOG_ERR, _("failed to read %s: %s"), fname, strerror(errno));
Simon Kelley849a8352006-06-09 21:02:31 +01001737 return 0;
1738 }
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001739
1740 mark_servers(SERV_FROM_RESOLV);
1741
Simon Kelley849a8352006-06-09 21:02:31 +01001742 while ((line = fgets(daemon->namebuff, MAXDNAME, f)))
1743 {
1744 union mysockaddr addr, source_addr;
1745 char *token = strtok(line, " \t\n\r");
1746
Simon Kelley5aabfc72007-08-29 11:24:47 +01001747 if (!token)
1748 continue;
1749 if (strcmp(token, "nameserver") != 0 && strcmp(token, "server") != 0)
Simon Kelley849a8352006-06-09 21:02:31 +01001750 continue;
1751 if (!(token = strtok(NULL, " \t\n\r")))
1752 continue;
1753
1754 memset(&addr, 0, sizeof(addr));
1755 memset(&source_addr, 0, sizeof(source_addr));
1756
1757 if ((addr.in.sin_addr.s_addr = inet_addr(token)) != (in_addr_t) -1)
1758 {
1759#ifdef HAVE_SOCKADDR_SA_LEN
1760 source_addr.in.sin_len = addr.in.sin_len = sizeof(source_addr.in);
1761#endif
1762 source_addr.in.sin_family = addr.in.sin_family = AF_INET;
1763 addr.in.sin_port = htons(NAMESERVER_PORT);
1764 source_addr.in.sin_addr.s_addr = INADDR_ANY;
1765 source_addr.in.sin_port = htons(daemon->query_port);
1766 }
Simon Kelley7de060b2011-08-26 17:24:52 +01001767 else
1768 {
1769 int scope_index = 0;
1770 char *scope_id = strchr(token, '%');
1771
1772 if (scope_id)
1773 {
1774 *(scope_id++) = 0;
1775 scope_index = if_nametoindex(scope_id);
1776 }
1777
1778 if (inet_pton(AF_INET6, token, &addr.in6.sin6_addr) > 0)
1779 {
Simon Kelley849a8352006-06-09 21:02:31 +01001780#ifdef HAVE_SOCKADDR_SA_LEN
Simon Kelley7de060b2011-08-26 17:24:52 +01001781 source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(source_addr.in6);
Simon Kelley849a8352006-06-09 21:02:31 +01001782#endif
Simon Kelley7de060b2011-08-26 17:24:52 +01001783 source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6;
1784 source_addr.in6.sin6_flowinfo = addr.in6.sin6_flowinfo = 0;
1785 addr.in6.sin6_port = htons(NAMESERVER_PORT);
1786 addr.in6.sin6_scope_id = scope_index;
1787 source_addr.in6.sin6_addr = in6addr_any;
1788 source_addr.in6.sin6_port = htons(daemon->query_port);
1789 source_addr.in6.sin6_scope_id = 0;
1790 }
1791 else
1792 continue;
Simon Kelley849a8352006-06-09 21:02:31 +01001793 }
Simon Kelley7de060b2011-08-26 17:24:52 +01001794
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001795 add_update_server(SERV_FROM_RESOLV, &addr, &source_addr, NULL, NULL);
Simon Kelley849a8352006-06-09 21:02:31 +01001796 gotone = 1;
1797 }
1798
Simon Kelley849a8352006-06-09 21:02:31 +01001799 fclose(f);
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001800 cleanup_servers();
Simon Kelley849a8352006-06-09 21:02:31 +01001801
1802 return gotone;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001803}
1804
Simon Kelley1ee9be42013-12-09 16:50:19 +00001805/* Called when addresses are added or deleted from an interface */
1806void newaddress(time_t now)
1807{
1808 (void)now;
1809
Simon Kelley89b12ed2014-03-06 13:27:57 +00001810 if (option_bool(OPT_CLEVERBIND) || option_bool(OPT_LOCAL_SERVICE) ||
1811 daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
Simon Kelley1ee9be42013-12-09 16:50:19 +00001812 enumerate_interfaces(0);
1813
1814 if (option_bool(OPT_CLEVERBIND))
1815 create_bound_listeners(0);
1816
1817#ifdef HAVE_DHCP6
1818 if (daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
1819 join_multicast(0);
1820
1821 if (daemon->doing_dhcp6 || daemon->doing_ra)
1822 dhcp_construct_contexts(now);
1823
1824 if (daemon->doing_dhcp6)
1825 lease_find_interfaces(now);
1826#endif
1827}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001828
1829
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001830
1831
1832