blob: 038151371508593ce40e72781f74e8635fc0e72f [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 Kelleyfd9fa482004-10-21 20:24:00 +01001237
Simon Kelley1a6bca82008-07-11 11:11:42 +01001238 /* when using random ports, servers which would otherwise use
1239 the INADDR_ANY/port0 socket have sfd set to NULL */
Simon Kelley73a08a22009-02-05 20:28:08 +00001240 if (!daemon->osport && intname[0] == 0)
Simon Kelley1a6bca82008-07-11 11:11:42 +01001241 {
1242 errno = 0;
1243
1244 if (addr->sa.sa_family == AF_INET &&
1245 addr->in.sin_addr.s_addr == INADDR_ANY &&
1246 addr->in.sin_port == htons(0))
1247 return NULL;
1248
1249#ifdef HAVE_IPV6
1250 if (addr->sa.sa_family == AF_INET6 &&
1251 memcmp(&addr->in6.sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0 &&
1252 addr->in6.sin6_port == htons(0))
1253 return NULL;
1254#endif
1255 }
Beniamino Galvani2675f202016-08-28 20:44:05 +01001256
1257 if (intname && strlen(intname) != 0)
1258 ifindex = if_nametoindex(intname); /* index == 0 when not binding to an interface */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001259
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001260 /* may have a suitable one already */
Simon Kelley824af852008-02-12 20:43:05 +00001261 for (sfd = daemon->sfds; sfd; sfd = sfd->next )
1262 if (sockaddr_isequal(&sfd->source_addr, addr) &&
Beniamino Galvani2675f202016-08-28 20:44:05 +01001263 strcmp(intname, sfd->interface) == 0 &&
1264 ifindex == sfd->ifindex)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001265 return sfd;
1266
1267 /* need to make a new one. */
1268 errno = ENOMEM; /* in case malloc fails. */
Simon Kelley5aabfc72007-08-29 11:24:47 +01001269 if (!(sfd = whine_malloc(sizeof(struct serverfd))))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001270 return NULL;
1271
1272 if ((sfd->fd = socket(addr->sa.sa_family, SOCK_DGRAM, 0)) == -1)
1273 {
1274 free(sfd);
1275 return NULL;
1276 }
1277
Simon Kelley9d6918d2017-10-13 17:55:09 +01001278 if (!local_bind(sfd->fd, addr, intname, ifindex, 0) || !fix_fd(sfd->fd))
Simon Kelley824af852008-02-12 20:43:05 +00001279 {
1280 errsave = errno; /* save error from bind. */
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001281 close(sfd->fd);
1282 free(sfd);
1283 errno = errsave;
1284 return NULL;
1285 }
Beniamino Galvani2675f202016-08-28 20:44:05 +01001286
Simon Kelley824af852008-02-12 20:43:05 +00001287 strcpy(sfd->interface, intname);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001288 sfd->source_addr = *addr;
Simon Kelley824af852008-02-12 20:43:05 +00001289 sfd->next = daemon->sfds;
Beniamino Galvani2675f202016-08-28 20:44:05 +01001290 sfd->ifindex = ifindex;
Simon Kelley824af852008-02-12 20:43:05 +00001291 daemon->sfds = sfd;
Beniamino Galvani2675f202016-08-28 20:44:05 +01001292
Simon Kelley824af852008-02-12 20:43:05 +00001293 return sfd;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001294}
1295
Simon Kelley824af852008-02-12 20:43:05 +00001296/* create upstream sockets during startup, before root is dropped which may be needed
1297 this allows query_port to be a low port and interface binding */
1298void pre_allocate_sfds(void)
1299{
1300 struct server *srv;
1301
1302 if (daemon->query_port != 0)
1303 {
1304 union mysockaddr addr;
1305 memset(&addr, 0, sizeof(addr));
1306 addr.in.sin_family = AF_INET;
1307 addr.in.sin_addr.s_addr = INADDR_ANY;
1308 addr.in.sin_port = htons(daemon->query_port);
1309#ifdef HAVE_SOCKADDR_SA_LEN
1310 addr.in.sin_len = sizeof(struct sockaddr_in);
1311#endif
1312 allocate_sfd(&addr, "");
1313#ifdef HAVE_IPV6
1314 memset(&addr, 0, sizeof(addr));
1315 addr.in6.sin6_family = AF_INET6;
1316 addr.in6.sin6_addr = in6addr_any;
1317 addr.in6.sin6_port = htons(daemon->query_port);
1318#ifdef HAVE_SOCKADDR_SA_LEN
1319 addr.in6.sin6_len = sizeof(struct sockaddr_in6);
1320#endif
1321 allocate_sfd(&addr, "");
1322#endif
1323 }
1324
1325 for (srv = daemon->servers; srv; srv = srv->next)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001326 if (!(srv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)) &&
Simon Kelley824af852008-02-12 20:43:05 +00001327 !allocate_sfd(&srv->source_addr, srv->interface) &&
Simon Kelley1a6bca82008-07-11 11:11:42 +01001328 errno != 0 &&
Simon Kelley28866e92011-02-14 20:19:14 +00001329 option_bool(OPT_NOWILD))
Simon Kelley824af852008-02-12 20:43:05 +00001330 {
Simon Kelley316e2732010-01-22 20:16:09 +00001331 prettyprint_addr(&srv->source_addr, daemon->namebuff);
Simon Kelley73a08a22009-02-05 20:28:08 +00001332 if (srv->interface[0] != 0)
Simon Kelley824af852008-02-12 20:43:05 +00001333 {
1334 strcat(daemon->namebuff, " ");
1335 strcat(daemon->namebuff, srv->interface);
1336 }
1337 die(_("failed to bind server socket for %s: %s"),
1338 daemon->namebuff, EC_BADNET);
1339 }
1340}
1341
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001342void mark_servers(int flag)
1343{
1344 struct server *serv;
1345
1346 /* mark everything with argument flag */
1347 for (serv = daemon->servers; serv; serv = serv->next)
Simon Kelley40766e52014-07-29 16:52:00 +01001348 {
1349 if (serv->flags & flag)
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001350 serv->flags |= SERV_MARK;
1351#ifdef HAVE_LOOP
Simon Kelley40766e52014-07-29 16:52:00 +01001352 /* Give looped servers another chance */
1353 serv->flags &= ~SERV_LOOP;
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001354#endif
Simon Kelley40766e52014-07-29 16:52:00 +01001355 }
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001356}
1357
1358void cleanup_servers(void)
1359{
1360 struct server *serv, *tmp, **up;
1361
1362 /* unlink and free anything still marked. */
1363 for (serv = daemon->servers, up = &daemon->servers; serv; serv = tmp)
1364 {
1365 tmp = serv->next;
1366 if (serv->flags & SERV_MARK)
1367 {
1368 server_gone(serv);
1369 *up = serv->next;
1370 if (serv->domain)
1371 free(serv->domain);
1372 free(serv);
1373 }
1374 else
1375 up = &serv->next;
1376 }
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001377
1378#ifdef HAVE_LOOP
1379 /* Now we have a new set of servers, test for loops. */
1380 loop_send_probes();
1381#endif
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001382}
1383
1384void add_update_server(int flags,
1385 union mysockaddr *addr,
1386 union mysockaddr *source_addr,
1387 const char *interface,
1388 const char *domain)
1389{
Simon Kelley7b1eae42014-02-20 13:43:28 +00001390 struct server *serv, *next = NULL;
1391 char *domain_str = NULL;
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001392
1393 /* See if there is a suitable candidate, and unmark */
1394 for (serv = daemon->servers; serv; serv = serv->next)
1395 if (serv->flags & SERV_MARK)
1396 {
1397 if (domain)
1398 {
1399 if (!(serv->flags & SERV_HAS_DOMAIN) || !hostname_isequal(domain, serv->domain))
1400 continue;
1401 }
1402 else
1403 {
1404 if (serv->flags & SERV_HAS_DOMAIN)
1405 continue;
1406 }
1407
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001408 break;
1409 }
Simon Kelley7b1eae42014-02-20 13:43:28 +00001410
1411 if (serv)
1412 {
1413 domain_str = serv->domain;
1414 next = serv->next;
1415 }
1416 else if ((serv = whine_malloc(sizeof (struct server))))
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001417 {
1418 /* Not found, create a new one. */
Simon Kelley7b1eae42014-02-20 13:43:28 +00001419 if (domain && !(domain_str = whine_malloc(strlen(domain)+1)))
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001420 {
1421 free(serv);
1422 serv = NULL;
1423 }
1424 else
1425 {
1426 struct server *s;
1427 /* Add to the end of the chain, for order */
1428 if (!daemon->servers)
1429 daemon->servers = serv;
1430 else
1431 {
1432 for (s = daemon->servers; s->next; s = s->next);
1433 s->next = serv;
1434 }
1435 if (domain)
Simon Kelley7b1eae42014-02-20 13:43:28 +00001436 strcpy(domain_str, domain);
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001437 }
1438 }
1439
1440 if (serv)
1441 {
Simon Kelley7b1eae42014-02-20 13:43:28 +00001442 memset(serv, 0, sizeof(struct server));
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001443 serv->flags = flags;
Simon Kelley7b1eae42014-02-20 13:43:28 +00001444 serv->domain = domain_str;
1445 serv->next = next;
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001446 serv->queries = serv->failed_queries = 0;
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001447#ifdef HAVE_LOOP
1448 serv->uid = rand32();
1449#endif
1450
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001451 if (domain)
1452 serv->flags |= SERV_HAS_DOMAIN;
1453
1454 if (interface)
Simon Kelley7b1eae42014-02-20 13:43:28 +00001455 strcpy(serv->interface, interface);
1456 if (addr)
1457 serv->addr = *addr;
1458 if (source_addr)
1459 serv->source_addr = *source_addr;
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001460 }
1461}
Simon Kelley824af852008-02-12 20:43:05 +00001462
Simon Kelley5aabfc72007-08-29 11:24:47 +01001463void check_servers(void)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001464{
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001465 struct irec *iface;
Simon Kelley7bcca002014-02-19 17:45:17 +00001466 struct server *serv;
Beniamino Galvani2675f202016-08-28 20:44:05 +01001467 struct serverfd *sfd, *tmp, **up;
Simon Kelleyb9702602016-05-03 22:34:06 +01001468 int port = 0, count;
Hannu Nyman3e2496f2017-02-11 13:44:08 +00001469 int locals = 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001470
Simon Kelley316e2732010-01-22 20:16:09 +00001471 /* interface may be new since startup */
Simon Kelley28866e92011-02-14 20:19:14 +00001472 if (!option_bool(OPT_NOWILD))
Simon Kelley115ac3e2013-05-20 11:28:32 +01001473 enumerate_interfaces(0);
Simon Kelley316e2732010-01-22 20:16:09 +00001474
Beniamino Galvani2675f202016-08-28 20:44:05 +01001475 for (sfd = daemon->sfds; sfd; sfd = sfd->next)
1476 sfd->used = 0;
1477
Simon Kelleyb9702602016-05-03 22:34:06 +01001478 for (count = 0, serv = daemon->servers; serv; serv = serv->next)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001479 {
Simon Kelley367341f2016-01-12 15:58:23 +00001480 if (!(serv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001481 {
Simon Kelley14ffa072016-04-25 16:36:44 +01001482 /* Init edns_pktsz for newly created server records. */
1483 if (serv->edns_pktsz == 0)
1484 serv->edns_pktsz = daemon->edns_pktsz;
1485
Simon Kelley367341f2016-01-12 15:58:23 +00001486#ifdef HAVE_DNSSEC
Simon Kelley92be34a2016-01-16 18:39:54 +00001487 if (option_bool(OPT_DNSSEC_VALID))
1488 {
Simon Kelleya49c5c22017-10-10 22:04:59 +01001489 if (!(serv->flags & SERV_FOR_NODOTS))
1490 serv->flags |= SERV_DO_DNSSEC;
1491
1492 /* Disable DNSSEC validation when using server=/domain/.... servers
1493 unless there's a configured trust anchor. */
Simon Kelley92be34a2016-01-16 18:39:54 +00001494 if (serv->flags & SERV_HAS_DOMAIN)
1495 {
1496 struct ds_config *ds;
1497 char *domain = serv->domain;
1498
1499 /* .example.com is valid */
1500 while (*domain == '.')
1501 domain++;
1502
1503 for (ds = daemon->ds; ds; ds = ds->next)
1504 if (ds->name[0] != 0 && hostname_isequal(domain, ds->name))
1505 break;
1506
1507 if (!ds)
1508 serv->flags &= ~SERV_DO_DNSSEC;
1509 }
Simon Kelley367341f2016-01-12 15:58:23 +00001510 }
1511#endif
1512
1513 port = prettyprint_addr(&serv->addr, daemon->namebuff);
1514
Simon Kelley16972692006-10-16 20:04:18 +01001515 /* 0.0.0.0 is nothing, the stack treats it like 127.0.0.1 */
Simon Kelley7bcca002014-02-19 17:45:17 +00001516 if (serv->addr.sa.sa_family == AF_INET &&
1517 serv->addr.in.sin_addr.s_addr == 0)
Simon Kelley16972692006-10-16 20:04:18 +01001518 {
Simon Kelley7bcca002014-02-19 17:45:17 +00001519 serv->flags |= SERV_MARK;
Simon Kelley16972692006-10-16 20:04:18 +01001520 continue;
1521 }
1522
Simon Kelley3d8df262005-08-29 12:19:27 +01001523 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelley7bcca002014-02-19 17:45:17 +00001524 if (sockaddr_isequal(&serv->addr, &iface->addr))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001525 break;
1526 if (iface)
1527 {
Simon Kelleyf2621c72007-04-29 19:47:21 +01001528 my_syslog(LOG_WARNING, _("ignoring nameserver %s - local interface"), daemon->namebuff);
Simon Kelley7bcca002014-02-19 17:45:17 +00001529 serv->flags |= SERV_MARK;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001530 continue;
1531 }
1532
1533 /* Do we need a socket set? */
Simon Kelley7bcca002014-02-19 17:45:17 +00001534 if (!serv->sfd &&
1535 !(serv->sfd = allocate_sfd(&serv->source_addr, serv->interface)) &&
Simon Kelley1a6bca82008-07-11 11:11:42 +01001536 errno != 0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001537 {
Simon Kelleyf2621c72007-04-29 19:47:21 +01001538 my_syslog(LOG_WARNING,
1539 _("ignoring nameserver %s - cannot make/bind socket: %s"),
1540 daemon->namebuff, strerror(errno));
Simon Kelley7bcca002014-02-19 17:45:17 +00001541 serv->flags |= SERV_MARK;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001542 continue;
1543 }
Simon Kelley16800ea2016-08-30 23:07:06 +01001544
1545 if (serv->sfd)
1546 serv->sfd->used = 1;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001547 }
1548
Simon Kelley979fe862015-03-19 22:50:22 +00001549 if (!(serv->flags & SERV_NO_REBIND) && !(serv->flags & SERV_LITERAL_ADDRESS))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001550 {
Simon Kelleyb9702602016-05-03 22:34:06 +01001551 if (++count > SERVERS_LOGGED)
1552 continue;
1553
Simon Kelley7bcca002014-02-19 17:45:17 +00001554 if (serv->flags & (SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_USE_RESOLV))
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001555 {
Simon Kelley367341f2016-01-12 15:58:23 +00001556 char *s1, *s2, *s3 = "";
1557#ifdef HAVE_DNSSEC
1558 if (option_bool(OPT_DNSSEC_VALID) && !(serv->flags & SERV_DO_DNSSEC))
1559 s3 = _("(no DNSSEC)");
1560#endif
Simon Kelley7bcca002014-02-19 17:45:17 +00001561 if (!(serv->flags & SERV_HAS_DOMAIN))
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001562 s1 = _("unqualified"), s2 = _("names");
Simon Kelley7bcca002014-02-19 17:45:17 +00001563 else if (strlen(serv->domain) == 0)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001564 s1 = _("default"), s2 = "";
1565 else
Simon Kelley7bcca002014-02-19 17:45:17 +00001566 s1 = _("domain"), s2 = serv->domain;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001567
Simon Kelley7bcca002014-02-19 17:45:17 +00001568 if (serv->flags & SERV_NO_ADDR)
Hannu Nyman3e2496f2017-02-11 13:44:08 +00001569 {
1570 count--;
1571 if (++locals <= LOCALS_LOGGED)
1572 my_syslog(LOG_INFO, _("using local addresses only for %s %s"), s1, s2);
1573 }
Simon Kelley7bcca002014-02-19 17:45:17 +00001574 else if (serv->flags & SERV_USE_RESOLV)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001575 my_syslog(LOG_INFO, _("using standard nameservers for %s %s"), s1, s2);
Simon Kelley979fe862015-03-19 22:50:22 +00001576 else
Simon Kelley367341f2016-01-12 15:58:23 +00001577 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 +01001578 }
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001579#ifdef HAVE_LOOP
1580 else if (serv->flags & SERV_LOOP)
1581 my_syslog(LOG_INFO, _("NOT using nameserver %s#%d - query loop detected"), daemon->namebuff, port);
1582#endif
Simon Kelley7bcca002014-02-19 17:45:17 +00001583 else if (serv->interface[0] != 0)
1584 my_syslog(LOG_INFO, _("using nameserver %s#%d(via %s)"), daemon->namebuff, port, serv->interface);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001585 else
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001586 my_syslog(LOG_INFO, _("using nameserver %s#%d"), daemon->namebuff, port);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001587 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001588 }
Simon Kelleyb9702602016-05-03 22:34:06 +01001589
Hannu Nyman3e2496f2017-02-11 13:44:08 +00001590 if (locals > LOCALS_LOGGED)
1591 my_syslog(LOG_INFO, _("using %d more local addresses"), locals - LOCALS_LOGGED);
Simon Kelleyb9702602016-05-03 22:34:06 +01001592 if (count - 1 > SERVERS_LOGGED)
1593 my_syslog(LOG_INFO, _("using %d more nameservers"), count - SERVERS_LOGGED - 1);
Simon Kelley7bcca002014-02-19 17:45:17 +00001594
Beniamino Galvani2675f202016-08-28 20:44:05 +01001595 /* Remove unused sfds */
1596 for (sfd = daemon->sfds, up = &daemon->sfds; sfd; sfd = tmp)
1597 {
1598 tmp = sfd->next;
1599 if (!sfd->used)
1600 {
1601 *up = sfd->next;
1602 close(sfd->fd);
1603 free(sfd);
1604 }
1605 else
1606 up = &sfd->next;
1607 }
1608
Simon Kelley7bcca002014-02-19 17:45:17 +00001609 cleanup_servers();
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001610}
Simon Kelley849a8352006-06-09 21:02:31 +01001611
1612/* Return zero if no servers found, in that case we keep polling.
1613 This is a protection against an update-time/write race on resolv.conf */
Simon Kelley5aabfc72007-08-29 11:24:47 +01001614int reload_servers(char *fname)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001615{
1616 FILE *f;
1617 char *line;
Simon Kelley849a8352006-06-09 21:02:31 +01001618 int gotone = 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001619
Simon Kelley849a8352006-06-09 21:02:31 +01001620 /* buff happens to be MAXDNAME long... */
1621 if (!(f = fopen(fname, "r")))
1622 {
Simon Kelleyf2621c72007-04-29 19:47:21 +01001623 my_syslog(LOG_ERR, _("failed to read %s: %s"), fname, strerror(errno));
Simon Kelley849a8352006-06-09 21:02:31 +01001624 return 0;
1625 }
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001626
1627 mark_servers(SERV_FROM_RESOLV);
1628
Simon Kelley849a8352006-06-09 21:02:31 +01001629 while ((line = fgets(daemon->namebuff, MAXDNAME, f)))
1630 {
1631 union mysockaddr addr, source_addr;
1632 char *token = strtok(line, " \t\n\r");
1633
Simon Kelley5aabfc72007-08-29 11:24:47 +01001634 if (!token)
1635 continue;
1636 if (strcmp(token, "nameserver") != 0 && strcmp(token, "server") != 0)
Simon Kelley849a8352006-06-09 21:02:31 +01001637 continue;
1638 if (!(token = strtok(NULL, " \t\n\r")))
1639 continue;
1640
1641 memset(&addr, 0, sizeof(addr));
1642 memset(&source_addr, 0, sizeof(source_addr));
1643
1644 if ((addr.in.sin_addr.s_addr = inet_addr(token)) != (in_addr_t) -1)
1645 {
1646#ifdef HAVE_SOCKADDR_SA_LEN
1647 source_addr.in.sin_len = addr.in.sin_len = sizeof(source_addr.in);
1648#endif
1649 source_addr.in.sin_family = addr.in.sin_family = AF_INET;
1650 addr.in.sin_port = htons(NAMESERVER_PORT);
1651 source_addr.in.sin_addr.s_addr = INADDR_ANY;
1652 source_addr.in.sin_port = htons(daemon->query_port);
1653 }
1654#ifdef HAVE_IPV6
Simon Kelley7de060b2011-08-26 17:24:52 +01001655 else
1656 {
1657 int scope_index = 0;
1658 char *scope_id = strchr(token, '%');
1659
1660 if (scope_id)
1661 {
1662 *(scope_id++) = 0;
1663 scope_index = if_nametoindex(scope_id);
1664 }
1665
1666 if (inet_pton(AF_INET6, token, &addr.in6.sin6_addr) > 0)
1667 {
Simon Kelley849a8352006-06-09 21:02:31 +01001668#ifdef HAVE_SOCKADDR_SA_LEN
Simon Kelley7de060b2011-08-26 17:24:52 +01001669 source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(source_addr.in6);
Simon Kelley849a8352006-06-09 21:02:31 +01001670#endif
Simon Kelley7de060b2011-08-26 17:24:52 +01001671 source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6;
1672 source_addr.in6.sin6_flowinfo = addr.in6.sin6_flowinfo = 0;
1673 addr.in6.sin6_port = htons(NAMESERVER_PORT);
1674 addr.in6.sin6_scope_id = scope_index;
1675 source_addr.in6.sin6_addr = in6addr_any;
1676 source_addr.in6.sin6_port = htons(daemon->query_port);
1677 source_addr.in6.sin6_scope_id = 0;
1678 }
1679 else
1680 continue;
Simon Kelley849a8352006-06-09 21:02:31 +01001681 }
Simon Kelley7de060b2011-08-26 17:24:52 +01001682#else /* IPV6 */
Simon Kelley849a8352006-06-09 21:02:31 +01001683 else
1684 continue;
Simon Kelley7de060b2011-08-26 17:24:52 +01001685#endif
1686
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001687 add_update_server(SERV_FROM_RESOLV, &addr, &source_addr, NULL, NULL);
Simon Kelley849a8352006-06-09 21:02:31 +01001688 gotone = 1;
1689 }
1690
Simon Kelley849a8352006-06-09 21:02:31 +01001691 fclose(f);
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001692 cleanup_servers();
Simon Kelley849a8352006-06-09 21:02:31 +01001693
1694 return gotone;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001695}
1696
Simon Kelley1ee9be42013-12-09 16:50:19 +00001697/* Called when addresses are added or deleted from an interface */
1698void newaddress(time_t now)
1699{
1700 (void)now;
1701
Simon Kelley89b12ed2014-03-06 13:27:57 +00001702 if (option_bool(OPT_CLEVERBIND) || option_bool(OPT_LOCAL_SERVICE) ||
1703 daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
Simon Kelley1ee9be42013-12-09 16:50:19 +00001704 enumerate_interfaces(0);
1705
1706 if (option_bool(OPT_CLEVERBIND))
1707 create_bound_listeners(0);
1708
1709#ifdef HAVE_DHCP6
1710 if (daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
1711 join_multicast(0);
1712
1713 if (daemon->doing_dhcp6 || daemon->doing_ra)
1714 dhcp_construct_contexts(now);
1715
1716 if (daemon->doing_dhcp6)
1717 lease_find_interfaces(now);
1718#endif
1719}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001720
1721
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001722
1723
1724