blob: 14d2af2ce313e224a87ee43f24aa090c49944aea [file] [log] [blame]
Simon Kelleyc47e3ba2014-01-08 17:07:54 +00001/* dnsmasq is Copyright (c) 2000-2014 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
181/* Fix for problem that the kernel sometimes reports the loopback inerface as the
182 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;
Simon Kelley91543f42013-09-23 12:41:20 +0100247#if defined(HAVE_DHCP) || defined(HAVE_TFTP)
Simon Kelley832af0b2007-01-21 20:01:28 +0000248 struct iname *tmp;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100249#endif
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100250
Vladislav Grishenko3b195962013-11-26 11:08:21 +0000251 (void)prefixlen;
252
Simon Kelley115ac3e2013-05-20 11:28:32 +0100253 if (!indextoname(param->fd, if_index, ifr.ifr_name) ||
254 ioctl(param->fd, SIOCGIFFLAGS, &ifr) == -1)
255 return 0;
Simon Kelley1f15b812009-10-13 17:49:32 +0100256
257 loopback = ifr.ifr_flags & IFF_LOOPBACK;
Simon Kelley9380ba72012-04-16 14:41:56 +0100258
259 if (loopback)
Simon Kelley3f2873d2013-05-14 11:28:47 +0100260 dhcp_ok = 0;
261
Simon Kelley115ac3e2013-05-20 11:28:32 +0100262 if (ioctl(param->fd, SIOCGIFMTU, &ifr) != -1)
Simon Kelley1f15b812009-10-13 17:49:32 +0100263 mtu = ifr.ifr_mtu;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100264
Simon Kelley115ac3e2013-05-20 11:28:32 +0100265 if (!label)
266 label = ifr.ifr_name;
Simon Kelleyc8a80482014-03-05 14:29:54 +0000267
268 /* maintain a list of all addresses on all interfaces for --local-service option */
269 if (option_bool(OPT_LOCAL_SERVICE))
270 {
271 struct addrlist *al;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100272
Simon Kelleyc8a80482014-03-05 14:29:54 +0000273 if (param->spare)
274 {
275 al = param->spare;
276 param->spare = al->next;
277 }
278 else
279 al = whine_malloc(sizeof(struct addrlist));
280
281 if (al)
282 {
283 al->next = daemon->interface_addrs;
284 daemon->interface_addrs = al;
285 al->prefixlen = prefixlen;
286
287 if (addr->sa.sa_family == AF_INET)
288 {
289 al->addr.addr.addr4 = addr->in.sin_addr;
290 al->flags = 0;
291 }
292#ifdef HAVE_IPV6
293 else
294 {
295 al->addr.addr.addr6 = addr->in6.sin6_addr;
296 al->flags = ADDRLIST_IPV6;
297 }
298#endif
299 }
300 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000301
Simon Kelley115ac3e2013-05-20 11:28:32 +0100302#ifdef HAVE_IPV6
303 if (addr->sa.sa_family != AF_INET6 || !IN6_IS_ADDR_LINKLOCAL(&addr->in6.sin6_addr))
304#endif
305 {
306 struct interface_name *int_name;
307 struct addrlist *al;
Simon Kelley376d48c2013-11-13 13:04:30 +0000308#ifdef HAVE_AUTH
309 struct auth_zone *zone;
310 struct auth_name_list *name;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100311
Simon Kelley376d48c2013-11-13 13:04:30 +0000312 /* Find subnets in auth_zones */
313 for (zone = daemon->auth_zones; zone; zone = zone->next)
314 for (name = zone->interface_names; name; name = name->next)
315 if (wildcard_match(name->name, label))
316 {
317 if (addr->sa.sa_family == AF_INET && (name->flags & AUTH4))
318 {
319 if (param->spare)
320 {
321 al = param->spare;
322 param->spare = al->next;
323 }
324 else
325 al = whine_malloc(sizeof(struct addrlist));
326
327 if (al)
328 {
329 al->next = zone->subnet;
330 zone->subnet = al;
331 al->prefixlen = prefixlen;
332 al->addr.addr.addr4 = addr->in.sin_addr;
333 al->flags = 0;
334 }
335 }
336
337#ifdef HAVE_IPV6
338 if (addr->sa.sa_family == AF_INET6 && (name->flags & AUTH6))
339 {
340 if (param->spare)
341 {
342 al = param->spare;
343 param->spare = al->next;
344 }
345 else
346 al = whine_malloc(sizeof(struct addrlist));
347
348 if (al)
349 {
350 al->next = zone->subnet;
351 zone->subnet = al;
Vladislav Grishenko3b195962013-11-26 11:08:21 +0000352 al->prefixlen = prefixlen;
353 al->addr.addr.addr6 = addr->in6.sin6_addr;
Simon Kelley376d48c2013-11-13 13:04:30 +0000354 al->flags = ADDRLIST_IPV6;
355 }
356 }
357#endif
358
359 }
360#endif
361
362 /* Update addresses from interface_names. These are a set independent
363 of the set we're listening on. */
Simon Kelley115ac3e2013-05-20 11:28:32 +0100364 for (int_name = daemon->int_names; int_name; int_name = int_name->next)
Simon Kelleyf7029f52013-11-21 15:09:09 +0000365 if (strncmp(label, int_name->intr, IF_NAMESIZE) == 0 &&
366 (addr->sa.sa_family == int_name->family || int_name->family == 0))
Simon Kelley115ac3e2013-05-20 11:28:32 +0100367 {
368 if (param->spare)
369 {
370 al = param->spare;
371 param->spare = al->next;
372 }
373 else
374 al = whine_malloc(sizeof(struct addrlist));
375
376 if (al)
377 {
Simon Kelley376d48c2013-11-13 13:04:30 +0000378 al->next = int_name->addr;
379 int_name->addr = al;
380
Simon Kelley115ac3e2013-05-20 11:28:32 +0100381 if (addr->sa.sa_family == AF_INET)
382 {
383 al->addr.addr.addr4 = addr->in.sin_addr;
Simon Kelley376d48c2013-11-13 13:04:30 +0000384 al->flags = 0;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100385 }
386#ifdef HAVE_IPV6
387 else
388 {
389 al->addr.addr.addr6 = addr->in6.sin6_addr;
Simon Kelley376d48c2013-11-13 13:04:30 +0000390 al->flags = ADDRLIST_IPV6;
Simon Kelley47669362014-12-17 12:41:56 +0000391 /* Privacy addresses and addresses still undergoing DAD and deprecated addresses
392 don't appear in forward queries, but will in reverse ones. */
393 if (!(iface_flags & IFACE_PERMANENT) || (iface_flags & (IFACE_DEPRECATED | IFACE_TENTATIVE)))
394 al->flags |= ADDRLIST_REVONLY;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100395 }
396#endif
397 }
398 }
399 }
400
401 /* check whether the interface IP has been added already
402 we call this routine multiple times. */
403 for (iface = daemon->interfaces; iface; iface = iface->next)
404 if (sockaddr_isequal(&iface->addr, addr))
405 {
Simon Kelley47669362014-12-17 12:41:56 +0000406 iface->dad = !!(iface_flags & IFACE_TENTATIVE);
Simon Kelley08619212013-12-02 14:43:48 +0000407 iface->found = 1; /* for garbage collection */
Simon Kelley115ac3e2013-05-20 11:28:32 +0100408 return 1;
409 }
410
411 /* If we are restricting the set of interfaces to use, make
Simon Kelley59353a62004-11-21 19:34:28 +0000412 sure that loopback interfaces are in that set. */
Simon Kelley1f15b812009-10-13 17:49:32 +0100413 if (daemon->if_names && loopback)
Simon Kelley59353a62004-11-21 19:34:28 +0000414 {
415 struct iname *lo;
416 for (lo = daemon->if_names; lo; lo = lo->next)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100417 if (lo->name && strcmp(lo->name, ifr.ifr_name) == 0)
Simon Kelley4ce4f372012-06-14 11:50:45 +0100418 break;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100419
Simon Kelley38365ff2013-02-05 14:35:54 +0000420 if (!lo && (lo = whine_malloc(sizeof(struct iname))))
Simon Kelley59353a62004-11-21 19:34:28 +0000421 {
Simon Kelley38365ff2013-02-05 14:35:54 +0000422 if ((lo->name = whine_malloc(strlen(ifr.ifr_name)+1)))
423 {
424 strcpy(lo->name, ifr.ifr_name);
425 lo->used = 1;
426 lo->next = daemon->if_names;
427 daemon->if_names = lo;
428 }
429 else
430 free(lo);
Simon Kelley59353a62004-11-21 19:34:28 +0000431 }
432 }
433
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100434 if (addr->sa.sa_family == AF_INET &&
Simon Kelley3f2873d2013-05-14 11:28:47 +0100435 !iface_check(AF_INET, (struct all_addr *)&addr->in.sin_addr, label, &auth_dns))
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100436 return 1;
Simon Kelley4f7b3042012-11-28 21:27:02 +0000437
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100438#ifdef HAVE_IPV6
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100439 if (addr->sa.sa_family == AF_INET6 &&
Simon Kelley3f2873d2013-05-14 11:28:47 +0100440 !iface_check(AF_INET6, (struct all_addr *)&addr->in6.sin6_addr, label, &auth_dns))
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100441 return 1;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100442#endif
Simon Kelley4f7b3042012-11-28 21:27:02 +0000443
444#ifdef HAVE_DHCP
445 /* No DHCP where we're doing auth DNS. */
446 if (auth_dns)
447 {
448 tftp_ok = 0;
449 dhcp_ok = 0;
450 }
451 else
452 for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
Simon Kelley49333cb2013-03-15 20:30:51 +0000453 if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
Simon Kelley4f7b3042012-11-28 21:27:02 +0000454 {
455 tftp_ok = 0;
456 dhcp_ok = 0;
457 }
458#endif
459
Simon Kelley2937f8a2013-07-29 19:49:07 +0100460
Simon Kelley91543f42013-09-23 12:41:20 +0100461#ifdef HAVE_TFTP
Simon Kelley2937f8a2013-07-29 19:49:07 +0100462 if (daemon->tftp_interfaces)
463 {
464 /* dedicated tftp interface list */
465 tftp_ok = 0;
466 for (tmp = daemon->tftp_interfaces; tmp; tmp = tmp->next)
467 if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
468 tftp_ok = 1;
469 }
Simon Kelley91543f42013-09-23 12:41:20 +0100470#endif
Simon Kelley2937f8a2013-07-29 19:49:07 +0100471
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100472 /* add to list */
Simon Kelley5aabfc72007-08-29 11:24:47 +0100473 if ((iface = whine_malloc(sizeof(struct irec))))
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100474 {
475 iface->addr = *addr;
476 iface->netmask = netmask;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100477 iface->tftp_ok = tftp_ok;
Simon Kelley9380ba72012-04-16 14:41:56 +0100478 iface->dhcp_ok = dhcp_ok;
Simon Kelley4f7b3042012-11-28 21:27:02 +0000479 iface->dns_auth = auth_dns;
Simon Kelley1f15b812009-10-13 17:49:32 +0100480 iface->mtu = mtu;
Simon Kelley47669362014-12-17 12:41:56 +0000481 iface->dad = !!(iface_flags & IFACE_TENTATIVE);
Simon Kelley08619212013-12-02 14:43:48 +0000482 iface->found = 1;
Simon Kelleydc27e142013-10-16 13:09:53 +0100483 iface->done = iface->multicast_done = iface->warned = 0;
Simon Kelley5d162f22012-12-20 14:55:46 +0000484 iface->index = if_index;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100485 if ((iface->name = whine_malloc(strlen(ifr.ifr_name)+1)))
Simon Kelley6f13e532012-04-17 14:25:06 +0100486 {
487 strcpy(iface->name, ifr.ifr_name);
Simon Kelley115ac3e2013-05-20 11:28:32 +0100488 iface->next = daemon->interfaces;
489 daemon->interfaces = iface;
Simon Kelley6f13e532012-04-17 14:25:06 +0100490 return 1;
491 }
492 free(iface);
Simon Kelley5d162f22012-12-20 14:55:46 +0000493
Simon Kelley44a2a312004-03-10 20:04:35 +0000494 }
495
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100496 errno = ENOMEM;
497 return 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000498}
499
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100500#ifdef HAVE_IPV6
Simon Kelleyc72daea2012-01-05 21:33:27 +0000501static int iface_allowed_v6(struct in6_addr *local, int prefix,
Simon Kelleybad7b872012-12-20 22:00:39 +0000502 int scope, int if_index, int flags,
Simon Kelley1f776932012-12-16 19:46:08 +0000503 int preferred, int valid, void *vparam)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000504{
Simon Kelley59353a62004-11-21 19:34:28 +0000505 union mysockaddr addr;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100506 struct in_addr netmask; /* dummy */
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100507 netmask.s_addr = 0;
Simon Kelley52b92f42012-01-22 16:05:15 +0000508
Simon Kelley52b92f42012-01-22 16:05:15 +0000509 (void)scope; /* warning */
Simon Kelley1f776932012-12-16 19:46:08 +0000510 (void)preferred;
511 (void)valid;
Simon Kelley44a2a312004-03-10 20:04:35 +0000512
Simon Kelley849a8352006-06-09 21:02:31 +0100513 memset(&addr, 0, sizeof(addr));
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000514#ifdef HAVE_SOCKADDR_SA_LEN
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100515 addr.in6.sin6_len = sizeof(addr.in6);
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000516#endif
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100517 addr.in6.sin6_family = AF_INET6;
518 addr.in6.sin6_addr = *local;
519 addr.in6.sin6_port = htons(daemon->port);
Simon Kelley62ab3cc2013-12-03 11:53:53 +0000520 /* FreeBSD insists this is zero for non-linklocal addresses */
521 if (IN6_IS_ADDR_LINKLOCAL(local))
522 addr.in6.sin6_scope_id = if_index;
523 else
524 addr.in6.sin6_scope_id = 0;
Simon Kelley1ee9be42013-12-09 16:50:19 +0000525
Simon Kelley47669362014-12-17 12:41:56 +0000526 return iface_allowed((struct iface_param *)vparam, if_index, NULL, &addr, netmask, prefix, flags);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100527}
528#endif
Simon Kelley59353a62004-11-21 19:34:28 +0000529
Simon Kelley3f2873d2013-05-14 11:28:47 +0100530static int iface_allowed_v4(struct in_addr local, int if_index, char *label,
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100531 struct in_addr netmask, struct in_addr broadcast, void *vparam)
532{
533 union mysockaddr addr;
Simon Kelley376d48c2013-11-13 13:04:30 +0000534 int prefix, bit;
Simon Kelley849a8352006-06-09 21:02:31 +0100535
536 memset(&addr, 0, sizeof(addr));
Simon Kelley1ab84e22004-01-29 16:48:35 +0000537#ifdef HAVE_SOCKADDR_SA_LEN
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100538 addr.in.sin_len = sizeof(addr.in);
Simon Kelley1ab84e22004-01-29 16:48:35 +0000539#endif
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100540 addr.in.sin_family = AF_INET;
541 addr.in.sin_addr = broadcast; /* warning */
542 addr.in.sin_addr = local;
543 addr.in.sin_port = htons(daemon->port);
Simon Kelley44a2a312004-03-10 20:04:35 +0000544
Simon Kelley376d48c2013-11-13 13:04:30 +0000545 /* determine prefix length from netmask */
546 for (prefix = 32, bit = 1; (bit & ntohl(netmask.s_addr)) == 0 && prefix != 0; bit = bit << 1, prefix--);
547
548 return iface_allowed((struct iface_param *)vparam, if_index, label, &addr, netmask, prefix, 0);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100549}
550
Simon Kelley115ac3e2013-05-20 11:28:32 +0100551int enumerate_interfaces(int reset)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100552{
Simon Kelley115ac3e2013-05-20 11:28:32 +0100553 static struct addrlist *spare = NULL;
Simon Kelleya0358e52014-06-07 13:38:48 +0100554 static int done = 0;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100555 struct iface_param param;
556 int errsave, ret = 1;
557 struct addrlist *addr, *tmp;
558 struct interface_name *intname;
Simon Kelley08619212013-12-02 14:43:48 +0000559 struct irec *iface;
Simon Kelley376d48c2013-11-13 13:04:30 +0000560#ifdef HAVE_AUTH
561 struct auth_zone *zone;
562#endif
563
Simon Kelley76dd75d2013-05-23 10:04:25 +0100564 /* Do this max once per select cycle - also inhibits netlink socket use
565 in TCP child processes. */
Simon Kelley397542b2013-09-05 11:27:34 +0100566
Simon Kelley115ac3e2013-05-20 11:28:32 +0100567 if (reset)
568 {
569 done = 0;
570 return 1;
571 }
572
Simon Kelleya0358e52014-06-07 13:38:48 +0100573 if (done)
Simon Kelley115ac3e2013-05-20 11:28:32 +0100574 return 1;
575
576 done = 1;
577
578 if ((param.fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
579 return 0;
580
Simon Kelley08619212013-12-02 14:43:48 +0000581 /* Mark interfaces for garbage collection */
582 for (iface = daemon->interfaces; iface; iface = iface->next)
583 iface->found = 0;
584
Simon Kelley115ac3e2013-05-20 11:28:32 +0100585 /* remove addresses stored against interface_names */
586 for (intname = daemon->int_names; intname; intname = intname->next)
587 {
Simon Kelley376d48c2013-11-13 13:04:30 +0000588 for (addr = intname->addr; addr; addr = tmp)
Simon Kelley115ac3e2013-05-20 11:28:32 +0100589 {
590 tmp = addr->next;
591 addr->next = spare;
592 spare = addr;
593 }
594
Simon Kelley376d48c2013-11-13 13:04:30 +0000595 intname->addr = NULL;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100596 }
Simon Kelley376d48c2013-11-13 13:04:30 +0000597
Simon Kelleyc8a80482014-03-05 14:29:54 +0000598 /* Remove list of addresses of local interfaces */
599 for (addr = daemon->interface_addrs; addr; addr = tmp)
600 {
601 tmp = addr->next;
602 addr->next = spare;
603 spare = addr;
604 }
605 daemon->interface_addrs = NULL;
606
Simon Kelley376d48c2013-11-13 13:04:30 +0000607#ifdef HAVE_AUTH
608 /* remove addresses stored against auth_zone subnets, but not
609 ones configured as address literals */
610 for (zone = daemon->auth_zones; zone; zone = zone->next)
611 if (zone->interface_names)
612 {
613 struct addrlist **up;
614 for (up = &zone->subnet, addr = zone->subnet; addr; addr = tmp)
615 {
616 tmp = addr->next;
617 if (addr->flags & ADDRLIST_LITERAL)
618 up = &addr->next;
619 else
620 {
621 *up = addr->next;
622 addr->next = spare;
623 spare = addr;
624 }
625 }
626 }
627#endif
628
Simon Kelley115ac3e2013-05-20 11:28:32 +0100629 param.spare = spare;
630
631#ifdef HAVE_IPV6
632 ret = iface_enumerate(AF_INET6, &param, iface_allowed_v6);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100633#endif
Simon Kelley28866e92011-02-14 20:19:14 +0000634
Simon Kelley115ac3e2013-05-20 11:28:32 +0100635 if (ret)
636 ret = iface_enumerate(AF_INET, &param, iface_allowed_v4);
637
638 errsave = errno;
639 close(param.fd);
Simon Kelley08619212013-12-02 14:43:48 +0000640
641 if (option_bool(OPT_CLEVERBIND))
642 {
643 /* Garbage-collect listeners listening on addresses that no longer exist.
644 Does nothing when not binding interfaces or for listeners on localhost,
645 since the ->iface field is NULL. Note that this needs the protections
646 against re-entrancy, hence it's here. It also means there's a possibility,
647 in OPT_CLEVERBIND mode, that at listener will just disappear after
648 a call to enumerate_interfaces, this is checked OK on all calls. */
649 struct listener *l, *tmp, **up;
650
651 for (up = &daemon->listeners, l = daemon->listeners; l; l = tmp)
652 {
653 tmp = l->next;
654
655 if (!l->iface || l->iface->found)
656 up = &l->next;
657 else
658 {
659 *up = l->next;
660
661 /* In case it ever returns */
662 l->iface->done = 0;
663
664 if (l->fd != -1)
665 close(l->fd);
666 if (l->tcpfd != -1)
667 close(l->tcpfd);
668 if (l->tftpfd != -1)
669 close(l->tftpfd);
670
671 free(l);
672 }
673 }
674 }
675
Simon Kelley115ac3e2013-05-20 11:28:32 +0100676 errno = errsave;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100677 spare = param.spare;
Simon Kelleya0358e52014-06-07 13:38:48 +0100678
Simon Kelley115ac3e2013-05-20 11:28:32 +0100679 return ret;
Simon Kelley44a2a312004-03-10 20:04:35 +0000680}
681
Simon Kelley5aabfc72007-08-29 11:24:47 +0100682/* set NONBLOCK bit on fd: See Stevens 16.6 */
Simon Kelley7cebd202006-05-06 14:13:33 +0100683int fix_fd(int fd)
684{
685 int flags;
686
687 if ((flags = fcntl(fd, F_GETFL)) == -1 ||
Simon Kelley5aabfc72007-08-29 11:24:47 +0100688 fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
Simon Kelley7cebd202006-05-06 14:13:33 +0100689 return 0;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100690
Simon Kelley7cebd202006-05-06 14:13:33 +0100691 return 1;
692}
693
Simon Kelley74c95c22011-10-19 09:33:39 +0100694static int make_sock(union mysockaddr *addr, int type, int dienow)
Simon Kelley44a2a312004-03-10 20:04:35 +0000695{
Simon Kelley28866e92011-02-14 20:19:14 +0000696 int family = addr->sa.sa_family;
697 int fd, rc, opt = 1;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100698
Simon Kelley28866e92011-02-14 20:19:14 +0000699 if ((fd = socket(family, type, 0)) == -1)
Simon Kelley316e2732010-01-22 20:16:09 +0000700 {
Matthias Andree71aaa5a2013-12-03 11:20:45 +0000701 int port, errsav;
Simon Kelley39f1b8e2012-06-20 20:04:27 +0100702 char *s;
Simon Kelley28866e92011-02-14 20:19:14 +0000703
704 /* No error if the kernel just doesn't support this IP flavour */
705 if (errno == EPROTONOSUPPORT ||
706 errno == EAFNOSUPPORT ||
707 errno == EINVAL)
708 return -1;
709
710 err:
Matthias Andree71aaa5a2013-12-03 11:20:45 +0000711 errsav = errno;
Simon Kelley39f1b8e2012-06-20 20:04:27 +0100712 port = prettyprint_addr(addr, daemon->addrbuff);
713 if (!option_bool(OPT_NOWILD) && !option_bool(OPT_CLEVERBIND))
714 sprintf(daemon->addrbuff, "port %d", port);
715 s = _("failed to create listening socket for %s: %s");
716
Simon Kelley5f11b3e2012-08-16 14:04:05 +0100717 if (fd != -1)
Matthias Andree71aaa5a2013-12-03 11:20:45 +0000718 close (fd);
719
720 errno = errsav;
Simon Kelley1ee9be42013-12-09 16:50:19 +0000721
Simon Kelley5f11b3e2012-08-16 14:04:05 +0100722 if (dienow)
723 {
724 /* failure to bind addresses given by --listen-address at this point
725 is OK if we're doing bind-dynamic */
726 if (!option_bool(OPT_CLEVERBIND))
727 die(s, daemon->addrbuff, EC_BADNET);
728 }
729 else
730 my_syslog(LOG_WARNING, s, daemon->addrbuff, strerror(errno));
731
Simon Kelley74c95c22011-10-19 09:33:39 +0100732 return -1;
Simon Kelley28866e92011-02-14 20:19:14 +0000733 }
Simon Kelley5f11b3e2012-08-16 14:04:05 +0100734
Simon Kelley28866e92011-02-14 20:19:14 +0000735 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || !fix_fd(fd))
736 goto err;
737
738#ifdef HAVE_IPV6
Simon Kelleyc72daea2012-01-05 21:33:27 +0000739 if (family == AF_INET6 && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)) == -1)
Simon Kelley28866e92011-02-14 20:19:14 +0000740 goto err;
741#endif
742
Simon Kelley74c95c22011-10-19 09:33:39 +0100743 if ((rc = bind(fd, (struct sockaddr *)addr, sa_len(addr))) == -1)
Simon Kelley28866e92011-02-14 20:19:14 +0000744 goto err;
745
746 if (type == SOCK_STREAM)
747 {
748 if (listen(fd, 5) == -1)
749 goto err;
750 }
Simon Kelley2329bef2013-12-03 13:41:16 +0000751 else if (family == AF_INET)
Simon Kelley28866e92011-02-14 20:19:14 +0000752 {
Simon Kelley2329bef2013-12-03 13:41:16 +0000753 if (!option_bool(OPT_NOWILD))
Simon Kelley28866e92011-02-14 20:19:14 +0000754 {
755#if defined(HAVE_LINUX_NETWORK)
Simon Kelleyc72daea2012-01-05 21:33:27 +0000756 if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) == -1)
Simon Kelley28866e92011-02-14 20:19:14 +0000757 goto err;
758#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
759 if (setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt)) == -1 ||
760 setsockopt(fd, IPPROTO_IP, IP_RECVIF, &opt, sizeof(opt)) == -1)
761 goto err;
762#endif
763 }
Simon Kelley28866e92011-02-14 20:19:14 +0000764 }
Simon Kelley2329bef2013-12-03 13:41:16 +0000765#ifdef HAVE_IPV6
766 else if (!set_ipv6pktinfo(fd))
767 goto err;
768#endif
Simon Kelleyc72daea2012-01-05 21:33:27 +0000769
Simon Kelley28866e92011-02-14 20:19:14 +0000770 return fd;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100771}
Simon Kelleyc72daea2012-01-05 21:33:27 +0000772
773#ifdef HAVE_IPV6
774int set_ipv6pktinfo(int fd)
775{
776 int opt = 1;
777
778 /* The API changed around Linux 2.6.14 but the old ABI is still supported:
779 handle all combinations of headers and kernel.
780 OpenWrt note that this fixes the problem addressed by your very broken patch. */
781 daemon->v6pktinfo = IPV6_PKTINFO;
782
783#ifdef IPV6_RECVPKTINFO
784 if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &opt, sizeof(opt)) != -1)
785 return 1;
786# ifdef IPV6_2292PKTINFO
787 else if (errno == ENOPROTOOPT && setsockopt(fd, IPPROTO_IPV6, IPV6_2292PKTINFO, &opt, sizeof(opt)) != -1)
788 {
789 daemon->v6pktinfo = IPV6_2292PKTINFO;
790 return 1;
791 }
792# endif
793#else
794 if (setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &opt, sizeof(opt)) != -1)
795 return 1;
796#endif
797
798 return 0;
799}
800#endif
Simon Kelley22ce5502013-01-22 13:53:04 +0000801
802
803/* Find the interface on which a TCP connection arrived, if possible, or zero otherwise. */
804int tcp_interface(int fd, int af)
805{
806 int if_index = 0;
807
808#ifdef HAVE_LINUX_NETWORK
809 int opt = 1;
810 struct cmsghdr *cmptr;
811 struct msghdr msg;
812
813 /* use mshdr do that the CMSDG_* macros are available */
814 msg.msg_control = daemon->packet;
815 msg.msg_controllen = daemon->packet_buff_sz;
816
817 /* we overwrote the buffer... */
818 daemon->srv_save = NULL;
819
820 if (af == AF_INET)
821 {
822 if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) != -1 &&
823 getsockopt(fd, IPPROTO_IP, IP_PKTOPTIONS, msg.msg_control, (socklen_t *)&msg.msg_controllen) != -1)
824 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
825 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
826 {
827 union {
828 unsigned char *c;
829 struct in_pktinfo *p;
830 } p;
831
832 p.c = CMSG_DATA(cmptr);
833 if_index = p.p->ipi_ifindex;
834 }
835 }
836#ifdef HAVE_IPV6
837 else
838 {
839 /* Only the RFC-2292 API has the ability to find the interface for TCP connections,
840 it was removed in RFC-3542 !!!!
841
842 Fortunately, Linux kept the 2292 ABI when it moved to 3542. The following code always
843 uses the old ABI, and should work with pre- and post-3542 kernel headers */
844
845#ifdef IPV6_2292PKTOPTIONS
846# define PKTOPTIONS IPV6_2292PKTOPTIONS
847#else
848# define PKTOPTIONS IPV6_PKTOPTIONS
849#endif
850
851 if (set_ipv6pktinfo(fd) &&
852 getsockopt(fd, IPPROTO_IPV6, PKTOPTIONS, msg.msg_control, (socklen_t *)&msg.msg_controllen) != -1)
853 {
854 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
855 if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
856 {
857 union {
858 unsigned char *c;
859 struct in6_pktinfo *p;
860 } p;
861 p.c = CMSG_DATA(cmptr);
862
863 if_index = p.p->ipi6_ifindex;
864 }
865 }
866 }
867#endif /* IPV6 */
868#endif /* Linux */
869
870 return if_index;
871}
Simon Kelley28866e92011-02-14 20:19:14 +0000872
Simon Kelley74c95c22011-10-19 09:33:39 +0100873static struct listener *create_listeners(union mysockaddr *addr, int do_tftp, int dienow)
Simon Kelley28866e92011-02-14 20:19:14 +0000874{
875 struct listener *l = NULL;
876 int fd = -1, tcpfd = -1, tftpfd = -1;
877
Vladislav Grishenko408c3682013-09-24 16:18:49 +0100878 (void)do_tftp;
879
Simon Kelley28866e92011-02-14 20:19:14 +0000880 if (daemon->port != 0)
881 {
Simon Kelley74c95c22011-10-19 09:33:39 +0100882 fd = make_sock(addr, SOCK_DGRAM, dienow);
883 tcpfd = make_sock(addr, SOCK_STREAM, dienow);
Simon Kelley28866e92011-02-14 20:19:14 +0000884 }
885
886#ifdef HAVE_TFTP
887 if (do_tftp)
888 {
889 if (addr->sa.sa_family == AF_INET)
890 {
891 /* port must be restored to DNS port for TCP code */
892 short save = addr->in.sin_port;
893 addr->in.sin_port = htons(TFTP_PORT);
Simon Kelley74c95c22011-10-19 09:33:39 +0100894 tftpfd = make_sock(addr, SOCK_DGRAM, dienow);
Simon Kelley28866e92011-02-14 20:19:14 +0000895 addr->in.sin_port = save;
896 }
897# ifdef HAVE_IPV6
898 else
899 {
900 short save = addr->in6.sin6_port;
901 addr->in6.sin6_port = htons(TFTP_PORT);
Simon Kelley74c95c22011-10-19 09:33:39 +0100902 tftpfd = make_sock(addr, SOCK_DGRAM, dienow);
Simon Kelley28866e92011-02-14 20:19:14 +0000903 addr->in6.sin6_port = save;
904 }
905# endif
906 }
Simon Kelley44a2a312004-03-10 20:04:35 +0000907#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100908
Simon Kelley28866e92011-02-14 20:19:14 +0000909 if (fd != -1 || tcpfd != -1 || tftpfd != -1)
910 {
911 l = safe_malloc(sizeof(struct listener));
912 l->next = NULL;
913 l->family = addr->sa.sa_family;
914 l->fd = fd;
915 l->tcpfd = tcpfd;
Simon Kelley08619212013-12-02 14:43:48 +0000916 l->tftpfd = tftpfd;
917 l->iface = NULL;
Simon Kelley28866e92011-02-14 20:19:14 +0000918 }
919
920 return l;
921}
922
Simon Kelley74c95c22011-10-19 09:33:39 +0100923void create_wildcard_listeners(void)
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100924{
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100925 union mysockaddr addr;
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100926 struct listener *l, *l6;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100927
Simon Kelley849a8352006-06-09 21:02:31 +0100928 memset(&addr, 0, sizeof(addr));
Simon Kelley28866e92011-02-14 20:19:14 +0000929#ifdef HAVE_SOCKADDR_SA_LEN
930 addr.in.sin_len = sizeof(addr.in);
931#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100932 addr.in.sin_family = AF_INET;
933 addr.in.sin_addr.s_addr = INADDR_ANY;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100934 addr.in.sin_port = htons(daemon->port);
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100935
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100936 l = create_listeners(&addr, !!option_bool(OPT_TFTP), 1);
Simon Kelley28866e92011-02-14 20:19:14 +0000937
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100938#ifdef HAVE_IPV6
Simon Kelley28866e92011-02-14 20:19:14 +0000939 memset(&addr, 0, sizeof(addr));
940# ifdef HAVE_SOCKADDR_SA_LEN
941 addr.in6.sin6_len = sizeof(addr.in6);
942# endif
943 addr.in6.sin6_family = AF_INET6;
944 addr.in6.sin6_addr = in6addr_any;
945 addr.in6.sin6_port = htons(daemon->port);
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100946
947 l6 = create_listeners(&addr, !!option_bool(OPT_TFTP), 1);
Simon Kelley28866e92011-02-14 20:19:14 +0000948 if (l)
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100949 l->next = l6;
Simon Kelley28866e92011-02-14 20:19:14 +0000950 else
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100951 l = l6;
Simon Kelley832af0b2007-01-21 20:01:28 +0000952#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100953
Simon Kelley74c95c22011-10-19 09:33:39 +0100954 daemon->listeners = l;
Simon Kelley44a2a312004-03-10 20:04:35 +0000955}
956
Simon Kelley74c95c22011-10-19 09:33:39 +0100957void create_bound_listeners(int dienow)
Simon Kelley44a2a312004-03-10 20:04:35 +0000958{
Simon Kelley74c95c22011-10-19 09:33:39 +0100959 struct listener *new;
Simon Kelley44a2a312004-03-10 20:04:35 +0000960 struct irec *iface;
Simon Kelley52d4abf2012-03-21 21:39:48 +0000961 struct iname *if_tmp;
Simon Kelley73a08a22009-02-05 20:28:08 +0000962
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100963 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelley08619212013-12-02 14:43:48 +0000964 if (!iface->done && !iface->dad && iface->found &&
Simon Kelley74c95c22011-10-19 09:33:39 +0100965 (new = create_listeners(&iface->addr, iface->tftp_ok, dienow)))
Simon Kelley28866e92011-02-14 20:19:14 +0000966 {
967 new->iface = iface;
Simon Kelley74c95c22011-10-19 09:33:39 +0100968 new->next = daemon->listeners;
969 daemon->listeners = new;
970 iface->done = 1;
Simon Kelley28866e92011-02-14 20:19:14 +0000971 }
Simon Kelley52d4abf2012-03-21 21:39:48 +0000972
973 /* Check for --listen-address options that haven't been used because there's
974 no interface with a matching address. These may be valid: eg it's possible
975 to listen on 127.0.1.1 even if the loopback interface is 127.0.0.1
976
Simon Kelley5f11b3e2012-08-16 14:04:05 +0100977 If the address isn't valid the bind() will fail and we'll die()
978 (except in bind-dynamic mode, when we'll complain but keep trying.)
Simon Kelley52d4abf2012-03-21 21:39:48 +0000979
980 The resulting listeners have the ->iface field NULL, and this has to be
981 handled by the DNS and TFTP code. It disables --localise-queries processing
982 (no netmask) and some MTU login the tftp code. */
983
984 for (if_tmp = daemon->if_addrs; if_tmp; if_tmp = if_tmp->next)
985 if (!if_tmp->used &&
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100986 (new = create_listeners(&if_tmp->addr, !!option_bool(OPT_TFTP), dienow)))
Simon Kelley52d4abf2012-03-21 21:39:48 +0000987 {
Simon Kelley52d4abf2012-03-21 21:39:48 +0000988 new->next = daemon->listeners;
989 daemon->listeners = new;
990 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000991}
992
Simon Kelleydc27e142013-10-16 13:09:53 +0100993/* In --bind-interfaces, the only access control is the addresses we're listening on.
994 There's nothing to avoid a query to the address of an internal interface arriving via
995 an external interface where we don't want to accept queries, except that in the usual
996 case the addresses of internal interfaces are RFC1918. When bind-interfaces in use,
997 and we listen on an address that looks like it's probably globally routeable, shout.
998
999 The fix is to use --bind-dynamic, which actually checks the arrival interface too.
1000 Tough if your platform doesn't support this.
Simon Kelley2329bef2013-12-03 13:41:16 +00001001
1002 Note that checking the arrival interface is supported in the standard IPv6 API and
1003 always done, so we don't warn about any IPv6 addresses here.
Simon Kelleydc27e142013-10-16 13:09:53 +01001004*/
1005
1006void warn_bound_listeners(void)
1007{
1008 struct irec *iface;
1009 int advice = 0;
1010
1011 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelleyf7029f52013-11-21 15:09:09 +00001012 if (!iface->dns_auth)
Simon Kelleydc27e142013-10-16 13:09:53 +01001013 {
Simon Kelleydc27e142013-10-16 13:09:53 +01001014 if (iface->addr.sa.sa_family == AF_INET)
1015 {
1016 if (!private_net(iface->addr.in.sin_addr, 1))
1017 {
1018 inet_ntop(AF_INET, &iface->addr.in.sin_addr, daemon->addrbuff, ADDRSTRLEN);
Simon Kelley2329bef2013-12-03 13:41:16 +00001019 iface->warned = advice = 1;
1020 my_syslog(LOG_WARNING,
1021 _("LOUD WARNING: listening on %s may accept requests via interfaces other than %s"),
1022 daemon->addrbuff, iface->name);
Simon Kelleydc27e142013-10-16 13:09:53 +01001023 }
1024 }
Simon Kelleydc27e142013-10-16 13:09:53 +01001025 }
1026
1027 if (advice)
Simon Kelleyf7029f52013-11-21 15:09:09 +00001028 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 +01001029}
1030
Simon Kelleyf7029f52013-11-21 15:09:09 +00001031void warn_int_names(void)
1032{
1033 struct interface_name *intname;
1034
1035 for (intname = daemon->int_names; intname; intname = intname->next)
1036 if (!intname->addr)
1037 my_syslog(LOG_WARNING, _("warning: no addresses found for interface %s"), intname->intr);
1038}
1039
Simon Kelley74c95c22011-10-19 09:33:39 +01001040int is_dad_listeners(void)
1041{
1042 struct irec *iface;
1043
1044 if (option_bool(OPT_NOWILD))
1045 for (iface = daemon->interfaces; iface; iface = iface->next)
1046 if (iface->dad && !iface->done)
1047 return 1;
1048
1049 return 0;
1050}
Simon Kelley5d162f22012-12-20 14:55:46 +00001051
1052#ifdef HAVE_DHCP6
1053void join_multicast(int dienow)
1054{
1055 struct irec *iface, *tmp;
1056
1057 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelley19624462012-12-28 11:18:09 +00001058 if (iface->addr.sa.sa_family == AF_INET6 && iface->dhcp_ok && !iface->multicast_done)
Simon Kelley5d162f22012-12-20 14:55:46 +00001059 {
1060 /* There's an irec per address but we only want to join for multicast
1061 once per interface. Weed out duplicates. */
1062 for (tmp = daemon->interfaces; tmp; tmp = tmp->next)
1063 if (tmp->multicast_done && tmp->index == iface->index)
1064 break;
1065
1066 iface->multicast_done = 1;
1067
1068 if (!tmp)
1069 {
1070 struct ipv6_mreq mreq;
1071 int err = 0;
1072
1073 mreq.ipv6mr_interface = iface->index;
1074
1075 inet_pton(AF_INET6, ALL_RELAY_AGENTS_AND_SERVERS, &mreq.ipv6mr_multiaddr);
1076
Simon Kelleyff7eea22013-09-04 18:01:38 +01001077 if ((daemon->doing_dhcp6 || daemon->relay6) &&
Simon Kelley5d162f22012-12-20 14:55:46 +00001078 setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
1079 err = 1;
1080
1081 inet_pton(AF_INET6, ALL_SERVERS, &mreq.ipv6mr_multiaddr);
1082
1083 if (daemon->doing_dhcp6 &&
1084 setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
1085 err = 1;
1086
1087 inet_pton(AF_INET6, ALL_ROUTERS, &mreq.ipv6mr_multiaddr);
1088
1089 if (daemon->doing_ra &&
1090 setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
1091 err = 1;
1092
1093 if (err)
1094 {
1095 char *s = _("interface %s failed to join DHCPv6 multicast group: %s");
1096 if (dienow)
1097 die(s, iface->name, EC_BADNET);
1098 else
1099 my_syslog(LOG_ERR, s, iface->name, strerror(errno));
1100 }
1101 }
1102 }
1103}
1104#endif
1105
Simon Kelley9009d742008-11-14 20:04:27 +00001106/* return a UDP socket bound to a random port, have to cope with straying into
Simon Kelley1a6bca82008-07-11 11:11:42 +01001107 occupied port nos and reserved ones. */
1108int random_sock(int family)
1109{
1110 int fd;
1111
1112 if ((fd = socket(family, SOCK_DGRAM, 0)) != -1)
1113 {
Simon Kelley3927da42008-07-20 15:10:39 +01001114 union mysockaddr addr;
Simon Kelley1ad24ae2008-07-20 20:22:50 +01001115 unsigned int ports_avail = 65536u - (unsigned short)daemon->min_port;
Simon Kelley9009d742008-11-14 20:04:27 +00001116 int tries = ports_avail < 30 ? 3 * ports_avail : 100;
Simon Kelley3927da42008-07-20 15:10:39 +01001117
Simon Kelley1a6bca82008-07-11 11:11:42 +01001118 memset(&addr, 0, sizeof(addr));
Simon Kelley3927da42008-07-20 15:10:39 +01001119 addr.sa.sa_family = family;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001120
Simon Kelley1ad24ae2008-07-20 20:22:50 +01001121 /* don't loop forever if all ports in use. */
1122
Simon Kelley1a6bca82008-07-11 11:11:42 +01001123 if (fix_fd(fd))
Simon Kelley9009d742008-11-14 20:04:27 +00001124 while(tries--)
Simon Kelley1a6bca82008-07-11 11:11:42 +01001125 {
1126 unsigned short port = rand16();
1127
Simon Kelley3927da42008-07-20 15:10:39 +01001128 if (daemon->min_port != 0)
Simon Kelley1ad24ae2008-07-20 20:22:50 +01001129 port = htons(daemon->min_port + (port % ((unsigned short)ports_avail)));
Simon Kelley1a6bca82008-07-11 11:11:42 +01001130
1131 if (family == AF_INET)
1132 {
1133 addr.in.sin_addr.s_addr = INADDR_ANY;
Simon Kelley3927da42008-07-20 15:10:39 +01001134 addr.in.sin_port = port;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001135#ifdef HAVE_SOCKADDR_SA_LEN
1136 addr.in.sin_len = sizeof(struct sockaddr_in);
1137#endif
1138 }
1139#ifdef HAVE_IPV6
1140 else
1141 {
1142 addr.in6.sin6_addr = in6addr_any;
Simon Kelley3927da42008-07-20 15:10:39 +01001143 addr.in6.sin6_port = port;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001144#ifdef HAVE_SOCKADDR_SA_LEN
1145 addr.in6.sin6_len = sizeof(struct sockaddr_in6);
1146#endif
1147 }
1148#endif
1149
1150 if (bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == 0)
1151 return fd;
1152
1153 if (errno != EADDRINUSE && errno != EACCES)
1154 break;
1155 }
1156
1157 close(fd);
1158 }
1159
1160 return -1;
1161}
1162
1163
Simon Kelley824af852008-02-12 20:43:05 +00001164int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp)
1165{
1166 union mysockaddr addr_copy = *addr;
1167
1168 /* cannot set source _port_ for TCP connections. */
1169 if (is_tcp)
1170 {
1171 if (addr_copy.sa.sa_family == AF_INET)
1172 addr_copy.in.sin_port = 0;
1173#ifdef HAVE_IPV6
1174 else
1175 addr_copy.in6.sin6_port = 0;
1176#endif
1177 }
1178
1179 if (bind(fd, (struct sockaddr *)&addr_copy, sa_len(&addr_copy)) == -1)
1180 return 0;
1181
1182#if defined(SO_BINDTODEVICE)
Simon Kelley73a08a22009-02-05 20:28:08 +00001183 if (intname[0] != 0 &&
Simon Kelley316e2732010-01-22 20:16:09 +00001184 setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, intname, IF_NAMESIZE) == -1)
Simon Kelley824af852008-02-12 20:43:05 +00001185 return 0;
1186#endif
1187
1188 return 1;
1189}
1190
1191static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001192{
1193 struct serverfd *sfd;
Simon Kelley824af852008-02-12 20:43:05 +00001194 int errsave;
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001195
Simon Kelley1a6bca82008-07-11 11:11:42 +01001196 /* when using random ports, servers which would otherwise use
1197 the INADDR_ANY/port0 socket have sfd set to NULL */
Simon Kelley73a08a22009-02-05 20:28:08 +00001198 if (!daemon->osport && intname[0] == 0)
Simon Kelley1a6bca82008-07-11 11:11:42 +01001199 {
1200 errno = 0;
1201
1202 if (addr->sa.sa_family == AF_INET &&
1203 addr->in.sin_addr.s_addr == INADDR_ANY &&
1204 addr->in.sin_port == htons(0))
1205 return NULL;
1206
1207#ifdef HAVE_IPV6
1208 if (addr->sa.sa_family == AF_INET6 &&
1209 memcmp(&addr->in6.sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0 &&
1210 addr->in6.sin6_port == htons(0))
1211 return NULL;
1212#endif
1213 }
1214
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001215 /* may have a suitable one already */
Simon Kelley824af852008-02-12 20:43:05 +00001216 for (sfd = daemon->sfds; sfd; sfd = sfd->next )
1217 if (sockaddr_isequal(&sfd->source_addr, addr) &&
1218 strcmp(intname, sfd->interface) == 0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001219 return sfd;
1220
1221 /* need to make a new one. */
1222 errno = ENOMEM; /* in case malloc fails. */
Simon Kelley5aabfc72007-08-29 11:24:47 +01001223 if (!(sfd = whine_malloc(sizeof(struct serverfd))))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001224 return NULL;
1225
1226 if ((sfd->fd = socket(addr->sa.sa_family, SOCK_DGRAM, 0)) == -1)
1227 {
1228 free(sfd);
1229 return NULL;
1230 }
1231
Simon Kelley824af852008-02-12 20:43:05 +00001232 if (!local_bind(sfd->fd, addr, intname, 0) || !fix_fd(sfd->fd))
1233 {
1234 errsave = errno; /* save error from bind. */
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001235 close(sfd->fd);
1236 free(sfd);
1237 errno = errsave;
1238 return NULL;
1239 }
Simon Kelley824af852008-02-12 20:43:05 +00001240
1241 strcpy(sfd->interface, intname);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001242 sfd->source_addr = *addr;
Simon Kelley824af852008-02-12 20:43:05 +00001243 sfd->next = daemon->sfds;
1244 daemon->sfds = sfd;
1245 return sfd;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001246}
1247
Simon Kelley824af852008-02-12 20:43:05 +00001248/* create upstream sockets during startup, before root is dropped which may be needed
1249 this allows query_port to be a low port and interface binding */
1250void pre_allocate_sfds(void)
1251{
1252 struct server *srv;
1253
1254 if (daemon->query_port != 0)
1255 {
1256 union mysockaddr addr;
1257 memset(&addr, 0, sizeof(addr));
1258 addr.in.sin_family = AF_INET;
1259 addr.in.sin_addr.s_addr = INADDR_ANY;
1260 addr.in.sin_port = htons(daemon->query_port);
1261#ifdef HAVE_SOCKADDR_SA_LEN
1262 addr.in.sin_len = sizeof(struct sockaddr_in);
1263#endif
1264 allocate_sfd(&addr, "");
1265#ifdef HAVE_IPV6
1266 memset(&addr, 0, sizeof(addr));
1267 addr.in6.sin6_family = AF_INET6;
1268 addr.in6.sin6_addr = in6addr_any;
1269 addr.in6.sin6_port = htons(daemon->query_port);
1270#ifdef HAVE_SOCKADDR_SA_LEN
1271 addr.in6.sin6_len = sizeof(struct sockaddr_in6);
1272#endif
1273 allocate_sfd(&addr, "");
1274#endif
1275 }
1276
1277 for (srv = daemon->servers; srv; srv = srv->next)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001278 if (!(srv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)) &&
Simon Kelley824af852008-02-12 20:43:05 +00001279 !allocate_sfd(&srv->source_addr, srv->interface) &&
Simon Kelley1a6bca82008-07-11 11:11:42 +01001280 errno != 0 &&
Simon Kelley28866e92011-02-14 20:19:14 +00001281 option_bool(OPT_NOWILD))
Simon Kelley824af852008-02-12 20:43:05 +00001282 {
Simon Kelley316e2732010-01-22 20:16:09 +00001283 prettyprint_addr(&srv->source_addr, daemon->namebuff);
Simon Kelley73a08a22009-02-05 20:28:08 +00001284 if (srv->interface[0] != 0)
Simon Kelley824af852008-02-12 20:43:05 +00001285 {
1286 strcat(daemon->namebuff, " ");
1287 strcat(daemon->namebuff, srv->interface);
1288 }
1289 die(_("failed to bind server socket for %s: %s"),
1290 daemon->namebuff, EC_BADNET);
1291 }
1292}
1293
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001294void mark_servers(int flag)
1295{
1296 struct server *serv;
1297
1298 /* mark everything with argument flag */
1299 for (serv = daemon->servers; serv; serv = serv->next)
Simon Kelley40766e52014-07-29 16:52:00 +01001300 {
1301 if (serv->flags & flag)
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001302 serv->flags |= SERV_MARK;
1303#ifdef HAVE_LOOP
Simon Kelley40766e52014-07-29 16:52:00 +01001304 /* Give looped servers another chance */
1305 serv->flags &= ~SERV_LOOP;
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001306#endif
Simon Kelley40766e52014-07-29 16:52:00 +01001307 }
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001308}
1309
1310void cleanup_servers(void)
1311{
1312 struct server *serv, *tmp, **up;
1313
1314 /* unlink and free anything still marked. */
1315 for (serv = daemon->servers, up = &daemon->servers; serv; serv = tmp)
1316 {
1317 tmp = serv->next;
1318 if (serv->flags & SERV_MARK)
1319 {
1320 server_gone(serv);
1321 *up = serv->next;
1322 if (serv->domain)
1323 free(serv->domain);
1324 free(serv);
1325 }
1326 else
1327 up = &serv->next;
1328 }
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001329
1330#ifdef HAVE_LOOP
1331 /* Now we have a new set of servers, test for loops. */
1332 loop_send_probes();
1333#endif
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001334}
1335
1336void add_update_server(int flags,
1337 union mysockaddr *addr,
1338 union mysockaddr *source_addr,
1339 const char *interface,
1340 const char *domain)
1341{
Simon Kelley7b1eae42014-02-20 13:43:28 +00001342 struct server *serv, *next = NULL;
1343 char *domain_str = NULL;
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001344
1345 /* See if there is a suitable candidate, and unmark */
1346 for (serv = daemon->servers; serv; serv = serv->next)
1347 if (serv->flags & SERV_MARK)
1348 {
1349 if (domain)
1350 {
1351 if (!(serv->flags & SERV_HAS_DOMAIN) || !hostname_isequal(domain, serv->domain))
1352 continue;
1353 }
1354 else
1355 {
1356 if (serv->flags & SERV_HAS_DOMAIN)
1357 continue;
1358 }
1359
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001360 break;
1361 }
Simon Kelley7b1eae42014-02-20 13:43:28 +00001362
1363 if (serv)
1364 {
1365 domain_str = serv->domain;
1366 next = serv->next;
1367 }
1368 else if ((serv = whine_malloc(sizeof (struct server))))
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001369 {
1370 /* Not found, create a new one. */
Simon Kelley7b1eae42014-02-20 13:43:28 +00001371 if (domain && !(domain_str = whine_malloc(strlen(domain)+1)))
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001372 {
1373 free(serv);
1374 serv = NULL;
1375 }
1376 else
1377 {
1378 struct server *s;
1379 /* Add to the end of the chain, for order */
1380 if (!daemon->servers)
1381 daemon->servers = serv;
1382 else
1383 {
1384 for (s = daemon->servers; s->next; s = s->next);
1385 s->next = serv;
1386 }
1387 if (domain)
Simon Kelley7b1eae42014-02-20 13:43:28 +00001388 strcpy(domain_str, domain);
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001389 }
1390 }
1391
1392 if (serv)
1393 {
Simon Kelley7b1eae42014-02-20 13:43:28 +00001394 memset(serv, 0, sizeof(struct server));
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001395 serv->flags = flags;
Simon Kelley7b1eae42014-02-20 13:43:28 +00001396 serv->domain = domain_str;
1397 serv->next = next;
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001398 serv->queries = serv->failed_queries = 0;
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001399#ifdef HAVE_LOOP
1400 serv->uid = rand32();
1401#endif
1402
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001403 if (domain)
1404 serv->flags |= SERV_HAS_DOMAIN;
1405
1406 if (interface)
Simon Kelley7b1eae42014-02-20 13:43:28 +00001407 strcpy(serv->interface, interface);
1408 if (addr)
1409 serv->addr = *addr;
1410 if (source_addr)
1411 serv->source_addr = *source_addr;
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001412 }
1413}
Simon Kelley824af852008-02-12 20:43:05 +00001414
Simon Kelley5aabfc72007-08-29 11:24:47 +01001415void check_servers(void)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001416{
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001417 struct irec *iface;
Simon Kelley7bcca002014-02-19 17:45:17 +00001418 struct server *serv;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001419 int port = 0;
1420
Simon Kelley316e2732010-01-22 20:16:09 +00001421 /* interface may be new since startup */
Simon Kelley28866e92011-02-14 20:19:14 +00001422 if (!option_bool(OPT_NOWILD))
Simon Kelley115ac3e2013-05-20 11:28:32 +01001423 enumerate_interfaces(0);
Simon Kelley316e2732010-01-22 20:16:09 +00001424
Simon Kelley7bcca002014-02-19 17:45:17 +00001425 for (serv = daemon->servers; serv; serv = serv->next)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001426 {
Simon Kelley7bcca002014-02-19 17:45:17 +00001427 if (!(serv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001428 {
Simon Kelley7bcca002014-02-19 17:45:17 +00001429 port = prettyprint_addr(&serv->addr, daemon->namebuff);
Simon Kelley3d8df262005-08-29 12:19:27 +01001430
Simon Kelley16972692006-10-16 20:04:18 +01001431 /* 0.0.0.0 is nothing, the stack treats it like 127.0.0.1 */
Simon Kelley7bcca002014-02-19 17:45:17 +00001432 if (serv->addr.sa.sa_family == AF_INET &&
1433 serv->addr.in.sin_addr.s_addr == 0)
Simon Kelley16972692006-10-16 20:04:18 +01001434 {
Simon Kelley7bcca002014-02-19 17:45:17 +00001435 serv->flags |= SERV_MARK;
Simon Kelley16972692006-10-16 20:04:18 +01001436 continue;
1437 }
1438
Simon Kelley3d8df262005-08-29 12:19:27 +01001439 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelley7bcca002014-02-19 17:45:17 +00001440 if (sockaddr_isequal(&serv->addr, &iface->addr))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001441 break;
1442 if (iface)
1443 {
Simon Kelleyf2621c72007-04-29 19:47:21 +01001444 my_syslog(LOG_WARNING, _("ignoring nameserver %s - local interface"), daemon->namebuff);
Simon Kelley7bcca002014-02-19 17:45:17 +00001445 serv->flags |= SERV_MARK;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001446 continue;
1447 }
1448
1449 /* Do we need a socket set? */
Simon Kelley7bcca002014-02-19 17:45:17 +00001450 if (!serv->sfd &&
1451 !(serv->sfd = allocate_sfd(&serv->source_addr, serv->interface)) &&
Simon Kelley1a6bca82008-07-11 11:11:42 +01001452 errno != 0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001453 {
Simon Kelleyf2621c72007-04-29 19:47:21 +01001454 my_syslog(LOG_WARNING,
1455 _("ignoring nameserver %s - cannot make/bind socket: %s"),
1456 daemon->namebuff, strerror(errno));
Simon Kelley7bcca002014-02-19 17:45:17 +00001457 serv->flags |= SERV_MARK;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001458 continue;
1459 }
1460 }
1461
Simon Kelley7bcca002014-02-19 17:45:17 +00001462 if (!(serv->flags & SERV_NO_REBIND))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001463 {
Simon Kelley7bcca002014-02-19 17:45:17 +00001464 if (serv->flags & (SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_USE_RESOLV))
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001465 {
1466 char *s1, *s2;
Simon Kelley7bcca002014-02-19 17:45:17 +00001467 if (!(serv->flags & SERV_HAS_DOMAIN))
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001468 s1 = _("unqualified"), s2 = _("names");
Simon Kelley7bcca002014-02-19 17:45:17 +00001469 else if (strlen(serv->domain) == 0)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001470 s1 = _("default"), s2 = "";
1471 else
Simon Kelley7bcca002014-02-19 17:45:17 +00001472 s1 = _("domain"), s2 = serv->domain;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001473
Simon Kelley7bcca002014-02-19 17:45:17 +00001474 if (serv->flags & SERV_NO_ADDR)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001475 my_syslog(LOG_INFO, _("using local addresses only for %s %s"), s1, s2);
Simon Kelley7bcca002014-02-19 17:45:17 +00001476 else if (serv->flags & SERV_USE_RESOLV)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001477 my_syslog(LOG_INFO, _("using standard nameservers for %s %s"), s1, s2);
Simon Kelley7bcca002014-02-19 17:45:17 +00001478 else if (!(serv->flags & SERV_LITERAL_ADDRESS))
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001479 my_syslog(LOG_INFO, _("using nameserver %s#%d for %s %s"), daemon->namebuff, port, s1, s2);
1480 }
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001481#ifdef HAVE_LOOP
1482 else if (serv->flags & SERV_LOOP)
1483 my_syslog(LOG_INFO, _("NOT using nameserver %s#%d - query loop detected"), daemon->namebuff, port);
1484#endif
Simon Kelley7bcca002014-02-19 17:45:17 +00001485 else if (serv->interface[0] != 0)
1486 my_syslog(LOG_INFO, _("using nameserver %s#%d(via %s)"), daemon->namebuff, port, serv->interface);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001487 else
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001488 my_syslog(LOG_INFO, _("using nameserver %s#%d"), daemon->namebuff, port);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001489 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001490 }
Simon Kelley7bcca002014-02-19 17:45:17 +00001491
1492 cleanup_servers();
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001493}
Simon Kelley849a8352006-06-09 21:02:31 +01001494
1495/* Return zero if no servers found, in that case we keep polling.
1496 This is a protection against an update-time/write race on resolv.conf */
Simon Kelley5aabfc72007-08-29 11:24:47 +01001497int reload_servers(char *fname)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001498{
1499 FILE *f;
1500 char *line;
Simon Kelley849a8352006-06-09 21:02:31 +01001501 int gotone = 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001502
Simon Kelley849a8352006-06-09 21:02:31 +01001503 /* buff happens to be MAXDNAME long... */
1504 if (!(f = fopen(fname, "r")))
1505 {
Simon Kelleyf2621c72007-04-29 19:47:21 +01001506 my_syslog(LOG_ERR, _("failed to read %s: %s"), fname, strerror(errno));
Simon Kelley849a8352006-06-09 21:02:31 +01001507 return 0;
1508 }
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001509
1510 mark_servers(SERV_FROM_RESOLV);
1511
Simon Kelley849a8352006-06-09 21:02:31 +01001512 while ((line = fgets(daemon->namebuff, MAXDNAME, f)))
1513 {
1514 union mysockaddr addr, source_addr;
1515 char *token = strtok(line, " \t\n\r");
1516
Simon Kelley5aabfc72007-08-29 11:24:47 +01001517 if (!token)
1518 continue;
1519 if (strcmp(token, "nameserver") != 0 && strcmp(token, "server") != 0)
Simon Kelley849a8352006-06-09 21:02:31 +01001520 continue;
1521 if (!(token = strtok(NULL, " \t\n\r")))
1522 continue;
1523
1524 memset(&addr, 0, sizeof(addr));
1525 memset(&source_addr, 0, sizeof(source_addr));
1526
1527 if ((addr.in.sin_addr.s_addr = inet_addr(token)) != (in_addr_t) -1)
1528 {
1529#ifdef HAVE_SOCKADDR_SA_LEN
1530 source_addr.in.sin_len = addr.in.sin_len = sizeof(source_addr.in);
1531#endif
1532 source_addr.in.sin_family = addr.in.sin_family = AF_INET;
1533 addr.in.sin_port = htons(NAMESERVER_PORT);
1534 source_addr.in.sin_addr.s_addr = INADDR_ANY;
1535 source_addr.in.sin_port = htons(daemon->query_port);
1536 }
1537#ifdef HAVE_IPV6
Simon Kelley7de060b2011-08-26 17:24:52 +01001538 else
1539 {
1540 int scope_index = 0;
1541 char *scope_id = strchr(token, '%');
1542
1543 if (scope_id)
1544 {
1545 *(scope_id++) = 0;
1546 scope_index = if_nametoindex(scope_id);
1547 }
1548
1549 if (inet_pton(AF_INET6, token, &addr.in6.sin6_addr) > 0)
1550 {
Simon Kelley849a8352006-06-09 21:02:31 +01001551#ifdef HAVE_SOCKADDR_SA_LEN
Simon Kelley7de060b2011-08-26 17:24:52 +01001552 source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(source_addr.in6);
Simon Kelley849a8352006-06-09 21:02:31 +01001553#endif
Simon Kelley7de060b2011-08-26 17:24:52 +01001554 source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6;
1555 source_addr.in6.sin6_flowinfo = addr.in6.sin6_flowinfo = 0;
1556 addr.in6.sin6_port = htons(NAMESERVER_PORT);
1557 addr.in6.sin6_scope_id = scope_index;
1558 source_addr.in6.sin6_addr = in6addr_any;
1559 source_addr.in6.sin6_port = htons(daemon->query_port);
1560 source_addr.in6.sin6_scope_id = 0;
1561 }
1562 else
1563 continue;
Simon Kelley849a8352006-06-09 21:02:31 +01001564 }
Simon Kelley7de060b2011-08-26 17:24:52 +01001565#else /* IPV6 */
Simon Kelley849a8352006-06-09 21:02:31 +01001566 else
1567 continue;
Simon Kelley7de060b2011-08-26 17:24:52 +01001568#endif
1569
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001570 add_update_server(SERV_FROM_RESOLV, &addr, &source_addr, NULL, NULL);
Simon Kelley849a8352006-06-09 21:02:31 +01001571 gotone = 1;
1572 }
1573
Simon Kelley849a8352006-06-09 21:02:31 +01001574 fclose(f);
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001575 cleanup_servers();
Simon Kelley849a8352006-06-09 21:02:31 +01001576
1577 return gotone;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001578}
1579
Simon Kelley1ee9be42013-12-09 16:50:19 +00001580/* Called when addresses are added or deleted from an interface */
1581void newaddress(time_t now)
1582{
1583 (void)now;
1584
Simon Kelley89b12ed2014-03-06 13:27:57 +00001585 if (option_bool(OPT_CLEVERBIND) || option_bool(OPT_LOCAL_SERVICE) ||
1586 daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
Simon Kelley1ee9be42013-12-09 16:50:19 +00001587 enumerate_interfaces(0);
1588
1589 if (option_bool(OPT_CLEVERBIND))
1590 create_bound_listeners(0);
1591
1592#ifdef HAVE_DHCP6
1593 if (daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
1594 join_multicast(0);
1595
1596 if (daemon->doing_dhcp6 || daemon->doing_ra)
1597 dhcp_construct_contexts(now);
1598
1599 if (daemon->doing_dhcp6)
1600 lease_find_interfaces(now);
1601#endif
1602}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001603
1604
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001605
1606
1607