blob: d71ceb863bc002355ec66072609a2b8f98aa8d29 [file] [log] [blame]
Simon Kelleyd1ced3a2018-01-01 22:18:03 +00001/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
Simon Kelley824af852008-02-12 20:43:05 +00005 the Free Software Foundation; version 2 dated June, 1991, or
6 (at your option) version 3 dated 29 June, 2007.
7
Simon Kelley9e4abcb2004-01-22 19:47:41 +00008 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
Simon Kelley824af852008-02-12 20:43:05 +000012
Simon Kelley73a08a22009-02-05 20:28:08 +000013 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>.
Simon Kelley9e4abcb2004-01-22 19:47:41 +000015*/
16
Simon Kelley9e4abcb2004-01-22 19:47:41 +000017#include "dnsmasq.h"
18
Simon Kelley7622fc02009-06-04 20:32:05 +010019#ifdef HAVE_LINUX_NETWORK
20
21int indextoname(int fd, int index, char *name)
22{
23 struct ifreq ifr;
24
25 if (index == 0)
26 return 0;
27
28 ifr.ifr_ifindex = index;
29 if (ioctl(fd, SIOCGIFNAME, &ifr) == -1)
30 return 0;
31
Petr Menšík47b45b22018-08-15 18:17:00 +020032 safe_strncpy(name, ifr.ifr_name, IF_NAMESIZE);
Simon Kelley7622fc02009-06-04 20:32:05 +010033
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;
Petr Menšík47b45b22018-08-15 18:17:00 +020085 safe_strncpy(lifr.lifr_name, lifrp->lifr_name, IF_NAMESIZE);
Simon Kelley28866e92011-02-14 20:19:14 +000086 if (ioctl(fd, SIOCGLIFINDEX, &lifr) < 0)
87 return 0;
88
89 if (lifr.lifr_index == index) {
Petr Menšík47b45b22018-08-15 18:17:00 +020090 safe_strncpy(name, lifr.lifr_name, IF_NAMESIZE);
Simon Kelley28866e92011-02-14 20:19:14 +000091 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 Kelley429798f2012-12-10 20:45:53 +0000140 else if (family == AF_INET6 &&
141 IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr,
142 &addr->addr.addr6))
Simon Kelleyedf0bde2013-07-29 17:21:48 +0100143 ret = match_addr = tmp->used = 1;
Simon Kelley429798f2012-12-10 20:45:53 +0000144 }
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100145 }
146
Simon Kelleyedf0bde2013-07-29 17:21:48 +0100147 if (!match_addr)
148 for (tmp = daemon->if_except; tmp; tmp = tmp->next)
149 if (tmp->name && wildcard_match(tmp->name, name))
150 ret = 0;
Simon Kelleyc72daea2012-01-05 21:33:27 +0000151
Simon Kelley429798f2012-12-10 20:45:53 +0000152
153 for (tmp = daemon->authinterface; tmp; tmp = tmp->next)
154 if (tmp->name)
155 {
Simon Kelleyf25e6c62013-11-17 12:23:42 +0000156 if (strcmp(tmp->name, name) == 0 &&
157 (tmp->addr.sa.sa_family == 0 || tmp->addr.sa.sa_family == family))
Simon Kelley429798f2012-12-10 20:45:53 +0000158 break;
159 }
160 else if (addr && tmp->addr.sa.sa_family == AF_INET && family == AF_INET &&
161 tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
162 break;
Simon Kelley429798f2012-12-10 20:45:53 +0000163 else if (addr && tmp->addr.sa.sa_family == AF_INET6 && family == AF_INET6 &&
164 IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, &addr->addr.addr6))
165 break;
Simon Kelley429798f2012-12-10 20:45:53 +0000166
167 if (tmp && auth)
168 {
169 *auth = 1;
170 ret = 1;
171 }
172
Simon Kelley309331f2006-04-22 15:05:01 +0100173 return ret;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100174}
Simon Kelleye25db1f2013-01-29 22:10:26 +0000175
176
Josh Soref730c6742017-02-06 16:14:04 +0000177/* Fix for problem that the kernel sometimes reports the loopback interface as the
Simon Kelleye25db1f2013-01-29 22:10:26 +0000178 arrival interface when a packet originates locally, even when sent to address of
179 an interface other than the loopback. Accept packet if it arrived via a loopback
180 interface, even when we're not accepting packets that way, as long as the destination
181 address is one we're believing. Interface list must be up-to-date before calling. */
182int loopback_exception(int fd, int family, struct all_addr *addr, char *name)
183{
184 struct ifreq ifr;
185 struct irec *iface;
186
Petr Menšík47b45b22018-08-15 18:17:00 +0200187 safe_strncpy(ifr.ifr_name, name, IF_NAMESIZE);
Simon Kelleye25db1f2013-01-29 22:10:26 +0000188 if (ioctl(fd, SIOCGIFFLAGS, &ifr) != -1 &&
189 ifr.ifr_flags & IFF_LOOPBACK)
190 {
191 for (iface = daemon->interfaces; iface; iface = iface->next)
192 if (iface->addr.sa.sa_family == family)
193 {
194 if (family == AF_INET)
195 {
196 if (iface->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
197 return 1;
198 }
Simon Kelleye25db1f2013-01-29 22:10:26 +0000199 else if (IN6_ARE_ADDR_EQUAL(&iface->addr.in6.sin6_addr, &addr->addr.addr6))
200 return 1;
Simon Kelleye25db1f2013-01-29 22:10:26 +0000201 }
202 }
203 return 0;
204}
205
Simon Kelley3f2873d2013-05-14 11:28:47 +0100206/* If we're configured with something like --interface=eth0:0 then we'll listen correctly
207 on the relevant address, but the name of the arrival interface, derived from the
208 index won't match the config. Check that we found an interface address for the arrival
209 interface: daemon->interfaces must be up-to-date. */
210int label_exception(int index, int family, struct all_addr *addr)
211{
212 struct irec *iface;
213
214 /* labels only supported on IPv4 addresses. */
215 if (family != AF_INET)
216 return 0;
217
218 for (iface = daemon->interfaces; iface; iface = iface->next)
219 if (iface->index == index && iface->addr.sa.sa_family == AF_INET &&
220 iface->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
221 return 1;
222
223 return 0;
224}
225
Simon Kelley115ac3e2013-05-20 11:28:32 +0100226struct iface_param {
227 struct addrlist *spare;
228 int fd;
229};
230
231static int iface_allowed(struct iface_param *param, int if_index, char *label,
Simon Kelley47669362014-12-17 12:41:56 +0000232 union mysockaddr *addr, struct in_addr netmask, int prefixlen, int iface_flags)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100233{
234 struct irec *iface;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100235 int mtu = 0, loopback;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100236 struct ifreq ifr;
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100237 int tftp_ok = !!option_bool(OPT_TFTP);
Simon Kelley9380ba72012-04-16 14:41:56 +0100238 int dhcp_ok = 1;
Simon Kelley4f7b3042012-11-28 21:27:02 +0000239 int auth_dns = 0;
Petr Menšíkad59f272017-03-17 17:22:19 +0000240 int is_label = 0;
Simon Kelley91543f42013-09-23 12:41:20 +0100241#if defined(HAVE_DHCP) || defined(HAVE_TFTP)
Simon Kelley832af0b2007-01-21 20:01:28 +0000242 struct iname *tmp;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100243#endif
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100244
Vladislav Grishenko3b195962013-11-26 11:08:21 +0000245 (void)prefixlen;
246
Simon Kelley115ac3e2013-05-20 11:28:32 +0100247 if (!indextoname(param->fd, if_index, ifr.ifr_name) ||
248 ioctl(param->fd, SIOCGIFFLAGS, &ifr) == -1)
249 return 0;
Simon Kelley1f15b812009-10-13 17:49:32 +0100250
251 loopback = ifr.ifr_flags & IFF_LOOPBACK;
Simon Kelley9380ba72012-04-16 14:41:56 +0100252
253 if (loopback)
Simon Kelley3f2873d2013-05-14 11:28:47 +0100254 dhcp_ok = 0;
255
Simon Kelley115ac3e2013-05-20 11:28:32 +0100256 if (ioctl(param->fd, SIOCGIFMTU, &ifr) != -1)
Simon Kelley1f15b812009-10-13 17:49:32 +0100257 mtu = ifr.ifr_mtu;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100258
Simon Kelley115ac3e2013-05-20 11:28:32 +0100259 if (!label)
260 label = ifr.ifr_name;
Petr Menšíkad59f272017-03-17 17:22:19 +0000261 else
262 is_label = strcmp(label, ifr.ifr_name);
Simon Kelleyc8a80482014-03-05 14:29:54 +0000263
264 /* maintain a list of all addresses on all interfaces for --local-service option */
265 if (option_bool(OPT_LOCAL_SERVICE))
266 {
267 struct addrlist *al;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100268
Simon Kelleyc8a80482014-03-05 14:29:54 +0000269 if (param->spare)
270 {
271 al = param->spare;
272 param->spare = al->next;
273 }
274 else
275 al = whine_malloc(sizeof(struct addrlist));
276
277 if (al)
278 {
279 al->next = daemon->interface_addrs;
280 daemon->interface_addrs = al;
281 al->prefixlen = prefixlen;
282
283 if (addr->sa.sa_family == AF_INET)
284 {
285 al->addr.addr.addr4 = addr->in.sin_addr;
286 al->flags = 0;
287 }
Simon Kelleyc8a80482014-03-05 14:29:54 +0000288 else
289 {
290 al->addr.addr.addr6 = addr->in6.sin6_addr;
291 al->flags = ADDRLIST_IPV6;
292 }
Simon Kelleyc8a80482014-03-05 14:29:54 +0000293 }
294 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000295
Simon Kelley115ac3e2013-05-20 11:28:32 +0100296 if (addr->sa.sa_family != AF_INET6 || !IN6_IS_ADDR_LINKLOCAL(&addr->in6.sin6_addr))
Simon Kelley115ac3e2013-05-20 11:28:32 +0100297 {
298 struct interface_name *int_name;
299 struct addrlist *al;
Simon Kelley376d48c2013-11-13 13:04:30 +0000300#ifdef HAVE_AUTH
301 struct auth_zone *zone;
302 struct auth_name_list *name;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100303
Simon Kelley376d48c2013-11-13 13:04:30 +0000304 /* Find subnets in auth_zones */
305 for (zone = daemon->auth_zones; zone; zone = zone->next)
306 for (name = zone->interface_names; name; name = name->next)
307 if (wildcard_match(name->name, label))
308 {
309 if (addr->sa.sa_family == AF_INET && (name->flags & AUTH4))
310 {
311 if (param->spare)
312 {
313 al = param->spare;
314 param->spare = al->next;
315 }
316 else
317 al = whine_malloc(sizeof(struct addrlist));
318
319 if (al)
320 {
321 al->next = zone->subnet;
322 zone->subnet = al;
323 al->prefixlen = prefixlen;
324 al->addr.addr.addr4 = addr->in.sin_addr;
325 al->flags = 0;
326 }
327 }
328
Simon Kelley376d48c2013-11-13 13:04:30 +0000329 if (addr->sa.sa_family == AF_INET6 && (name->flags & AUTH6))
330 {
331 if (param->spare)
332 {
333 al = param->spare;
334 param->spare = al->next;
335 }
336 else
337 al = whine_malloc(sizeof(struct addrlist));
338
339 if (al)
340 {
341 al->next = zone->subnet;
342 zone->subnet = al;
Vladislav Grishenko3b195962013-11-26 11:08:21 +0000343 al->prefixlen = prefixlen;
344 al->addr.addr.addr6 = addr->in6.sin6_addr;
Simon Kelley376d48c2013-11-13 13:04:30 +0000345 al->flags = ADDRLIST_IPV6;
346 }
347 }
Simon Kelley376d48c2013-11-13 13:04:30 +0000348 }
349#endif
350
351 /* Update addresses from interface_names. These are a set independent
352 of the set we're listening on. */
Simon Kelley115ac3e2013-05-20 11:28:32 +0100353 for (int_name = daemon->int_names; int_name; int_name = int_name->next)
Simon Kelleyf7029f52013-11-21 15:09:09 +0000354 if (strncmp(label, int_name->intr, IF_NAMESIZE) == 0 &&
355 (addr->sa.sa_family == int_name->family || int_name->family == 0))
Simon Kelley115ac3e2013-05-20 11:28:32 +0100356 {
357 if (param->spare)
358 {
359 al = param->spare;
360 param->spare = al->next;
361 }
362 else
363 al = whine_malloc(sizeof(struct addrlist));
364
365 if (al)
366 {
Simon Kelley376d48c2013-11-13 13:04:30 +0000367 al->next = int_name->addr;
368 int_name->addr = al;
369
Simon Kelley115ac3e2013-05-20 11:28:32 +0100370 if (addr->sa.sa_family == AF_INET)
371 {
372 al->addr.addr.addr4 = addr->in.sin_addr;
Simon Kelley376d48c2013-11-13 13:04:30 +0000373 al->flags = 0;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100374 }
Simon Kelley115ac3e2013-05-20 11:28:32 +0100375 else
376 {
377 al->addr.addr.addr6 = addr->in6.sin6_addr;
Simon Kelley376d48c2013-11-13 13:04:30 +0000378 al->flags = ADDRLIST_IPV6;
Simon Kelley47669362014-12-17 12:41:56 +0000379 /* Privacy addresses and addresses still undergoing DAD and deprecated addresses
380 don't appear in forward queries, but will in reverse ones. */
381 if (!(iface_flags & IFACE_PERMANENT) || (iface_flags & (IFACE_DEPRECATED | IFACE_TENTATIVE)))
382 al->flags |= ADDRLIST_REVONLY;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100383 }
Simon Kelley115ac3e2013-05-20 11:28:32 +0100384 }
385 }
386 }
387
388 /* check whether the interface IP has been added already
389 we call this routine multiple times. */
390 for (iface = daemon->interfaces; iface; iface = iface->next)
391 if (sockaddr_isequal(&iface->addr, addr))
392 {
Simon Kelley47669362014-12-17 12:41:56 +0000393 iface->dad = !!(iface_flags & IFACE_TENTATIVE);
Simon Kelley08619212013-12-02 14:43:48 +0000394 iface->found = 1; /* for garbage collection */
Simon Kelley115ac3e2013-05-20 11:28:32 +0100395 return 1;
396 }
397
398 /* If we are restricting the set of interfaces to use, make
Simon Kelley59353a62004-11-21 19:34:28 +0000399 sure that loopback interfaces are in that set. */
Simon Kelley1f15b812009-10-13 17:49:32 +0100400 if (daemon->if_names && loopback)
Simon Kelley59353a62004-11-21 19:34:28 +0000401 {
402 struct iname *lo;
403 for (lo = daemon->if_names; lo; lo = lo->next)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100404 if (lo->name && strcmp(lo->name, ifr.ifr_name) == 0)
Simon Kelley4ce4f372012-06-14 11:50:45 +0100405 break;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100406
Simon Kelley38365ff2013-02-05 14:35:54 +0000407 if (!lo && (lo = whine_malloc(sizeof(struct iname))))
Simon Kelley59353a62004-11-21 19:34:28 +0000408 {
Simon Kelley38365ff2013-02-05 14:35:54 +0000409 if ((lo->name = whine_malloc(strlen(ifr.ifr_name)+1)))
410 {
411 strcpy(lo->name, ifr.ifr_name);
412 lo->used = 1;
413 lo->next = daemon->if_names;
414 daemon->if_names = lo;
415 }
416 else
417 free(lo);
Simon Kelley59353a62004-11-21 19:34:28 +0000418 }
419 }
420
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100421 if (addr->sa.sa_family == AF_INET &&
Simon Kelley3f2873d2013-05-14 11:28:47 +0100422 !iface_check(AF_INET, (struct all_addr *)&addr->in.sin_addr, label, &auth_dns))
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100423 return 1;
Simon Kelley4f7b3042012-11-28 21:27:02 +0000424
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100425 if (addr->sa.sa_family == AF_INET6 &&
Simon Kelley3f2873d2013-05-14 11:28:47 +0100426 !iface_check(AF_INET6, (struct all_addr *)&addr->in6.sin6_addr, label, &auth_dns))
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100427 return 1;
Simon Kelley4f7b3042012-11-28 21:27:02 +0000428
429#ifdef HAVE_DHCP
430 /* No DHCP where we're doing auth DNS. */
431 if (auth_dns)
432 {
433 tftp_ok = 0;
434 dhcp_ok = 0;
435 }
436 else
437 for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
Simon Kelley49333cb2013-03-15 20:30:51 +0000438 if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
Simon Kelley4f7b3042012-11-28 21:27:02 +0000439 {
440 tftp_ok = 0;
441 dhcp_ok = 0;
442 }
443#endif
444
Simon Kelley2937f8a2013-07-29 19:49:07 +0100445
Simon Kelley91543f42013-09-23 12:41:20 +0100446#ifdef HAVE_TFTP
Simon Kelley2937f8a2013-07-29 19:49:07 +0100447 if (daemon->tftp_interfaces)
448 {
449 /* dedicated tftp interface list */
450 tftp_ok = 0;
451 for (tmp = daemon->tftp_interfaces; tmp; tmp = tmp->next)
452 if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
453 tftp_ok = 1;
454 }
Simon Kelley91543f42013-09-23 12:41:20 +0100455#endif
Simon Kelley2937f8a2013-07-29 19:49:07 +0100456
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100457 /* add to list */
Simon Kelley5aabfc72007-08-29 11:24:47 +0100458 if ((iface = whine_malloc(sizeof(struct irec))))
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100459 {
460 iface->addr = *addr;
461 iface->netmask = netmask;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100462 iface->tftp_ok = tftp_ok;
Simon Kelley9380ba72012-04-16 14:41:56 +0100463 iface->dhcp_ok = dhcp_ok;
Simon Kelley4f7b3042012-11-28 21:27:02 +0000464 iface->dns_auth = auth_dns;
Simon Kelley1f15b812009-10-13 17:49:32 +0100465 iface->mtu = mtu;
Simon Kelley47669362014-12-17 12:41:56 +0000466 iface->dad = !!(iface_flags & IFACE_TENTATIVE);
Simon Kelley08619212013-12-02 14:43:48 +0000467 iface->found = 1;
Simon Kelleydc27e142013-10-16 13:09:53 +0100468 iface->done = iface->multicast_done = iface->warned = 0;
Simon Kelley5d162f22012-12-20 14:55:46 +0000469 iface->index = if_index;
Petr Menšíkad59f272017-03-17 17:22:19 +0000470 iface->label = is_label;
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100471 if ((iface->name = whine_malloc(strlen(ifr.ifr_name)+1)))
Simon Kelley6f13e532012-04-17 14:25:06 +0100472 {
473 strcpy(iface->name, ifr.ifr_name);
Simon Kelley115ac3e2013-05-20 11:28:32 +0100474 iface->next = daemon->interfaces;
475 daemon->interfaces = iface;
Simon Kelley6f13e532012-04-17 14:25:06 +0100476 return 1;
477 }
478 free(iface);
Simon Kelley5d162f22012-12-20 14:55:46 +0000479
Simon Kelley44a2a312004-03-10 20:04:35 +0000480 }
481
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100482 errno = ENOMEM;
483 return 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000484}
485
Simon Kelleyc72daea2012-01-05 21:33:27 +0000486static int iface_allowed_v6(struct in6_addr *local, int prefix,
Simon Kelleybad7b872012-12-20 22:00:39 +0000487 int scope, int if_index, int flags,
Simon Kelley1f776932012-12-16 19:46:08 +0000488 int preferred, int valid, void *vparam)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000489{
Simon Kelley59353a62004-11-21 19:34:28 +0000490 union mysockaddr addr;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100491 struct in_addr netmask; /* dummy */
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100492 netmask.s_addr = 0;
Simon Kelley52b92f42012-01-22 16:05:15 +0000493
Simon Kelley52b92f42012-01-22 16:05:15 +0000494 (void)scope; /* warning */
Simon Kelley1f776932012-12-16 19:46:08 +0000495 (void)preferred;
496 (void)valid;
Simon Kelley44a2a312004-03-10 20:04:35 +0000497
Simon Kelley849a8352006-06-09 21:02:31 +0100498 memset(&addr, 0, sizeof(addr));
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000499#ifdef HAVE_SOCKADDR_SA_LEN
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100500 addr.in6.sin6_len = sizeof(addr.in6);
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000501#endif
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100502 addr.in6.sin6_family = AF_INET6;
503 addr.in6.sin6_addr = *local;
504 addr.in6.sin6_port = htons(daemon->port);
Simon Kelley62ab3cc2013-12-03 11:53:53 +0000505 /* FreeBSD insists this is zero for non-linklocal addresses */
506 if (IN6_IS_ADDR_LINKLOCAL(local))
507 addr.in6.sin6_scope_id = if_index;
508 else
509 addr.in6.sin6_scope_id = 0;
Simon Kelley1ee9be42013-12-09 16:50:19 +0000510
Simon Kelley47669362014-12-17 12:41:56 +0000511 return iface_allowed((struct iface_param *)vparam, if_index, NULL, &addr, netmask, prefix, flags);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100512}
Simon Kelley59353a62004-11-21 19:34:28 +0000513
Simon Kelley3f2873d2013-05-14 11:28:47 +0100514static int iface_allowed_v4(struct in_addr local, int if_index, char *label,
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100515 struct in_addr netmask, struct in_addr broadcast, void *vparam)
516{
517 union mysockaddr addr;
Simon Kelley376d48c2013-11-13 13:04:30 +0000518 int prefix, bit;
Simon Kelleyb8ac4662016-03-10 18:40:53 +0000519
520 (void)broadcast; /* warning */
Simon Kelley849a8352006-06-09 21:02:31 +0100521
522 memset(&addr, 0, sizeof(addr));
Simon Kelley1ab84e22004-01-29 16:48:35 +0000523#ifdef HAVE_SOCKADDR_SA_LEN
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100524 addr.in.sin_len = sizeof(addr.in);
Simon Kelley1ab84e22004-01-29 16:48:35 +0000525#endif
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100526 addr.in.sin_family = AF_INET;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100527 addr.in.sin_addr = local;
528 addr.in.sin_port = htons(daemon->port);
Simon Kelley44a2a312004-03-10 20:04:35 +0000529
Simon Kelley376d48c2013-11-13 13:04:30 +0000530 /* determine prefix length from netmask */
531 for (prefix = 32, bit = 1; (bit & ntohl(netmask.s_addr)) == 0 && prefix != 0; bit = bit << 1, prefix--);
532
533 return iface_allowed((struct iface_param *)vparam, if_index, label, &addr, netmask, prefix, 0);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100534}
535
Simon Kelley115ac3e2013-05-20 11:28:32 +0100536int enumerate_interfaces(int reset)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100537{
Simon Kelley115ac3e2013-05-20 11:28:32 +0100538 static struct addrlist *spare = NULL;
Simon Kelleya0358e52014-06-07 13:38:48 +0100539 static int done = 0;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100540 struct iface_param param;
541 int errsave, ret = 1;
542 struct addrlist *addr, *tmp;
543 struct interface_name *intname;
Simon Kelley08619212013-12-02 14:43:48 +0000544 struct irec *iface;
Simon Kelley376d48c2013-11-13 13:04:30 +0000545#ifdef HAVE_AUTH
546 struct auth_zone *zone;
547#endif
548
Simon Kelley76dd75d2013-05-23 10:04:25 +0100549 /* Do this max once per select cycle - also inhibits netlink socket use
550 in TCP child processes. */
Simon Kelley397542b2013-09-05 11:27:34 +0100551
Simon Kelley115ac3e2013-05-20 11:28:32 +0100552 if (reset)
553 {
554 done = 0;
555 return 1;
556 }
557
Simon Kelleya0358e52014-06-07 13:38:48 +0100558 if (done)
Simon Kelley115ac3e2013-05-20 11:28:32 +0100559 return 1;
560
561 done = 1;
562
563 if ((param.fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
564 return 0;
565
Simon Kelley08619212013-12-02 14:43:48 +0000566 /* Mark interfaces for garbage collection */
567 for (iface = daemon->interfaces; iface; iface = iface->next)
568 iface->found = 0;
569
Simon Kelley115ac3e2013-05-20 11:28:32 +0100570 /* remove addresses stored against interface_names */
571 for (intname = daemon->int_names; intname; intname = intname->next)
572 {
Simon Kelley376d48c2013-11-13 13:04:30 +0000573 for (addr = intname->addr; addr; addr = tmp)
Simon Kelley115ac3e2013-05-20 11:28:32 +0100574 {
575 tmp = addr->next;
576 addr->next = spare;
577 spare = addr;
578 }
579
Simon Kelley376d48c2013-11-13 13:04:30 +0000580 intname->addr = NULL;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100581 }
Simon Kelley376d48c2013-11-13 13:04:30 +0000582
Simon Kelleyc8a80482014-03-05 14:29:54 +0000583 /* Remove list of addresses of local interfaces */
584 for (addr = daemon->interface_addrs; addr; addr = tmp)
585 {
586 tmp = addr->next;
587 addr->next = spare;
588 spare = addr;
589 }
590 daemon->interface_addrs = NULL;
591
Simon Kelley376d48c2013-11-13 13:04:30 +0000592#ifdef HAVE_AUTH
593 /* remove addresses stored against auth_zone subnets, but not
594 ones configured as address literals */
595 for (zone = daemon->auth_zones; zone; zone = zone->next)
596 if (zone->interface_names)
597 {
598 struct addrlist **up;
599 for (up = &zone->subnet, addr = zone->subnet; addr; addr = tmp)
600 {
601 tmp = addr->next;
602 if (addr->flags & ADDRLIST_LITERAL)
603 up = &addr->next;
604 else
605 {
606 *up = addr->next;
607 addr->next = spare;
608 spare = addr;
609 }
610 }
611 }
612#endif
613
Simon Kelley115ac3e2013-05-20 11:28:32 +0100614 param.spare = spare;
615
Simon Kelley115ac3e2013-05-20 11:28:32 +0100616 ret = iface_enumerate(AF_INET6, &param, iface_allowed_v6);
Simon Kelley28866e92011-02-14 20:19:14 +0000617
Simon Kelley115ac3e2013-05-20 11:28:32 +0100618 if (ret)
619 ret = iface_enumerate(AF_INET, &param, iface_allowed_v4);
620
621 errsave = errno;
622 close(param.fd);
Simon Kelley08619212013-12-02 14:43:48 +0000623
624 if (option_bool(OPT_CLEVERBIND))
625 {
626 /* Garbage-collect listeners listening on addresses that no longer exist.
627 Does nothing when not binding interfaces or for listeners on localhost,
628 since the ->iface field is NULL. Note that this needs the protections
Josh Soref730c6742017-02-06 16:14:04 +0000629 against reentrancy, hence it's here. It also means there's a possibility,
Simon Kelley08619212013-12-02 14:43:48 +0000630 in OPT_CLEVERBIND mode, that at listener will just disappear after
631 a call to enumerate_interfaces, this is checked OK on all calls. */
632 struct listener *l, *tmp, **up;
633
634 for (up = &daemon->listeners, l = daemon->listeners; l; l = tmp)
635 {
636 tmp = l->next;
637
638 if (!l->iface || l->iface->found)
639 up = &l->next;
640 else
641 {
642 *up = l->next;
643
644 /* In case it ever returns */
645 l->iface->done = 0;
646
647 if (l->fd != -1)
648 close(l->fd);
649 if (l->tcpfd != -1)
650 close(l->tcpfd);
651 if (l->tftpfd != -1)
652 close(l->tftpfd);
653
654 free(l);
655 }
656 }
657 }
658
Simon Kelley115ac3e2013-05-20 11:28:32 +0100659 errno = errsave;
Simon Kelley115ac3e2013-05-20 11:28:32 +0100660 spare = param.spare;
Simon Kelleya0358e52014-06-07 13:38:48 +0100661
Simon Kelley115ac3e2013-05-20 11:28:32 +0100662 return ret;
Simon Kelley44a2a312004-03-10 20:04:35 +0000663}
664
Simon Kelley5aabfc72007-08-29 11:24:47 +0100665/* set NONBLOCK bit on fd: See Stevens 16.6 */
Simon Kelley7cebd202006-05-06 14:13:33 +0100666int fix_fd(int fd)
667{
668 int flags;
669
670 if ((flags = fcntl(fd, F_GETFL)) == -1 ||
Simon Kelley5aabfc72007-08-29 11:24:47 +0100671 fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
Simon Kelley7cebd202006-05-06 14:13:33 +0100672 return 0;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100673
Simon Kelley7cebd202006-05-06 14:13:33 +0100674 return 1;
675}
676
Simon Kelley74c95c22011-10-19 09:33:39 +0100677static int make_sock(union mysockaddr *addr, int type, int dienow)
Simon Kelley44a2a312004-03-10 20:04:35 +0000678{
Simon Kelley28866e92011-02-14 20:19:14 +0000679 int family = addr->sa.sa_family;
680 int fd, rc, opt = 1;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100681
Simon Kelley28866e92011-02-14 20:19:14 +0000682 if ((fd = socket(family, type, 0)) == -1)
Simon Kelley316e2732010-01-22 20:16:09 +0000683 {
Josh Soref730c6742017-02-06 16:14:04 +0000684 int port, errsave;
Simon Kelley39f1b8e2012-06-20 20:04:27 +0100685 char *s;
Simon Kelley28866e92011-02-14 20:19:14 +0000686
687 /* No error if the kernel just doesn't support this IP flavour */
688 if (errno == EPROTONOSUPPORT ||
689 errno == EAFNOSUPPORT ||
690 errno == EINVAL)
691 return -1;
692
693 err:
Josh Soref730c6742017-02-06 16:14:04 +0000694 errsave = errno;
Simon Kelley39f1b8e2012-06-20 20:04:27 +0100695 port = prettyprint_addr(addr, daemon->addrbuff);
696 if (!option_bool(OPT_NOWILD) && !option_bool(OPT_CLEVERBIND))
697 sprintf(daemon->addrbuff, "port %d", port);
698 s = _("failed to create listening socket for %s: %s");
699
Simon Kelley5f11b3e2012-08-16 14:04:05 +0100700 if (fd != -1)
Matthias Andree71aaa5a2013-12-03 11:20:45 +0000701 close (fd);
702
Josh Soref730c6742017-02-06 16:14:04 +0000703 errno = errsave;
Simon Kelley1ee9be42013-12-09 16:50:19 +0000704
Simon Kelley5f11b3e2012-08-16 14:04:05 +0100705 if (dienow)
706 {
707 /* failure to bind addresses given by --listen-address at this point
708 is OK if we're doing bind-dynamic */
709 if (!option_bool(OPT_CLEVERBIND))
710 die(s, daemon->addrbuff, EC_BADNET);
711 }
712 else
713 my_syslog(LOG_WARNING, s, daemon->addrbuff, strerror(errno));
714
Simon Kelley74c95c22011-10-19 09:33:39 +0100715 return -1;
Simon Kelley28866e92011-02-14 20:19:14 +0000716 }
Simon Kelley5f11b3e2012-08-16 14:04:05 +0100717
Simon Kelley28866e92011-02-14 20:19:14 +0000718 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || !fix_fd(fd))
719 goto err;
720
Simon Kelleyc72daea2012-01-05 21:33:27 +0000721 if (family == AF_INET6 && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)) == -1)
Simon Kelley28866e92011-02-14 20:19:14 +0000722 goto err;
Simon Kelley28866e92011-02-14 20:19:14 +0000723
Simon Kelley74c95c22011-10-19 09:33:39 +0100724 if ((rc = bind(fd, (struct sockaddr *)addr, sa_len(addr))) == -1)
Simon Kelley28866e92011-02-14 20:19:14 +0000725 goto err;
726
727 if (type == SOCK_STREAM)
728 {
Simon Kelley09b768e2016-12-22 22:16:58 +0000729 if (listen(fd, TCP_BACKLOG) == -1)
Simon Kelley28866e92011-02-14 20:19:14 +0000730 goto err;
731 }
Simon Kelley2329bef2013-12-03 13:41:16 +0000732 else if (family == AF_INET)
Simon Kelley28866e92011-02-14 20:19:14 +0000733 {
Simon Kelley2329bef2013-12-03 13:41:16 +0000734 if (!option_bool(OPT_NOWILD))
Simon Kelley28866e92011-02-14 20:19:14 +0000735 {
736#if defined(HAVE_LINUX_NETWORK)
Simon Kelleyc72daea2012-01-05 21:33:27 +0000737 if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) == -1)
Simon Kelley28866e92011-02-14 20:19:14 +0000738 goto err;
739#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
740 if (setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt)) == -1 ||
741 setsockopt(fd, IPPROTO_IP, IP_RECVIF, &opt, sizeof(opt)) == -1)
742 goto err;
743#endif
744 }
Simon Kelley28866e92011-02-14 20:19:14 +0000745 }
Simon Kelley2329bef2013-12-03 13:41:16 +0000746 else if (!set_ipv6pktinfo(fd))
747 goto err;
Simon Kelleyc72daea2012-01-05 21:33:27 +0000748
Simon Kelley28866e92011-02-14 20:19:14 +0000749 return fd;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100750}
Simon Kelleyc72daea2012-01-05 21:33:27 +0000751
Simon Kelleyc72daea2012-01-05 21:33:27 +0000752int set_ipv6pktinfo(int fd)
753{
754 int opt = 1;
755
756 /* The API changed around Linux 2.6.14 but the old ABI is still supported:
757 handle all combinations of headers and kernel.
758 OpenWrt note that this fixes the problem addressed by your very broken patch. */
759 daemon->v6pktinfo = IPV6_PKTINFO;
760
761#ifdef IPV6_RECVPKTINFO
762 if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &opt, sizeof(opt)) != -1)
763 return 1;
764# ifdef IPV6_2292PKTINFO
765 else if (errno == ENOPROTOOPT && setsockopt(fd, IPPROTO_IPV6, IPV6_2292PKTINFO, &opt, sizeof(opt)) != -1)
766 {
767 daemon->v6pktinfo = IPV6_2292PKTINFO;
768 return 1;
769 }
770# endif
771#else
772 if (setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &opt, sizeof(opt)) != -1)
773 return 1;
774#endif
775
776 return 0;
777}
Simon Kelley22ce5502013-01-22 13:53:04 +0000778
779
780/* Find the interface on which a TCP connection arrived, if possible, or zero otherwise. */
781int tcp_interface(int fd, int af)
782{
783 int if_index = 0;
784
785#ifdef HAVE_LINUX_NETWORK
786 int opt = 1;
787 struct cmsghdr *cmptr;
788 struct msghdr msg;
Simon Kelley529b0302016-03-16 19:00:45 +0000789 socklen_t len;
Simon Kelley22ce5502013-01-22 13:53:04 +0000790
Simon Kelley529b0302016-03-16 19:00:45 +0000791 /* use mshdr so that the CMSDG_* macros are available */
Simon Kelley22ce5502013-01-22 13:53:04 +0000792 msg.msg_control = daemon->packet;
Simon Kelley529b0302016-03-16 19:00:45 +0000793 msg.msg_controllen = len = daemon->packet_buff_sz;
Simon Kelley22ce5502013-01-22 13:53:04 +0000794
795 /* we overwrote the buffer... */
796 daemon->srv_save = NULL;
797
798 if (af == AF_INET)
799 {
800 if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) != -1 &&
Simon Kelley529b0302016-03-16 19:00:45 +0000801 getsockopt(fd, IPPROTO_IP, IP_PKTOPTIONS, msg.msg_control, &len) != -1)
802 {
803 msg.msg_controllen = len;
804 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
805 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
806 {
807 union {
808 unsigned char *c;
809 struct in_pktinfo *p;
810 } p;
811
812 p.c = CMSG_DATA(cmptr);
813 if_index = p.p->ipi_ifindex;
814 }
815 }
Simon Kelley22ce5502013-01-22 13:53:04 +0000816 }
Simon Kelley22ce5502013-01-22 13:53:04 +0000817 else
818 {
819 /* Only the RFC-2292 API has the ability to find the interface for TCP connections,
820 it was removed in RFC-3542 !!!!
821
822 Fortunately, Linux kept the 2292 ABI when it moved to 3542. The following code always
823 uses the old ABI, and should work with pre- and post-3542 kernel headers */
824
825#ifdef IPV6_2292PKTOPTIONS
826# define PKTOPTIONS IPV6_2292PKTOPTIONS
827#else
828# define PKTOPTIONS IPV6_PKTOPTIONS
829#endif
830
831 if (set_ipv6pktinfo(fd) &&
Simon Kelley529b0302016-03-16 19:00:45 +0000832 getsockopt(fd, IPPROTO_IPV6, PKTOPTIONS, msg.msg_control, &len) != -1)
Simon Kelley22ce5502013-01-22 13:53:04 +0000833 {
Simon Kelley529b0302016-03-16 19:00:45 +0000834 msg.msg_controllen = len;
835 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
Simon Kelley22ce5502013-01-22 13:53:04 +0000836 if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
837 {
838 union {
839 unsigned char *c;
840 struct in6_pktinfo *p;
841 } p;
842 p.c = CMSG_DATA(cmptr);
843
844 if_index = p.p->ipi6_ifindex;
845 }
846 }
847 }
Simon Kelley22ce5502013-01-22 13:53:04 +0000848#endif /* Linux */
849
850 return if_index;
851}
Simon Kelley28866e92011-02-14 20:19:14 +0000852
Simon Kelley74c95c22011-10-19 09:33:39 +0100853static struct listener *create_listeners(union mysockaddr *addr, int do_tftp, int dienow)
Simon Kelley28866e92011-02-14 20:19:14 +0000854{
855 struct listener *l = NULL;
856 int fd = -1, tcpfd = -1, tftpfd = -1;
857
Vladislav Grishenko408c3682013-09-24 16:18:49 +0100858 (void)do_tftp;
859
Simon Kelley28866e92011-02-14 20:19:14 +0000860 if (daemon->port != 0)
861 {
Simon Kelley74c95c22011-10-19 09:33:39 +0100862 fd = make_sock(addr, SOCK_DGRAM, dienow);
863 tcpfd = make_sock(addr, SOCK_STREAM, dienow);
Simon Kelley28866e92011-02-14 20:19:14 +0000864 }
865
866#ifdef HAVE_TFTP
867 if (do_tftp)
868 {
869 if (addr->sa.sa_family == AF_INET)
870 {
871 /* port must be restored to DNS port for TCP code */
872 short save = addr->in.sin_port;
873 addr->in.sin_port = htons(TFTP_PORT);
Simon Kelley74c95c22011-10-19 09:33:39 +0100874 tftpfd = make_sock(addr, SOCK_DGRAM, dienow);
Simon Kelley28866e92011-02-14 20:19:14 +0000875 addr->in.sin_port = save;
876 }
Simon Kelley28866e92011-02-14 20:19:14 +0000877 else
878 {
879 short save = addr->in6.sin6_port;
880 addr->in6.sin6_port = htons(TFTP_PORT);
Simon Kelley74c95c22011-10-19 09:33:39 +0100881 tftpfd = make_sock(addr, SOCK_DGRAM, dienow);
Simon Kelley28866e92011-02-14 20:19:14 +0000882 addr->in6.sin6_port = save;
883 }
Simon Kelley28866e92011-02-14 20:19:14 +0000884 }
Simon Kelley44a2a312004-03-10 20:04:35 +0000885#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100886
Simon Kelley28866e92011-02-14 20:19:14 +0000887 if (fd != -1 || tcpfd != -1 || tftpfd != -1)
888 {
889 l = safe_malloc(sizeof(struct listener));
890 l->next = NULL;
891 l->family = addr->sa.sa_family;
892 l->fd = fd;
893 l->tcpfd = tcpfd;
Simon Kelley08619212013-12-02 14:43:48 +0000894 l->tftpfd = tftpfd;
895 l->iface = NULL;
Simon Kelley28866e92011-02-14 20:19:14 +0000896 }
897
898 return l;
899}
900
Simon Kelley74c95c22011-10-19 09:33:39 +0100901void create_wildcard_listeners(void)
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100902{
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100903 union mysockaddr addr;
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100904 struct listener *l, *l6;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100905
Simon Kelley849a8352006-06-09 21:02:31 +0100906 memset(&addr, 0, sizeof(addr));
Simon Kelley28866e92011-02-14 20:19:14 +0000907#ifdef HAVE_SOCKADDR_SA_LEN
908 addr.in.sin_len = sizeof(addr.in);
909#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100910 addr.in.sin_family = AF_INET;
911 addr.in.sin_addr.s_addr = INADDR_ANY;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100912 addr.in.sin_port = htons(daemon->port);
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100913
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100914 l = create_listeners(&addr, !!option_bool(OPT_TFTP), 1);
Simon Kelley28866e92011-02-14 20:19:14 +0000915
Simon Kelley28866e92011-02-14 20:19:14 +0000916 memset(&addr, 0, sizeof(addr));
Simon Kelleyee875042018-10-23 22:10:17 +0100917#ifdef HAVE_SOCKADDR_SA_LEN
Simon Kelley28866e92011-02-14 20:19:14 +0000918 addr.in6.sin6_len = sizeof(addr.in6);
Simon Kelleyee875042018-10-23 22:10:17 +0100919#endif
Simon Kelley28866e92011-02-14 20:19:14 +0000920 addr.in6.sin6_family = AF_INET6;
921 addr.in6.sin6_addr = in6addr_any;
922 addr.in6.sin6_port = htons(daemon->port);
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100923
924 l6 = create_listeners(&addr, !!option_bool(OPT_TFTP), 1);
Simon Kelley28866e92011-02-14 20:19:14 +0000925 if (l)
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100926 l->next = l6;
Simon Kelley28866e92011-02-14 20:19:14 +0000927 else
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100928 l = l6;
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100929
Simon Kelley74c95c22011-10-19 09:33:39 +0100930 daemon->listeners = l;
Simon Kelley44a2a312004-03-10 20:04:35 +0000931}
932
Simon Kelley74c95c22011-10-19 09:33:39 +0100933void create_bound_listeners(int dienow)
Simon Kelley44a2a312004-03-10 20:04:35 +0000934{
Simon Kelley74c95c22011-10-19 09:33:39 +0100935 struct listener *new;
Simon Kelley44a2a312004-03-10 20:04:35 +0000936 struct irec *iface;
Simon Kelley52d4abf2012-03-21 21:39:48 +0000937 struct iname *if_tmp;
Simon Kelley73a08a22009-02-05 20:28:08 +0000938
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100939 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelley08619212013-12-02 14:43:48 +0000940 if (!iface->done && !iface->dad && iface->found &&
Simon Kelley74c95c22011-10-19 09:33:39 +0100941 (new = create_listeners(&iface->addr, iface->tftp_ok, dienow)))
Simon Kelley28866e92011-02-14 20:19:14 +0000942 {
943 new->iface = iface;
Simon Kelley74c95c22011-10-19 09:33:39 +0100944 new->next = daemon->listeners;
945 daemon->listeners = new;
946 iface->done = 1;
Simon Kelley28866e92011-02-14 20:19:14 +0000947 }
Simon Kelley52d4abf2012-03-21 21:39:48 +0000948
949 /* Check for --listen-address options that haven't been used because there's
950 no interface with a matching address. These may be valid: eg it's possible
951 to listen on 127.0.1.1 even if the loopback interface is 127.0.0.1
952
Simon Kelley5f11b3e2012-08-16 14:04:05 +0100953 If the address isn't valid the bind() will fail and we'll die()
954 (except in bind-dynamic mode, when we'll complain but keep trying.)
Simon Kelley52d4abf2012-03-21 21:39:48 +0000955
956 The resulting listeners have the ->iface field NULL, and this has to be
957 handled by the DNS and TFTP code. It disables --localise-queries processing
958 (no netmask) and some MTU login the tftp code. */
959
960 for (if_tmp = daemon->if_addrs; if_tmp; if_tmp = if_tmp->next)
961 if (!if_tmp->used &&
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100962 (new = create_listeners(&if_tmp->addr, !!option_bool(OPT_TFTP), dienow)))
Simon Kelley52d4abf2012-03-21 21:39:48 +0000963 {
Simon Kelley52d4abf2012-03-21 21:39:48 +0000964 new->next = daemon->listeners;
965 daemon->listeners = new;
966 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000967}
968
Simon Kelleydc27e142013-10-16 13:09:53 +0100969/* In --bind-interfaces, the only access control is the addresses we're listening on.
970 There's nothing to avoid a query to the address of an internal interface arriving via
971 an external interface where we don't want to accept queries, except that in the usual
972 case the addresses of internal interfaces are RFC1918. When bind-interfaces in use,
973 and we listen on an address that looks like it's probably globally routeable, shout.
974
975 The fix is to use --bind-dynamic, which actually checks the arrival interface too.
976 Tough if your platform doesn't support this.
Simon Kelley2329bef2013-12-03 13:41:16 +0000977
978 Note that checking the arrival interface is supported in the standard IPv6 API and
979 always done, so we don't warn about any IPv6 addresses here.
Simon Kelleydc27e142013-10-16 13:09:53 +0100980*/
981
982void warn_bound_listeners(void)
983{
984 struct irec *iface;
985 int advice = 0;
986
987 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelleyf7029f52013-11-21 15:09:09 +0000988 if (!iface->dns_auth)
Simon Kelleydc27e142013-10-16 13:09:53 +0100989 {
Simon Kelleydc27e142013-10-16 13:09:53 +0100990 if (iface->addr.sa.sa_family == AF_INET)
991 {
992 if (!private_net(iface->addr.in.sin_addr, 1))
993 {
994 inet_ntop(AF_INET, &iface->addr.in.sin_addr, daemon->addrbuff, ADDRSTRLEN);
Simon Kelley2329bef2013-12-03 13:41:16 +0000995 iface->warned = advice = 1;
996 my_syslog(LOG_WARNING,
997 _("LOUD WARNING: listening on %s may accept requests via interfaces other than %s"),
998 daemon->addrbuff, iface->name);
Simon Kelleydc27e142013-10-16 13:09:53 +0100999 }
1000 }
Simon Kelleydc27e142013-10-16 13:09:53 +01001001 }
1002
1003 if (advice)
Simon Kelleyf7029f52013-11-21 15:09:09 +00001004 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 +01001005}
1006
Petr Menšíkad59f272017-03-17 17:22:19 +00001007void warn_wild_labels(void)
1008{
1009 struct irec *iface;
1010
1011 for (iface = daemon->interfaces; iface; iface = iface->next)
1012 if (iface->found && iface->name && iface->label)
1013 my_syslog(LOG_WARNING, _("warning: using interface %s instead"), iface->name);
1014}
1015
Simon Kelleyf7029f52013-11-21 15:09:09 +00001016void warn_int_names(void)
1017{
1018 struct interface_name *intname;
1019
1020 for (intname = daemon->int_names; intname; intname = intname->next)
1021 if (!intname->addr)
1022 my_syslog(LOG_WARNING, _("warning: no addresses found for interface %s"), intname->intr);
1023}
1024
Simon Kelley74c95c22011-10-19 09:33:39 +01001025int is_dad_listeners(void)
1026{
1027 struct irec *iface;
1028
1029 if (option_bool(OPT_NOWILD))
1030 for (iface = daemon->interfaces; iface; iface = iface->next)
1031 if (iface->dad && !iface->done)
1032 return 1;
1033
1034 return 0;
1035}
Simon Kelley5d162f22012-12-20 14:55:46 +00001036
1037#ifdef HAVE_DHCP6
1038void join_multicast(int dienow)
1039{
1040 struct irec *iface, *tmp;
1041
1042 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelley19624462012-12-28 11:18:09 +00001043 if (iface->addr.sa.sa_family == AF_INET6 && iface->dhcp_ok && !iface->multicast_done)
Simon Kelley5d162f22012-12-20 14:55:46 +00001044 {
1045 /* There's an irec per address but we only want to join for multicast
1046 once per interface. Weed out duplicates. */
1047 for (tmp = daemon->interfaces; tmp; tmp = tmp->next)
1048 if (tmp->multicast_done && tmp->index == iface->index)
1049 break;
1050
1051 iface->multicast_done = 1;
1052
1053 if (!tmp)
1054 {
1055 struct ipv6_mreq mreq;
1056 int err = 0;
1057
1058 mreq.ipv6mr_interface = iface->index;
1059
1060 inet_pton(AF_INET6, ALL_RELAY_AGENTS_AND_SERVERS, &mreq.ipv6mr_multiaddr);
1061
Simon Kelleyff7eea22013-09-04 18:01:38 +01001062 if ((daemon->doing_dhcp6 || daemon->relay6) &&
Simon Kelley5d162f22012-12-20 14:55:46 +00001063 setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
Simon Kelley9cdcfe92015-08-26 22:38:08 +01001064 err = errno;
Simon Kelley5d162f22012-12-20 14:55:46 +00001065
1066 inet_pton(AF_INET6, ALL_SERVERS, &mreq.ipv6mr_multiaddr);
1067
1068 if (daemon->doing_dhcp6 &&
1069 setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
Simon Kelley9cdcfe92015-08-26 22:38:08 +01001070 err = errno;
Simon Kelley5d162f22012-12-20 14:55:46 +00001071
1072 inet_pton(AF_INET6, ALL_ROUTERS, &mreq.ipv6mr_multiaddr);
1073
1074 if (daemon->doing_ra &&
1075 setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
Simon Kelley9cdcfe92015-08-26 22:38:08 +01001076 err = errno;
Simon Kelley5d162f22012-12-20 14:55:46 +00001077
1078 if (err)
1079 {
1080 char *s = _("interface %s failed to join DHCPv6 multicast group: %s");
Simon Kelley9cdcfe92015-08-26 22:38:08 +01001081 errno = err;
1082
1083#ifdef HAVE_LINUX_NETWORK
1084 if (errno == ENOMEM)
1085 my_syslog(LOG_ERR, _("try increasing /proc/sys/net/core/optmem_max"));
1086#endif
1087
Simon Kelley5d162f22012-12-20 14:55:46 +00001088 if (dienow)
1089 die(s, iface->name, EC_BADNET);
1090 else
1091 my_syslog(LOG_ERR, s, iface->name, strerror(errno));
1092 }
1093 }
1094 }
1095}
1096#endif
1097
Simon Kelley9009d742008-11-14 20:04:27 +00001098/* return a UDP socket bound to a random port, have to cope with straying into
Simon Kelley1a6bca82008-07-11 11:11:42 +01001099 occupied port nos and reserved ones. */
1100int random_sock(int family)
1101{
1102 int fd;
1103
1104 if ((fd = socket(family, SOCK_DGRAM, 0)) != -1)
1105 {
Simon Kelley3927da42008-07-20 15:10:39 +01001106 union mysockaddr addr;
Hans Dedecker926332a2016-01-23 10:48:12 +00001107 unsigned int ports_avail = ((unsigned short)daemon->max_port - (unsigned short)daemon->min_port) + 1;
Simon Kelley9009d742008-11-14 20:04:27 +00001108 int tries = ports_avail < 30 ? 3 * ports_avail : 100;
Simon Kelley3927da42008-07-20 15:10:39 +01001109
Simon Kelley1a6bca82008-07-11 11:11:42 +01001110 memset(&addr, 0, sizeof(addr));
Simon Kelley3927da42008-07-20 15:10:39 +01001111 addr.sa.sa_family = family;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001112
Simon Kelley1ad24ae2008-07-20 20:22:50 +01001113 /* don't loop forever if all ports in use. */
1114
Simon Kelley1a6bca82008-07-11 11:11:42 +01001115 if (fix_fd(fd))
Simon Kelley9009d742008-11-14 20:04:27 +00001116 while(tries--)
Simon Kelley1a6bca82008-07-11 11:11:42 +01001117 {
Simon Kelleybaf553d2018-01-29 22:49:27 +00001118 unsigned short port = htons(daemon->min_port + (rand16() % ((unsigned short)ports_avail)));
Simon Kelley1a6bca82008-07-11 11:11:42 +01001119
1120 if (family == AF_INET)
1121 {
1122 addr.in.sin_addr.s_addr = INADDR_ANY;
Simon Kelley3927da42008-07-20 15:10:39 +01001123 addr.in.sin_port = port;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001124#ifdef HAVE_SOCKADDR_SA_LEN
1125 addr.in.sin_len = sizeof(struct sockaddr_in);
1126#endif
1127 }
Simon Kelley1a6bca82008-07-11 11:11:42 +01001128 else
1129 {
1130 addr.in6.sin6_addr = in6addr_any;
Simon Kelley3927da42008-07-20 15:10:39 +01001131 addr.in6.sin6_port = port;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001132#ifdef HAVE_SOCKADDR_SA_LEN
1133 addr.in6.sin6_len = sizeof(struct sockaddr_in6);
1134#endif
1135 }
Simon Kelley1a6bca82008-07-11 11:11:42 +01001136
1137 if (bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == 0)
1138 return fd;
1139
1140 if (errno != EADDRINUSE && errno != EACCES)
1141 break;
1142 }
1143
1144 close(fd);
1145 }
1146
1147 return -1;
1148}
1149
1150
Simon Kelley9d6918d2017-10-13 17:55:09 +01001151int local_bind(int fd, union mysockaddr *addr, char *intname, unsigned int ifindex, int is_tcp)
Simon Kelley824af852008-02-12 20:43:05 +00001152{
1153 union mysockaddr addr_copy = *addr;
1154
1155 /* cannot set source _port_ for TCP connections. */
1156 if (is_tcp)
1157 {
1158 if (addr_copy.sa.sa_family == AF_INET)
1159 addr_copy.in.sin_port = 0;
Simon Kelley824af852008-02-12 20:43:05 +00001160 else
1161 addr_copy.in6.sin6_port = 0;
Simon Kelley824af852008-02-12 20:43:05 +00001162 }
1163
1164 if (bind(fd, (struct sockaddr *)&addr_copy, sa_len(&addr_copy)) == -1)
1165 return 0;
Simon Kelley9d6918d2017-10-13 17:55:09 +01001166
1167 if (!is_tcp && ifindex > 0)
1168 {
1169#if defined(IP_UNICAST_IF)
1170 if (addr_copy.sa.sa_family == AF_INET)
1171 {
1172 uint32_t ifindex_opt = htonl(ifindex);
1173 return setsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex_opt, sizeof(ifindex_opt)) == 0;
1174 }
1175#endif
Simon Kelleyee875042018-10-23 22:10:17 +01001176#if defined (IPV6_UNICAST_IF)
Simon Kelley9d6918d2017-10-13 17:55:09 +01001177 if (addr_copy.sa.sa_family == AF_INET6)
1178 {
1179 uint32_t ifindex_opt = htonl(ifindex);
1180 return setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_IF, &ifindex_opt, sizeof(ifindex_opt)) == 0;
1181 }
1182#endif
1183 }
1184
Simon Kelley824af852008-02-12 20:43:05 +00001185#if defined(SO_BINDTODEVICE)
Simon Kelley73a08a22009-02-05 20:28:08 +00001186 if (intname[0] != 0 &&
Simon Kelley316e2732010-01-22 20:16:09 +00001187 setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, intname, IF_NAMESIZE) == -1)
Simon Kelley824af852008-02-12 20:43:05 +00001188 return 0;
1189#endif
1190
1191 return 1;
1192}
1193
1194static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001195{
1196 struct serverfd *sfd;
Beniamino Galvani2675f202016-08-28 20:44:05 +01001197 unsigned int ifindex = 0;
Simon Kelley824af852008-02-12 20:43:05 +00001198 int errsave;
Simon Kelleye83915d2018-04-10 21:27:26 +01001199 int opt = 1;
1200
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
Simon Kelley1a6bca82008-07-11 11:11:42 +01001212 if (addr->sa.sa_family == AF_INET6 &&
1213 memcmp(&addr->in6.sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0 &&
1214 addr->in6.sin6_port == htons(0))
1215 return NULL;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001216 }
Beniamino Galvani2675f202016-08-28 20:44:05 +01001217
1218 if (intname && strlen(intname) != 0)
1219 ifindex = if_nametoindex(intname); /* index == 0 when not binding to an interface */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001220
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001221 /* may have a suitable one already */
Simon Kelley824af852008-02-12 20:43:05 +00001222 for (sfd = daemon->sfds; sfd; sfd = sfd->next )
1223 if (sockaddr_isequal(&sfd->source_addr, addr) &&
Beniamino Galvani2675f202016-08-28 20:44:05 +01001224 strcmp(intname, sfd->interface) == 0 &&
1225 ifindex == sfd->ifindex)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001226 return sfd;
1227
1228 /* need to make a new one. */
1229 errno = ENOMEM; /* in case malloc fails. */
Simon Kelley5aabfc72007-08-29 11:24:47 +01001230 if (!(sfd = whine_malloc(sizeof(struct serverfd))))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001231 return NULL;
1232
1233 if ((sfd->fd = socket(addr->sa.sa_family, SOCK_DGRAM, 0)) == -1)
1234 {
1235 free(sfd);
1236 return NULL;
1237 }
Simon Kelleye83915d2018-04-10 21:27:26 +01001238
1239 if ((addr->sa.sa_family == AF_INET6 && setsockopt(sfd->fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)) == -1) ||
1240 !local_bind(sfd->fd, addr, intname, ifindex, 0) || !fix_fd(sfd->fd))
Simon Kelley824af852008-02-12 20:43:05 +00001241 {
Simon Kelleye83915d2018-04-10 21:27:26 +01001242 errsave = errno; /* save error from bind/setsockopt. */
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001243 close(sfd->fd);
1244 free(sfd);
1245 errno = errsave;
1246 return NULL;
1247 }
Beniamino Galvani2675f202016-08-28 20:44:05 +01001248
Petr Menšík47b45b22018-08-15 18:17:00 +02001249 safe_strncpy(sfd->interface, intname, sizeof(sfd->interface));
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001250 sfd->source_addr = *addr;
Simon Kelley824af852008-02-12 20:43:05 +00001251 sfd->next = daemon->sfds;
Beniamino Galvani2675f202016-08-28 20:44:05 +01001252 sfd->ifindex = ifindex;
Simon Kelley4441cf72018-04-10 21:39:54 +01001253 sfd->preallocated = 0;
Simon Kelley824af852008-02-12 20:43:05 +00001254 daemon->sfds = sfd;
Beniamino Galvani2675f202016-08-28 20:44:05 +01001255
Simon Kelley824af852008-02-12 20:43:05 +00001256 return sfd;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001257}
1258
Simon Kelley824af852008-02-12 20:43:05 +00001259/* create upstream sockets during startup, before root is dropped which may be needed
1260 this allows query_port to be a low port and interface binding */
1261void pre_allocate_sfds(void)
1262{
1263 struct server *srv;
Simon Kelley4441cf72018-04-10 21:39:54 +01001264 struct serverfd *sfd;
Simon Kelley824af852008-02-12 20:43:05 +00001265
1266 if (daemon->query_port != 0)
1267 {
1268 union mysockaddr addr;
1269 memset(&addr, 0, sizeof(addr));
1270 addr.in.sin_family = AF_INET;
1271 addr.in.sin_addr.s_addr = INADDR_ANY;
1272 addr.in.sin_port = htons(daemon->query_port);
1273#ifdef HAVE_SOCKADDR_SA_LEN
1274 addr.in.sin_len = sizeof(struct sockaddr_in);
1275#endif
Simon Kelley4441cf72018-04-10 21:39:54 +01001276 if ((sfd = allocate_sfd(&addr, "")))
1277 sfd->preallocated = 1;
Simon Kelleyee875042018-10-23 22:10:17 +01001278
Simon Kelley824af852008-02-12 20:43:05 +00001279 memset(&addr, 0, sizeof(addr));
1280 addr.in6.sin6_family = AF_INET6;
1281 addr.in6.sin6_addr = in6addr_any;
1282 addr.in6.sin6_port = htons(daemon->query_port);
1283#ifdef HAVE_SOCKADDR_SA_LEN
1284 addr.in6.sin6_len = sizeof(struct sockaddr_in6);
1285#endif
Simon Kelley4441cf72018-04-10 21:39:54 +01001286 if ((sfd = allocate_sfd(&addr, "")))
1287 sfd->preallocated = 1;
Simon Kelley824af852008-02-12 20:43:05 +00001288 }
1289
1290 for (srv = daemon->servers; srv; srv = srv->next)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001291 if (!(srv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)) &&
Simon Kelley824af852008-02-12 20:43:05 +00001292 !allocate_sfd(&srv->source_addr, srv->interface) &&
Simon Kelley1a6bca82008-07-11 11:11:42 +01001293 errno != 0 &&
Simon Kelley28866e92011-02-14 20:19:14 +00001294 option_bool(OPT_NOWILD))
Simon Kelley824af852008-02-12 20:43:05 +00001295 {
Simon Kelley316e2732010-01-22 20:16:09 +00001296 prettyprint_addr(&srv->source_addr, daemon->namebuff);
Simon Kelley73a08a22009-02-05 20:28:08 +00001297 if (srv->interface[0] != 0)
Simon Kelley824af852008-02-12 20:43:05 +00001298 {
1299 strcat(daemon->namebuff, " ");
1300 strcat(daemon->namebuff, srv->interface);
1301 }
1302 die(_("failed to bind server socket for %s: %s"),
1303 daemon->namebuff, EC_BADNET);
1304 }
1305}
1306
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001307void mark_servers(int flag)
1308{
1309 struct server *serv;
1310
1311 /* mark everything with argument flag */
1312 for (serv = daemon->servers; serv; serv = serv->next)
Simon Kelley40766e52014-07-29 16:52:00 +01001313 {
1314 if (serv->flags & flag)
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001315 serv->flags |= SERV_MARK;
1316#ifdef HAVE_LOOP
Simon Kelley40766e52014-07-29 16:52:00 +01001317 /* Give looped servers another chance */
1318 serv->flags &= ~SERV_LOOP;
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001319#endif
Simon Kelley40766e52014-07-29 16:52:00 +01001320 }
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001321}
1322
1323void cleanup_servers(void)
1324{
1325 struct server *serv, *tmp, **up;
1326
1327 /* unlink and free anything still marked. */
1328 for (serv = daemon->servers, up = &daemon->servers; serv; serv = tmp)
1329 {
1330 tmp = serv->next;
1331 if (serv->flags & SERV_MARK)
1332 {
1333 server_gone(serv);
1334 *up = serv->next;
1335 if (serv->domain)
1336 free(serv->domain);
1337 free(serv);
1338 }
1339 else
1340 up = &serv->next;
1341 }
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001342
1343#ifdef HAVE_LOOP
1344 /* Now we have a new set of servers, test for loops. */
1345 loop_send_probes();
1346#endif
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001347}
1348
1349void add_update_server(int flags,
1350 union mysockaddr *addr,
1351 union mysockaddr *source_addr,
1352 const char *interface,
1353 const char *domain)
1354{
Simon Kelley7b1eae42014-02-20 13:43:28 +00001355 struct server *serv, *next = NULL;
1356 char *domain_str = NULL;
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001357
1358 /* See if there is a suitable candidate, and unmark */
1359 for (serv = daemon->servers; serv; serv = serv->next)
1360 if (serv->flags & SERV_MARK)
1361 {
1362 if (domain)
1363 {
1364 if (!(serv->flags & SERV_HAS_DOMAIN) || !hostname_isequal(domain, serv->domain))
1365 continue;
1366 }
1367 else
1368 {
1369 if (serv->flags & SERV_HAS_DOMAIN)
1370 continue;
1371 }
1372
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001373 break;
1374 }
Simon Kelley7b1eae42014-02-20 13:43:28 +00001375
1376 if (serv)
1377 {
1378 domain_str = serv->domain;
1379 next = serv->next;
1380 }
1381 else if ((serv = whine_malloc(sizeof (struct server))))
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001382 {
1383 /* Not found, create a new one. */
Simon Kelley7b1eae42014-02-20 13:43:28 +00001384 if (domain && !(domain_str = whine_malloc(strlen(domain)+1)))
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001385 {
1386 free(serv);
1387 serv = NULL;
1388 }
1389 else
1390 {
1391 struct server *s;
1392 /* Add to the end of the chain, for order */
1393 if (!daemon->servers)
1394 daemon->servers = serv;
1395 else
1396 {
1397 for (s = daemon->servers; s->next; s = s->next);
1398 s->next = serv;
1399 }
1400 if (domain)
Simon Kelley7b1eae42014-02-20 13:43:28 +00001401 strcpy(domain_str, domain);
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001402 }
1403 }
1404
1405 if (serv)
1406 {
Simon Kelley7b1eae42014-02-20 13:43:28 +00001407 memset(serv, 0, sizeof(struct server));
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001408 serv->flags = flags;
Simon Kelley7b1eae42014-02-20 13:43:28 +00001409 serv->domain = domain_str;
1410 serv->next = next;
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001411 serv->queries = serv->failed_queries = 0;
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001412#ifdef HAVE_LOOP
1413 serv->uid = rand32();
1414#endif
1415
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001416 if (domain)
1417 serv->flags |= SERV_HAS_DOMAIN;
1418
1419 if (interface)
Petr Menšík47b45b22018-08-15 18:17:00 +02001420 safe_strncpy(serv->interface, interface, sizeof(serv->interface));
Simon Kelley7b1eae42014-02-20 13:43:28 +00001421 if (addr)
1422 serv->addr = *addr;
1423 if (source_addr)
1424 serv->source_addr = *source_addr;
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001425 }
1426}
Simon Kelley824af852008-02-12 20:43:05 +00001427
Simon Kelley5aabfc72007-08-29 11:24:47 +01001428void check_servers(void)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001429{
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001430 struct irec *iface;
Simon Kelley7bcca002014-02-19 17:45:17 +00001431 struct server *serv;
Beniamino Galvani2675f202016-08-28 20:44:05 +01001432 struct serverfd *sfd, *tmp, **up;
Simon Kelleyb9702602016-05-03 22:34:06 +01001433 int port = 0, count;
Hannu Nyman3e2496f2017-02-11 13:44:08 +00001434 int locals = 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001435
Simon Kelley316e2732010-01-22 20:16:09 +00001436 /* interface may be new since startup */
Simon Kelley28866e92011-02-14 20:19:14 +00001437 if (!option_bool(OPT_NOWILD))
Simon Kelley115ac3e2013-05-20 11:28:32 +01001438 enumerate_interfaces(0);
Simon Kelley4441cf72018-04-10 21:39:54 +01001439
1440 /* don't garbage collect pre-allocated sfds. */
Beniamino Galvani2675f202016-08-28 20:44:05 +01001441 for (sfd = daemon->sfds; sfd; sfd = sfd->next)
Simon Kelley4441cf72018-04-10 21:39:54 +01001442 sfd->used = sfd->preallocated;
Beniamino Galvani2675f202016-08-28 20:44:05 +01001443
Simon Kelleyb9702602016-05-03 22:34:06 +01001444 for (count = 0, serv = daemon->servers; serv; serv = serv->next)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001445 {
Simon Kelley367341f2016-01-12 15:58:23 +00001446 if (!(serv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001447 {
Simon Kelley14ffa072016-04-25 16:36:44 +01001448 /* Init edns_pktsz for newly created server records. */
1449 if (serv->edns_pktsz == 0)
1450 serv->edns_pktsz = daemon->edns_pktsz;
1451
Simon Kelley367341f2016-01-12 15:58:23 +00001452#ifdef HAVE_DNSSEC
Simon Kelley92be34a2016-01-16 18:39:54 +00001453 if (option_bool(OPT_DNSSEC_VALID))
1454 {
Simon Kelleya49c5c22017-10-10 22:04:59 +01001455 if (!(serv->flags & SERV_FOR_NODOTS))
1456 serv->flags |= SERV_DO_DNSSEC;
1457
1458 /* Disable DNSSEC validation when using server=/domain/.... servers
1459 unless there's a configured trust anchor. */
Simon Kelley92be34a2016-01-16 18:39:54 +00001460 if (serv->flags & SERV_HAS_DOMAIN)
1461 {
1462 struct ds_config *ds;
1463 char *domain = serv->domain;
1464
1465 /* .example.com is valid */
1466 while (*domain == '.')
1467 domain++;
1468
1469 for (ds = daemon->ds; ds; ds = ds->next)
1470 if (ds->name[0] != 0 && hostname_isequal(domain, ds->name))
1471 break;
1472
1473 if (!ds)
1474 serv->flags &= ~SERV_DO_DNSSEC;
1475 }
Simon Kelley367341f2016-01-12 15:58:23 +00001476 }
1477#endif
1478
1479 port = prettyprint_addr(&serv->addr, daemon->namebuff);
1480
Simon Kelley16972692006-10-16 20:04:18 +01001481 /* 0.0.0.0 is nothing, the stack treats it like 127.0.0.1 */
Simon Kelley7bcca002014-02-19 17:45:17 +00001482 if (serv->addr.sa.sa_family == AF_INET &&
1483 serv->addr.in.sin_addr.s_addr == 0)
Simon Kelley16972692006-10-16 20:04:18 +01001484 {
Simon Kelley7bcca002014-02-19 17:45:17 +00001485 serv->flags |= SERV_MARK;
Simon Kelley16972692006-10-16 20:04:18 +01001486 continue;
1487 }
1488
Simon Kelley3d8df262005-08-29 12:19:27 +01001489 for (iface = daemon->interfaces; iface; iface = iface->next)
Simon Kelley7bcca002014-02-19 17:45:17 +00001490 if (sockaddr_isequal(&serv->addr, &iface->addr))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001491 break;
1492 if (iface)
1493 {
Simon Kelleyf2621c72007-04-29 19:47:21 +01001494 my_syslog(LOG_WARNING, _("ignoring nameserver %s - local interface"), daemon->namebuff);
Simon Kelley7bcca002014-02-19 17:45:17 +00001495 serv->flags |= SERV_MARK;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001496 continue;
1497 }
1498
1499 /* Do we need a socket set? */
Simon Kelley7bcca002014-02-19 17:45:17 +00001500 if (!serv->sfd &&
1501 !(serv->sfd = allocate_sfd(&serv->source_addr, serv->interface)) &&
Simon Kelley1a6bca82008-07-11 11:11:42 +01001502 errno != 0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001503 {
Simon Kelleyf2621c72007-04-29 19:47:21 +01001504 my_syslog(LOG_WARNING,
1505 _("ignoring nameserver %s - cannot make/bind socket: %s"),
1506 daemon->namebuff, strerror(errno));
Simon Kelley7bcca002014-02-19 17:45:17 +00001507 serv->flags |= SERV_MARK;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001508 continue;
1509 }
Simon Kelley16800ea2016-08-30 23:07:06 +01001510
1511 if (serv->sfd)
1512 serv->sfd->used = 1;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001513 }
1514
Simon Kelley979fe862015-03-19 22:50:22 +00001515 if (!(serv->flags & SERV_NO_REBIND) && !(serv->flags & SERV_LITERAL_ADDRESS))
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001516 {
Simon Kelleyb9702602016-05-03 22:34:06 +01001517 if (++count > SERVERS_LOGGED)
1518 continue;
1519
Simon Kelley7bcca002014-02-19 17:45:17 +00001520 if (serv->flags & (SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_USE_RESOLV))
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001521 {
Simon Kelley367341f2016-01-12 15:58:23 +00001522 char *s1, *s2, *s3 = "";
1523#ifdef HAVE_DNSSEC
1524 if (option_bool(OPT_DNSSEC_VALID) && !(serv->flags & SERV_DO_DNSSEC))
1525 s3 = _("(no DNSSEC)");
1526#endif
Simon Kelley7bcca002014-02-19 17:45:17 +00001527 if (!(serv->flags & SERV_HAS_DOMAIN))
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001528 s1 = _("unqualified"), s2 = _("names");
Simon Kelley7bcca002014-02-19 17:45:17 +00001529 else if (strlen(serv->domain) == 0)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001530 s1 = _("default"), s2 = "";
1531 else
Simon Kelley7bcca002014-02-19 17:45:17 +00001532 s1 = _("domain"), s2 = serv->domain;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001533
Simon Kelley7bcca002014-02-19 17:45:17 +00001534 if (serv->flags & SERV_NO_ADDR)
Hannu Nyman3e2496f2017-02-11 13:44:08 +00001535 {
1536 count--;
1537 if (++locals <= LOCALS_LOGGED)
1538 my_syslog(LOG_INFO, _("using local addresses only for %s %s"), s1, s2);
1539 }
Simon Kelley7bcca002014-02-19 17:45:17 +00001540 else if (serv->flags & SERV_USE_RESOLV)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001541 my_syslog(LOG_INFO, _("using standard nameservers for %s %s"), s1, s2);
Simon Kelley979fe862015-03-19 22:50:22 +00001542 else
Simon Kelley367341f2016-01-12 15:58:23 +00001543 my_syslog(LOG_INFO, _("using nameserver %s#%d for %s %s %s"), daemon->namebuff, port, s1, s2, s3);
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001544 }
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +01001545#ifdef HAVE_LOOP
1546 else if (serv->flags & SERV_LOOP)
1547 my_syslog(LOG_INFO, _("NOT using nameserver %s#%d - query loop detected"), daemon->namebuff, port);
1548#endif
Simon Kelley7bcca002014-02-19 17:45:17 +00001549 else if (serv->interface[0] != 0)
1550 my_syslog(LOG_INFO, _("using nameserver %s#%d(via %s)"), daemon->namebuff, port, serv->interface);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001551 else
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001552 my_syslog(LOG_INFO, _("using nameserver %s#%d"), daemon->namebuff, port);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001553 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001554 }
Simon Kelleyb9702602016-05-03 22:34:06 +01001555
Hannu Nyman3e2496f2017-02-11 13:44:08 +00001556 if (locals > LOCALS_LOGGED)
1557 my_syslog(LOG_INFO, _("using %d more local addresses"), locals - LOCALS_LOGGED);
Simon Kelleyb9702602016-05-03 22:34:06 +01001558 if (count - 1 > SERVERS_LOGGED)
1559 my_syslog(LOG_INFO, _("using %d more nameservers"), count - SERVERS_LOGGED - 1);
Simon Kelley7bcca002014-02-19 17:45:17 +00001560
Beniamino Galvani2675f202016-08-28 20:44:05 +01001561 /* Remove unused sfds */
1562 for (sfd = daemon->sfds, up = &daemon->sfds; sfd; sfd = tmp)
1563 {
1564 tmp = sfd->next;
1565 if (!sfd->used)
1566 {
1567 *up = sfd->next;
1568 close(sfd->fd);
1569 free(sfd);
1570 }
1571 else
1572 up = &sfd->next;
1573 }
1574
Simon Kelley7bcca002014-02-19 17:45:17 +00001575 cleanup_servers();
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001576}
Simon Kelley849a8352006-06-09 21:02:31 +01001577
1578/* Return zero if no servers found, in that case we keep polling.
1579 This is a protection against an update-time/write race on resolv.conf */
Simon Kelley5aabfc72007-08-29 11:24:47 +01001580int reload_servers(char *fname)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001581{
1582 FILE *f;
1583 char *line;
Simon Kelley849a8352006-06-09 21:02:31 +01001584 int gotone = 0;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001585
Simon Kelley849a8352006-06-09 21:02:31 +01001586 /* buff happens to be MAXDNAME long... */
1587 if (!(f = fopen(fname, "r")))
1588 {
Simon Kelleyf2621c72007-04-29 19:47:21 +01001589 my_syslog(LOG_ERR, _("failed to read %s: %s"), fname, strerror(errno));
Simon Kelley849a8352006-06-09 21:02:31 +01001590 return 0;
1591 }
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001592
1593 mark_servers(SERV_FROM_RESOLV);
1594
Simon Kelley849a8352006-06-09 21:02:31 +01001595 while ((line = fgets(daemon->namebuff, MAXDNAME, f)))
1596 {
1597 union mysockaddr addr, source_addr;
1598 char *token = strtok(line, " \t\n\r");
1599
Simon Kelley5aabfc72007-08-29 11:24:47 +01001600 if (!token)
1601 continue;
1602 if (strcmp(token, "nameserver") != 0 && strcmp(token, "server") != 0)
Simon Kelley849a8352006-06-09 21:02:31 +01001603 continue;
1604 if (!(token = strtok(NULL, " \t\n\r")))
1605 continue;
1606
1607 memset(&addr, 0, sizeof(addr));
1608 memset(&source_addr, 0, sizeof(source_addr));
1609
1610 if ((addr.in.sin_addr.s_addr = inet_addr(token)) != (in_addr_t) -1)
1611 {
1612#ifdef HAVE_SOCKADDR_SA_LEN
1613 source_addr.in.sin_len = addr.in.sin_len = sizeof(source_addr.in);
1614#endif
1615 source_addr.in.sin_family = addr.in.sin_family = AF_INET;
1616 addr.in.sin_port = htons(NAMESERVER_PORT);
1617 source_addr.in.sin_addr.s_addr = INADDR_ANY;
1618 source_addr.in.sin_port = htons(daemon->query_port);
1619 }
Simon Kelley7de060b2011-08-26 17:24:52 +01001620 else
1621 {
1622 int scope_index = 0;
1623 char *scope_id = strchr(token, '%');
1624
1625 if (scope_id)
1626 {
1627 *(scope_id++) = 0;
1628 scope_index = if_nametoindex(scope_id);
1629 }
1630
1631 if (inet_pton(AF_INET6, token, &addr.in6.sin6_addr) > 0)
1632 {
Simon Kelley849a8352006-06-09 21:02:31 +01001633#ifdef HAVE_SOCKADDR_SA_LEN
Simon Kelley7de060b2011-08-26 17:24:52 +01001634 source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(source_addr.in6);
Simon Kelley849a8352006-06-09 21:02:31 +01001635#endif
Simon Kelley7de060b2011-08-26 17:24:52 +01001636 source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6;
1637 source_addr.in6.sin6_flowinfo = addr.in6.sin6_flowinfo = 0;
1638 addr.in6.sin6_port = htons(NAMESERVER_PORT);
1639 addr.in6.sin6_scope_id = scope_index;
1640 source_addr.in6.sin6_addr = in6addr_any;
1641 source_addr.in6.sin6_port = htons(daemon->query_port);
1642 source_addr.in6.sin6_scope_id = 0;
1643 }
1644 else
1645 continue;
Simon Kelley849a8352006-06-09 21:02:31 +01001646 }
Simon Kelley7de060b2011-08-26 17:24:52 +01001647
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001648 add_update_server(SERV_FROM_RESOLV, &addr, &source_addr, NULL, NULL);
Simon Kelley849a8352006-06-09 21:02:31 +01001649 gotone = 1;
1650 }
1651
Simon Kelley849a8352006-06-09 21:02:31 +01001652 fclose(f);
Simon Kelleyd68c2ca2014-02-18 22:30:30 +00001653 cleanup_servers();
Simon Kelley849a8352006-06-09 21:02:31 +01001654
1655 return gotone;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001656}
1657
Simon Kelley1ee9be42013-12-09 16:50:19 +00001658/* Called when addresses are added or deleted from an interface */
1659void newaddress(time_t now)
1660{
1661 (void)now;
1662
Simon Kelley89b12ed2014-03-06 13:27:57 +00001663 if (option_bool(OPT_CLEVERBIND) || option_bool(OPT_LOCAL_SERVICE) ||
1664 daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
Simon Kelley1ee9be42013-12-09 16:50:19 +00001665 enumerate_interfaces(0);
1666
1667 if (option_bool(OPT_CLEVERBIND))
1668 create_bound_listeners(0);
1669
1670#ifdef HAVE_DHCP6
1671 if (daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
1672 join_multicast(0);
1673
1674 if (daemon->doing_dhcp6 || daemon->doing_ra)
1675 dhcp_construct_contexts(now);
1676
1677 if (daemon->doing_dhcp6)
1678 lease_find_interfaces(now);
1679#endif
1680}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001681
1682
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001683
1684
1685