blob: 3db7c43b35c94e0858920add9b32aca76b77e9ca [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 Kelleydc27e142013-10-16 13:09:53 +010019#ifndef IN6_IS_ADDR_ULA
20#define IN6_IS_ADDR_ULA(a) ((((__const uint32_t *) (a))[0] & htonl (0xfe00000)) == htonl (0xfc000000))
21#endif
22
Simon Kelley7622fc02009-06-04 20:32:05 +010023#ifdef HAVE_LINUX_NETWORK
24
25int indextoname(int fd, int index, char *name)
26{
27 struct ifreq ifr;
28
29 if (index == 0)
30 return 0;
31
32 ifr.ifr_ifindex = index;
33 if (ioctl(fd, SIOCGIFNAME, &ifr) == -1)
34 return 0;
35
36 strncpy(name, ifr.ifr_name, IF_NAMESIZE);
37
38 return 1;
39}
40
Simon Kelley28866e92011-02-14 20:19:14 +000041
42#elif defined(HAVE_SOLARIS_NETWORK)
43
44#include <zone.h>
45#include <alloca.h>
46#ifndef LIFC_UNDER_IPMP
47# define LIFC_UNDER_IPMP 0
48#endif
49
50int indextoname(int fd, int index, char *name)
51{
52 int64_t lifc_flags;
53 struct lifnum lifn;
54 int numifs, bufsize, i;
55 struct lifconf lifc;
56 struct lifreq *lifrp;
57
58 if (index == 0)
59 return 0;
60
61 if (getzoneid() == GLOBAL_ZONEID)
62 {
63 if (!if_indextoname(index, name))
64 return 0;
65 return 1;
66 }
67
68 lifc_flags = LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES | LIFC_UNDER_IPMP;
69 lifn.lifn_family = AF_UNSPEC;
70 lifn.lifn_flags = lifc_flags;
71 if (ioctl(fd, SIOCGLIFNUM, &lifn) < 0)
72 return 0;
73
74 numifs = lifn.lifn_count;
75 bufsize = numifs * sizeof(struct lifreq);
76
77 lifc.lifc_family = AF_UNSPEC;
78 lifc.lifc_flags = lifc_flags;
79 lifc.lifc_len = bufsize;
80 lifc.lifc_buf = alloca(bufsize);
81
82 if (ioctl(fd, SIOCGLIFCONF, &lifc) < 0)
83 return 0;
84
85 lifrp = lifc.lifc_req;
86 for (i = lifc.lifc_len / sizeof(struct lifreq); i; i--, lifrp++)
87 {
88 struct lifreq lifr;
89 strncpy(lifr.lifr_name, lifrp->lifr_name, IF_NAMESIZE);
90 if (ioctl(fd, SIOCGLIFINDEX, &lifr) < 0)
91 return 0;
92
93 if (lifr.lifr_index == index) {
94 strncpy(name, lifr.lifr_name, IF_NAMESIZE);
95 return 1;
96 }
97 }
98 return 0;
99}
100
101
Simon Kelley7622fc02009-06-04 20:32:05 +0100102#else
103
104int indextoname(int fd, int index, char *name)
105{
Simon Kelley115ac3e2013-05-20 11:28:32 +0100106 (void)fd;
107
Simon Kelley7622fc02009-06-04 20:32:05 +0100108 if (index == 0 || !if_indextoname(index, name))
109 return 0;
110
111 return 1;
112}
113
114#endif
115
Simon Kelley4f7b3042012-11-28 21:27:02 +0000116int iface_check(int family, struct all_addr *addr, char *name, int *auth)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000117{
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000118 struct iname *tmp;
Simon Kelleyedf0bde2013-07-29 17:21:48 +0100119 int ret = 1, match_addr = 0;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100120
Simon Kelley309331f2006-04-22 15:05:01 +0100121 /* Note: have to check all and not bail out early, so that we set the
Simon Kelley89500e32013-09-20 16:29:20 +0100122 "used" flags.
123
124 May be called with family == AF_LOCALto check interface by name only. */
Simon Kelley429798f2012-12-10 20:45:53 +0000125
Simon Kelley4f7b3042012-11-28 21:27:02 +0000126 if (auth)
Simon Kelley429798f2012-12-10 20:45:53 +0000127 *auth = 0;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100128
Simon Kelleyc72daea2012-01-05 21:33:27 +0000129 if (daemon->if_names || daemon->if_addrs)
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100130 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100131 ret = 0;
132
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100133 for (tmp = daemon->if_names; tmp; tmp = tmp->next)
Simon Kelley49333cb2013-03-15 20:30:51 +0000134 if (tmp->name && wildcard_match(tmp->name, name))
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100135 ret = tmp->used = 1;
136
Simon Kelley429798f2012-12-10 20:45:53 +0000137 if (addr)
138 for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
139 if (tmp->addr.sa.sa_family == family)
140 {
141 if (family == AF_INET &&
142 tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
Simon Kelleyedf0bde2013-07-29 17:21:48 +0100143 ret = match_addr = tmp->used = 1;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100144#ifdef HAVE_IPV6
Simon Kelley429798f2012-12-10 20:45:53 +0000145 else if (family == AF_INET6 &&
146 IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr,
147 &addr->addr.addr6))
Simon Kelleyedf0bde2013-07-29 17:21:48 +0100148 ret = match_addr = tmp->used = 1;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100149#endif
Simon Kelley429798f2012-12-10 20:45:53 +0000150 }
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100151 }
152
Simon Kelleyedf0bde2013-07-29 17:21:48 +0100153 if (!match_addr)
154 for (tmp = daemon->if_except; tmp; tmp = tmp->next)
155 if (tmp->name && wildcard_match(tmp->name, name))
156 ret = 0;
Simon Kelleyc72daea2012-01-05 21:33:27 +0000157
Simon Kelley429798f2012-12-10 20:45:53 +0000158
159 for (tmp = daemon->authinterface; tmp; tmp = tmp->next)
160 if (tmp->name)
161 {
Simon Kelleyf25e6c62013-11-17 12:23:42 +0000162 if (strcmp(tmp->name, name) == 0 &&
163 (tmp->addr.sa.sa_family == 0 || tmp->addr.sa.sa_family == family))
Simon Kelley429798f2012-12-10 20:45:53 +0000164 break;
165 }
166 else if (addr && tmp->addr.sa.sa_family == AF_INET && family == AF_INET &&
167 tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
168 break;
169#ifdef HAVE_IPV6
170 else if (addr && tmp->addr.sa.sa_family == AF_INET6 && family == AF_INET6 &&
171 IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, &addr->addr.addr6))
172 break;
173#endif
174
175 if (tmp && auth)
176 {
177 *auth = 1;
178 ret = 1;
179 }
180
Simon Kelley309331f2006-04-22 15:05:01 +0100181 return ret;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100182}
Simon Kelleye25db1f2013-01-29 22:10:26 +0000183
184
185/* Fix for problem that the kernel sometimes reports the loopback inerface as the
186 arrival interface when a packet originates locally, even when sent to address of
187 an interface other than the loopback. Accept packet if it arrived via a loopback
188 interface, even when we're not accepting packets that way, as long as the destination
189 address is one we're believing. Interface list must be up-to-date before calling. */
190int loopback_exception(int fd, int family, struct all_addr *addr, char *name)
191{
192 struct ifreq ifr;
193 struct irec *iface;
194
195 strncpy(ifr.ifr_name, name, IF_NAMESIZE);
196 if (ioctl(fd, SIOCGIFFLAGS, &ifr) != -1 &&
197 ifr.ifr_flags & IFF_LOOPBACK)
198 {
199 for (iface = daemon->interfaces; iface; iface = iface->next)
200 if (iface->addr.sa.sa_family == family)
201 {
202 if (family == AF_INET)
203 {
204 if (iface->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
205 return 1;
206 }
207#ifdef HAVE_IPV6
208 else if (IN6_ARE_ADDR_EQUAL(&iface->addr.in6.sin6_addr, &addr->addr.addr6))
209 return 1;
210#endif
211
212 }
213 }
214 return 0;
215}
216
Simon Kelley3f2873d2013-05-14 11:28:47 +0100217/* If we're configured with something like --interface=eth0:0 then we'll listen correctly
218 on the relevant address, but the name of the arrival interface, derived from the
219 index won't match the config. Check that we found an interface address for the arrival
220 interface: daemon->interfaces must be up-to-date. */
221int label_exception(int index, int family, struct all_addr *addr)
222{
223 struct irec *iface;
224
225 /* labels only supported on IPv4 addresses. */
226 if (family != AF_INET)
227 return 0;
228
229 for (iface = daemon->interfaces; iface; iface = iface->next)
230 if (iface->index == index && iface->addr.sa.sa_family == AF_INET &&
231 iface->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
232 return 1;
233
234 return 0;
235}
236
Simon Kelley115ac3e2013-05-20 11:28:32 +0100237struct iface_param {
238 struct addrlist *spare;
239 int fd;
240};
241
242static int iface_allowed(struct iface_param *param, int if_index, char *label,
Simon Kelley376d48c2013-11-13 13:04:30 +0000243 union mysockaddr *addr, struct in_addr netmask, int prefixlen, int dad)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100244{
245 struct irec *iface;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100246 int mtu = 0, loopback;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100247 struct ifreq ifr;
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100248 int tftp_ok = !!option_bool(OPT_TFTP);
Simon Kelley9380ba72012-04-16 14:41:56 +0100249 int dhcp_ok = 1;
Simon Kelley4f7b3042012-11-28 21:27:02 +0000250 int auth_dns = 0;
Simon Kelley91543f42013-09-23 12:41:20 +0100251#if defined(HAVE_DHCP) || defined(HAVE_TFTP)
Simon Kelley832af0b2007-01-21 20:01:28 +0000252 struct iname *tmp;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100253#endif
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100254
Vladislav Grishenko3b195962013-11-26 11:08:21 +0000255 (void)prefixlen;
256
Simon Kelley115ac3e2013-05-20 11:28:32 +0100257 if (!indextoname(param->fd, if_index, ifr.ifr_name) ||
258 ioctl(param->fd, SIOCGIFFLAGS, &ifr) == -1)
259 return 0;
Simon Kelley1f15b812009-10-13 17:49:32 +0100260
261 loopback = ifr.ifr_flags & IFF_LOOPBACK;
Simon Kelley9380ba72012-04-16 14:41:56 +0100262
263 if (loopback)
Simon Kelley3f2873d2013-05-14 11:28:47 +0100264 dhcp_ok = 0;
265
Simon Kelley115ac3e2013-05-20 11:28:32 +0100266 if (ioctl(param->fd, SIOCGIFMTU, &ifr) != -1)
Simon Kelley1f15b812009-10-13 17:49:32 +0100267 mtu = ifr.ifr_mtu;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100268
Simon Kelley115ac3e2013-05-20 11:28:32 +0100269 if (!label)
270 label = ifr.ifr_name;
Simon Kelleyc8a80482014-03-05 14:29:54 +0000271
272 /* maintain a list of all addresses on all interfaces for --local-service option */
273 if (option_bool(OPT_LOCAL_SERVICE))
274 {
275 struct addrlist *al;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100276
Simon Kelleyc8a80482014-03-05 14:29:54 +0000277 if (param->spare)
278 {
279 al = param->spare;
280 param->spare = al->next;
281 }
282 else
283 al = whine_malloc(sizeof(struct addrlist));
284
285 if (al)
286 {
287 al->next = daemon->interface_addrs;
288 daemon->interface_addrs = al;
289 al->prefixlen = prefixlen;
290
291 if (addr->sa.sa_family == AF_INET)
292 {
293 al->addr.addr.addr4 = addr->in.sin_addr;
294 al->flags = 0;
295 }
296#ifdef HAVE_IPV6
297 else
298 {
299 al->addr.addr.addr6 = addr->in6.sin6_addr;
300 al->flags = ADDRLIST_IPV6;
301 }
302#endif
303 }
304 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000305
Simon Kelley115ac3e2013-05-20 11:28:32 +0100306#ifdef HAVE_IPV6
307 if (addr->sa.sa_family != AF_INET6 || !IN6_IS_ADDR_LINKLOCAL(&addr->in6.sin6_addr))
308#endif
309 {
310 struct interface_name *int_name;
311 struct addrlist *al;
Simon Kelley376d48c2013-11-13 13:04:30 +0000312#ifdef HAVE_AUTH
313 struct auth_zone *zone;
314 struct auth_name_list *name;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100315
Simon Kelley376d48c2013-11-13 13:04:30 +0000316 /* Find subnets in auth_zones */
317 for (zone = daemon->auth_zones; zone; zone = zone->next)
318 for (name = zone->interface_names; name; name = name->next)
319 if (wildcard_match(name->name, label))
320 {
321 if (addr->sa.sa_family == AF_INET && (name->flags & AUTH4))
322 {
323 if (param->spare)
324 {
325 al = param->spare;
326 param->spare = al->next;
327 }
328 else
329 al = whine_malloc(sizeof(struct addrlist));
330
331 if (al)
332 {
333 al->next = zone->subnet;
334 zone->subnet = al;
335 al->prefixlen = prefixlen;
336 al->addr.addr.addr4 = addr->in.sin_addr;
337 al->flags = 0;
338 }
339 }
340
341#ifdef HAVE_IPV6
342 if (addr->sa.sa_family == AF_INET6 && (name->flags & AUTH6))
343 {
344 if (param->spare)
345 {
346 al = param->spare;
347 param->spare = al->next;
348 }
349 else
350 al = whine_malloc(sizeof(struct addrlist));
351
352 if (al)
353 {
354 al->next = zone->subnet;
355 zone->subnet = al;
Vladislav Grishenko3b195962013-11-26 11:08:21 +0000356 al->prefixlen = prefixlen;
357 al->addr.addr.addr6 = addr->in6.sin6_addr;
Simon Kelley376d48c2013-11-13 13:04:30 +0000358 al->flags = ADDRLIST_IPV6;
359 }
360 }
361#endif
362
363 }
364#endif
365
366 /* Update addresses from interface_names. These are a set independent
367 of the set we're listening on. */
Simon Kelley115ac3e2013-05-20 11:28:32 +0100368 for (int_name = daemon->int_names; int_name; int_name = int_name->next)
Simon Kelleyf7029f52013-11-21 15:09:09 +0000369 if (strncmp(label, int_name->intr, IF_NAMESIZE) == 0 &&
370 (addr->sa.sa_family == int_name->family || int_name->family == 0))
Simon Kelley115ac3e2013-05-20 11:28:32 +0100371 {
372 if (param->spare)
373 {
374 al = param->spare;
375 param->spare = al->next;
376 }
377 else
378 al = whine_malloc(sizeof(struct addrlist));
379
380 if (al)
381 {
Simon Kelley376d48c2013-11-13 13:04:30 +0000382 al->next = int_name->addr;
383 int_name->addr = al;
384
Simon Kelley115ac3e2013-05-20 11:28:32 +0100385 if (addr->sa.sa_family == AF_INET)
386 {
387 al->addr.addr.addr4 = addr->in.sin_addr;
Simon Kelley376d48c2013-11-13 13:04:30 +0000388 al->flags = 0;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100389 }
390#ifdef HAVE_IPV6
391 else
392 {
393 al->addr.addr.addr6 = addr->in6.sin6_addr;
Simon Kelley376d48c2013-11-13 13:04:30 +0000394 al->flags = ADDRLIST_IPV6;
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 {
406 iface->dad = dad;
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 Kelley74c95c22011-10-19 09:33:39 +0100481 iface->dad = dad;
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 Kelley376d48c2013-11-13 13:04:30 +0000526 return iface_allowed((struct iface_param *)vparam, if_index, NULL, &addr, netmask, prefix, !!(flags & IFACE_TENTATIVE));
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 Kelley397542b2013-09-05 11:27:34 +0100554 static int done = 0, active = 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 Kelley397542b2013-09-05 11:27:34 +0100573 if (done || active)
Simon Kelley115ac3e2013-05-20 11:28:32 +0100574 return 1;
575
576 done = 1;
577
Simon Kelley397542b2013-09-05 11:27:34 +0100578 /* protect against recusive calls from iface_enumerate(); */
579 active = 1;
580
Simon Kelley115ac3e2013-05-20 11:28:32 +0100581 if ((param.fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
582 return 0;
583
Simon Kelley08619212013-12-02 14:43:48 +0000584 /* Mark interfaces for garbage collection */
585 for (iface = daemon->interfaces; iface; iface = iface->next)
586 iface->found = 0;
587
Simon Kelley115ac3e2013-05-20 11:28:32 +0100588 /* remove addresses stored against interface_names */
589 for (intname = daemon->int_names; intname; intname = intname->next)
590 {
Simon Kelley376d48c2013-11-13 13:04:30 +0000591 for (addr = intname->addr; addr; addr = tmp)
Simon Kelley115ac3e2013-05-20 11:28:32 +0100592 {
593 tmp = addr->next;
594 addr->next = spare;
595 spare = addr;
596 }
597
Simon Kelley376d48c2013-11-13 13:04:30 +0000598 intname->addr = NULL;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100599 }
Simon Kelley376d48c2013-11-13 13:04:30 +0000600
Simon Kelleyc8a80482014-03-05 14:29:54 +0000601 /* Remove list of addresses of local interfaces */
602 for (addr = daemon->interface_addrs; addr; addr = tmp)
603 {
604 tmp = addr->next;
605 addr->next = spare;
606 spare = addr;
607 }
608 daemon->interface_addrs = NULL;
609
Simon Kelley376d48c2013-11-13 13:04:30 +0000610#ifdef HAVE_AUTH
611 /* remove addresses stored against auth_zone subnets, but not
612 ones configured as address literals */
613 for (zone = daemon->auth_zones; zone; zone = zone->next)
614 if (zone->interface_names)
615 {
616 struct addrlist **up;
617 for (up = &zone->subnet, addr = zone->subnet; addr; addr = tmp)
618 {
619 tmp = addr->next;
620 if (addr->flags & ADDRLIST_LITERAL)
621 up = &addr->next;
622 else
623 {
624 *up = addr->next;
625 addr->next = spare;
626 spare = addr;
627 }
628 }
629 }
630#endif
631
Simon Kelley115ac3e2013-05-20 11:28:32 +0100632 param.spare = spare;
633
634#ifdef HAVE_IPV6
635 ret = iface_enumerate(AF_INET6, &param, iface_allowed_v6);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100636#endif
Simon Kelley28866e92011-02-14 20:19:14 +0000637
Simon Kelley115ac3e2013-05-20 11:28:32 +0100638 if (ret)
639 ret = iface_enumerate(AF_INET, &param, iface_allowed_v4);
640
641 errsave = errno;
642 close(param.fd);
Simon Kelley08619212013-12-02 14:43:48 +0000643
644 if (option_bool(OPT_CLEVERBIND))
645 {
646 /* Garbage-collect listeners listening on addresses that no longer exist.
647 Does nothing when not binding interfaces or for listeners on localhost,
648 since the ->iface field is NULL. Note that this needs the protections
649 against re-entrancy, hence it's here. It also means there's a possibility,
650 in OPT_CLEVERBIND mode, that at listener will just disappear after
651 a call to enumerate_interfaces, this is checked OK on all calls. */
652 struct listener *l, *tmp, **up;
653
654 for (up = &daemon->listeners, l = daemon->listeners; l; l = tmp)
655 {
656 tmp = l->next;
657
658 if (!l->iface || l->iface->found)
659 up = &l->next;
660 else
661 {
662 *up = l->next;
663
664 /* In case it ever returns */
665 l->iface->done = 0;
666
667 if (l->fd != -1)
668 close(l->fd);
669 if (l->tcpfd != -1)
670 close(l->tcpfd);
671 if (l->tftpfd != -1)
672 close(l->tftpfd);
673
674 free(l);
675 }
676 }
677 }
678
Simon Kelley115ac3e2013-05-20 11:28:32 +0100679 errno = errsave;
Simon Kelley08619212013-12-02 14:43:48 +0000680
Simon Kelley115ac3e2013-05-20 11:28:32 +0100681 spare = param.spare;
Simon Kelley397542b2013-09-05 11:27:34 +0100682 active = 0;
Simon Kelley08619212013-12-02 14:43:48 +0000683
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 {
Matthias Andree71aaa5a2013-12-03 11:20:45 +0000706 int port, errsav;
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:
Matthias Andree71aaa5a2013-12-03 11:20:45 +0000716 errsav = 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
725 errno = errsav;
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 {
753 if (listen(fd, 5) == -1)
754 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;
817
818 /* use mshdr do that the CMSDG_* macros are available */
819 msg.msg_control = daemon->packet;
820 msg.msg_controllen = daemon->packet_buff_sz;
821
822 /* we overwrote the buffer... */
823 daemon->srv_save = NULL;
824
825 if (af == AF_INET)
826 {
827 if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) != -1 &&
828 getsockopt(fd, IPPROTO_IP, IP_PKTOPTIONS, msg.msg_control, (socklen_t *)&msg.msg_controllen) != -1)
829 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
830 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
831 {
832 union {
833 unsigned char *c;
834 struct in_pktinfo *p;
835 } p;
836
837 p.c = CMSG_DATA(cmptr);
838 if_index = p.p->ipi_ifindex;
839 }
840 }
841#ifdef HAVE_IPV6
842 else
843 {
844 /* Only the RFC-2292 API has the ability to find the interface for TCP connections,
845 it was removed in RFC-3542 !!!!
846
847 Fortunately, Linux kept the 2292 ABI when it moved to 3542. The following code always
848 uses the old ABI, and should work with pre- and post-3542 kernel headers */
849
850#ifdef IPV6_2292PKTOPTIONS
851# define PKTOPTIONS IPV6_2292PKTOPTIONS
852#else
853# define PKTOPTIONS IPV6_PKTOPTIONS
854#endif
855
856 if (set_ipv6pktinfo(fd) &&
857 getsockopt(fd, IPPROTO_IPV6, PKTOPTIONS, msg.msg_control, (socklen_t *)&msg.msg_controllen) != -1)
858 {
859 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
860 if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
861 {
862 union {
863 unsigned char *c;
864 struct in6_pktinfo *p;
865 } p;
866 p.c = CMSG_DATA(cmptr);
867
868 if_index = p.p->ipi6_ifindex;
869 }
870 }
871 }
872#endif /* IPV6 */
873#endif /* Linux */
874
875 return if_index;
876}
Simon Kelley28866e92011-02-14 20:19:14 +0000877
Simon Kelley74c95c22011-10-19 09:33:39 +0100878static struct listener *create_listeners(union mysockaddr *addr, int do_tftp, int dienow)
Simon Kelley28866e92011-02-14 20:19:14 +0000879{
880 struct listener *l = NULL;
881 int fd = -1, tcpfd = -1, tftpfd = -1;
882
Vladislav Grishenko408c3682013-09-24 16:18:49 +0100883 (void)do_tftp;
884
Simon Kelley28866e92011-02-14 20:19:14 +0000885 if (daemon->port != 0)
886 {
Simon Kelley74c95c22011-10-19 09:33:39 +0100887 fd = make_sock(addr, SOCK_DGRAM, dienow);
888 tcpfd = make_sock(addr, SOCK_STREAM, dienow);
Simon Kelley28866e92011-02-14 20:19:14 +0000889 }
890
891#ifdef HAVE_TFTP
892 if (do_tftp)
893 {
894 if (addr->sa.sa_family == AF_INET)
895 {
896 /* port must be restored to DNS port for TCP code */
897 short save = addr->in.sin_port;
898 addr->in.sin_port = htons(TFTP_PORT);
Simon Kelley74c95c22011-10-19 09:33:39 +0100899 tftpfd = make_sock(addr, SOCK_DGRAM, dienow);
Simon Kelley28866e92011-02-14 20:19:14 +0000900 addr->in.sin_port = save;
901 }
902# ifdef HAVE_IPV6
903 else
904 {
905 short save = addr->in6.sin6_port;
906 addr->in6.sin6_port = htons(TFTP_PORT);
Simon Kelley74c95c22011-10-19 09:33:39 +0100907 tftpfd = make_sock(addr, SOCK_DGRAM, dienow);
Simon Kelley28866e92011-02-14 20:19:14 +0000908 addr->in6.sin6_port = save;
909 }
910# endif
911 }
Simon Kelley44a2a312004-03-10 20:04:35 +0000912#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100913
Simon Kelley28866e92011-02-14 20:19:14 +0000914 if (fd != -1 || tcpfd != -1 || tftpfd != -1)
915 {
916 l = safe_malloc(sizeof(struct listener));
917 l->next = NULL;
918 l->family = addr->sa.sa_family;
919 l->fd = fd;
920 l->tcpfd = tcpfd;
Simon Kelley08619212013-12-02 14:43:48 +0000921 l->tftpfd = tftpfd;
922 l->iface = NULL;
Simon Kelley28866e92011-02-14 20:19:14 +0000923 }
924
925 return l;
926}
927
Simon Kelley74c95c22011-10-19 09:33:39 +0100928void create_wildcard_listeners(void)
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100929{
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100930 union mysockaddr addr;
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100931 struct listener *l, *l6;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100932
Simon Kelley849a8352006-06-09 21:02:31 +0100933 memset(&addr, 0, sizeof(addr));
Simon Kelley28866e92011-02-14 20:19:14 +0000934#ifdef HAVE_SOCKADDR_SA_LEN
935 addr.in.sin_len = sizeof(addr.in);
936#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100937 addr.in.sin_family = AF_INET;
938 addr.in.sin_addr.s_addr = INADDR_ANY;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100939 addr.in.sin_port = htons(daemon->port);
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100940
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100941 l = create_listeners(&addr, !!option_bool(OPT_TFTP), 1);
Simon Kelley28866e92011-02-14 20:19:14 +0000942
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100943#ifdef HAVE_IPV6
Simon Kelley28866e92011-02-14 20:19:14 +0000944 memset(&addr, 0, sizeof(addr));
945# ifdef HAVE_SOCKADDR_SA_LEN
946 addr.in6.sin6_len = sizeof(addr.in6);
947# endif
948 addr.in6.sin6_family = AF_INET6;
949 addr.in6.sin6_addr = in6addr_any;
950 addr.in6.sin6_port = htons(daemon->port);
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100951
952 l6 = create_listeners(&addr, !!option_bool(OPT_TFTP), 1);
Simon Kelley28866e92011-02-14 20:19:14 +0000953 if (l)
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100954 l->next = l6;
Simon Kelley28866e92011-02-14 20:19:14 +0000955 else
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100956 l = l6;
Simon Kelley832af0b2007-01-21 20:01:28 +0000957#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100958
Simon Kelley74c95c22011-10-19 09:33:39 +0100959 daemon->listeners = l;
Simon Kelley44a2a312004-03-10 20:04:35 +0000960}
961
Simon Kelley74c95c22011-10-19 09:33:39 +0100962void create_bound_listeners(int dienow)
Simon Kelley44a2a312004-03-10 20:04:35 +0000963{
Simon Kelley74c95c22011-10-19 09:33:39 +0100964 struct listener *new;
Simon Kelley44a2a312004-03-10 20:04:35 +0000965 struct irec *iface;
Simon Kelley52d4abf2012-03-21 21:39:48 +0000966 struct iname *if_tmp;
Simon Kelley73a08a22009-02-05 20:28:08 +0000967
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100968 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelley08619212013-12-02 14:43:48 +0000969 if (!iface->done && !iface->dad && iface->found &&
Simon Kelley74c95c22011-10-19 09:33:39 +0100970 (new = create_listeners(&iface->addr, iface->tftp_ok, dienow)))
Simon Kelley28866e92011-02-14 20:19:14 +0000971 {
972 new->iface = iface;
Simon Kelley74c95c22011-10-19 09:33:39 +0100973 new->next = daemon->listeners;
974 daemon->listeners = new;
975 iface->done = 1;
Simon Kelley28866e92011-02-14 20:19:14 +0000976 }
Simon Kelley52d4abf2012-03-21 21:39:48 +0000977
978 /* Check for --listen-address options that haven't been used because there's
979 no interface with a matching address. These may be valid: eg it's possible
980 to listen on 127.0.1.1 even if the loopback interface is 127.0.0.1
981
Simon Kelley5f11b3e2012-08-16 14:04:05 +0100982 If the address isn't valid the bind() will fail and we'll die()
983 (except in bind-dynamic mode, when we'll complain but keep trying.)
Simon Kelley52d4abf2012-03-21 21:39:48 +0000984
985 The resulting listeners have the ->iface field NULL, and this has to be
986 handled by the DNS and TFTP code. It disables --localise-queries processing
987 (no netmask) and some MTU login the tftp code. */
988
989 for (if_tmp = daemon->if_addrs; if_tmp; if_tmp = if_tmp->next)
990 if (!if_tmp->used &&
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100991 (new = create_listeners(&if_tmp->addr, !!option_bool(OPT_TFTP), dienow)))
Simon Kelley52d4abf2012-03-21 21:39:48 +0000992 {
Simon Kelley52d4abf2012-03-21 21:39:48 +0000993 new->next = daemon->listeners;
994 daemon->listeners = new;
995 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000996}
997
Simon Kelleydc27e142013-10-16 13:09:53 +0100998/* In --bind-interfaces, the only access control is the addresses we're listening on.
999 There's nothing to avoid a query to the address of an internal interface arriving via
1000 an external interface where we don't want to accept queries, except that in the usual
1001 case the addresses of internal interfaces are RFC1918. When bind-interfaces in use,
1002 and we listen on an address that looks like it's probably globally routeable, shout.
1003
1004 The fix is to use --bind-dynamic, which actually checks the arrival interface too.
1005 Tough if your platform doesn't support this.
Simon Kelley2329bef2013-12-03 13:41:16 +00001006
1007 Note that checking the arrival interface is supported in the standard IPv6 API and
1008 always done, so we don't warn about any IPv6 addresses here.
Simon Kelleydc27e142013-10-16 13:09:53 +01001009*/
1010
1011void warn_bound_listeners(void)
1012{
1013 struct irec *iface;
1014 int advice = 0;
1015
1016 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelleyf7029f52013-11-21 15:09:09 +00001017 if (!iface->dns_auth)
Simon Kelleydc27e142013-10-16 13:09:53 +01001018 {
Simon Kelleydc27e142013-10-16 13:09:53 +01001019 if (iface->addr.sa.sa_family == AF_INET)
1020 {
1021 if (!private_net(iface->addr.in.sin_addr, 1))
1022 {
1023 inet_ntop(AF_INET, &iface->addr.in.sin_addr, daemon->addrbuff, ADDRSTRLEN);
Simon Kelley2329bef2013-12-03 13:41:16 +00001024 iface->warned = advice = 1;
1025 my_syslog(LOG_WARNING,
1026 _("LOUD WARNING: listening on %s may accept requests via interfaces other than %s"),
1027 daemon->addrbuff, iface->name);
Simon Kelleydc27e142013-10-16 13:09:53 +01001028 }
1029 }
Simon Kelleydc27e142013-10-16 13:09:53 +01001030 }
1031
1032 if (advice)
Simon Kelleyf7029f52013-11-21 15:09:09 +00001033 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 +01001034}
1035
Simon Kelleyf7029f52013-11-21 15:09:09 +00001036void warn_int_names(void)
1037{
1038 struct interface_name *intname;
1039
1040 for (intname = daemon->int_names; intname; intname = intname->next)
1041 if (!intname->addr)
1042 my_syslog(LOG_WARNING, _("warning: no addresses found for interface %s"), intname->intr);
1043}
1044
Simon Kelley74c95c22011-10-19 09:33:39 +01001045int is_dad_listeners(void)
1046{
1047 struct irec *iface;
1048
1049 if (option_bool(OPT_NOWILD))
1050 for (iface = daemon->interfaces; iface; iface = iface->next)
1051 if (iface->dad && !iface->done)
1052 return 1;
1053
1054 return 0;
1055}
Simon Kelley5d162f22012-12-20 14:55:46 +00001056
1057#ifdef HAVE_DHCP6
1058void join_multicast(int dienow)
1059{
1060 struct irec *iface, *tmp;
1061
1062 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelley19624462012-12-28 11:18:09 +00001063 if (iface->addr.sa.sa_family == AF_INET6 && iface->dhcp_ok && !iface->multicast_done)
Simon Kelley5d162f22012-12-20 14:55:46 +00001064 {
1065 /* There's an irec per address but we only want to join for multicast
1066 once per interface. Weed out duplicates. */
1067 for (tmp = daemon->interfaces; tmp; tmp = tmp->next)
1068 if (tmp->multicast_done && tmp->index == iface->index)
1069 break;
1070
1071 iface->multicast_done = 1;
1072
1073 if (!tmp)
1074 {
1075 struct ipv6_mreq mreq;
1076 int err = 0;
1077
1078 mreq.ipv6mr_interface = iface->index;
1079
1080 inet_pton(AF_INET6, ALL_RELAY_AGENTS_AND_SERVERS, &mreq.ipv6mr_multiaddr);
1081
Simon Kelleyff7eea22013-09-04 18:01:38 +01001082 if ((daemon->doing_dhcp6 || daemon->relay6) &&
Simon Kelley5d162f22012-12-20 14:55:46 +00001083 setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
1084 err = 1;
1085
1086 inet_pton(AF_INET6, ALL_SERVERS, &mreq.ipv6mr_multiaddr);
1087
1088 if (daemon->doing_dhcp6 &&
1089 setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
1090 err = 1;
1091
1092 inet_pton(AF_INET6, ALL_ROUTERS, &mreq.ipv6mr_multiaddr);
1093
1094 if (daemon->doing_ra &&
1095 setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
1096 err = 1;
1097
1098 if (err)
1099 {
1100 char *s = _("interface %s failed to join DHCPv6 multicast group: %s");
1101 if (dienow)
1102 die(s, iface->name, EC_BADNET);
1103 else
1104 my_syslog(LOG_ERR, s, iface->name, strerror(errno));
1105 }
1106 }
1107 }
1108}
1109#endif
1110
Simon Kelley9009d742008-11-14 20:04:27 +00001111/* return a UDP socket bound to a random port, have to cope with straying into
Simon Kelley1a6bca82008-07-11 11:11:42 +01001112 occupied port nos and reserved ones. */
1113int random_sock(int family)
1114{
1115 int fd;
1116
1117 if ((fd = socket(family, SOCK_DGRAM, 0)) != -1)
1118 {
Simon Kelley3927da42008-07-20 15:10:39 +01001119 union mysockaddr addr;
Simon Kelley1ad24ae2008-07-20 20:22:50 +01001120 unsigned int ports_avail = 65536u - (unsigned short)daemon->min_port;
Simon Kelley9009d742008-11-14 20:04:27 +00001121 int tries = ports_avail < 30 ? 3 * ports_avail : 100;
Simon Kelley3927da42008-07-20 15:10:39 +01001122
Simon Kelley1a6bca82008-07-11 11:11:42 +01001123 memset(&addr, 0, sizeof(addr));
Simon Kelley3927da42008-07-20 15:10:39 +01001124 addr.sa.sa_family = family;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001125
Simon Kelley1ad24ae2008-07-20 20:22:50 +01001126 /* don't loop forever if all ports in use. */
1127
Simon Kelley1a6bca82008-07-11 11:11:42 +01001128 if (fix_fd(fd))
Simon Kelley9009d742008-11-14 20:04:27 +00001129 while(tries--)
Simon Kelley1a6bca82008-07-11 11:11:42 +01001130 {
1131 unsigned short port = rand16();
1132
Simon Kelley3927da42008-07-20 15:10:39 +01001133 if (daemon->min_port != 0)
Simon Kelley1ad24ae2008-07-20 20:22:50 +01001134 port = htons(daemon->min_port + (port % ((unsigned short)ports_avail)));
Simon Kelley1a6bca82008-07-11 11:11:42 +01001135
1136 if (family == AF_INET)
1137 {
1138 addr.in.sin_addr.s_addr = INADDR_ANY;
Simon Kelley3927da42008-07-20 15:10:39 +01001139 addr.in.sin_port = port;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001140#ifdef HAVE_SOCKADDR_SA_LEN
1141 addr.in.sin_len = sizeof(struct sockaddr_in);
1142#endif
1143 }
1144#ifdef HAVE_IPV6
1145 else
1146 {
1147 addr.in6.sin6_addr = in6addr_any;
Simon Kelley3927da42008-07-20 15:10:39 +01001148 addr.in6.sin6_port = port;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001149#ifdef HAVE_SOCKADDR_SA_LEN
1150 addr.in6.sin6_len = sizeof(struct sockaddr_in6);
1151#endif
1152 }
1153#endif
1154
1155 if (bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == 0)
1156 return fd;
1157
1158 if (errno != EADDRINUSE && errno != EACCES)
1159 break;
1160 }
1161
1162 close(fd);
1163 }
1164
1165 return -1;
1166}
1167
1168
Simon Kelley824af852008-02-12 20:43:05 +00001169int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp)
1170{
1171 union mysockaddr addr_copy = *addr;
1172
1173 /* cannot set source _port_ for TCP connections. */
1174 if (is_tcp)
1175 {
1176 if (addr_copy.sa.sa_family == AF_INET)
1177 addr_copy.in.sin_port = 0;
1178#ifdef HAVE_IPV6
1179 else
1180 addr_copy.in6.sin6_port = 0;
1181#endif
1182 }
1183
1184 if (bind(fd, (struct sockaddr *)&addr_copy, sa_len(&addr_copy)) == -1)
1185 return 0;
1186
1187#if defined(SO_BINDTODEVICE)
Simon Kelley73a08a22009-02-05 20:28:08 +00001188 if (intname[0] != 0 &&
Simon Kelley316e2732010-01-22 20:16:09 +00001189 setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, intname, IF_NAMESIZE) == -1)
Simon Kelley824af852008-02-12 20:43:05 +00001190 return 0;
1191#endif
1192
1193 return 1;
1194}
1195
1196static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001197{
1198 struct serverfd *sfd;
Simon Kelley824af852008-02-12 20:43:05 +00001199 int errsave;
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001200
Simon Kelley1a6bca82008-07-11 11:11:42 +01001201 /* when using random ports, servers which would otherwise use
1202 the INADDR_ANY/port0 socket have sfd set to NULL */
Simon Kelley73a08a22009-02-05 20:28:08 +00001203 if (!daemon->osport && intname[0] == 0)
Simon Kelley1a6bca82008-07-11 11:11:42 +01001204 {
1205 errno = 0;
1206
1207 if (addr->sa.sa_family == AF_INET &&
1208 addr->in.sin_addr.s_addr == INADDR_ANY &&
1209 addr->in.sin_port == htons(0))
1210 return NULL;
1211
1212#ifdef HAVE_IPV6
1213 if (addr->sa.sa_family == AF_INET6 &&
1214 memcmp(&addr->in6.sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0 &&
1215 addr->in6.sin6_port == htons(0))
1216 return NULL;
1217#endif
1218 }
1219
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001220 /* may have a suitable one already */
Simon Kelley824af852008-02-12 20:43:05 +00001221 for (sfd = daemon->sfds; sfd; sfd = sfd->next )
1222 if (sockaddr_isequal(&sfd->source_addr, addr) &&
1223 strcmp(intname, sfd->interface) == 0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001224 return sfd;
1225
1226 /* need to make a new one. */
1227 errno = ENOMEM; /* in case malloc fails. */
Simon Kelley5aabfc72007-08-29 11:24:47 +01001228 if (!(sfd = whine_malloc(sizeof(struct serverfd))))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001229 return NULL;
1230
1231 if ((sfd->fd = socket(addr->sa.sa_family, SOCK_DGRAM, 0)) == -1)
1232 {
1233 free(sfd);
1234 return NULL;
1235 }
1236
Simon Kelley824af852008-02-12 20:43:05 +00001237 if (!local_bind(sfd->fd, addr, intname, 0) || !fix_fd(sfd->fd))
1238 {
1239 errsave = errno; /* save error from bind. */
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001240 close(sfd->fd);
1241 free(sfd);
1242 errno = errsave;
1243 return NULL;
1244 }
Simon Kelley824af852008-02-12 20:43:05 +00001245
1246 strcpy(sfd->interface, intname);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001247 sfd->source_addr = *addr;
Simon Kelley824af852008-02-12 20:43:05 +00001248 sfd->next = daemon->sfds;
1249 daemon->sfds = sfd;
1250 return sfd;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001251}
1252
Simon Kelley824af852008-02-12 20:43:05 +00001253/* create upstream sockets during startup, before root is dropped which may be needed
1254 this allows query_port to be a low port and interface binding */
1255void pre_allocate_sfds(void)
1256{
1257 struct server *srv;
1258
1259 if (daemon->query_port != 0)
1260 {
1261 union mysockaddr addr;
1262 memset(&addr, 0, sizeof(addr));
1263 addr.in.sin_family = AF_INET;
1264 addr.in.sin_addr.s_addr = INADDR_ANY;
1265 addr.in.sin_port = htons(daemon->query_port);
1266#ifdef HAVE_SOCKADDR_SA_LEN
1267 addr.in.sin_len = sizeof(struct sockaddr_in);
1268#endif
1269 allocate_sfd(&addr, "");
1270#ifdef HAVE_IPV6
1271 memset(&addr, 0, sizeof(addr));
1272 addr.in6.sin6_family = AF_INET6;
1273 addr.in6.sin6_addr = in6addr_any;
1274 addr.in6.sin6_port = htons(daemon->query_port);
1275#ifdef HAVE_SOCKADDR_SA_LEN
1276 addr.in6.sin6_len = sizeof(struct sockaddr_in6);
1277#endif
1278 allocate_sfd(&addr, "");
1279#endif
1280 }
1281
1282 for (srv = daemon->servers; srv; srv = srv->next)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001283 if (!(srv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)) &&
Simon Kelley824af852008-02-12 20:43:05 +00001284 !allocate_sfd(&srv->source_addr, srv->interface) &&
Simon Kelley1a6bca82008-07-11 11:11:42 +01001285 errno != 0 &&
Simon Kelley28866e92011-02-14 20:19:14 +00001286 option_bool(OPT_NOWILD))
Simon Kelley824af852008-02-12 20:43:05 +00001287 {
Simon Kelley316e2732010-01-22 20:16:09 +00001288 prettyprint_addr(&srv->source_addr, daemon->namebuff);
Simon Kelley73a08a22009-02-05 20:28:08 +00001289 if (srv->interface[0] != 0)
Simon Kelley824af852008-02-12 20:43:05 +00001290 {
1291 strcat(daemon->namebuff, " ");
1292 strcat(daemon->namebuff, srv->interface);
1293 }
1294 die(_("failed to bind server socket for %s: %s"),
1295 daemon->namebuff, EC_BADNET);
1296 }
1297}
1298
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001299void mark_servers(int flag)
1300{
1301 struct server *serv;
1302
1303 /* mark everything with argument flag */
1304 for (serv = daemon->servers; serv; serv = serv->next)
1305 if (serv->flags & flag)
1306 serv->flags |= SERV_MARK;
1307}
1308
1309void cleanup_servers(void)
1310{
1311 struct server *serv, *tmp, **up;
1312
1313 /* unlink and free anything still marked. */
1314 for (serv = daemon->servers, up = &daemon->servers; serv; serv = tmp)
1315 {
1316 tmp = serv->next;
1317 if (serv->flags & SERV_MARK)
1318 {
1319 server_gone(serv);
1320 *up = serv->next;
1321 if (serv->domain)
1322 free(serv->domain);
1323 free(serv);
1324 }
1325 else
1326 up = &serv->next;
1327 }
1328}
1329
1330void add_update_server(int flags,
1331 union mysockaddr *addr,
1332 union mysockaddr *source_addr,
1333 const char *interface,
1334 const char *domain)
1335{
Simon Kelley7b1eae42014-02-20 13:43:28 +00001336 struct server *serv, *next = NULL;
1337 char *domain_str = NULL;
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001338
1339 /* See if there is a suitable candidate, and unmark */
1340 for (serv = daemon->servers; serv; serv = serv->next)
1341 if (serv->flags & SERV_MARK)
1342 {
1343 if (domain)
1344 {
1345 if (!(serv->flags & SERV_HAS_DOMAIN) || !hostname_isequal(domain, serv->domain))
1346 continue;
1347 }
1348 else
1349 {
1350 if (serv->flags & SERV_HAS_DOMAIN)
1351 continue;
1352 }
1353
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001354 break;
1355 }
Simon Kelley7b1eae42014-02-20 13:43:28 +00001356
1357 if (serv)
1358 {
1359 domain_str = serv->domain;
1360 next = serv->next;
1361 }
1362 else if ((serv = whine_malloc(sizeof (struct server))))
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001363 {
1364 /* Not found, create a new one. */
Simon Kelley7b1eae42014-02-20 13:43:28 +00001365 if (domain && !(domain_str = whine_malloc(strlen(domain)+1)))
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001366 {
1367 free(serv);
1368 serv = NULL;
1369 }
1370 else
1371 {
1372 struct server *s;
1373 /* Add to the end of the chain, for order */
1374 if (!daemon->servers)
1375 daemon->servers = serv;
1376 else
1377 {
1378 for (s = daemon->servers; s->next; s = s->next);
1379 s->next = serv;
1380 }
1381 if (domain)
Simon Kelley7b1eae42014-02-20 13:43:28 +00001382 strcpy(domain_str, domain);
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001383 }
1384 }
1385
1386 if (serv)
1387 {
Simon Kelley7b1eae42014-02-20 13:43:28 +00001388 memset(serv, 0, sizeof(struct server));
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001389 serv->flags = flags;
Simon Kelley7b1eae42014-02-20 13:43:28 +00001390 serv->domain = domain_str;
1391 serv->next = next;
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001392 serv->queries = serv->failed_queries = 0;
1393
1394 if (domain)
1395 serv->flags |= SERV_HAS_DOMAIN;
1396
1397 if (interface)
Simon Kelley7b1eae42014-02-20 13:43:28 +00001398 strcpy(serv->interface, interface);
1399 if (addr)
1400 serv->addr = *addr;
1401 if (source_addr)
1402 serv->source_addr = *source_addr;
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001403 }
1404}
Simon Kelley824af852008-02-12 20:43:05 +00001405
Simon Kelley5aabfc72007-08-29 11:24:47 +01001406void check_servers(void)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001407{
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001408 struct irec *iface;
Simon Kelley7bcca002014-02-19 17:45:17 +00001409 struct server *serv;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001410 int port = 0;
1411
Simon Kelley316e2732010-01-22 20:16:09 +00001412 /* interface may be new since startup */
Simon Kelley28866e92011-02-14 20:19:14 +00001413 if (!option_bool(OPT_NOWILD))
Simon Kelley115ac3e2013-05-20 11:28:32 +01001414 enumerate_interfaces(0);
Simon Kelley316e2732010-01-22 20:16:09 +00001415
Simon Kelley7bcca002014-02-19 17:45:17 +00001416 for (serv = daemon->servers; serv; serv = serv->next)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001417 {
Simon Kelley7bcca002014-02-19 17:45:17 +00001418 if (!(serv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001419 {
Simon Kelley7bcca002014-02-19 17:45:17 +00001420 port = prettyprint_addr(&serv->addr, daemon->namebuff);
Simon Kelley3d8df262005-08-29 12:19:27 +01001421
Simon Kelley16972692006-10-16 20:04:18 +01001422 /* 0.0.0.0 is nothing, the stack treats it like 127.0.0.1 */
Simon Kelley7bcca002014-02-19 17:45:17 +00001423 if (serv->addr.sa.sa_family == AF_INET &&
1424 serv->addr.in.sin_addr.s_addr == 0)
Simon Kelley16972692006-10-16 20:04:18 +01001425 {
Simon Kelley7bcca002014-02-19 17:45:17 +00001426 serv->flags |= SERV_MARK;
Simon Kelley16972692006-10-16 20:04:18 +01001427 continue;
1428 }
1429
Simon Kelley3d8df262005-08-29 12:19:27 +01001430 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelley7bcca002014-02-19 17:45:17 +00001431 if (sockaddr_isequal(&serv->addr, &iface->addr))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001432 break;
1433 if (iface)
1434 {
Simon Kelleyf2621c72007-04-29 19:47:21 +01001435 my_syslog(LOG_WARNING, _("ignoring nameserver %s - local interface"), daemon->namebuff);
Simon Kelley7bcca002014-02-19 17:45:17 +00001436 serv->flags |= SERV_MARK;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001437 continue;
1438 }
1439
1440 /* Do we need a socket set? */
Simon Kelley7bcca002014-02-19 17:45:17 +00001441 if (!serv->sfd &&
1442 !(serv->sfd = allocate_sfd(&serv->source_addr, serv->interface)) &&
Simon Kelley1a6bca82008-07-11 11:11:42 +01001443 errno != 0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001444 {
Simon Kelleyf2621c72007-04-29 19:47:21 +01001445 my_syslog(LOG_WARNING,
1446 _("ignoring nameserver %s - cannot make/bind socket: %s"),
1447 daemon->namebuff, strerror(errno));
Simon Kelley7bcca002014-02-19 17:45:17 +00001448 serv->flags |= SERV_MARK;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001449 continue;
1450 }
1451 }
1452
Simon Kelley7bcca002014-02-19 17:45:17 +00001453 if (!(serv->flags & SERV_NO_REBIND))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001454 {
Simon Kelley7bcca002014-02-19 17:45:17 +00001455 if (serv->flags & (SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_USE_RESOLV))
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001456 {
1457 char *s1, *s2;
Simon Kelley7bcca002014-02-19 17:45:17 +00001458 if (!(serv->flags & SERV_HAS_DOMAIN))
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001459 s1 = _("unqualified"), s2 = _("names");
Simon Kelley7bcca002014-02-19 17:45:17 +00001460 else if (strlen(serv->domain) == 0)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001461 s1 = _("default"), s2 = "";
1462 else
Simon Kelley7bcca002014-02-19 17:45:17 +00001463 s1 = _("domain"), s2 = serv->domain;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001464
Simon Kelley7bcca002014-02-19 17:45:17 +00001465 if (serv->flags & SERV_NO_ADDR)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001466 my_syslog(LOG_INFO, _("using local addresses only for %s %s"), s1, s2);
Simon Kelley7bcca002014-02-19 17:45:17 +00001467 else if (serv->flags & SERV_USE_RESOLV)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001468 my_syslog(LOG_INFO, _("using standard nameservers for %s %s"), s1, s2);
Simon Kelley7bcca002014-02-19 17:45:17 +00001469 else if (!(serv->flags & SERV_LITERAL_ADDRESS))
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001470 my_syslog(LOG_INFO, _("using nameserver %s#%d for %s %s"), daemon->namebuff, port, s1, s2);
1471 }
Simon Kelley7bcca002014-02-19 17:45:17 +00001472 else if (serv->interface[0] != 0)
1473 my_syslog(LOG_INFO, _("using nameserver %s#%d(via %s)"), daemon->namebuff, port, serv->interface);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001474 else
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001475 my_syslog(LOG_INFO, _("using nameserver %s#%d"), daemon->namebuff, port);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001476 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001477 }
Simon Kelley7bcca002014-02-19 17:45:17 +00001478
1479 cleanup_servers();
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001480}
Simon Kelley849a8352006-06-09 21:02:31 +01001481
1482/* Return zero if no servers found, in that case we keep polling.
1483 This is a protection against an update-time/write race on resolv.conf */
Simon Kelley5aabfc72007-08-29 11:24:47 +01001484int reload_servers(char *fname)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001485{
1486 FILE *f;
1487 char *line;
Simon Kelley849a8352006-06-09 21:02:31 +01001488 int gotone = 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001489
Simon Kelley849a8352006-06-09 21:02:31 +01001490 /* buff happens to be MAXDNAME long... */
1491 if (!(f = fopen(fname, "r")))
1492 {
Simon Kelleyf2621c72007-04-29 19:47:21 +01001493 my_syslog(LOG_ERR, _("failed to read %s: %s"), fname, strerror(errno));
Simon Kelley849a8352006-06-09 21:02:31 +01001494 return 0;
1495 }
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001496
1497 mark_servers(SERV_FROM_RESOLV);
1498
Simon Kelley849a8352006-06-09 21:02:31 +01001499 while ((line = fgets(daemon->namebuff, MAXDNAME, f)))
1500 {
1501 union mysockaddr addr, source_addr;
1502 char *token = strtok(line, " \t\n\r");
1503
Simon Kelley5aabfc72007-08-29 11:24:47 +01001504 if (!token)
1505 continue;
1506 if (strcmp(token, "nameserver") != 0 && strcmp(token, "server") != 0)
Simon Kelley849a8352006-06-09 21:02:31 +01001507 continue;
1508 if (!(token = strtok(NULL, " \t\n\r")))
1509 continue;
1510
1511 memset(&addr, 0, sizeof(addr));
1512 memset(&source_addr, 0, sizeof(source_addr));
1513
1514 if ((addr.in.sin_addr.s_addr = inet_addr(token)) != (in_addr_t) -1)
1515 {
1516#ifdef HAVE_SOCKADDR_SA_LEN
1517 source_addr.in.sin_len = addr.in.sin_len = sizeof(source_addr.in);
1518#endif
1519 source_addr.in.sin_family = addr.in.sin_family = AF_INET;
1520 addr.in.sin_port = htons(NAMESERVER_PORT);
1521 source_addr.in.sin_addr.s_addr = INADDR_ANY;
1522 source_addr.in.sin_port = htons(daemon->query_port);
1523 }
1524#ifdef HAVE_IPV6
Simon Kelley7de060b2011-08-26 17:24:52 +01001525 else
1526 {
1527 int scope_index = 0;
1528 char *scope_id = strchr(token, '%');
1529
1530 if (scope_id)
1531 {
1532 *(scope_id++) = 0;
1533 scope_index = if_nametoindex(scope_id);
1534 }
1535
1536 if (inet_pton(AF_INET6, token, &addr.in6.sin6_addr) > 0)
1537 {
Simon Kelley849a8352006-06-09 21:02:31 +01001538#ifdef HAVE_SOCKADDR_SA_LEN
Simon Kelley7de060b2011-08-26 17:24:52 +01001539 source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(source_addr.in6);
Simon Kelley849a8352006-06-09 21:02:31 +01001540#endif
Simon Kelley7de060b2011-08-26 17:24:52 +01001541 source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6;
1542 source_addr.in6.sin6_flowinfo = addr.in6.sin6_flowinfo = 0;
1543 addr.in6.sin6_port = htons(NAMESERVER_PORT);
1544 addr.in6.sin6_scope_id = scope_index;
1545 source_addr.in6.sin6_addr = in6addr_any;
1546 source_addr.in6.sin6_port = htons(daemon->query_port);
1547 source_addr.in6.sin6_scope_id = 0;
1548 }
1549 else
1550 continue;
Simon Kelley849a8352006-06-09 21:02:31 +01001551 }
Simon Kelley7de060b2011-08-26 17:24:52 +01001552#else /* IPV6 */
Simon Kelley849a8352006-06-09 21:02:31 +01001553 else
1554 continue;
Simon Kelley7de060b2011-08-26 17:24:52 +01001555#endif
1556
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001557 add_update_server(SERV_FROM_RESOLV, &addr, &source_addr, NULL, NULL);
Simon Kelley849a8352006-06-09 21:02:31 +01001558 gotone = 1;
1559 }
1560
Simon Kelley849a8352006-06-09 21:02:31 +01001561 fclose(f);
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001562 cleanup_servers();
Simon Kelley849a8352006-06-09 21:02:31 +01001563
1564 return gotone;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001565}
1566
Simon Kelley1ee9be42013-12-09 16:50:19 +00001567#if defined(HAVE_LINUX_NETWORK) || defined(HAVE_BSD_NETWORK)
1568/* Called when addresses are added or deleted from an interface */
1569void newaddress(time_t now)
1570{
1571 (void)now;
1572
Simon Kelley89b12ed2014-03-06 13:27:57 +00001573 if (option_bool(OPT_CLEVERBIND) || option_bool(OPT_LOCAL_SERVICE) ||
1574 daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
Simon Kelley1ee9be42013-12-09 16:50:19 +00001575 enumerate_interfaces(0);
1576
1577 if (option_bool(OPT_CLEVERBIND))
1578 create_bound_listeners(0);
1579
1580#ifdef HAVE_DHCP6
1581 if (daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
1582 join_multicast(0);
1583
1584 if (daemon->doing_dhcp6 || daemon->doing_ra)
1585 dhcp_construct_contexts(now);
1586
1587 if (daemon->doing_dhcp6)
1588 lease_find_interfaces(now);
1589#endif
1590}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001591
Simon Kelley1ee9be42013-12-09 16:50:19 +00001592#endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001593
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001594
1595
1596