blob: e5ceb76df5ca190e2d9c1c70c02f984de6d56987 [file] [log] [blame]
Simon Kelleyc49778d2016-01-06 18:52:33 +00001/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
Simon Kelley824af852008-02-12 20:43:05 +00005 the Free Software Foundation; version 2 dated June, 1991, or
6 (at your option) version 3 dated 29 June, 2007.
7
Simon Kelley9e4abcb2004-01-22 19:47:41 +00008 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
Simon Kelley824af852008-02-12 20:43:05 +000012
Simon Kelley73a08a22009-02-05 20:28:08 +000013 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>.
Simon Kelley9e4abcb2004-01-22 19:47:41 +000015*/
16
Simon Kelley9e4abcb2004-01-22 19:47:41 +000017#include "dnsmasq.h"
18
Simon Kelley7622fc02009-06-04 20:32:05 +010019#ifdef HAVE_LINUX_NETWORK
20
21int indextoname(int fd, int index, char *name)
22{
23 struct ifreq ifr;
24
25 if (index == 0)
26 return 0;
27
28 ifr.ifr_ifindex = index;
29 if (ioctl(fd, SIOCGIFNAME, &ifr) == -1)
30 return 0;
31
32 strncpy(name, ifr.ifr_name, IF_NAMESIZE);
33
34 return 1;
35}
36
Simon Kelley28866e92011-02-14 20:19:14 +000037
38#elif defined(HAVE_SOLARIS_NETWORK)
39
40#include <zone.h>
41#include <alloca.h>
42#ifndef LIFC_UNDER_IPMP
43# define LIFC_UNDER_IPMP 0
44#endif
45
46int indextoname(int fd, int index, char *name)
47{
48 int64_t lifc_flags;
49 struct lifnum lifn;
50 int numifs, bufsize, i;
51 struct lifconf lifc;
52 struct lifreq *lifrp;
53
54 if (index == 0)
55 return 0;
56
57 if (getzoneid() == GLOBAL_ZONEID)
58 {
59 if (!if_indextoname(index, name))
60 return 0;
61 return 1;
62 }
63
64 lifc_flags = LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES | LIFC_UNDER_IPMP;
65 lifn.lifn_family = AF_UNSPEC;
66 lifn.lifn_flags = lifc_flags;
67 if (ioctl(fd, SIOCGLIFNUM, &lifn) < 0)
68 return 0;
69
70 numifs = lifn.lifn_count;
71 bufsize = numifs * sizeof(struct lifreq);
72
73 lifc.lifc_family = AF_UNSPEC;
74 lifc.lifc_flags = lifc_flags;
75 lifc.lifc_len = bufsize;
76 lifc.lifc_buf = alloca(bufsize);
77
78 if (ioctl(fd, SIOCGLIFCONF, &lifc) < 0)
79 return 0;
80
81 lifrp = lifc.lifc_req;
82 for (i = lifc.lifc_len / sizeof(struct lifreq); i; i--, lifrp++)
83 {
84 struct lifreq lifr;
85 strncpy(lifr.lifr_name, lifrp->lifr_name, IF_NAMESIZE);
86 if (ioctl(fd, SIOCGLIFINDEX, &lifr) < 0)
87 return 0;
88
89 if (lifr.lifr_index == index) {
90 strncpy(name, lifr.lifr_name, IF_NAMESIZE);
91 return 1;
92 }
93 }
94 return 0;
95}
96
97
Simon Kelley7622fc02009-06-04 20:32:05 +010098#else
99
100int indextoname(int fd, int index, char *name)
101{
Simon Kelley115ac3e2013-05-20 11:28:32 +0100102 (void)fd;
103
Simon Kelley7622fc02009-06-04 20:32:05 +0100104 if (index == 0 || !if_indextoname(index, name))
105 return 0;
106
107 return 1;
108}
109
110#endif
111
Simon Kelley4f7b3042012-11-28 21:27:02 +0000112int iface_check(int family, struct all_addr *addr, char *name, int *auth)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000113{
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000114 struct iname *tmp;
Simon Kelleyedf0bde2013-07-29 17:21:48 +0100115 int ret = 1, match_addr = 0;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100116
Simon Kelley309331f2006-04-22 15:05:01 +0100117 /* Note: have to check all and not bail out early, so that we set the
Simon Kelley89500e32013-09-20 16:29:20 +0100118 "used" flags.
119
120 May be called with family == AF_LOCALto check interface by name only. */
Simon Kelley429798f2012-12-10 20:45:53 +0000121
Simon Kelley4f7b3042012-11-28 21:27:02 +0000122 if (auth)
Simon Kelley429798f2012-12-10 20:45:53 +0000123 *auth = 0;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100124
Simon Kelleyc72daea2012-01-05 21:33:27 +0000125 if (daemon->if_names || daemon->if_addrs)
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100126 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100127 ret = 0;
128
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100129 for (tmp = daemon->if_names; tmp; tmp = tmp->next)
Simon Kelley49333cb2013-03-15 20:30:51 +0000130 if (tmp->name && wildcard_match(tmp->name, name))
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100131 ret = tmp->used = 1;
132
Simon Kelley429798f2012-12-10 20:45:53 +0000133 if (addr)
134 for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
135 if (tmp->addr.sa.sa_family == family)
136 {
137 if (family == AF_INET &&
138 tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
Simon Kelleyedf0bde2013-07-29 17:21:48 +0100139 ret = match_addr = tmp->used = 1;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100140#ifdef HAVE_IPV6
Simon Kelley429798f2012-12-10 20:45:53 +0000141 else if (family == AF_INET6 &&
142 IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr,
143 &addr->addr.addr6))
Simon Kelleyedf0bde2013-07-29 17:21:48 +0100144 ret = match_addr = tmp->used = 1;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100145#endif
Simon Kelley429798f2012-12-10 20:45:53 +0000146 }
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100147 }
148
Simon Kelleyedf0bde2013-07-29 17:21:48 +0100149 if (!match_addr)
150 for (tmp = daemon->if_except; tmp; tmp = tmp->next)
151 if (tmp->name && wildcard_match(tmp->name, name))
152 ret = 0;
Simon Kelleyc72daea2012-01-05 21:33:27 +0000153
Simon Kelley429798f2012-12-10 20:45:53 +0000154
155 for (tmp = daemon->authinterface; tmp; tmp = tmp->next)
156 if (tmp->name)
157 {
Simon Kelleyf25e6c62013-11-17 12:23:42 +0000158 if (strcmp(tmp->name, name) == 0 &&
159 (tmp->addr.sa.sa_family == 0 || tmp->addr.sa.sa_family == family))
Simon Kelley429798f2012-12-10 20:45:53 +0000160 break;
161 }
162 else if (addr && tmp->addr.sa.sa_family == AF_INET && family == AF_INET &&
163 tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
164 break;
165#ifdef HAVE_IPV6
166 else if (addr && tmp->addr.sa.sa_family == AF_INET6 && family == AF_INET6 &&
167 IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, &addr->addr.addr6))
168 break;
169#endif
170
171 if (tmp && auth)
172 {
173 *auth = 1;
174 ret = 1;
175 }
176
Simon Kelley309331f2006-04-22 15:05:01 +0100177 return ret;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100178}
Simon Kelleye25db1f2013-01-29 22:10:26 +0000179
180
Josh Soref730c6742017-02-06 16:14:04 +0000181/* Fix for problem that the kernel sometimes reports the loopback interface as the
Simon Kelleye25db1f2013-01-29 22:10:26 +0000182 arrival interface when a packet originates locally, even when sent to address of
183 an interface other than the loopback. Accept packet if it arrived via a loopback
184 interface, even when we're not accepting packets that way, as long as the destination
185 address is one we're believing. Interface list must be up-to-date before calling. */
186int loopback_exception(int fd, int family, struct all_addr *addr, char *name)
187{
188 struct ifreq ifr;
189 struct irec *iface;
190
191 strncpy(ifr.ifr_name, name, IF_NAMESIZE);
192 if (ioctl(fd, SIOCGIFFLAGS, &ifr) != -1 &&
193 ifr.ifr_flags & IFF_LOOPBACK)
194 {
195 for (iface = daemon->interfaces; iface; iface = iface->next)
196 if (iface->addr.sa.sa_family == family)
197 {
198 if (family == AF_INET)
199 {
200 if (iface->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
201 return 1;
202 }
203#ifdef HAVE_IPV6
204 else if (IN6_ARE_ADDR_EQUAL(&iface->addr.in6.sin6_addr, &addr->addr.addr6))
205 return 1;
206#endif
207
208 }
209 }
210 return 0;
211}
212
Simon Kelley3f2873d2013-05-14 11:28:47 +0100213/* If we're configured with something like --interface=eth0:0 then we'll listen correctly
214 on the relevant address, but the name of the arrival interface, derived from the
215 index won't match the config. Check that we found an interface address for the arrival
216 interface: daemon->interfaces must be up-to-date. */
217int label_exception(int index, int family, struct all_addr *addr)
218{
219 struct irec *iface;
220
221 /* labels only supported on IPv4 addresses. */
222 if (family != AF_INET)
223 return 0;
224
225 for (iface = daemon->interfaces; iface; iface = iface->next)
226 if (iface->index == index && iface->addr.sa.sa_family == AF_INET &&
227 iface->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
228 return 1;
229
230 return 0;
231}
232
Simon Kelley115ac3e2013-05-20 11:28:32 +0100233struct iface_param {
234 struct addrlist *spare;
235 int fd;
236};
237
238static int iface_allowed(struct iface_param *param, int if_index, char *label,
Simon Kelley47669362014-12-17 12:41:56 +0000239 union mysockaddr *addr, struct in_addr netmask, int prefixlen, int iface_flags)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100240{
241 struct irec *iface;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100242 int mtu = 0, loopback;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100243 struct ifreq ifr;
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100244 int tftp_ok = !!option_bool(OPT_TFTP);
Simon Kelley9380ba72012-04-16 14:41:56 +0100245 int dhcp_ok = 1;
Simon Kelley4f7b3042012-11-28 21:27:02 +0000246 int auth_dns = 0;
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 {
1152 unsigned short port = rand16();
1153
Hans Dedecker926332a2016-01-23 10:48:12 +00001154 if (daemon->min_port != 0 || daemon->max_port != MAX_PORT)
1155 port = htons(daemon->min_port + (port % ((unsigned short)ports_avail)));
Simon Kelley1a6bca82008-07-11 11:11:42 +01001156
1157 if (family == AF_INET)
1158 {
1159 addr.in.sin_addr.s_addr = INADDR_ANY;
Simon Kelley3927da42008-07-20 15:10:39 +01001160 addr.in.sin_port = port;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001161#ifdef HAVE_SOCKADDR_SA_LEN
1162 addr.in.sin_len = sizeof(struct sockaddr_in);
1163#endif
1164 }
1165#ifdef HAVE_IPV6
1166 else
1167 {
1168 addr.in6.sin6_addr = in6addr_any;
Simon Kelley3927da42008-07-20 15:10:39 +01001169 addr.in6.sin6_port = port;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001170#ifdef HAVE_SOCKADDR_SA_LEN
1171 addr.in6.sin6_len = sizeof(struct sockaddr_in6);
1172#endif
1173 }
1174#endif
1175
1176 if (bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == 0)
1177 return fd;
1178
1179 if (errno != EADDRINUSE && errno != EACCES)
1180 break;
1181 }
1182
1183 close(fd);
1184 }
1185
1186 return -1;
1187}
1188
1189
Simon Kelley824af852008-02-12 20:43:05 +00001190int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp)
1191{
1192 union mysockaddr addr_copy = *addr;
1193
1194 /* cannot set source _port_ for TCP connections. */
1195 if (is_tcp)
1196 {
1197 if (addr_copy.sa.sa_family == AF_INET)
1198 addr_copy.in.sin_port = 0;
1199#ifdef HAVE_IPV6
1200 else
1201 addr_copy.in6.sin6_port = 0;
1202#endif
1203 }
1204
1205 if (bind(fd, (struct sockaddr *)&addr_copy, sa_len(&addr_copy)) == -1)
1206 return 0;
1207
1208#if defined(SO_BINDTODEVICE)
Simon Kelley73a08a22009-02-05 20:28:08 +00001209 if (intname[0] != 0 &&
Simon Kelley316e2732010-01-22 20:16:09 +00001210 setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, intname, IF_NAMESIZE) == -1)
Simon Kelley824af852008-02-12 20:43:05 +00001211 return 0;
1212#endif
1213
1214 return 1;
1215}
1216
1217static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001218{
1219 struct serverfd *sfd;
Beniamino Galvani2675f202016-08-28 20:44:05 +01001220 unsigned int ifindex = 0;
Simon Kelley824af852008-02-12 20:43:05 +00001221 int errsave;
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001222
Simon Kelley1a6bca82008-07-11 11:11:42 +01001223 /* when using random ports, servers which would otherwise use
1224 the INADDR_ANY/port0 socket have sfd set to NULL */
Simon Kelley73a08a22009-02-05 20:28:08 +00001225 if (!daemon->osport && intname[0] == 0)
Simon Kelley1a6bca82008-07-11 11:11:42 +01001226 {
1227 errno = 0;
1228
1229 if (addr->sa.sa_family == AF_INET &&
1230 addr->in.sin_addr.s_addr == INADDR_ANY &&
1231 addr->in.sin_port == htons(0))
1232 return NULL;
1233
1234#ifdef HAVE_IPV6
1235 if (addr->sa.sa_family == AF_INET6 &&
1236 memcmp(&addr->in6.sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0 &&
1237 addr->in6.sin6_port == htons(0))
1238 return NULL;
1239#endif
1240 }
Beniamino Galvani2675f202016-08-28 20:44:05 +01001241
1242 if (intname && strlen(intname) != 0)
1243 ifindex = if_nametoindex(intname); /* index == 0 when not binding to an interface */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001244
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001245 /* may have a suitable one already */
Simon Kelley824af852008-02-12 20:43:05 +00001246 for (sfd = daemon->sfds; sfd; sfd = sfd->next )
1247 if (sockaddr_isequal(&sfd->source_addr, addr) &&
Beniamino Galvani2675f202016-08-28 20:44:05 +01001248 strcmp(intname, sfd->interface) == 0 &&
1249 ifindex == sfd->ifindex)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001250 return sfd;
1251
1252 /* need to make a new one. */
1253 errno = ENOMEM; /* in case malloc fails. */
Simon Kelley5aabfc72007-08-29 11:24:47 +01001254 if (!(sfd = whine_malloc(sizeof(struct serverfd))))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001255 return NULL;
1256
1257 if ((sfd->fd = socket(addr->sa.sa_family, SOCK_DGRAM, 0)) == -1)
1258 {
1259 free(sfd);
1260 return NULL;
1261 }
1262
Simon Kelley824af852008-02-12 20:43:05 +00001263 if (!local_bind(sfd->fd, addr, intname, 0) || !fix_fd(sfd->fd))
1264 {
1265 errsave = errno; /* save error from bind. */
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001266 close(sfd->fd);
1267 free(sfd);
1268 errno = errsave;
1269 return NULL;
1270 }
Beniamino Galvani2675f202016-08-28 20:44:05 +01001271
Simon Kelley824af852008-02-12 20:43:05 +00001272 strcpy(sfd->interface, intname);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001273 sfd->source_addr = *addr;
Simon Kelley824af852008-02-12 20:43:05 +00001274 sfd->next = daemon->sfds;
Beniamino Galvani2675f202016-08-28 20:44:05 +01001275 sfd->ifindex = ifindex;
Simon Kelley824af852008-02-12 20:43:05 +00001276 daemon->sfds = sfd;
Beniamino Galvani2675f202016-08-28 20:44:05 +01001277
Simon Kelley824af852008-02-12 20:43:05 +00001278 return sfd;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001279}
1280
Simon Kelley824af852008-02-12 20:43:05 +00001281/* create upstream sockets during startup, before root is dropped which may be needed
1282 this allows query_port to be a low port and interface binding */
1283void pre_allocate_sfds(void)
1284{
1285 struct server *srv;
1286
1287 if (daemon->query_port != 0)
1288 {
1289 union mysockaddr addr;
1290 memset(&addr, 0, sizeof(addr));
1291 addr.in.sin_family = AF_INET;
1292 addr.in.sin_addr.s_addr = INADDR_ANY;
1293 addr.in.sin_port = htons(daemon->query_port);
1294#ifdef HAVE_SOCKADDR_SA_LEN
1295 addr.in.sin_len = sizeof(struct sockaddr_in);
1296#endif
1297 allocate_sfd(&addr, "");
1298#ifdef HAVE_IPV6
1299 memset(&addr, 0, sizeof(addr));
1300 addr.in6.sin6_family = AF_INET6;
1301 addr.in6.sin6_addr = in6addr_any;
1302 addr.in6.sin6_port = htons(daemon->query_port);
1303#ifdef HAVE_SOCKADDR_SA_LEN
1304 addr.in6.sin6_len = sizeof(struct sockaddr_in6);
1305#endif
1306 allocate_sfd(&addr, "");
1307#endif
1308 }
1309
1310 for (srv = daemon->servers; srv; srv = srv->next)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001311 if (!(srv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)) &&
Simon Kelley824af852008-02-12 20:43:05 +00001312 !allocate_sfd(&srv->source_addr, srv->interface) &&
Simon Kelley1a6bca82008-07-11 11:11:42 +01001313 errno != 0 &&
Simon Kelley28866e92011-02-14 20:19:14 +00001314 option_bool(OPT_NOWILD))
Simon Kelley824af852008-02-12 20:43:05 +00001315 {
Simon Kelley316e2732010-01-22 20:16:09 +00001316 prettyprint_addr(&srv->source_addr, daemon->namebuff);
Simon Kelley73a08a22009-02-05 20:28:08 +00001317 if (srv->interface[0] != 0)
Simon Kelley824af852008-02-12 20:43:05 +00001318 {
1319 strcat(daemon->namebuff, " ");
1320 strcat(daemon->namebuff, srv->interface);
1321 }
1322 die(_("failed to bind server socket for %s: %s"),
1323 daemon->namebuff, EC_BADNET);
1324 }
1325}
1326
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001327void mark_servers(int flag)
1328{
1329 struct server *serv;
1330
1331 /* mark everything with argument flag */
1332 for (serv = daemon->servers; serv; serv = serv->next)
Simon Kelley40766e52014-07-29 16:52:00 +01001333 {
1334 if (serv->flags & flag)
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001335 serv->flags |= SERV_MARK;
1336#ifdef HAVE_LOOP
Simon Kelley40766e52014-07-29 16:52:00 +01001337 /* Give looped servers another chance */
1338 serv->flags &= ~SERV_LOOP;
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001339#endif
Simon Kelley40766e52014-07-29 16:52:00 +01001340 }
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001341}
1342
1343void cleanup_servers(void)
1344{
1345 struct server *serv, *tmp, **up;
1346
1347 /* unlink and free anything still marked. */
1348 for (serv = daemon->servers, up = &daemon->servers; serv; serv = tmp)
1349 {
1350 tmp = serv->next;
1351 if (serv->flags & SERV_MARK)
1352 {
1353 server_gone(serv);
1354 *up = serv->next;
1355 if (serv->domain)
1356 free(serv->domain);
1357 free(serv);
1358 }
1359 else
1360 up = &serv->next;
1361 }
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001362
1363#ifdef HAVE_LOOP
1364 /* Now we have a new set of servers, test for loops. */
1365 loop_send_probes();
1366#endif
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001367}
1368
1369void add_update_server(int flags,
1370 union mysockaddr *addr,
1371 union mysockaddr *source_addr,
1372 const char *interface,
1373 const char *domain)
1374{
Simon Kelley7b1eae42014-02-20 13:43:28 +00001375 struct server *serv, *next = NULL;
1376 char *domain_str = NULL;
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001377
1378 /* See if there is a suitable candidate, and unmark */
1379 for (serv = daemon->servers; serv; serv = serv->next)
1380 if (serv->flags & SERV_MARK)
1381 {
1382 if (domain)
1383 {
1384 if (!(serv->flags & SERV_HAS_DOMAIN) || !hostname_isequal(domain, serv->domain))
1385 continue;
1386 }
1387 else
1388 {
1389 if (serv->flags & SERV_HAS_DOMAIN)
1390 continue;
1391 }
1392
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001393 break;
1394 }
Simon Kelley7b1eae42014-02-20 13:43:28 +00001395
1396 if (serv)
1397 {
1398 domain_str = serv->domain;
1399 next = serv->next;
1400 }
1401 else if ((serv = whine_malloc(sizeof (struct server))))
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001402 {
1403 /* Not found, create a new one. */
Simon Kelley7b1eae42014-02-20 13:43:28 +00001404 if (domain && !(domain_str = whine_malloc(strlen(domain)+1)))
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001405 {
1406 free(serv);
1407 serv = NULL;
1408 }
1409 else
1410 {
1411 struct server *s;
1412 /* Add to the end of the chain, for order */
1413 if (!daemon->servers)
1414 daemon->servers = serv;
1415 else
1416 {
1417 for (s = daemon->servers; s->next; s = s->next);
1418 s->next = serv;
1419 }
1420 if (domain)
Simon Kelley7b1eae42014-02-20 13:43:28 +00001421 strcpy(domain_str, domain);
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001422 }
1423 }
1424
1425 if (serv)
1426 {
Simon Kelley7b1eae42014-02-20 13:43:28 +00001427 memset(serv, 0, sizeof(struct server));
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001428 serv->flags = flags;
Simon Kelley7b1eae42014-02-20 13:43:28 +00001429 serv->domain = domain_str;
1430 serv->next = next;
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001431 serv->queries = serv->failed_queries = 0;
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001432#ifdef HAVE_LOOP
1433 serv->uid = rand32();
1434#endif
1435
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001436 if (domain)
1437 serv->flags |= SERV_HAS_DOMAIN;
1438
1439 if (interface)
Simon Kelley7b1eae42014-02-20 13:43:28 +00001440 strcpy(serv->interface, interface);
1441 if (addr)
1442 serv->addr = *addr;
1443 if (source_addr)
1444 serv->source_addr = *source_addr;
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001445 }
1446}
Simon Kelley824af852008-02-12 20:43:05 +00001447
Simon Kelley5aabfc72007-08-29 11:24:47 +01001448void check_servers(void)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001449{
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001450 struct irec *iface;
Simon Kelley7bcca002014-02-19 17:45:17 +00001451 struct server *serv;
Beniamino Galvani2675f202016-08-28 20:44:05 +01001452 struct serverfd *sfd, *tmp, **up;
Simon Kelleyb9702602016-05-03 22:34:06 +01001453 int port = 0, count;
Hannu Nyman3e2496f2017-02-11 13:44:08 +00001454 int locals = 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001455
Simon Kelley316e2732010-01-22 20:16:09 +00001456 /* interface may be new since startup */
Simon Kelley28866e92011-02-14 20:19:14 +00001457 if (!option_bool(OPT_NOWILD))
Simon Kelley115ac3e2013-05-20 11:28:32 +01001458 enumerate_interfaces(0);
Simon Kelley316e2732010-01-22 20:16:09 +00001459
Beniamino Galvani2675f202016-08-28 20:44:05 +01001460 for (sfd = daemon->sfds; sfd; sfd = sfd->next)
1461 sfd->used = 0;
1462
Simon Kelley367341f2016-01-12 15:58:23 +00001463#ifdef HAVE_DNSSEC
1464 /* Disable DNSSEC validation when using server=/domain/.... servers
1465 unless there's a configured trust anchor. */
1466 for (serv = daemon->servers; serv; serv = serv->next)
1467 serv->flags |= SERV_DO_DNSSEC;
1468#endif
1469
Simon Kelleyb9702602016-05-03 22:34:06 +01001470 for (count = 0, serv = daemon->servers; serv; serv = serv->next)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001471 {
Simon Kelley367341f2016-01-12 15:58:23 +00001472 if (!(serv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001473 {
Simon Kelley14ffa072016-04-25 16:36:44 +01001474 /* Init edns_pktsz for newly created server records. */
1475 if (serv->edns_pktsz == 0)
1476 serv->edns_pktsz = daemon->edns_pktsz;
1477
Simon Kelley367341f2016-01-12 15:58:23 +00001478#ifdef HAVE_DNSSEC
Simon Kelley92be34a2016-01-16 18:39:54 +00001479 if (option_bool(OPT_DNSSEC_VALID))
1480 {
1481 if (serv->flags & SERV_HAS_DOMAIN)
1482 {
1483 struct ds_config *ds;
1484 char *domain = serv->domain;
1485
1486 /* .example.com is valid */
1487 while (*domain == '.')
1488 domain++;
1489
1490 for (ds = daemon->ds; ds; ds = ds->next)
1491 if (ds->name[0] != 0 && hostname_isequal(domain, ds->name))
1492 break;
1493
1494 if (!ds)
1495 serv->flags &= ~SERV_DO_DNSSEC;
1496 }
1497 else if (serv->flags & SERV_FOR_NODOTS)
Simon Kelley367341f2016-01-12 15:58:23 +00001498 serv->flags &= ~SERV_DO_DNSSEC;
1499 }
1500#endif
1501
1502 port = prettyprint_addr(&serv->addr, daemon->namebuff);
1503
Simon Kelley16972692006-10-16 20:04:18 +01001504 /* 0.0.0.0 is nothing, the stack treats it like 127.0.0.1 */
Simon Kelley7bcca002014-02-19 17:45:17 +00001505 if (serv->addr.sa.sa_family == AF_INET &&
1506 serv->addr.in.sin_addr.s_addr == 0)
Simon Kelley16972692006-10-16 20:04:18 +01001507 {
Simon Kelley7bcca002014-02-19 17:45:17 +00001508 serv->flags |= SERV_MARK;
Simon Kelley16972692006-10-16 20:04:18 +01001509 continue;
1510 }
1511
Simon Kelley3d8df262005-08-29 12:19:27 +01001512 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelley7bcca002014-02-19 17:45:17 +00001513 if (sockaddr_isequal(&serv->addr, &iface->addr))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001514 break;
1515 if (iface)
1516 {
Simon Kelleyf2621c72007-04-29 19:47:21 +01001517 my_syslog(LOG_WARNING, _("ignoring nameserver %s - local interface"), daemon->namebuff);
Simon Kelley7bcca002014-02-19 17:45:17 +00001518 serv->flags |= SERV_MARK;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001519 continue;
1520 }
1521
1522 /* Do we need a socket set? */
Simon Kelley7bcca002014-02-19 17:45:17 +00001523 if (!serv->sfd &&
1524 !(serv->sfd = allocate_sfd(&serv->source_addr, serv->interface)) &&
Simon Kelley1a6bca82008-07-11 11:11:42 +01001525 errno != 0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001526 {
Simon Kelleyf2621c72007-04-29 19:47:21 +01001527 my_syslog(LOG_WARNING,
1528 _("ignoring nameserver %s - cannot make/bind socket: %s"),
1529 daemon->namebuff, strerror(errno));
Simon Kelley7bcca002014-02-19 17:45:17 +00001530 serv->flags |= SERV_MARK;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001531 continue;
1532 }
Simon Kelley16800ea2016-08-30 23:07:06 +01001533
1534 if (serv->sfd)
1535 serv->sfd->used = 1;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001536 }
1537
Simon Kelley979fe862015-03-19 22:50:22 +00001538 if (!(serv->flags & SERV_NO_REBIND) && !(serv->flags & SERV_LITERAL_ADDRESS))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001539 {
Simon Kelleyb9702602016-05-03 22:34:06 +01001540 if (++count > SERVERS_LOGGED)
1541 continue;
1542
Simon Kelley7bcca002014-02-19 17:45:17 +00001543 if (serv->flags & (SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_USE_RESOLV))
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001544 {
Simon Kelley367341f2016-01-12 15:58:23 +00001545 char *s1, *s2, *s3 = "";
1546#ifdef HAVE_DNSSEC
1547 if (option_bool(OPT_DNSSEC_VALID) && !(serv->flags & SERV_DO_DNSSEC))
1548 s3 = _("(no DNSSEC)");
1549#endif
Simon Kelley7bcca002014-02-19 17:45:17 +00001550 if (!(serv->flags & SERV_HAS_DOMAIN))
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001551 s1 = _("unqualified"), s2 = _("names");
Simon Kelley7bcca002014-02-19 17:45:17 +00001552 else if (strlen(serv->domain) == 0)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001553 s1 = _("default"), s2 = "";
1554 else
Simon Kelley7bcca002014-02-19 17:45:17 +00001555 s1 = _("domain"), s2 = serv->domain;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001556
Simon Kelley7bcca002014-02-19 17:45:17 +00001557 if (serv->flags & SERV_NO_ADDR)
Hannu Nyman3e2496f2017-02-11 13:44:08 +00001558 {
1559 count--;
1560 if (++locals <= LOCALS_LOGGED)
1561 my_syslog(LOG_INFO, _("using local addresses only for %s %s"), s1, s2);
1562 }
Simon Kelley7bcca002014-02-19 17:45:17 +00001563 else if (serv->flags & SERV_USE_RESOLV)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001564 my_syslog(LOG_INFO, _("using standard nameservers for %s %s"), s1, s2);
Simon Kelley979fe862015-03-19 22:50:22 +00001565 else
Simon Kelley367341f2016-01-12 15:58:23 +00001566 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 +01001567 }
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001568#ifdef HAVE_LOOP
1569 else if (serv->flags & SERV_LOOP)
1570 my_syslog(LOG_INFO, _("NOT using nameserver %s#%d - query loop detected"), daemon->namebuff, port);
1571#endif
Simon Kelley7bcca002014-02-19 17:45:17 +00001572 else if (serv->interface[0] != 0)
1573 my_syslog(LOG_INFO, _("using nameserver %s#%d(via %s)"), daemon->namebuff, port, serv->interface);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001574 else
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001575 my_syslog(LOG_INFO, _("using nameserver %s#%d"), daemon->namebuff, port);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001576 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001577 }
Simon Kelleyb9702602016-05-03 22:34:06 +01001578
Hannu Nyman3e2496f2017-02-11 13:44:08 +00001579 if (locals > LOCALS_LOGGED)
1580 my_syslog(LOG_INFO, _("using %d more local addresses"), locals - LOCALS_LOGGED);
Simon Kelleyb9702602016-05-03 22:34:06 +01001581 if (count - 1 > SERVERS_LOGGED)
1582 my_syslog(LOG_INFO, _("using %d more nameservers"), count - SERVERS_LOGGED - 1);
Simon Kelley7bcca002014-02-19 17:45:17 +00001583
Beniamino Galvani2675f202016-08-28 20:44:05 +01001584 /* Remove unused sfds */
1585 for (sfd = daemon->sfds, up = &daemon->sfds; sfd; sfd = tmp)
1586 {
1587 tmp = sfd->next;
1588 if (!sfd->used)
1589 {
1590 *up = sfd->next;
1591 close(sfd->fd);
1592 free(sfd);
1593 }
1594 else
1595 up = &sfd->next;
1596 }
1597
Simon Kelley7bcca002014-02-19 17:45:17 +00001598 cleanup_servers();
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001599}
Simon Kelley849a8352006-06-09 21:02:31 +01001600
1601/* Return zero if no servers found, in that case we keep polling.
1602 This is a protection against an update-time/write race on resolv.conf */
Simon Kelley5aabfc72007-08-29 11:24:47 +01001603int reload_servers(char *fname)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001604{
1605 FILE *f;
1606 char *line;
Simon Kelley849a8352006-06-09 21:02:31 +01001607 int gotone = 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001608
Simon Kelley849a8352006-06-09 21:02:31 +01001609 /* buff happens to be MAXDNAME long... */
1610 if (!(f = fopen(fname, "r")))
1611 {
Simon Kelleyf2621c72007-04-29 19:47:21 +01001612 my_syslog(LOG_ERR, _("failed to read %s: %s"), fname, strerror(errno));
Simon Kelley849a8352006-06-09 21:02:31 +01001613 return 0;
1614 }
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001615
1616 mark_servers(SERV_FROM_RESOLV);
1617
Simon Kelley849a8352006-06-09 21:02:31 +01001618 while ((line = fgets(daemon->namebuff, MAXDNAME, f)))
1619 {
1620 union mysockaddr addr, source_addr;
1621 char *token = strtok(line, " \t\n\r");
1622
Simon Kelley5aabfc72007-08-29 11:24:47 +01001623 if (!token)
1624 continue;
1625 if (strcmp(token, "nameserver") != 0 && strcmp(token, "server") != 0)
Simon Kelley849a8352006-06-09 21:02:31 +01001626 continue;
1627 if (!(token = strtok(NULL, " \t\n\r")))
1628 continue;
1629
1630 memset(&addr, 0, sizeof(addr));
1631 memset(&source_addr, 0, sizeof(source_addr));
1632
1633 if ((addr.in.sin_addr.s_addr = inet_addr(token)) != (in_addr_t) -1)
1634 {
1635#ifdef HAVE_SOCKADDR_SA_LEN
1636 source_addr.in.sin_len = addr.in.sin_len = sizeof(source_addr.in);
1637#endif
1638 source_addr.in.sin_family = addr.in.sin_family = AF_INET;
1639 addr.in.sin_port = htons(NAMESERVER_PORT);
1640 source_addr.in.sin_addr.s_addr = INADDR_ANY;
1641 source_addr.in.sin_port = htons(daemon->query_port);
1642 }
1643#ifdef HAVE_IPV6
Simon Kelley7de060b2011-08-26 17:24:52 +01001644 else
1645 {
1646 int scope_index = 0;
1647 char *scope_id = strchr(token, '%');
1648
1649 if (scope_id)
1650 {
1651 *(scope_id++) = 0;
1652 scope_index = if_nametoindex(scope_id);
1653 }
1654
1655 if (inet_pton(AF_INET6, token, &addr.in6.sin6_addr) > 0)
1656 {
Simon Kelley849a8352006-06-09 21:02:31 +01001657#ifdef HAVE_SOCKADDR_SA_LEN
Simon Kelley7de060b2011-08-26 17:24:52 +01001658 source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(source_addr.in6);
Simon Kelley849a8352006-06-09 21:02:31 +01001659#endif
Simon Kelley7de060b2011-08-26 17:24:52 +01001660 source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6;
1661 source_addr.in6.sin6_flowinfo = addr.in6.sin6_flowinfo = 0;
1662 addr.in6.sin6_port = htons(NAMESERVER_PORT);
1663 addr.in6.sin6_scope_id = scope_index;
1664 source_addr.in6.sin6_addr = in6addr_any;
1665 source_addr.in6.sin6_port = htons(daemon->query_port);
1666 source_addr.in6.sin6_scope_id = 0;
1667 }
1668 else
1669 continue;
Simon Kelley849a8352006-06-09 21:02:31 +01001670 }
Simon Kelley7de060b2011-08-26 17:24:52 +01001671#else /* IPV6 */
Simon Kelley849a8352006-06-09 21:02:31 +01001672 else
1673 continue;
Simon Kelley7de060b2011-08-26 17:24:52 +01001674#endif
1675
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001676 add_update_server(SERV_FROM_RESOLV, &addr, &source_addr, NULL, NULL);
Simon Kelley849a8352006-06-09 21:02:31 +01001677 gotone = 1;
1678 }
1679
Simon Kelley849a8352006-06-09 21:02:31 +01001680 fclose(f);
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001681 cleanup_servers();
Simon Kelley849a8352006-06-09 21:02:31 +01001682
1683 return gotone;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001684}
1685
Simon Kelley1ee9be42013-12-09 16:50:19 +00001686/* Called when addresses are added or deleted from an interface */
1687void newaddress(time_t now)
1688{
1689 (void)now;
1690
Simon Kelley89b12ed2014-03-06 13:27:57 +00001691 if (option_bool(OPT_CLEVERBIND) || option_bool(OPT_LOCAL_SERVICE) ||
1692 daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
Simon Kelley1ee9be42013-12-09 16:50:19 +00001693 enumerate_interfaces(0);
1694
1695 if (option_bool(OPT_CLEVERBIND))
1696 create_bound_listeners(0);
1697
1698#ifdef HAVE_DHCP6
1699 if (daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
1700 join_multicast(0);
1701
1702 if (daemon->doing_dhcp6 || daemon->doing_ra)
1703 dhcp_construct_contexts(now);
1704
1705 if (daemon->doing_dhcp6)
1706 lease_find_interfaces(now);
1707#endif
1708}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001709
1710
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001711
1712
1713