blob: 1af4dbc2bcf1ac5e388e5b71bd32e4b2e1854f74 [file] [log] [blame]
Simon Kelleyd1ced3a2018-01-01 22:18:03 +00001/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
Simon Kelley824af852008-02-12 20:43:05 +00005 the Free Software Foundation; version 2 dated June, 1991, or
6 (at your option) version 3 dated 29 June, 2007.
7
Simon Kelley9e4abcb2004-01-22 19:47:41 +00008 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
Simon Kelley824af852008-02-12 20:43:05 +000012
Simon Kelley73a08a22009-02-05 20:28:08 +000013 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>.
Simon Kelley9e4abcb2004-01-22 19:47:41 +000015*/
16
Simon Kelley9e4abcb2004-01-22 19:47:41 +000017#include "dnsmasq.h"
18
Simon Kelley7622fc02009-06-04 20:32:05 +010019#ifdef HAVE_LINUX_NETWORK
20
21int indextoname(int fd, int index, char *name)
22{
23 struct ifreq ifr;
24
25 if (index == 0)
26 return 0;
27
28 ifr.ifr_ifindex = index;
29 if (ioctl(fd, SIOCGIFNAME, &ifr) == -1)
30 return 0;
31
32 strncpy(name, ifr.ifr_name, IF_NAMESIZE);
33
34 return 1;
35}
36
Simon Kelley28866e92011-02-14 20:19:14 +000037
38#elif defined(HAVE_SOLARIS_NETWORK)
39
40#include <zone.h>
41#include <alloca.h>
42#ifndef LIFC_UNDER_IPMP
43# define LIFC_UNDER_IPMP 0
44#endif
45
46int indextoname(int fd, int index, char *name)
47{
48 int64_t lifc_flags;
49 struct lifnum lifn;
50 int numifs, bufsize, i;
51 struct lifconf lifc;
52 struct lifreq *lifrp;
53
54 if (index == 0)
55 return 0;
56
57 if (getzoneid() == GLOBAL_ZONEID)
58 {
59 if (!if_indextoname(index, name))
60 return 0;
61 return 1;
62 }
63
64 lifc_flags = LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES | LIFC_UNDER_IPMP;
65 lifn.lifn_family = AF_UNSPEC;
66 lifn.lifn_flags = lifc_flags;
67 if (ioctl(fd, SIOCGLIFNUM, &lifn) < 0)
68 return 0;
69
70 numifs = lifn.lifn_count;
71 bufsize = numifs * sizeof(struct lifreq);
72
73 lifc.lifc_family = AF_UNSPEC;
74 lifc.lifc_flags = lifc_flags;
75 lifc.lifc_len = bufsize;
76 lifc.lifc_buf = alloca(bufsize);
77
78 if (ioctl(fd, SIOCGLIFCONF, &lifc) < 0)
79 return 0;
80
81 lifrp = lifc.lifc_req;
82 for (i = lifc.lifc_len / sizeof(struct lifreq); i; i--, lifrp++)
83 {
84 struct lifreq lifr;
85 strncpy(lifr.lifr_name, lifrp->lifr_name, IF_NAMESIZE);
86 if (ioctl(fd, SIOCGLIFINDEX, &lifr) < 0)
87 return 0;
88
89 if (lifr.lifr_index == index) {
90 strncpy(name, lifr.lifr_name, IF_NAMESIZE);
91 return 1;
92 }
93 }
94 return 0;
95}
96
97
Simon Kelley7622fc02009-06-04 20:32:05 +010098#else
99
100int indextoname(int fd, int index, char *name)
101{
Simon Kelley115ac3e2013-05-20 11:28:32 +0100102 (void)fd;
103
Simon Kelley7622fc02009-06-04 20:32:05 +0100104 if (index == 0 || !if_indextoname(index, name))
105 return 0;
106
107 return 1;
108}
109
110#endif
111
Simon Kelley4f7b3042012-11-28 21:27:02 +0000112int iface_check(int family, struct all_addr *addr, char *name, int *auth)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000113{
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000114 struct iname *tmp;
Simon Kelleyedf0bde2013-07-29 17:21:48 +0100115 int ret = 1, match_addr = 0;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100116
Simon Kelley309331f2006-04-22 15:05:01 +0100117 /* Note: have to check all and not bail out early, so that we set the
Simon Kelley89500e32013-09-20 16:29:20 +0100118 "used" flags.
119
120 May be called with family == AF_LOCALto check interface by name only. */
Simon Kelley429798f2012-12-10 20:45:53 +0000121
Simon Kelley4f7b3042012-11-28 21:27:02 +0000122 if (auth)
Simon Kelley429798f2012-12-10 20:45:53 +0000123 *auth = 0;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100124
Simon Kelleyc72daea2012-01-05 21:33:27 +0000125 if (daemon->if_names || daemon->if_addrs)
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100126 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100127 ret = 0;
128
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100129 for (tmp = daemon->if_names; tmp; tmp = tmp->next)
Simon Kelley49333cb2013-03-15 20:30:51 +0000130 if (tmp->name && wildcard_match(tmp->name, name))
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100131 ret = tmp->used = 1;
132
Simon Kelley429798f2012-12-10 20:45:53 +0000133 if (addr)
134 for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
135 if (tmp->addr.sa.sa_family == family)
136 {
137 if (family == AF_INET &&
138 tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
Simon Kelleyedf0bde2013-07-29 17:21:48 +0100139 ret = match_addr = tmp->used = 1;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100140#ifdef HAVE_IPV6
Simon Kelley429798f2012-12-10 20:45:53 +0000141 else if (family == AF_INET6 &&
142 IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr,
143 &addr->addr.addr6))
Simon Kelleyedf0bde2013-07-29 17:21:48 +0100144 ret = match_addr = tmp->used = 1;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100145#endif
Simon Kelley429798f2012-12-10 20:45:53 +0000146 }
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100147 }
148
Simon Kelleyedf0bde2013-07-29 17:21:48 +0100149 if (!match_addr)
150 for (tmp = daemon->if_except; tmp; tmp = tmp->next)
151 if (tmp->name && wildcard_match(tmp->name, name))
152 ret = 0;
Simon Kelleyc72daea2012-01-05 21:33:27 +0000153
Simon Kelley429798f2012-12-10 20:45:53 +0000154
155 for (tmp = daemon->authinterface; tmp; tmp = tmp->next)
156 if (tmp->name)
157 {
Simon Kelleyf25e6c62013-11-17 12:23:42 +0000158 if (strcmp(tmp->name, name) == 0 &&
159 (tmp->addr.sa.sa_family == 0 || tmp->addr.sa.sa_family == family))
Simon Kelley429798f2012-12-10 20:45:53 +0000160 break;
161 }
162 else if (addr && tmp->addr.sa.sa_family == AF_INET && family == AF_INET &&
163 tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
164 break;
165#ifdef HAVE_IPV6
166 else if (addr && tmp->addr.sa.sa_family == AF_INET6 && family == AF_INET6 &&
167 IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, &addr->addr.addr6))
168 break;
169#endif
170
171 if (tmp && auth)
172 {
173 *auth = 1;
174 ret = 1;
175 }
176
Simon Kelley309331f2006-04-22 15:05:01 +0100177 return ret;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100178}
Simon Kelleye25db1f2013-01-29 22:10:26 +0000179
180
Josh Soref730c6742017-02-06 16:14:04 +0000181/* Fix for problem that the kernel sometimes reports the loopback interface as the
Simon Kelleye25db1f2013-01-29 22:10:26 +0000182 arrival interface when a packet originates locally, even when sent to address of
183 an interface other than the loopback. Accept packet if it arrived via a loopback
184 interface, even when we're not accepting packets that way, as long as the destination
185 address is one we're believing. Interface list must be up-to-date before calling. */
186int loopback_exception(int fd, int family, struct all_addr *addr, char *name)
187{
188 struct ifreq ifr;
189 struct irec *iface;
190
191 strncpy(ifr.ifr_name, name, IF_NAMESIZE);
192 if (ioctl(fd, SIOCGIFFLAGS, &ifr) != -1 &&
193 ifr.ifr_flags & IFF_LOOPBACK)
194 {
195 for (iface = daemon->interfaces; iface; iface = iface->next)
196 if (iface->addr.sa.sa_family == family)
197 {
198 if (family == AF_INET)
199 {
200 if (iface->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
201 return 1;
202 }
203#ifdef HAVE_IPV6
204 else if (IN6_ARE_ADDR_EQUAL(&iface->addr.in6.sin6_addr, &addr->addr.addr6))
205 return 1;
206#endif
207
208 }
209 }
210 return 0;
211}
212
Simon Kelley3f2873d2013-05-14 11:28:47 +0100213/* If we're configured with something like --interface=eth0:0 then we'll listen correctly
214 on the relevant address, but the name of the arrival interface, derived from the
215 index won't match the config. Check that we found an interface address for the arrival
216 interface: daemon->interfaces must be up-to-date. */
217int label_exception(int index, int family, struct all_addr *addr)
218{
219 struct irec *iface;
220
221 /* labels only supported on IPv4 addresses. */
222 if (family != AF_INET)
223 return 0;
224
225 for (iface = daemon->interfaces; iface; iface = iface->next)
226 if (iface->index == index && iface->addr.sa.sa_family == AF_INET &&
227 iface->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
228 return 1;
229
230 return 0;
231}
232
Simon Kelley115ac3e2013-05-20 11:28:32 +0100233struct iface_param {
234 struct addrlist *spare;
235 int fd;
236};
237
238static int iface_allowed(struct iface_param *param, int if_index, char *label,
Simon Kelley47669362014-12-17 12:41:56 +0000239 union mysockaddr *addr, struct in_addr netmask, int prefixlen, int iface_flags)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100240{
241 struct irec *iface;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100242 int mtu = 0, loopback;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100243 struct ifreq ifr;
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100244 int tftp_ok = !!option_bool(OPT_TFTP);
Simon Kelley9380ba72012-04-16 14:41:56 +0100245 int dhcp_ok = 1;
Simon Kelley4f7b3042012-11-28 21:27:02 +0000246 int auth_dns = 0;
Petr Menšíkad59f272017-03-17 17:22:19 +0000247 int is_label = 0;
Simon Kelley91543f42013-09-23 12:41:20 +0100248#if defined(HAVE_DHCP) || defined(HAVE_TFTP)
Simon Kelley832af0b2007-01-21 20:01:28 +0000249 struct iname *tmp;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100250#endif
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100251
Vladislav Grishenko3b195962013-11-26 11:08:21 +0000252 (void)prefixlen;
253
Simon Kelley115ac3e2013-05-20 11:28:32 +0100254 if (!indextoname(param->fd, if_index, ifr.ifr_name) ||
255 ioctl(param->fd, SIOCGIFFLAGS, &ifr) == -1)
256 return 0;
Simon Kelley1f15b812009-10-13 17:49:32 +0100257
258 loopback = ifr.ifr_flags & IFF_LOOPBACK;
Simon Kelley9380ba72012-04-16 14:41:56 +0100259
260 if (loopback)
Simon Kelley3f2873d2013-05-14 11:28:47 +0100261 dhcp_ok = 0;
262
Simon Kelley115ac3e2013-05-20 11:28:32 +0100263 if (ioctl(param->fd, SIOCGIFMTU, &ifr) != -1)
Simon Kelley1f15b812009-10-13 17:49:32 +0100264 mtu = ifr.ifr_mtu;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100265
Simon Kelley115ac3e2013-05-20 11:28:32 +0100266 if (!label)
267 label = ifr.ifr_name;
Petr Menšíkad59f272017-03-17 17:22:19 +0000268 else
269 is_label = strcmp(label, ifr.ifr_name);
Simon Kelleyc8a80482014-03-05 14:29:54 +0000270
271 /* maintain a list of all addresses on all interfaces for --local-service option */
272 if (option_bool(OPT_LOCAL_SERVICE))
273 {
274 struct addrlist *al;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100275
Simon Kelleyc8a80482014-03-05 14:29:54 +0000276 if (param->spare)
277 {
278 al = param->spare;
279 param->spare = al->next;
280 }
281 else
282 al = whine_malloc(sizeof(struct addrlist));
283
284 if (al)
285 {
286 al->next = daemon->interface_addrs;
287 daemon->interface_addrs = al;
288 al->prefixlen = prefixlen;
289
290 if (addr->sa.sa_family == AF_INET)
291 {
292 al->addr.addr.addr4 = addr->in.sin_addr;
293 al->flags = 0;
294 }
295#ifdef HAVE_IPV6
296 else
297 {
298 al->addr.addr.addr6 = addr->in6.sin6_addr;
299 al->flags = ADDRLIST_IPV6;
300 }
301#endif
302 }
303 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000304
Simon Kelley115ac3e2013-05-20 11:28:32 +0100305#ifdef HAVE_IPV6
306 if (addr->sa.sa_family != AF_INET6 || !IN6_IS_ADDR_LINKLOCAL(&addr->in6.sin6_addr))
307#endif
308 {
309 struct interface_name *int_name;
310 struct addrlist *al;
Simon Kelley376d48c2013-11-13 13:04:30 +0000311#ifdef HAVE_AUTH
312 struct auth_zone *zone;
313 struct auth_name_list *name;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100314
Simon Kelley376d48c2013-11-13 13:04:30 +0000315 /* Find subnets in auth_zones */
316 for (zone = daemon->auth_zones; zone; zone = zone->next)
317 for (name = zone->interface_names; name; name = name->next)
318 if (wildcard_match(name->name, label))
319 {
320 if (addr->sa.sa_family == AF_INET && (name->flags & AUTH4))
321 {
322 if (param->spare)
323 {
324 al = param->spare;
325 param->spare = al->next;
326 }
327 else
328 al = whine_malloc(sizeof(struct addrlist));
329
330 if (al)
331 {
332 al->next = zone->subnet;
333 zone->subnet = al;
334 al->prefixlen = prefixlen;
335 al->addr.addr.addr4 = addr->in.sin_addr;
336 al->flags = 0;
337 }
338 }
339
340#ifdef HAVE_IPV6
341 if (addr->sa.sa_family == AF_INET6 && (name->flags & AUTH6))
342 {
343 if (param->spare)
344 {
345 al = param->spare;
346 param->spare = al->next;
347 }
348 else
349 al = whine_malloc(sizeof(struct addrlist));
350
351 if (al)
352 {
353 al->next = zone->subnet;
354 zone->subnet = al;
Vladislav Grishenko3b195962013-11-26 11:08:21 +0000355 al->prefixlen = prefixlen;
356 al->addr.addr.addr6 = addr->in6.sin6_addr;
Simon Kelley376d48c2013-11-13 13:04:30 +0000357 al->flags = ADDRLIST_IPV6;
358 }
359 }
360#endif
361
362 }
363#endif
364
365 /* Update addresses from interface_names. These are a set independent
366 of the set we're listening on. */
Simon Kelley115ac3e2013-05-20 11:28:32 +0100367 for (int_name = daemon->int_names; int_name; int_name = int_name->next)
Simon Kelleyf7029f52013-11-21 15:09:09 +0000368 if (strncmp(label, int_name->intr, IF_NAMESIZE) == 0 &&
369 (addr->sa.sa_family == int_name->family || int_name->family == 0))
Simon Kelley115ac3e2013-05-20 11:28:32 +0100370 {
371 if (param->spare)
372 {
373 al = param->spare;
374 param->spare = al->next;
375 }
376 else
377 al = whine_malloc(sizeof(struct addrlist));
378
379 if (al)
380 {
Simon Kelley376d48c2013-11-13 13:04:30 +0000381 al->next = int_name->addr;
382 int_name->addr = al;
383
Simon Kelley115ac3e2013-05-20 11:28:32 +0100384 if (addr->sa.sa_family == AF_INET)
385 {
386 al->addr.addr.addr4 = addr->in.sin_addr;
Simon Kelley376d48c2013-11-13 13:04:30 +0000387 al->flags = 0;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100388 }
389#ifdef HAVE_IPV6
390 else
391 {
392 al->addr.addr.addr6 = addr->in6.sin6_addr;
Simon Kelley376d48c2013-11-13 13:04:30 +0000393 al->flags = ADDRLIST_IPV6;
Simon Kelley47669362014-12-17 12:41:56 +0000394 /* Privacy addresses and addresses still undergoing DAD and deprecated addresses
395 don't appear in forward queries, but will in reverse ones. */
396 if (!(iface_flags & IFACE_PERMANENT) || (iface_flags & (IFACE_DEPRECATED | IFACE_TENTATIVE)))
397 al->flags |= ADDRLIST_REVONLY;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100398 }
399#endif
400 }
401 }
402 }
403
404 /* check whether the interface IP has been added already
405 we call this routine multiple times. */
406 for (iface = daemon->interfaces; iface; iface = iface->next)
407 if (sockaddr_isequal(&iface->addr, addr))
408 {
Simon Kelley47669362014-12-17 12:41:56 +0000409 iface->dad = !!(iface_flags & IFACE_TENTATIVE);
Simon Kelley08619212013-12-02 14:43:48 +0000410 iface->found = 1; /* for garbage collection */
Simon Kelley115ac3e2013-05-20 11:28:32 +0100411 return 1;
412 }
413
414 /* If we are restricting the set of interfaces to use, make
Simon Kelley59353a62004-11-21 19:34:28 +0000415 sure that loopback interfaces are in that set. */
Simon Kelley1f15b812009-10-13 17:49:32 +0100416 if (daemon->if_names && loopback)
Simon Kelley59353a62004-11-21 19:34:28 +0000417 {
418 struct iname *lo;
419 for (lo = daemon->if_names; lo; lo = lo->next)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100420 if (lo->name && strcmp(lo->name, ifr.ifr_name) == 0)
Simon Kelley4ce4f372012-06-14 11:50:45 +0100421 break;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100422
Simon Kelley38365ff2013-02-05 14:35:54 +0000423 if (!lo && (lo = whine_malloc(sizeof(struct iname))))
Simon Kelley59353a62004-11-21 19:34:28 +0000424 {
Simon Kelley38365ff2013-02-05 14:35:54 +0000425 if ((lo->name = whine_malloc(strlen(ifr.ifr_name)+1)))
426 {
427 strcpy(lo->name, ifr.ifr_name);
428 lo->used = 1;
429 lo->next = daemon->if_names;
430 daemon->if_names = lo;
431 }
432 else
433 free(lo);
Simon Kelley59353a62004-11-21 19:34:28 +0000434 }
435 }
436
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100437 if (addr->sa.sa_family == AF_INET &&
Simon Kelley3f2873d2013-05-14 11:28:47 +0100438 !iface_check(AF_INET, (struct all_addr *)&addr->in.sin_addr, label, &auth_dns))
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100439 return 1;
Simon Kelley4f7b3042012-11-28 21:27:02 +0000440
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100441#ifdef HAVE_IPV6
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100442 if (addr->sa.sa_family == AF_INET6 &&
Simon Kelley3f2873d2013-05-14 11:28:47 +0100443 !iface_check(AF_INET6, (struct all_addr *)&addr->in6.sin6_addr, label, &auth_dns))
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100444 return 1;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100445#endif
Simon Kelley4f7b3042012-11-28 21:27:02 +0000446
447#ifdef HAVE_DHCP
448 /* No DHCP where we're doing auth DNS. */
449 if (auth_dns)
450 {
451 tftp_ok = 0;
452 dhcp_ok = 0;
453 }
454 else
455 for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
Simon Kelley49333cb2013-03-15 20:30:51 +0000456 if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
Simon Kelley4f7b3042012-11-28 21:27:02 +0000457 {
458 tftp_ok = 0;
459 dhcp_ok = 0;
460 }
461#endif
462
Simon Kelley2937f8a2013-07-29 19:49:07 +0100463
Simon Kelley91543f42013-09-23 12:41:20 +0100464#ifdef HAVE_TFTP
Simon Kelley2937f8a2013-07-29 19:49:07 +0100465 if (daemon->tftp_interfaces)
466 {
467 /* dedicated tftp interface list */
468 tftp_ok = 0;
469 for (tmp = daemon->tftp_interfaces; tmp; tmp = tmp->next)
470 if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
471 tftp_ok = 1;
472 }
Simon Kelley91543f42013-09-23 12:41:20 +0100473#endif
Simon Kelley2937f8a2013-07-29 19:49:07 +0100474
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100475 /* add to list */
Simon Kelley5aabfc72007-08-29 11:24:47 +0100476 if ((iface = whine_malloc(sizeof(struct irec))))
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100477 {
478 iface->addr = *addr;
479 iface->netmask = netmask;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100480 iface->tftp_ok = tftp_ok;
Simon Kelley9380ba72012-04-16 14:41:56 +0100481 iface->dhcp_ok = dhcp_ok;
Simon Kelley4f7b3042012-11-28 21:27:02 +0000482 iface->dns_auth = auth_dns;
Simon Kelley1f15b812009-10-13 17:49:32 +0100483 iface->mtu = mtu;
Simon Kelley47669362014-12-17 12:41:56 +0000484 iface->dad = !!(iface_flags & IFACE_TENTATIVE);
Simon Kelley08619212013-12-02 14:43:48 +0000485 iface->found = 1;
Simon Kelleydc27e142013-10-16 13:09:53 +0100486 iface->done = iface->multicast_done = iface->warned = 0;
Simon Kelley5d162f22012-12-20 14:55:46 +0000487 iface->index = if_index;
Petr Menšíkad59f272017-03-17 17:22:19 +0000488 iface->label = is_label;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100489 if ((iface->name = whine_malloc(strlen(ifr.ifr_name)+1)))
Simon Kelley6f13e532012-04-17 14:25:06 +0100490 {
491 strcpy(iface->name, ifr.ifr_name);
Simon Kelley115ac3e2013-05-20 11:28:32 +0100492 iface->next = daemon->interfaces;
493 daemon->interfaces = iface;
Simon Kelley6f13e532012-04-17 14:25:06 +0100494 return 1;
495 }
496 free(iface);
Simon Kelley5d162f22012-12-20 14:55:46 +0000497
Simon Kelley44a2a312004-03-10 20:04:35 +0000498 }
499
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100500 errno = ENOMEM;
501 return 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000502}
503
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100504#ifdef HAVE_IPV6
Simon Kelleyc72daea2012-01-05 21:33:27 +0000505static int iface_allowed_v6(struct in6_addr *local, int prefix,
Simon Kelleybad7b872012-12-20 22:00:39 +0000506 int scope, int if_index, int flags,
Simon Kelley1f776932012-12-16 19:46:08 +0000507 int preferred, int valid, void *vparam)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000508{
Simon Kelley59353a62004-11-21 19:34:28 +0000509 union mysockaddr addr;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100510 struct in_addr netmask; /* dummy */
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100511 netmask.s_addr = 0;
Simon Kelley52b92f42012-01-22 16:05:15 +0000512
Simon Kelley52b92f42012-01-22 16:05:15 +0000513 (void)scope; /* warning */
Simon Kelley1f776932012-12-16 19:46:08 +0000514 (void)preferred;
515 (void)valid;
Simon Kelley44a2a312004-03-10 20:04:35 +0000516
Simon Kelley849a8352006-06-09 21:02:31 +0100517 memset(&addr, 0, sizeof(addr));
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000518#ifdef HAVE_SOCKADDR_SA_LEN
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100519 addr.in6.sin6_len = sizeof(addr.in6);
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000520#endif
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100521 addr.in6.sin6_family = AF_INET6;
522 addr.in6.sin6_addr = *local;
523 addr.in6.sin6_port = htons(daemon->port);
Simon Kelley62ab3cc2013-12-03 11:53:53 +0000524 /* FreeBSD insists this is zero for non-linklocal addresses */
525 if (IN6_IS_ADDR_LINKLOCAL(local))
526 addr.in6.sin6_scope_id = if_index;
527 else
528 addr.in6.sin6_scope_id = 0;
Simon Kelley1ee9be42013-12-09 16:50:19 +0000529
Simon Kelley47669362014-12-17 12:41:56 +0000530 return iface_allowed((struct iface_param *)vparam, if_index, NULL, &addr, netmask, prefix, flags);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100531}
532#endif
Simon Kelley59353a62004-11-21 19:34:28 +0000533
Simon Kelley3f2873d2013-05-14 11:28:47 +0100534static int iface_allowed_v4(struct in_addr local, int if_index, char *label,
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100535 struct in_addr netmask, struct in_addr broadcast, void *vparam)
536{
537 union mysockaddr addr;
Simon Kelley376d48c2013-11-13 13:04:30 +0000538 int prefix, bit;
Simon Kelleyb8ac4662016-03-10 18:40:53 +0000539
540 (void)broadcast; /* warning */
Simon Kelley849a8352006-06-09 21:02:31 +0100541
542 memset(&addr, 0, sizeof(addr));
Simon Kelley1ab84e22004-01-29 16:48:35 +0000543#ifdef HAVE_SOCKADDR_SA_LEN
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100544 addr.in.sin_len = sizeof(addr.in);
Simon Kelley1ab84e22004-01-29 16:48:35 +0000545#endif
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100546 addr.in.sin_family = AF_INET;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100547 addr.in.sin_addr = local;
548 addr.in.sin_port = htons(daemon->port);
Simon Kelley44a2a312004-03-10 20:04:35 +0000549
Simon Kelley376d48c2013-11-13 13:04:30 +0000550 /* determine prefix length from netmask */
551 for (prefix = 32, bit = 1; (bit & ntohl(netmask.s_addr)) == 0 && prefix != 0; bit = bit << 1, prefix--);
552
553 return iface_allowed((struct iface_param *)vparam, if_index, label, &addr, netmask, prefix, 0);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100554}
555
Simon Kelley115ac3e2013-05-20 11:28:32 +0100556int enumerate_interfaces(int reset)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100557{
Simon Kelley115ac3e2013-05-20 11:28:32 +0100558 static struct addrlist *spare = NULL;
Simon Kelleya0358e52014-06-07 13:38:48 +0100559 static int done = 0;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100560 struct iface_param param;
561 int errsave, ret = 1;
562 struct addrlist *addr, *tmp;
563 struct interface_name *intname;
Simon Kelley08619212013-12-02 14:43:48 +0000564 struct irec *iface;
Simon Kelley376d48c2013-11-13 13:04:30 +0000565#ifdef HAVE_AUTH
566 struct auth_zone *zone;
567#endif
568
Simon Kelley76dd75d2013-05-23 10:04:25 +0100569 /* Do this max once per select cycle - also inhibits netlink socket use
570 in TCP child processes. */
Simon Kelley397542b2013-09-05 11:27:34 +0100571
Simon Kelley115ac3e2013-05-20 11:28:32 +0100572 if (reset)
573 {
574 done = 0;
575 return 1;
576 }
577
Simon Kelleya0358e52014-06-07 13:38:48 +0100578 if (done)
Simon Kelley115ac3e2013-05-20 11:28:32 +0100579 return 1;
580
581 done = 1;
582
583 if ((param.fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
584 return 0;
585
Simon Kelley08619212013-12-02 14:43:48 +0000586 /* Mark interfaces for garbage collection */
587 for (iface = daemon->interfaces; iface; iface = iface->next)
588 iface->found = 0;
589
Simon Kelley115ac3e2013-05-20 11:28:32 +0100590 /* remove addresses stored against interface_names */
591 for (intname = daemon->int_names; intname; intname = intname->next)
592 {
Simon Kelley376d48c2013-11-13 13:04:30 +0000593 for (addr = intname->addr; addr; addr = tmp)
Simon Kelley115ac3e2013-05-20 11:28:32 +0100594 {
595 tmp = addr->next;
596 addr->next = spare;
597 spare = addr;
598 }
599
Simon Kelley376d48c2013-11-13 13:04:30 +0000600 intname->addr = NULL;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100601 }
Simon Kelley376d48c2013-11-13 13:04:30 +0000602
Simon Kelleyc8a80482014-03-05 14:29:54 +0000603 /* Remove list of addresses of local interfaces */
604 for (addr = daemon->interface_addrs; addr; addr = tmp)
605 {
606 tmp = addr->next;
607 addr->next = spare;
608 spare = addr;
609 }
610 daemon->interface_addrs = NULL;
611
Simon Kelley376d48c2013-11-13 13:04:30 +0000612#ifdef HAVE_AUTH
613 /* remove addresses stored against auth_zone subnets, but not
614 ones configured as address literals */
615 for (zone = daemon->auth_zones; zone; zone = zone->next)
616 if (zone->interface_names)
617 {
618 struct addrlist **up;
619 for (up = &zone->subnet, addr = zone->subnet; addr; addr = tmp)
620 {
621 tmp = addr->next;
622 if (addr->flags & ADDRLIST_LITERAL)
623 up = &addr->next;
624 else
625 {
626 *up = addr->next;
627 addr->next = spare;
628 spare = addr;
629 }
630 }
631 }
632#endif
633
Simon Kelley115ac3e2013-05-20 11:28:32 +0100634 param.spare = spare;
635
636#ifdef HAVE_IPV6
637 ret = iface_enumerate(AF_INET6, &param, iface_allowed_v6);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100638#endif
Simon Kelley28866e92011-02-14 20:19:14 +0000639
Simon Kelley115ac3e2013-05-20 11:28:32 +0100640 if (ret)
641 ret = iface_enumerate(AF_INET, &param, iface_allowed_v4);
642
643 errsave = errno;
644 close(param.fd);
Simon Kelley08619212013-12-02 14:43:48 +0000645
646 if (option_bool(OPT_CLEVERBIND))
647 {
648 /* Garbage-collect listeners listening on addresses that no longer exist.
649 Does nothing when not binding interfaces or for listeners on localhost,
650 since the ->iface field is NULL. Note that this needs the protections
Josh Soref730c6742017-02-06 16:14:04 +0000651 against reentrancy, hence it's here. It also means there's a possibility,
Simon Kelley08619212013-12-02 14:43:48 +0000652 in OPT_CLEVERBIND mode, that at listener will just disappear after
653 a call to enumerate_interfaces, this is checked OK on all calls. */
654 struct listener *l, *tmp, **up;
655
656 for (up = &daemon->listeners, l = daemon->listeners; l; l = tmp)
657 {
658 tmp = l->next;
659
660 if (!l->iface || l->iface->found)
661 up = &l->next;
662 else
663 {
664 *up = l->next;
665
666 /* In case it ever returns */
667 l->iface->done = 0;
668
669 if (l->fd != -1)
670 close(l->fd);
671 if (l->tcpfd != -1)
672 close(l->tcpfd);
673 if (l->tftpfd != -1)
674 close(l->tftpfd);
675
676 free(l);
677 }
678 }
679 }
680
Simon Kelley115ac3e2013-05-20 11:28:32 +0100681 errno = errsave;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100682 spare = param.spare;
Simon Kelleya0358e52014-06-07 13:38:48 +0100683
Simon Kelley115ac3e2013-05-20 11:28:32 +0100684 return ret;
Simon Kelley44a2a312004-03-10 20:04:35 +0000685}
686
Simon Kelley5aabfc72007-08-29 11:24:47 +0100687/* set NONBLOCK bit on fd: See Stevens 16.6 */
Simon Kelley7cebd202006-05-06 14:13:33 +0100688int fix_fd(int fd)
689{
690 int flags;
691
692 if ((flags = fcntl(fd, F_GETFL)) == -1 ||
Simon Kelley5aabfc72007-08-29 11:24:47 +0100693 fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
Simon Kelley7cebd202006-05-06 14:13:33 +0100694 return 0;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100695
Simon Kelley7cebd202006-05-06 14:13:33 +0100696 return 1;
697}
698
Simon Kelley74c95c22011-10-19 09:33:39 +0100699static int make_sock(union mysockaddr *addr, int type, int dienow)
Simon Kelley44a2a312004-03-10 20:04:35 +0000700{
Simon Kelley28866e92011-02-14 20:19:14 +0000701 int family = addr->sa.sa_family;
702 int fd, rc, opt = 1;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100703
Simon Kelley28866e92011-02-14 20:19:14 +0000704 if ((fd = socket(family, type, 0)) == -1)
Simon Kelley316e2732010-01-22 20:16:09 +0000705 {
Josh Soref730c6742017-02-06 16:14:04 +0000706 int port, errsave;
Simon Kelley39f1b8e2012-06-20 20:04:27 +0100707 char *s;
Simon Kelley28866e92011-02-14 20:19:14 +0000708
709 /* No error if the kernel just doesn't support this IP flavour */
710 if (errno == EPROTONOSUPPORT ||
711 errno == EAFNOSUPPORT ||
712 errno == EINVAL)
713 return -1;
714
715 err:
Josh Soref730c6742017-02-06 16:14:04 +0000716 errsave = errno;
Simon Kelley39f1b8e2012-06-20 20:04:27 +0100717 port = prettyprint_addr(addr, daemon->addrbuff);
718 if (!option_bool(OPT_NOWILD) && !option_bool(OPT_CLEVERBIND))
719 sprintf(daemon->addrbuff, "port %d", port);
720 s = _("failed to create listening socket for %s: %s");
721
Simon Kelley5f11b3e2012-08-16 14:04:05 +0100722 if (fd != -1)
Matthias Andree71aaa5a2013-12-03 11:20:45 +0000723 close (fd);
724
Josh Soref730c6742017-02-06 16:14:04 +0000725 errno = errsave;
Simon Kelley1ee9be42013-12-09 16:50:19 +0000726
Simon Kelley5f11b3e2012-08-16 14:04:05 +0100727 if (dienow)
728 {
729 /* failure to bind addresses given by --listen-address at this point
730 is OK if we're doing bind-dynamic */
731 if (!option_bool(OPT_CLEVERBIND))
732 die(s, daemon->addrbuff, EC_BADNET);
733 }
734 else
735 my_syslog(LOG_WARNING, s, daemon->addrbuff, strerror(errno));
736
Simon Kelley74c95c22011-10-19 09:33:39 +0100737 return -1;
Simon Kelley28866e92011-02-14 20:19:14 +0000738 }
Simon Kelley5f11b3e2012-08-16 14:04:05 +0100739
Simon Kelley28866e92011-02-14 20:19:14 +0000740 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || !fix_fd(fd))
741 goto err;
742
743#ifdef HAVE_IPV6
Simon Kelleyc72daea2012-01-05 21:33:27 +0000744 if (family == AF_INET6 && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)) == -1)
Simon Kelley28866e92011-02-14 20:19:14 +0000745 goto err;
746#endif
747
Simon Kelley74c95c22011-10-19 09:33:39 +0100748 if ((rc = bind(fd, (struct sockaddr *)addr, sa_len(addr))) == -1)
Simon Kelley28866e92011-02-14 20:19:14 +0000749 goto err;
750
751 if (type == SOCK_STREAM)
752 {
Simon Kelley09b768e2016-12-22 22:16:58 +0000753 if (listen(fd, TCP_BACKLOG) == -1)
Simon Kelley28866e92011-02-14 20:19:14 +0000754 goto err;
755 }
Simon Kelley2329bef2013-12-03 13:41:16 +0000756 else if (family == AF_INET)
Simon Kelley28866e92011-02-14 20:19:14 +0000757 {
Simon Kelley2329bef2013-12-03 13:41:16 +0000758 if (!option_bool(OPT_NOWILD))
Simon Kelley28866e92011-02-14 20:19:14 +0000759 {
760#if defined(HAVE_LINUX_NETWORK)
Simon Kelleyc72daea2012-01-05 21:33:27 +0000761 if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) == -1)
Simon Kelley28866e92011-02-14 20:19:14 +0000762 goto err;
763#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
764 if (setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt)) == -1 ||
765 setsockopt(fd, IPPROTO_IP, IP_RECVIF, &opt, sizeof(opt)) == -1)
766 goto err;
767#endif
768 }
Simon Kelley28866e92011-02-14 20:19:14 +0000769 }
Simon Kelley2329bef2013-12-03 13:41:16 +0000770#ifdef HAVE_IPV6
771 else if (!set_ipv6pktinfo(fd))
772 goto err;
773#endif
Simon Kelleyc72daea2012-01-05 21:33:27 +0000774
Simon Kelley28866e92011-02-14 20:19:14 +0000775 return fd;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100776}
Simon Kelleyc72daea2012-01-05 21:33:27 +0000777
778#ifdef HAVE_IPV6
779int set_ipv6pktinfo(int fd)
780{
781 int opt = 1;
782
783 /* The API changed around Linux 2.6.14 but the old ABI is still supported:
784 handle all combinations of headers and kernel.
785 OpenWrt note that this fixes the problem addressed by your very broken patch. */
786 daemon->v6pktinfo = IPV6_PKTINFO;
787
788#ifdef IPV6_RECVPKTINFO
789 if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &opt, sizeof(opt)) != -1)
790 return 1;
791# ifdef IPV6_2292PKTINFO
792 else if (errno == ENOPROTOOPT && setsockopt(fd, IPPROTO_IPV6, IPV6_2292PKTINFO, &opt, sizeof(opt)) != -1)
793 {
794 daemon->v6pktinfo = IPV6_2292PKTINFO;
795 return 1;
796 }
797# endif
798#else
799 if (setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &opt, sizeof(opt)) != -1)
800 return 1;
801#endif
802
803 return 0;
804}
805#endif
Simon Kelley22ce5502013-01-22 13:53:04 +0000806
807
808/* Find the interface on which a TCP connection arrived, if possible, or zero otherwise. */
809int tcp_interface(int fd, int af)
810{
811 int if_index = 0;
812
813#ifdef HAVE_LINUX_NETWORK
814 int opt = 1;
815 struct cmsghdr *cmptr;
816 struct msghdr msg;
Simon Kelley529b0302016-03-16 19:00:45 +0000817 socklen_t len;
Simon Kelley22ce5502013-01-22 13:53:04 +0000818
Simon Kelley529b0302016-03-16 19:00:45 +0000819 /* use mshdr so that the CMSDG_* macros are available */
Simon Kelley22ce5502013-01-22 13:53:04 +0000820 msg.msg_control = daemon->packet;
Simon Kelley529b0302016-03-16 19:00:45 +0000821 msg.msg_controllen = len = daemon->packet_buff_sz;
Simon Kelley22ce5502013-01-22 13:53:04 +0000822
823 /* we overwrote the buffer... */
824 daemon->srv_save = NULL;
825
826 if (af == AF_INET)
827 {
828 if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) != -1 &&
Simon Kelley529b0302016-03-16 19:00:45 +0000829 getsockopt(fd, IPPROTO_IP, IP_PKTOPTIONS, msg.msg_control, &len) != -1)
830 {
831 msg.msg_controllen = len;
832 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
833 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
834 {
835 union {
836 unsigned char *c;
837 struct in_pktinfo *p;
838 } p;
839
840 p.c = CMSG_DATA(cmptr);
841 if_index = p.p->ipi_ifindex;
842 }
843 }
Simon Kelley22ce5502013-01-22 13:53:04 +0000844 }
845#ifdef HAVE_IPV6
846 else
847 {
848 /* Only the RFC-2292 API has the ability to find the interface for TCP connections,
849 it was removed in RFC-3542 !!!!
850
851 Fortunately, Linux kept the 2292 ABI when it moved to 3542. The following code always
852 uses the old ABI, and should work with pre- and post-3542 kernel headers */
853
854#ifdef IPV6_2292PKTOPTIONS
855# define PKTOPTIONS IPV6_2292PKTOPTIONS
856#else
857# define PKTOPTIONS IPV6_PKTOPTIONS
858#endif
859
860 if (set_ipv6pktinfo(fd) &&
Simon Kelley529b0302016-03-16 19:00:45 +0000861 getsockopt(fd, IPPROTO_IPV6, PKTOPTIONS, msg.msg_control, &len) != -1)
Simon Kelley22ce5502013-01-22 13:53:04 +0000862 {
Simon Kelley529b0302016-03-16 19:00:45 +0000863 msg.msg_controllen = len;
864 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
Simon Kelley22ce5502013-01-22 13:53:04 +0000865 if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
866 {
867 union {
868 unsigned char *c;
869 struct in6_pktinfo *p;
870 } p;
871 p.c = CMSG_DATA(cmptr);
872
873 if_index = p.p->ipi6_ifindex;
874 }
875 }
876 }
877#endif /* IPV6 */
878#endif /* Linux */
879
880 return if_index;
881}
Simon Kelley28866e92011-02-14 20:19:14 +0000882
Simon Kelley74c95c22011-10-19 09:33:39 +0100883static struct listener *create_listeners(union mysockaddr *addr, int do_tftp, int dienow)
Simon Kelley28866e92011-02-14 20:19:14 +0000884{
885 struct listener *l = NULL;
886 int fd = -1, tcpfd = -1, tftpfd = -1;
887
Vladislav Grishenko408c3682013-09-24 16:18:49 +0100888 (void)do_tftp;
889
Simon Kelley28866e92011-02-14 20:19:14 +0000890 if (daemon->port != 0)
891 {
Simon Kelley74c95c22011-10-19 09:33:39 +0100892 fd = make_sock(addr, SOCK_DGRAM, dienow);
893 tcpfd = make_sock(addr, SOCK_STREAM, dienow);
Simon Kelley28866e92011-02-14 20:19:14 +0000894 }
895
896#ifdef HAVE_TFTP
897 if (do_tftp)
898 {
899 if (addr->sa.sa_family == AF_INET)
900 {
901 /* port must be restored to DNS port for TCP code */
902 short save = addr->in.sin_port;
903 addr->in.sin_port = htons(TFTP_PORT);
Simon Kelley74c95c22011-10-19 09:33:39 +0100904 tftpfd = make_sock(addr, SOCK_DGRAM, dienow);
Simon Kelley28866e92011-02-14 20:19:14 +0000905 addr->in.sin_port = save;
906 }
907# ifdef HAVE_IPV6
908 else
909 {
910 short save = addr->in6.sin6_port;
911 addr->in6.sin6_port = htons(TFTP_PORT);
Simon Kelley74c95c22011-10-19 09:33:39 +0100912 tftpfd = make_sock(addr, SOCK_DGRAM, dienow);
Simon Kelley28866e92011-02-14 20:19:14 +0000913 addr->in6.sin6_port = save;
914 }
915# endif
916 }
Simon Kelley44a2a312004-03-10 20:04:35 +0000917#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100918
Simon Kelley28866e92011-02-14 20:19:14 +0000919 if (fd != -1 || tcpfd != -1 || tftpfd != -1)
920 {
921 l = safe_malloc(sizeof(struct listener));
922 l->next = NULL;
923 l->family = addr->sa.sa_family;
924 l->fd = fd;
925 l->tcpfd = tcpfd;
Simon Kelley08619212013-12-02 14:43:48 +0000926 l->tftpfd = tftpfd;
927 l->iface = NULL;
Simon Kelley28866e92011-02-14 20:19:14 +0000928 }
929
930 return l;
931}
932
Simon Kelley74c95c22011-10-19 09:33:39 +0100933void create_wildcard_listeners(void)
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100934{
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100935 union mysockaddr addr;
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100936 struct listener *l, *l6;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100937
Simon Kelley849a8352006-06-09 21:02:31 +0100938 memset(&addr, 0, sizeof(addr));
Simon Kelley28866e92011-02-14 20:19:14 +0000939#ifdef HAVE_SOCKADDR_SA_LEN
940 addr.in.sin_len = sizeof(addr.in);
941#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100942 addr.in.sin_family = AF_INET;
943 addr.in.sin_addr.s_addr = INADDR_ANY;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100944 addr.in.sin_port = htons(daemon->port);
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100945
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100946 l = create_listeners(&addr, !!option_bool(OPT_TFTP), 1);
Simon Kelley28866e92011-02-14 20:19:14 +0000947
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100948#ifdef HAVE_IPV6
Simon Kelley28866e92011-02-14 20:19:14 +0000949 memset(&addr, 0, sizeof(addr));
950# ifdef HAVE_SOCKADDR_SA_LEN
951 addr.in6.sin6_len = sizeof(addr.in6);
952# endif
953 addr.in6.sin6_family = AF_INET6;
954 addr.in6.sin6_addr = in6addr_any;
955 addr.in6.sin6_port = htons(daemon->port);
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100956
957 l6 = create_listeners(&addr, !!option_bool(OPT_TFTP), 1);
Simon Kelley28866e92011-02-14 20:19:14 +0000958 if (l)
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100959 l->next = l6;
Simon Kelley28866e92011-02-14 20:19:14 +0000960 else
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100961 l = l6;
Simon Kelley832af0b2007-01-21 20:01:28 +0000962#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100963
Simon Kelley74c95c22011-10-19 09:33:39 +0100964 daemon->listeners = l;
Simon Kelley44a2a312004-03-10 20:04:35 +0000965}
966
Simon Kelley74c95c22011-10-19 09:33:39 +0100967void create_bound_listeners(int dienow)
Simon Kelley44a2a312004-03-10 20:04:35 +0000968{
Simon Kelley74c95c22011-10-19 09:33:39 +0100969 struct listener *new;
Simon Kelley44a2a312004-03-10 20:04:35 +0000970 struct irec *iface;
Simon Kelley52d4abf2012-03-21 21:39:48 +0000971 struct iname *if_tmp;
Simon Kelley73a08a22009-02-05 20:28:08 +0000972
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100973 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelley08619212013-12-02 14:43:48 +0000974 if (!iface->done && !iface->dad && iface->found &&
Simon Kelley74c95c22011-10-19 09:33:39 +0100975 (new = create_listeners(&iface->addr, iface->tftp_ok, dienow)))
Simon Kelley28866e92011-02-14 20:19:14 +0000976 {
977 new->iface = iface;
Simon Kelley74c95c22011-10-19 09:33:39 +0100978 new->next = daemon->listeners;
979 daemon->listeners = new;
980 iface->done = 1;
Simon Kelley28866e92011-02-14 20:19:14 +0000981 }
Simon Kelley52d4abf2012-03-21 21:39:48 +0000982
983 /* Check for --listen-address options that haven't been used because there's
984 no interface with a matching address. These may be valid: eg it's possible
985 to listen on 127.0.1.1 even if the loopback interface is 127.0.0.1
986
Simon Kelley5f11b3e2012-08-16 14:04:05 +0100987 If the address isn't valid the bind() will fail and we'll die()
988 (except in bind-dynamic mode, when we'll complain but keep trying.)
Simon Kelley52d4abf2012-03-21 21:39:48 +0000989
990 The resulting listeners have the ->iface field NULL, and this has to be
991 handled by the DNS and TFTP code. It disables --localise-queries processing
992 (no netmask) and some MTU login the tftp code. */
993
994 for (if_tmp = daemon->if_addrs; if_tmp; if_tmp = if_tmp->next)
995 if (!if_tmp->used &&
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100996 (new = create_listeners(&if_tmp->addr, !!option_bool(OPT_TFTP), dienow)))
Simon Kelley52d4abf2012-03-21 21:39:48 +0000997 {
Simon Kelley52d4abf2012-03-21 21:39:48 +0000998 new->next = daemon->listeners;
999 daemon->listeners = new;
1000 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001001}
1002
Simon Kelleydc27e142013-10-16 13:09:53 +01001003/* In --bind-interfaces, the only access control is the addresses we're listening on.
1004 There's nothing to avoid a query to the address of an internal interface arriving via
1005 an external interface where we don't want to accept queries, except that in the usual
1006 case the addresses of internal interfaces are RFC1918. When bind-interfaces in use,
1007 and we listen on an address that looks like it's probably globally routeable, shout.
1008
1009 The fix is to use --bind-dynamic, which actually checks the arrival interface too.
1010 Tough if your platform doesn't support this.
Simon Kelley2329bef2013-12-03 13:41:16 +00001011
1012 Note that checking the arrival interface is supported in the standard IPv6 API and
1013 always done, so we don't warn about any IPv6 addresses here.
Simon Kelleydc27e142013-10-16 13:09:53 +01001014*/
1015
1016void warn_bound_listeners(void)
1017{
1018 struct irec *iface;
1019 int advice = 0;
1020
1021 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelleyf7029f52013-11-21 15:09:09 +00001022 if (!iface->dns_auth)
Simon Kelleydc27e142013-10-16 13:09:53 +01001023 {
Simon Kelleydc27e142013-10-16 13:09:53 +01001024 if (iface->addr.sa.sa_family == AF_INET)
1025 {
1026 if (!private_net(iface->addr.in.sin_addr, 1))
1027 {
1028 inet_ntop(AF_INET, &iface->addr.in.sin_addr, daemon->addrbuff, ADDRSTRLEN);
Simon Kelley2329bef2013-12-03 13:41:16 +00001029 iface->warned = advice = 1;
1030 my_syslog(LOG_WARNING,
1031 _("LOUD WARNING: listening on %s may accept requests via interfaces other than %s"),
1032 daemon->addrbuff, iface->name);
Simon Kelleydc27e142013-10-16 13:09:53 +01001033 }
1034 }
Simon Kelleydc27e142013-10-16 13:09:53 +01001035 }
1036
1037 if (advice)
Simon Kelleyf7029f52013-11-21 15:09:09 +00001038 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 +01001039}
1040
Petr Menšíkad59f272017-03-17 17:22:19 +00001041void warn_wild_labels(void)
1042{
1043 struct irec *iface;
1044
1045 for (iface = daemon->interfaces; iface; iface = iface->next)
1046 if (iface->found && iface->name && iface->label)
1047 my_syslog(LOG_WARNING, _("warning: using interface %s instead"), iface->name);
1048}
1049
Simon Kelleyf7029f52013-11-21 15:09:09 +00001050void warn_int_names(void)
1051{
1052 struct interface_name *intname;
1053
1054 for (intname = daemon->int_names; intname; intname = intname->next)
1055 if (!intname->addr)
1056 my_syslog(LOG_WARNING, _("warning: no addresses found for interface %s"), intname->intr);
1057}
1058
Simon Kelley74c95c22011-10-19 09:33:39 +01001059int is_dad_listeners(void)
1060{
1061 struct irec *iface;
1062
1063 if (option_bool(OPT_NOWILD))
1064 for (iface = daemon->interfaces; iface; iface = iface->next)
1065 if (iface->dad && !iface->done)
1066 return 1;
1067
1068 return 0;
1069}
Simon Kelley5d162f22012-12-20 14:55:46 +00001070
1071#ifdef HAVE_DHCP6
1072void join_multicast(int dienow)
1073{
1074 struct irec *iface, *tmp;
1075
1076 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelley19624462012-12-28 11:18:09 +00001077 if (iface->addr.sa.sa_family == AF_INET6 && iface->dhcp_ok && !iface->multicast_done)
Simon Kelley5d162f22012-12-20 14:55:46 +00001078 {
1079 /* There's an irec per address but we only want to join for multicast
1080 once per interface. Weed out duplicates. */
1081 for (tmp = daemon->interfaces; tmp; tmp = tmp->next)
1082 if (tmp->multicast_done && tmp->index == iface->index)
1083 break;
1084
1085 iface->multicast_done = 1;
1086
1087 if (!tmp)
1088 {
1089 struct ipv6_mreq mreq;
1090 int err = 0;
1091
1092 mreq.ipv6mr_interface = iface->index;
1093
1094 inet_pton(AF_INET6, ALL_RELAY_AGENTS_AND_SERVERS, &mreq.ipv6mr_multiaddr);
1095
Simon Kelleyff7eea22013-09-04 18:01:38 +01001096 if ((daemon->doing_dhcp6 || daemon->relay6) &&
Simon Kelley5d162f22012-12-20 14:55:46 +00001097 setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
Simon Kelley9cdcfe92015-08-26 22:38:08 +01001098 err = errno;
Simon Kelley5d162f22012-12-20 14:55:46 +00001099
1100 inet_pton(AF_INET6, ALL_SERVERS, &mreq.ipv6mr_multiaddr);
1101
1102 if (daemon->doing_dhcp6 &&
1103 setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
Simon Kelley9cdcfe92015-08-26 22:38:08 +01001104 err = errno;
Simon Kelley5d162f22012-12-20 14:55:46 +00001105
1106 inet_pton(AF_INET6, ALL_ROUTERS, &mreq.ipv6mr_multiaddr);
1107
1108 if (daemon->doing_ra &&
1109 setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
Simon Kelley9cdcfe92015-08-26 22:38:08 +01001110 err = errno;
Simon Kelley5d162f22012-12-20 14:55:46 +00001111
1112 if (err)
1113 {
1114 char *s = _("interface %s failed to join DHCPv6 multicast group: %s");
Simon Kelley9cdcfe92015-08-26 22:38:08 +01001115 errno = err;
1116
1117#ifdef HAVE_LINUX_NETWORK
1118 if (errno == ENOMEM)
1119 my_syslog(LOG_ERR, _("try increasing /proc/sys/net/core/optmem_max"));
1120#endif
1121
Simon Kelley5d162f22012-12-20 14:55:46 +00001122 if (dienow)
1123 die(s, iface->name, EC_BADNET);
1124 else
1125 my_syslog(LOG_ERR, s, iface->name, strerror(errno));
1126 }
1127 }
1128 }
1129}
1130#endif
1131
Simon Kelley9009d742008-11-14 20:04:27 +00001132/* return a UDP socket bound to a random port, have to cope with straying into
Simon Kelley1a6bca82008-07-11 11:11:42 +01001133 occupied port nos and reserved ones. */
1134int random_sock(int family)
1135{
1136 int fd;
1137
1138 if ((fd = socket(family, SOCK_DGRAM, 0)) != -1)
1139 {
Simon Kelley3927da42008-07-20 15:10:39 +01001140 union mysockaddr addr;
Hans Dedecker926332a2016-01-23 10:48:12 +00001141 unsigned int ports_avail = ((unsigned short)daemon->max_port - (unsigned short)daemon->min_port) + 1;
Simon Kelley9009d742008-11-14 20:04:27 +00001142 int tries = ports_avail < 30 ? 3 * ports_avail : 100;
Simon Kelley3927da42008-07-20 15:10:39 +01001143
Simon Kelley1a6bca82008-07-11 11:11:42 +01001144 memset(&addr, 0, sizeof(addr));
Simon Kelley3927da42008-07-20 15:10:39 +01001145 addr.sa.sa_family = family;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001146
Simon Kelley1ad24ae2008-07-20 20:22:50 +01001147 /* don't loop forever if all ports in use. */
1148
Simon Kelley1a6bca82008-07-11 11:11:42 +01001149 if (fix_fd(fd))
Simon Kelley9009d742008-11-14 20:04:27 +00001150 while(tries--)
Simon Kelley1a6bca82008-07-11 11:11:42 +01001151 {
Simon Kelleybaf553d2018-01-29 22:49:27 +00001152 unsigned short port = htons(daemon->min_port + (rand16() % ((unsigned short)ports_avail)));
Simon Kelley1a6bca82008-07-11 11:11:42 +01001153
1154 if (family == AF_INET)
1155 {
1156 addr.in.sin_addr.s_addr = INADDR_ANY;
Simon Kelley3927da42008-07-20 15:10:39 +01001157 addr.in.sin_port = port;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001158#ifdef HAVE_SOCKADDR_SA_LEN
1159 addr.in.sin_len = sizeof(struct sockaddr_in);
1160#endif
1161 }
1162#ifdef HAVE_IPV6
1163 else
1164 {
1165 addr.in6.sin6_addr = in6addr_any;
Simon Kelley3927da42008-07-20 15:10:39 +01001166 addr.in6.sin6_port = port;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001167#ifdef HAVE_SOCKADDR_SA_LEN
1168 addr.in6.sin6_len = sizeof(struct sockaddr_in6);
1169#endif
1170 }
1171#endif
1172
1173 if (bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == 0)
1174 return fd;
1175
1176 if (errno != EADDRINUSE && errno != EACCES)
1177 break;
1178 }
1179
1180 close(fd);
1181 }
1182
1183 return -1;
1184}
1185
1186
Simon Kelley9d6918d2017-10-13 17:55:09 +01001187int local_bind(int fd, union mysockaddr *addr, char *intname, unsigned int ifindex, int is_tcp)
Simon Kelley824af852008-02-12 20:43:05 +00001188{
1189 union mysockaddr addr_copy = *addr;
1190
1191 /* cannot set source _port_ for TCP connections. */
1192 if (is_tcp)
1193 {
1194 if (addr_copy.sa.sa_family == AF_INET)
1195 addr_copy.in.sin_port = 0;
1196#ifdef HAVE_IPV6
1197 else
1198 addr_copy.in6.sin6_port = 0;
1199#endif
1200 }
1201
1202 if (bind(fd, (struct sockaddr *)&addr_copy, sa_len(&addr_copy)) == -1)
1203 return 0;
Simon Kelley9d6918d2017-10-13 17:55:09 +01001204
1205 if (!is_tcp && ifindex > 0)
1206 {
1207#if defined(IP_UNICAST_IF)
1208 if (addr_copy.sa.sa_family == AF_INET)
1209 {
1210 uint32_t ifindex_opt = htonl(ifindex);
1211 return setsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex_opt, sizeof(ifindex_opt)) == 0;
1212 }
1213#endif
1214#if defined(HAVE_IPV6) && defined (IPV6_UNICAST_IF)
1215 if (addr_copy.sa.sa_family == AF_INET6)
1216 {
1217 uint32_t ifindex_opt = htonl(ifindex);
1218 return setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_IF, &ifindex_opt, sizeof(ifindex_opt)) == 0;
1219 }
1220#endif
1221 }
1222
Simon Kelley824af852008-02-12 20:43:05 +00001223#if defined(SO_BINDTODEVICE)
Simon Kelley73a08a22009-02-05 20:28:08 +00001224 if (intname[0] != 0 &&
Simon Kelley316e2732010-01-22 20:16:09 +00001225 setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, intname, IF_NAMESIZE) == -1)
Simon Kelley824af852008-02-12 20:43:05 +00001226 return 0;
1227#endif
1228
1229 return 1;
1230}
1231
1232static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001233{
1234 struct serverfd *sfd;
Beniamino Galvani2675f202016-08-28 20:44:05 +01001235 unsigned int ifindex = 0;
Simon Kelley824af852008-02-12 20:43:05 +00001236 int errsave;
Simon Kelleye83915d2018-04-10 21:27:26 +01001237 int opt = 1;
1238
Simon Kelley1a6bca82008-07-11 11:11:42 +01001239 /* when using random ports, servers which would otherwise use
1240 the INADDR_ANY/port0 socket have sfd set to NULL */
Simon Kelley73a08a22009-02-05 20:28:08 +00001241 if (!daemon->osport && intname[0] == 0)
Simon Kelley1a6bca82008-07-11 11:11:42 +01001242 {
1243 errno = 0;
1244
1245 if (addr->sa.sa_family == AF_INET &&
1246 addr->in.sin_addr.s_addr == INADDR_ANY &&
1247 addr->in.sin_port == htons(0))
1248 return NULL;
1249
1250#ifdef HAVE_IPV6
1251 if (addr->sa.sa_family == AF_INET6 &&
1252 memcmp(&addr->in6.sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0 &&
1253 addr->in6.sin6_port == htons(0))
1254 return NULL;
1255#endif
1256 }
Beniamino Galvani2675f202016-08-28 20:44:05 +01001257
1258 if (intname && strlen(intname) != 0)
1259 ifindex = if_nametoindex(intname); /* index == 0 when not binding to an interface */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001260
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001261 /* may have a suitable one already */
Simon Kelley824af852008-02-12 20:43:05 +00001262 for (sfd = daemon->sfds; sfd; sfd = sfd->next )
1263 if (sockaddr_isequal(&sfd->source_addr, addr) &&
Beniamino Galvani2675f202016-08-28 20:44:05 +01001264 strcmp(intname, sfd->interface) == 0 &&
1265 ifindex == sfd->ifindex)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001266 return sfd;
1267
1268 /* need to make a new one. */
1269 errno = ENOMEM; /* in case malloc fails. */
Simon Kelley5aabfc72007-08-29 11:24:47 +01001270 if (!(sfd = whine_malloc(sizeof(struct serverfd))))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001271 return NULL;
1272
1273 if ((sfd->fd = socket(addr->sa.sa_family, SOCK_DGRAM, 0)) == -1)
1274 {
1275 free(sfd);
1276 return NULL;
1277 }
Simon Kelleye83915d2018-04-10 21:27:26 +01001278
1279 if ((addr->sa.sa_family == AF_INET6 && setsockopt(sfd->fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)) == -1) ||
1280 !local_bind(sfd->fd, addr, intname, ifindex, 0) || !fix_fd(sfd->fd))
Simon Kelley824af852008-02-12 20:43:05 +00001281 {
Simon Kelleye83915d2018-04-10 21:27:26 +01001282 errsave = errno; /* save error from bind/setsockopt. */
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001283 close(sfd->fd);
1284 free(sfd);
1285 errno = errsave;
1286 return NULL;
1287 }
Beniamino Galvani2675f202016-08-28 20:44:05 +01001288
Simon Kelley824af852008-02-12 20:43:05 +00001289 strcpy(sfd->interface, intname);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001290 sfd->source_addr = *addr;
Simon Kelley824af852008-02-12 20:43:05 +00001291 sfd->next = daemon->sfds;
Beniamino Galvani2675f202016-08-28 20:44:05 +01001292 sfd->ifindex = ifindex;
Simon Kelley824af852008-02-12 20:43:05 +00001293 daemon->sfds = sfd;
Beniamino Galvani2675f202016-08-28 20:44:05 +01001294
Simon Kelley824af852008-02-12 20:43:05 +00001295 return sfd;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001296}
1297
Simon Kelley824af852008-02-12 20:43:05 +00001298/* create upstream sockets during startup, before root is dropped which may be needed
1299 this allows query_port to be a low port and interface binding */
1300void pre_allocate_sfds(void)
1301{
1302 struct server *srv;
1303
1304 if (daemon->query_port != 0)
1305 {
1306 union mysockaddr addr;
1307 memset(&addr, 0, sizeof(addr));
1308 addr.in.sin_family = AF_INET;
1309 addr.in.sin_addr.s_addr = INADDR_ANY;
1310 addr.in.sin_port = htons(daemon->query_port);
1311#ifdef HAVE_SOCKADDR_SA_LEN
1312 addr.in.sin_len = sizeof(struct sockaddr_in);
1313#endif
1314 allocate_sfd(&addr, "");
1315#ifdef HAVE_IPV6
1316 memset(&addr, 0, sizeof(addr));
1317 addr.in6.sin6_family = AF_INET6;
1318 addr.in6.sin6_addr = in6addr_any;
1319 addr.in6.sin6_port = htons(daemon->query_port);
1320#ifdef HAVE_SOCKADDR_SA_LEN
1321 addr.in6.sin6_len = sizeof(struct sockaddr_in6);
1322#endif
1323 allocate_sfd(&addr, "");
1324#endif
1325 }
1326
1327 for (srv = daemon->servers; srv; srv = srv->next)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001328 if (!(srv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)) &&
Simon Kelley824af852008-02-12 20:43:05 +00001329 !allocate_sfd(&srv->source_addr, srv->interface) &&
Simon Kelley1a6bca82008-07-11 11:11:42 +01001330 errno != 0 &&
Simon Kelley28866e92011-02-14 20:19:14 +00001331 option_bool(OPT_NOWILD))
Simon Kelley824af852008-02-12 20:43:05 +00001332 {
Simon Kelley316e2732010-01-22 20:16:09 +00001333 prettyprint_addr(&srv->source_addr, daemon->namebuff);
Simon Kelley73a08a22009-02-05 20:28:08 +00001334 if (srv->interface[0] != 0)
Simon Kelley824af852008-02-12 20:43:05 +00001335 {
1336 strcat(daemon->namebuff, " ");
1337 strcat(daemon->namebuff, srv->interface);
1338 }
1339 die(_("failed to bind server socket for %s: %s"),
1340 daemon->namebuff, EC_BADNET);
1341 }
1342}
1343
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001344void mark_servers(int flag)
1345{
1346 struct server *serv;
1347
1348 /* mark everything with argument flag */
1349 for (serv = daemon->servers; serv; serv = serv->next)
Simon Kelley40766e52014-07-29 16:52:00 +01001350 {
1351 if (serv->flags & flag)
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001352 serv->flags |= SERV_MARK;
1353#ifdef HAVE_LOOP
Simon Kelley40766e52014-07-29 16:52:00 +01001354 /* Give looped servers another chance */
1355 serv->flags &= ~SERV_LOOP;
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001356#endif
Simon Kelley40766e52014-07-29 16:52:00 +01001357 }
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001358}
1359
1360void cleanup_servers(void)
1361{
1362 struct server *serv, *tmp, **up;
1363
1364 /* unlink and free anything still marked. */
1365 for (serv = daemon->servers, up = &daemon->servers; serv; serv = tmp)
1366 {
1367 tmp = serv->next;
1368 if (serv->flags & SERV_MARK)
1369 {
1370 server_gone(serv);
1371 *up = serv->next;
1372 if (serv->domain)
1373 free(serv->domain);
1374 free(serv);
1375 }
1376 else
1377 up = &serv->next;
1378 }
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001379
1380#ifdef HAVE_LOOP
1381 /* Now we have a new set of servers, test for loops. */
1382 loop_send_probes();
1383#endif
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001384}
1385
1386void add_update_server(int flags,
1387 union mysockaddr *addr,
1388 union mysockaddr *source_addr,
1389 const char *interface,
1390 const char *domain)
1391{
Simon Kelley7b1eae42014-02-20 13:43:28 +00001392 struct server *serv, *next = NULL;
1393 char *domain_str = NULL;
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001394
1395 /* See if there is a suitable candidate, and unmark */
1396 for (serv = daemon->servers; serv; serv = serv->next)
1397 if (serv->flags & SERV_MARK)
1398 {
1399 if (domain)
1400 {
1401 if (!(serv->flags & SERV_HAS_DOMAIN) || !hostname_isequal(domain, serv->domain))
1402 continue;
1403 }
1404 else
1405 {
1406 if (serv->flags & SERV_HAS_DOMAIN)
1407 continue;
1408 }
1409
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001410 break;
1411 }
Simon Kelley7b1eae42014-02-20 13:43:28 +00001412
1413 if (serv)
1414 {
1415 domain_str = serv->domain;
1416 next = serv->next;
1417 }
1418 else if ((serv = whine_malloc(sizeof (struct server))))
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001419 {
1420 /* Not found, create a new one. */
Simon Kelley7b1eae42014-02-20 13:43:28 +00001421 if (domain && !(domain_str = whine_malloc(strlen(domain)+1)))
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001422 {
1423 free(serv);
1424 serv = NULL;
1425 }
1426 else
1427 {
1428 struct server *s;
1429 /* Add to the end of the chain, for order */
1430 if (!daemon->servers)
1431 daemon->servers = serv;
1432 else
1433 {
1434 for (s = daemon->servers; s->next; s = s->next);
1435 s->next = serv;
1436 }
1437 if (domain)
Simon Kelley7b1eae42014-02-20 13:43:28 +00001438 strcpy(domain_str, domain);
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001439 }
1440 }
1441
1442 if (serv)
1443 {
Simon Kelley7b1eae42014-02-20 13:43:28 +00001444 memset(serv, 0, sizeof(struct server));
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001445 serv->flags = flags;
Simon Kelley7b1eae42014-02-20 13:43:28 +00001446 serv->domain = domain_str;
1447 serv->next = next;
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001448 serv->queries = serv->failed_queries = 0;
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001449#ifdef HAVE_LOOP
1450 serv->uid = rand32();
1451#endif
1452
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001453 if (domain)
1454 serv->flags |= SERV_HAS_DOMAIN;
1455
1456 if (interface)
Simon Kelley7b1eae42014-02-20 13:43:28 +00001457 strcpy(serv->interface, interface);
1458 if (addr)
1459 serv->addr = *addr;
1460 if (source_addr)
1461 serv->source_addr = *source_addr;
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001462 }
1463}
Simon Kelley824af852008-02-12 20:43:05 +00001464
Simon Kelley5aabfc72007-08-29 11:24:47 +01001465void check_servers(void)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001466{
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001467 struct irec *iface;
Simon Kelley7bcca002014-02-19 17:45:17 +00001468 struct server *serv;
Beniamino Galvani2675f202016-08-28 20:44:05 +01001469 struct serverfd *sfd, *tmp, **up;
Simon Kelleyb9702602016-05-03 22:34:06 +01001470 int port = 0, count;
Hannu Nyman3e2496f2017-02-11 13:44:08 +00001471 int locals = 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001472
Simon Kelley316e2732010-01-22 20:16:09 +00001473 /* interface may be new since startup */
Simon Kelley28866e92011-02-14 20:19:14 +00001474 if (!option_bool(OPT_NOWILD))
Simon Kelley115ac3e2013-05-20 11:28:32 +01001475 enumerate_interfaces(0);
Simon Kelley316e2732010-01-22 20:16:09 +00001476
Beniamino Galvani2675f202016-08-28 20:44:05 +01001477 for (sfd = daemon->sfds; sfd; sfd = sfd->next)
1478 sfd->used = 0;
1479
Simon Kelleyb9702602016-05-03 22:34:06 +01001480 for (count = 0, serv = daemon->servers; serv; serv = serv->next)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001481 {
Simon Kelley367341f2016-01-12 15:58:23 +00001482 if (!(serv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001483 {
Simon Kelley14ffa072016-04-25 16:36:44 +01001484 /* Init edns_pktsz for newly created server records. */
1485 if (serv->edns_pktsz == 0)
1486 serv->edns_pktsz = daemon->edns_pktsz;
1487
Simon Kelley367341f2016-01-12 15:58:23 +00001488#ifdef HAVE_DNSSEC
Simon Kelley92be34a2016-01-16 18:39:54 +00001489 if (option_bool(OPT_DNSSEC_VALID))
1490 {
Simon Kelleya49c5c22017-10-10 22:04:59 +01001491 if (!(serv->flags & SERV_FOR_NODOTS))
1492 serv->flags |= SERV_DO_DNSSEC;
1493
1494 /* Disable DNSSEC validation when using server=/domain/.... servers
1495 unless there's a configured trust anchor. */
Simon Kelley92be34a2016-01-16 18:39:54 +00001496 if (serv->flags & SERV_HAS_DOMAIN)
1497 {
1498 struct ds_config *ds;
1499 char *domain = serv->domain;
1500
1501 /* .example.com is valid */
1502 while (*domain == '.')
1503 domain++;
1504
1505 for (ds = daemon->ds; ds; ds = ds->next)
1506 if (ds->name[0] != 0 && hostname_isequal(domain, ds->name))
1507 break;
1508
1509 if (!ds)
1510 serv->flags &= ~SERV_DO_DNSSEC;
1511 }
Simon Kelley367341f2016-01-12 15:58:23 +00001512 }
1513#endif
1514
1515 port = prettyprint_addr(&serv->addr, daemon->namebuff);
1516
Simon Kelley16972692006-10-16 20:04:18 +01001517 /* 0.0.0.0 is nothing, the stack treats it like 127.0.0.1 */
Simon Kelley7bcca002014-02-19 17:45:17 +00001518 if (serv->addr.sa.sa_family == AF_INET &&
1519 serv->addr.in.sin_addr.s_addr == 0)
Simon Kelley16972692006-10-16 20:04:18 +01001520 {
Simon Kelley7bcca002014-02-19 17:45:17 +00001521 serv->flags |= SERV_MARK;
Simon Kelley16972692006-10-16 20:04:18 +01001522 continue;
1523 }
1524
Simon Kelley3d8df262005-08-29 12:19:27 +01001525 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelley7bcca002014-02-19 17:45:17 +00001526 if (sockaddr_isequal(&serv->addr, &iface->addr))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001527 break;
1528 if (iface)
1529 {
Simon Kelleyf2621c72007-04-29 19:47:21 +01001530 my_syslog(LOG_WARNING, _("ignoring nameserver %s - local interface"), daemon->namebuff);
Simon Kelley7bcca002014-02-19 17:45:17 +00001531 serv->flags |= SERV_MARK;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001532 continue;
1533 }
1534
1535 /* Do we need a socket set? */
Simon Kelley7bcca002014-02-19 17:45:17 +00001536 if (!serv->sfd &&
1537 !(serv->sfd = allocate_sfd(&serv->source_addr, serv->interface)) &&
Simon Kelley1a6bca82008-07-11 11:11:42 +01001538 errno != 0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001539 {
Simon Kelleyf2621c72007-04-29 19:47:21 +01001540 my_syslog(LOG_WARNING,
1541 _("ignoring nameserver %s - cannot make/bind socket: %s"),
1542 daemon->namebuff, strerror(errno));
Simon Kelley7bcca002014-02-19 17:45:17 +00001543 serv->flags |= SERV_MARK;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001544 continue;
1545 }
Simon Kelley16800ea2016-08-30 23:07:06 +01001546
1547 if (serv->sfd)
1548 serv->sfd->used = 1;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001549 }
1550
Simon Kelley979fe862015-03-19 22:50:22 +00001551 if (!(serv->flags & SERV_NO_REBIND) && !(serv->flags & SERV_LITERAL_ADDRESS))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001552 {
Simon Kelleyb9702602016-05-03 22:34:06 +01001553 if (++count > SERVERS_LOGGED)
1554 continue;
1555
Simon Kelley7bcca002014-02-19 17:45:17 +00001556 if (serv->flags & (SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_USE_RESOLV))
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001557 {
Simon Kelley367341f2016-01-12 15:58:23 +00001558 char *s1, *s2, *s3 = "";
1559#ifdef HAVE_DNSSEC
1560 if (option_bool(OPT_DNSSEC_VALID) && !(serv->flags & SERV_DO_DNSSEC))
1561 s3 = _("(no DNSSEC)");
1562#endif
Simon Kelley7bcca002014-02-19 17:45:17 +00001563 if (!(serv->flags & SERV_HAS_DOMAIN))
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001564 s1 = _("unqualified"), s2 = _("names");
Simon Kelley7bcca002014-02-19 17:45:17 +00001565 else if (strlen(serv->domain) == 0)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001566 s1 = _("default"), s2 = "";
1567 else
Simon Kelley7bcca002014-02-19 17:45:17 +00001568 s1 = _("domain"), s2 = serv->domain;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001569
Simon Kelley7bcca002014-02-19 17:45:17 +00001570 if (serv->flags & SERV_NO_ADDR)
Hannu Nyman3e2496f2017-02-11 13:44:08 +00001571 {
1572 count--;
1573 if (++locals <= LOCALS_LOGGED)
1574 my_syslog(LOG_INFO, _("using local addresses only for %s %s"), s1, s2);
1575 }
Simon Kelley7bcca002014-02-19 17:45:17 +00001576 else if (serv->flags & SERV_USE_RESOLV)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001577 my_syslog(LOG_INFO, _("using standard nameservers for %s %s"), s1, s2);
Simon Kelley979fe862015-03-19 22:50:22 +00001578 else
Simon Kelley367341f2016-01-12 15:58:23 +00001579 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 +01001580 }
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001581#ifdef HAVE_LOOP
1582 else if (serv->flags & SERV_LOOP)
1583 my_syslog(LOG_INFO, _("NOT using nameserver %s#%d - query loop detected"), daemon->namebuff, port);
1584#endif
Simon Kelley7bcca002014-02-19 17:45:17 +00001585 else if (serv->interface[0] != 0)
1586 my_syslog(LOG_INFO, _("using nameserver %s#%d(via %s)"), daemon->namebuff, port, serv->interface);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001587 else
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001588 my_syslog(LOG_INFO, _("using nameserver %s#%d"), daemon->namebuff, port);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001589 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001590 }
Simon Kelleyb9702602016-05-03 22:34:06 +01001591
Hannu Nyman3e2496f2017-02-11 13:44:08 +00001592 if (locals > LOCALS_LOGGED)
1593 my_syslog(LOG_INFO, _("using %d more local addresses"), locals - LOCALS_LOGGED);
Simon Kelleyb9702602016-05-03 22:34:06 +01001594 if (count - 1 > SERVERS_LOGGED)
1595 my_syslog(LOG_INFO, _("using %d more nameservers"), count - SERVERS_LOGGED - 1);
Simon Kelley7bcca002014-02-19 17:45:17 +00001596
Beniamino Galvani2675f202016-08-28 20:44:05 +01001597 /* Remove unused sfds */
1598 for (sfd = daemon->sfds, up = &daemon->sfds; sfd; sfd = tmp)
1599 {
1600 tmp = sfd->next;
1601 if (!sfd->used)
1602 {
1603 *up = sfd->next;
1604 close(sfd->fd);
1605 free(sfd);
1606 }
1607 else
1608 up = &sfd->next;
1609 }
1610
Simon Kelley7bcca002014-02-19 17:45:17 +00001611 cleanup_servers();
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001612}
Simon Kelley849a8352006-06-09 21:02:31 +01001613
1614/* Return zero if no servers found, in that case we keep polling.
1615 This is a protection against an update-time/write race on resolv.conf */
Simon Kelley5aabfc72007-08-29 11:24:47 +01001616int reload_servers(char *fname)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001617{
1618 FILE *f;
1619 char *line;
Simon Kelley849a8352006-06-09 21:02:31 +01001620 int gotone = 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001621
Simon Kelley849a8352006-06-09 21:02:31 +01001622 /* buff happens to be MAXDNAME long... */
1623 if (!(f = fopen(fname, "r")))
1624 {
Simon Kelleyf2621c72007-04-29 19:47:21 +01001625 my_syslog(LOG_ERR, _("failed to read %s: %s"), fname, strerror(errno));
Simon Kelley849a8352006-06-09 21:02:31 +01001626 return 0;
1627 }
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001628
1629 mark_servers(SERV_FROM_RESOLV);
1630
Simon Kelley849a8352006-06-09 21:02:31 +01001631 while ((line = fgets(daemon->namebuff, MAXDNAME, f)))
1632 {
1633 union mysockaddr addr, source_addr;
1634 char *token = strtok(line, " \t\n\r");
1635
Simon Kelley5aabfc72007-08-29 11:24:47 +01001636 if (!token)
1637 continue;
1638 if (strcmp(token, "nameserver") != 0 && strcmp(token, "server") != 0)
Simon Kelley849a8352006-06-09 21:02:31 +01001639 continue;
1640 if (!(token = strtok(NULL, " \t\n\r")))
1641 continue;
1642
1643 memset(&addr, 0, sizeof(addr));
1644 memset(&source_addr, 0, sizeof(source_addr));
1645
1646 if ((addr.in.sin_addr.s_addr = inet_addr(token)) != (in_addr_t) -1)
1647 {
1648#ifdef HAVE_SOCKADDR_SA_LEN
1649 source_addr.in.sin_len = addr.in.sin_len = sizeof(source_addr.in);
1650#endif
1651 source_addr.in.sin_family = addr.in.sin_family = AF_INET;
1652 addr.in.sin_port = htons(NAMESERVER_PORT);
1653 source_addr.in.sin_addr.s_addr = INADDR_ANY;
1654 source_addr.in.sin_port = htons(daemon->query_port);
1655 }
1656#ifdef HAVE_IPV6
Simon Kelley7de060b2011-08-26 17:24:52 +01001657 else
1658 {
1659 int scope_index = 0;
1660 char *scope_id = strchr(token, '%');
1661
1662 if (scope_id)
1663 {
1664 *(scope_id++) = 0;
1665 scope_index = if_nametoindex(scope_id);
1666 }
1667
1668 if (inet_pton(AF_INET6, token, &addr.in6.sin6_addr) > 0)
1669 {
Simon Kelley849a8352006-06-09 21:02:31 +01001670#ifdef HAVE_SOCKADDR_SA_LEN
Simon Kelley7de060b2011-08-26 17:24:52 +01001671 source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(source_addr.in6);
Simon Kelley849a8352006-06-09 21:02:31 +01001672#endif
Simon Kelley7de060b2011-08-26 17:24:52 +01001673 source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6;
1674 source_addr.in6.sin6_flowinfo = addr.in6.sin6_flowinfo = 0;
1675 addr.in6.sin6_port = htons(NAMESERVER_PORT);
1676 addr.in6.sin6_scope_id = scope_index;
1677 source_addr.in6.sin6_addr = in6addr_any;
1678 source_addr.in6.sin6_port = htons(daemon->query_port);
1679 source_addr.in6.sin6_scope_id = 0;
1680 }
1681 else
1682 continue;
Simon Kelley849a8352006-06-09 21:02:31 +01001683 }
Simon Kelley7de060b2011-08-26 17:24:52 +01001684#else /* IPV6 */
Simon Kelley849a8352006-06-09 21:02:31 +01001685 else
1686 continue;
Simon Kelley7de060b2011-08-26 17:24:52 +01001687#endif
1688
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001689 add_update_server(SERV_FROM_RESOLV, &addr, &source_addr, NULL, NULL);
Simon Kelley849a8352006-06-09 21:02:31 +01001690 gotone = 1;
1691 }
1692
Simon Kelley849a8352006-06-09 21:02:31 +01001693 fclose(f);
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001694 cleanup_servers();
Simon Kelley849a8352006-06-09 21:02:31 +01001695
1696 return gotone;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001697}
1698
Simon Kelley1ee9be42013-12-09 16:50:19 +00001699/* Called when addresses are added or deleted from an interface */
1700void newaddress(time_t now)
1701{
1702 (void)now;
1703
Simon Kelley89b12ed2014-03-06 13:27:57 +00001704 if (option_bool(OPT_CLEVERBIND) || option_bool(OPT_LOCAL_SERVICE) ||
1705 daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
Simon Kelley1ee9be42013-12-09 16:50:19 +00001706 enumerate_interfaces(0);
1707
1708 if (option_bool(OPT_CLEVERBIND))
1709 create_bound_listeners(0);
1710
1711#ifdef HAVE_DHCP6
1712 if (daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
1713 join_multicast(0);
1714
1715 if (daemon->doing_dhcp6 || daemon->doing_ra)
1716 dhcp_construct_contexts(now);
1717
1718 if (daemon->doing_dhcp6)
1719 lease_find_interfaces(now);
1720#endif
1721}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001722
1723
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001724
1725
1726