Annotation of embedaddon/dnsmasq/src/network.c, revision 1.1.1.5
1.1.1.5 ! misho 1: /* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
1.1 misho 2:
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
5: the Free Software Foundation; version 2 dated June, 1991, or
6: (at your option) version 3 dated 29 June, 2007.
7:
8: 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.
12:
13: 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/>.
15: */
16:
17: #include "dnsmasq.h"
18:
19: #ifdef HAVE_LINUX_NETWORK
20:
21: int 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:
1.1.1.4 misho 32: safe_strncpy(name, ifr.ifr_name, IF_NAMESIZE);
1.1 misho 33:
1.1.1.5 ! misho 34: return 1;
1.1 misho 35: }
36:
37:
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:
46: int 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;
1.1.1.4 misho 85: safe_strncpy(lifr.lifr_name, lifrp->lifr_name, IF_NAMESIZE);
1.1 misho 86: if (ioctl(fd, SIOCGLIFINDEX, &lifr) < 0)
87: return 0;
88:
89: if (lifr.lifr_index == index) {
1.1.1.4 misho 90: safe_strncpy(name, lifr.lifr_name, IF_NAMESIZE);
1.1 misho 91: return 1;
92: }
93: }
94: return 0;
95: }
96:
97:
98: #else
99:
100: int indextoname(int fd, int index, char *name)
101: {
1.1.1.2 misho 102: (void)fd;
103:
1.1 misho 104: if (index == 0 || !if_indextoname(index, name))
105: return 0;
106:
107: return 1;
108: }
109:
110: #endif
111:
1.1.1.4 misho 112: int iface_check(int family, union all_addr *addr, char *name, int *auth)
1.1 misho 113: {
114: struct iname *tmp;
1.1.1.2 misho 115: int ret = 1, match_addr = 0;
1.1 misho 116:
1.1.1.5 ! misho 117: /* Note: have to check all and not bail out early, so that we set the "used" flags.
! 118: May be called with family == AF_LOCAL to check interface by name only. */
1.1 misho 119:
120: if (daemon->if_names || daemon->if_addrs)
121: {
122: ret = 0;
123:
124: for (tmp = daemon->if_names; tmp; tmp = tmp->next)
125: if (tmp->name && wildcard_match(tmp->name, name))
126: ret = tmp->used = 1;
127:
128: if (addr)
129: for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
130: if (tmp->addr.sa.sa_family == family)
131: {
132: if (family == AF_INET &&
1.1.1.4 misho 133: tmp->addr.in.sin_addr.s_addr == addr->addr4.s_addr)
1.1.1.2 misho 134: ret = match_addr = tmp->used = 1;
1.1 misho 135: else if (family == AF_INET6 &&
136: IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr,
1.1.1.4 misho 137: &addr->addr6))
1.1.1.2 misho 138: ret = match_addr = tmp->used = 1;
1.1 misho 139: }
140: }
141:
1.1.1.2 misho 142: if (!match_addr)
143: for (tmp = daemon->if_except; tmp; tmp = tmp->next)
144: if (tmp->name && wildcard_match(tmp->name, name))
145: ret = 0;
1.1 misho 146:
1.1.1.5 ! misho 147: if (auth)
! 148: {
! 149: *auth = 0;
1.1 misho 150:
1.1.1.5 ! misho 151: for (tmp = daemon->authinterface; tmp; tmp = tmp->next)
! 152: if (tmp->name)
! 153: {
! 154: if (strcmp(tmp->name, name) == 0 &&
! 155: (tmp->addr.sa.sa_family == 0 || tmp->addr.sa.sa_family == family))
! 156: break;
! 157: }
! 158: else if (addr && tmp->addr.sa.sa_family == AF_INET && family == AF_INET &&
! 159: tmp->addr.in.sin_addr.s_addr == addr->addr4.s_addr)
1.1 misho 160: break;
1.1.1.5 ! misho 161: else if (addr && tmp->addr.sa.sa_family == AF_INET6 && family == AF_INET6 &&
! 162: IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, &addr->addr6))
! 163: break;
! 164:
! 165: if (tmp)
! 166: {
! 167: *auth = 1;
! 168: ret = 1;
! 169: }
1.1 misho 170: }
171:
172: return ret;
173: }
174:
175:
1.1.1.4 misho 176: /* Fix for problem that the kernel sometimes reports the loopback interface as the
1.1 misho 177: arrival interface when a packet originates locally, even when sent to address of
178: an interface other than the loopback. Accept packet if it arrived via a loopback
179: interface, even when we're not accepting packets that way, as long as the destination
180: address is one we're believing. Interface list must be up-to-date before calling. */
1.1.1.4 misho 181: int loopback_exception(int fd, int family, union all_addr *addr, char *name)
1.1 misho 182: {
183: struct ifreq ifr;
184: struct irec *iface;
185:
1.1.1.4 misho 186: safe_strncpy(ifr.ifr_name, name, IF_NAMESIZE);
1.1 misho 187: if (ioctl(fd, SIOCGIFFLAGS, &ifr) != -1 &&
188: ifr.ifr_flags & IFF_LOOPBACK)
189: {
190: for (iface = daemon->interfaces; iface; iface = iface->next)
191: if (iface->addr.sa.sa_family == family)
192: {
193: if (family == AF_INET)
194: {
1.1.1.4 misho 195: if (iface->addr.in.sin_addr.s_addr == addr->addr4.s_addr)
1.1 misho 196: return 1;
197: }
1.1.1.4 misho 198: else if (IN6_ARE_ADDR_EQUAL(&iface->addr.in6.sin6_addr, &addr->addr6))
1.1 misho 199: return 1;
200: }
201: }
202: return 0;
203: }
204:
1.1.1.2 misho 205: /* If we're configured with something like --interface=eth0:0 then we'll listen correctly
206: on the relevant address, but the name of the arrival interface, derived from the
207: index won't match the config. Check that we found an interface address for the arrival
208: interface: daemon->interfaces must be up-to-date. */
1.1.1.4 misho 209: int label_exception(int index, int family, union all_addr *addr)
1.1 misho 210: {
211: struct irec *iface;
1.1.1.2 misho 212:
213: /* labels only supported on IPv4 addresses. */
214: if (family != AF_INET)
215: return 0;
216:
217: for (iface = daemon->interfaces; iface; iface = iface->next)
218: if (iface->index == index && iface->addr.sa.sa_family == AF_INET &&
1.1.1.4 misho 219: iface->addr.in.sin_addr.s_addr == addr->addr4.s_addr)
1.1.1.2 misho 220: return 1;
221:
222: return 0;
223: }
224:
225: struct iface_param {
226: struct addrlist *spare;
227: int fd;
228: };
229:
230: static int iface_allowed(struct iface_param *param, int if_index, char *label,
1.1.1.3 misho 231: union mysockaddr *addr, struct in_addr netmask, int prefixlen, int iface_flags)
1.1.1.2 misho 232: {
233: struct irec *iface;
1.1.1.5 ! misho 234: struct cond_domain *cond;
! 235: int loopback;
1.1 misho 236: struct ifreq ifr;
237: int tftp_ok = !!option_bool(OPT_TFTP);
238: int dhcp_ok = 1;
239: int auth_dns = 0;
1.1.1.4 misho 240: int is_label = 0;
1.1.1.2 misho 241: #if defined(HAVE_DHCP) || defined(HAVE_TFTP)
1.1 misho 242: struct iname *tmp;
243: #endif
244:
1.1.1.2 misho 245: (void)prefixlen;
1.1 misho 246:
1.1.1.2 misho 247: if (!indextoname(param->fd, if_index, ifr.ifr_name) ||
248: ioctl(param->fd, SIOCGIFFLAGS, &ifr) == -1)
249: return 0;
1.1 misho 250:
251: loopback = ifr.ifr_flags & IFF_LOOPBACK;
252:
253: if (loopback)
1.1.1.2 misho 254: dhcp_ok = 0;
255:
256: if (!label)
257: label = ifr.ifr_name;
1.1.1.4 misho 258: else
259: is_label = strcmp(label, ifr.ifr_name);
1.1.1.2 misho 260:
261: /* maintain a list of all addresses on all interfaces for --local-service option */
262: if (option_bool(OPT_LOCAL_SERVICE))
263: {
264: struct addrlist *al;
265:
266: if (param->spare)
267: {
268: al = param->spare;
269: param->spare = al->next;
270: }
271: else
272: al = whine_malloc(sizeof(struct addrlist));
273:
274: if (al)
275: {
276: al->next = daemon->interface_addrs;
277: daemon->interface_addrs = al;
278: al->prefixlen = prefixlen;
279:
280: if (addr->sa.sa_family == AF_INET)
281: {
1.1.1.4 misho 282: al->addr.addr4 = addr->in.sin_addr;
1.1.1.2 misho 283: al->flags = 0;
284: }
285: else
286: {
1.1.1.4 misho 287: al->addr.addr6 = addr->in6.sin6_addr;
1.1.1.2 misho 288: al->flags = ADDRLIST_IPV6;
289: }
290: }
291: }
1.1 misho 292:
1.1.1.2 misho 293: if (addr->sa.sa_family != AF_INET6 || !IN6_IS_ADDR_LINKLOCAL(&addr->in6.sin6_addr))
294: {
295: struct interface_name *int_name;
296: struct addrlist *al;
297: #ifdef HAVE_AUTH
298: struct auth_zone *zone;
299: struct auth_name_list *name;
300:
301: /* Find subnets in auth_zones */
302: for (zone = daemon->auth_zones; zone; zone = zone->next)
303: for (name = zone->interface_names; name; name = name->next)
304: if (wildcard_match(name->name, label))
305: {
306: if (addr->sa.sa_family == AF_INET && (name->flags & AUTH4))
307: {
308: if (param->spare)
309: {
310: al = param->spare;
311: param->spare = al->next;
312: }
313: else
314: al = whine_malloc(sizeof(struct addrlist));
315:
316: if (al)
317: {
318: al->next = zone->subnet;
319: zone->subnet = al;
320: al->prefixlen = prefixlen;
1.1.1.4 misho 321: al->addr.addr4 = addr->in.sin_addr;
1.1.1.2 misho 322: al->flags = 0;
323: }
324: }
325:
326: if (addr->sa.sa_family == AF_INET6 && (name->flags & AUTH6))
327: {
328: if (param->spare)
329: {
330: al = param->spare;
331: param->spare = al->next;
332: }
333: else
334: al = whine_malloc(sizeof(struct addrlist));
335:
336: if (al)
337: {
338: al->next = zone->subnet;
339: zone->subnet = al;
340: al->prefixlen = prefixlen;
1.1.1.4 misho 341: al->addr.addr6 = addr->in6.sin6_addr;
1.1.1.2 misho 342: al->flags = ADDRLIST_IPV6;
343: }
344: }
345: }
346: #endif
347:
348: /* Update addresses from interface_names. These are a set independent
349: of the set we're listening on. */
350: for (int_name = daemon->int_names; int_name; int_name = int_name->next)
1.1.1.5 ! misho 351: if (strncmp(label, int_name->intr, IF_NAMESIZE) == 0)
1.1.1.2 misho 352: {
1.1.1.5 ! misho 353: struct addrlist *lp;
! 354:
! 355: al = NULL;
! 356:
! 357: if (addr->sa.sa_family == AF_INET && (int_name->flags & (IN4 | INP4)))
1.1.1.2 misho 358: {
1.1.1.5 ! misho 359: struct in_addr newaddr = addr->in.sin_addr;
! 360:
! 361: if (int_name->flags & INP4)
! 362: {
! 363: if (netmask.s_addr == 0xffffffff)
! 364: continue;
! 365:
! 366: newaddr.s_addr = (addr->in.sin_addr.s_addr & netmask.s_addr) |
! 367: (int_name->proto4.s_addr & ~netmask.s_addr);
! 368: }
! 369:
! 370: /* check for duplicates. */
! 371: for (lp = int_name->addr; lp; lp = lp->next)
! 372: if (lp->flags == 0 && lp->addr.addr4.s_addr == newaddr.s_addr)
! 373: break;
! 374:
! 375: if (!lp)
! 376: {
! 377: if (param->spare)
! 378: {
! 379: al = param->spare;
! 380: param->spare = al->next;
! 381: }
! 382: else
! 383: al = whine_malloc(sizeof(struct addrlist));
! 384:
! 385: if (al)
! 386: {
! 387: al->flags = 0;
! 388: al->addr.addr4 = newaddr;
! 389: }
! 390: }
! 391: }
! 392:
! 393: if (addr->sa.sa_family == AF_INET6 && (int_name->flags & (IN6 | INP6)))
! 394: {
! 395: struct in6_addr newaddr = addr->in6.sin6_addr;
! 396:
! 397: if (int_name->flags & INP6)
! 398: {
! 399: int i;
! 400:
! 401: /* No sense in doing /128. */
! 402: if (prefixlen == 128)
! 403: continue;
! 404:
! 405: for (i = 0; i < 16; i++)
! 406: {
! 407: int bits = ((i+1)*8) - prefixlen;
! 408:
! 409: if (bits >= 8)
! 410: newaddr.s6_addr[i] = int_name->proto6.s6_addr[i];
! 411: else if (bits >= 0)
! 412: {
! 413: unsigned char mask = 0xff << bits;
! 414: newaddr.s6_addr[i] =
! 415: (addr->in6.sin6_addr.s6_addr[i] & mask) |
! 416: (int_name->proto6.s6_addr[i] & ~mask);
! 417: }
! 418: }
! 419: }
! 420:
! 421: /* check for duplicates. */
! 422: for (lp = int_name->addr; lp; lp = lp->next)
! 423: if ((lp->flags & ADDRLIST_IPV6) &&
! 424: IN6_ARE_ADDR_EQUAL(&lp->addr.addr6, &newaddr))
! 425: break;
! 426:
! 427: if (!lp)
! 428: {
! 429: if (param->spare)
! 430: {
! 431: al = param->spare;
! 432: param->spare = al->next;
! 433: }
! 434: else
! 435: al = whine_malloc(sizeof(struct addrlist));
! 436:
! 437: if (al)
! 438: {
! 439: al->flags = ADDRLIST_IPV6;
! 440: al->addr.addr6 = newaddr;
! 441:
! 442: /* Privacy addresses and addresses still undergoing DAD and deprecated addresses
! 443: don't appear in forward queries, but will in reverse ones. */
! 444: if (!(iface_flags & IFACE_PERMANENT) || (iface_flags & (IFACE_DEPRECATED | IFACE_TENTATIVE)))
! 445: al->flags |= ADDRLIST_REVONLY;
! 446: }
! 447: }
1.1.1.2 misho 448: }
449:
450: if (al)
451: {
452: al->next = int_name->addr;
453: int_name->addr = al;
454: }
455: }
456: }
1.1.1.5 ! misho 457:
! 458: /* Update addresses for domain=<domain>,<interface> */
! 459: for (cond = daemon->cond_domain; cond; cond = cond->next)
! 460: if (cond->interface && strncmp(label, cond->interface, IF_NAMESIZE) == 0)
! 461: {
! 462: struct addrlist *al;
! 463:
! 464: if (param->spare)
! 465: {
! 466: al = param->spare;
! 467: param->spare = al->next;
! 468: }
! 469: else
! 470: al = whine_malloc(sizeof(struct addrlist));
! 471:
! 472: if (addr->sa.sa_family == AF_INET)
! 473: {
! 474: al->addr.addr4 = addr->in.sin_addr;
! 475: al->flags = 0;
! 476: }
! 477: else
! 478: {
! 479: al->addr.addr6 = addr->in6.sin6_addr;
! 480: al->flags = ADDRLIST_IPV6;
! 481: }
! 482:
! 483: al->prefixlen = prefixlen;
! 484: al->next = cond->al;
! 485: cond->al = al;
! 486: }
! 487:
1.1.1.2 misho 488: /* check whether the interface IP has been added already
489: we call this routine multiple times. */
490: for (iface = daemon->interfaces; iface; iface = iface->next)
1.1.1.4 misho 491: if (sockaddr_isequal(&iface->addr, addr) && iface->index == if_index)
1.1.1.2 misho 492: {
1.1.1.3 misho 493: iface->dad = !!(iface_flags & IFACE_TENTATIVE);
1.1.1.2 misho 494: iface->found = 1; /* for garbage collection */
1.1.1.4 misho 495: iface->netmask = netmask;
1.1.1.2 misho 496: return 1;
497: }
498:
499: /* If we are restricting the set of interfaces to use, make
1.1 misho 500: sure that loopback interfaces are in that set. */
501: if (daemon->if_names && loopback)
502: {
503: struct iname *lo;
504: for (lo = daemon->if_names; lo; lo = lo->next)
505: if (lo->name && strcmp(lo->name, ifr.ifr_name) == 0)
506: break;
507:
508: if (!lo && (lo = whine_malloc(sizeof(struct iname))))
509: {
510: if ((lo->name = whine_malloc(strlen(ifr.ifr_name)+1)))
511: {
512: strcpy(lo->name, ifr.ifr_name);
513: lo->used = 1;
514: lo->next = daemon->if_names;
515: daemon->if_names = lo;
516: }
517: else
518: free(lo);
519: }
520: }
521:
522: if (addr->sa.sa_family == AF_INET &&
1.1.1.4 misho 523: !iface_check(AF_INET, (union all_addr *)&addr->in.sin_addr, label, &auth_dns))
1.1 misho 524: return 1;
525:
526: if (addr->sa.sa_family == AF_INET6 &&
1.1.1.4 misho 527: !iface_check(AF_INET6, (union all_addr *)&addr->in6.sin6_addr, label, &auth_dns))
1.1 misho 528: return 1;
529:
530: #ifdef HAVE_DHCP
531: /* No DHCP where we're doing auth DNS. */
532: if (auth_dns)
533: {
534: tftp_ok = 0;
535: dhcp_ok = 0;
536: }
537: else
538: for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
539: if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
540: {
541: tftp_ok = 0;
542: dhcp_ok = 0;
543: }
544: #endif
545:
1.1.1.2 misho 546:
547: #ifdef HAVE_TFTP
548: if (daemon->tftp_interfaces)
549: {
550: /* dedicated tftp interface list */
551: tftp_ok = 0;
552: for (tmp = daemon->tftp_interfaces; tmp; tmp = tmp->next)
553: if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
554: tftp_ok = 1;
555: }
556: #endif
557:
1.1 misho 558: /* add to list */
559: if ((iface = whine_malloc(sizeof(struct irec))))
560: {
1.1.1.5 ! misho 561: int mtu = 0;
! 562:
! 563: if (ioctl(param->fd, SIOCGIFMTU, &ifr) != -1)
! 564: mtu = ifr.ifr_mtu;
! 565:
1.1 misho 566: iface->addr = *addr;
567: iface->netmask = netmask;
568: iface->tftp_ok = tftp_ok;
569: iface->dhcp_ok = dhcp_ok;
570: iface->dns_auth = auth_dns;
571: iface->mtu = mtu;
1.1.1.3 misho 572: iface->dad = !!(iface_flags & IFACE_TENTATIVE);
1.1.1.2 misho 573: iface->found = 1;
574: iface->done = iface->multicast_done = iface->warned = 0;
1.1 misho 575: iface->index = if_index;
1.1.1.4 misho 576: iface->label = is_label;
1.1 misho 577: if ((iface->name = whine_malloc(strlen(ifr.ifr_name)+1)))
578: {
579: strcpy(iface->name, ifr.ifr_name);
1.1.1.2 misho 580: iface->next = daemon->interfaces;
581: daemon->interfaces = iface;
1.1 misho 582: return 1;
583: }
584: free(iface);
585:
586: }
587:
588: errno = ENOMEM;
589: return 0;
590: }
591:
592: static int iface_allowed_v6(struct in6_addr *local, int prefix,
593: int scope, int if_index, int flags,
594: int preferred, int valid, void *vparam)
595: {
596: union mysockaddr addr;
597: struct in_addr netmask; /* dummy */
598: netmask.s_addr = 0;
599:
600: (void)scope; /* warning */
601: (void)preferred;
602: (void)valid;
603:
604: memset(&addr, 0, sizeof(addr));
605: #ifdef HAVE_SOCKADDR_SA_LEN
606: addr.in6.sin6_len = sizeof(addr.in6);
607: #endif
608: addr.in6.sin6_family = AF_INET6;
609: addr.in6.sin6_addr = *local;
610: addr.in6.sin6_port = htons(daemon->port);
1.1.1.2 misho 611: /* FreeBSD insists this is zero for non-linklocal addresses */
612: if (IN6_IS_ADDR_LINKLOCAL(local))
613: addr.in6.sin6_scope_id = if_index;
614: else
615: addr.in6.sin6_scope_id = 0;
1.1 misho 616:
1.1.1.3 misho 617: return iface_allowed((struct iface_param *)vparam, if_index, NULL, &addr, netmask, prefix, flags);
1.1 misho 618: }
619:
1.1.1.2 misho 620: static int iface_allowed_v4(struct in_addr local, int if_index, char *label,
1.1 misho 621: struct in_addr netmask, struct in_addr broadcast, void *vparam)
622: {
623: union mysockaddr addr;
1.1.1.2 misho 624: int prefix, bit;
1.1.1.3 misho 625:
626: (void)broadcast; /* warning */
1.1 misho 627:
628: memset(&addr, 0, sizeof(addr));
629: #ifdef HAVE_SOCKADDR_SA_LEN
630: addr.in.sin_len = sizeof(addr.in);
631: #endif
632: addr.in.sin_family = AF_INET;
633: addr.in.sin_addr = local;
634: addr.in.sin_port = htons(daemon->port);
635:
1.1.1.2 misho 636: /* determine prefix length from netmask */
637: for (prefix = 32, bit = 1; (bit & ntohl(netmask.s_addr)) == 0 && prefix != 0; bit = bit << 1, prefix--);
638:
639: return iface_allowed((struct iface_param *)vparam, if_index, label, &addr, netmask, prefix, 0);
1.1 misho 640: }
1.1.1.4 misho 641:
642: /*
643: * Clean old interfaces no longer found.
644: */
645: static void clean_interfaces()
646: {
647: struct irec *iface;
648: struct irec **up = &daemon->interfaces;
649:
650: for (iface = *up; iface; iface = *up)
651: {
652: if (!iface->found && !iface->done)
653: {
654: *up = iface->next;
655: free(iface->name);
656: free(iface);
657: }
658: else
659: {
660: up = &iface->next;
661: }
662: }
663: }
664:
665: /** Release listener if no other interface needs it.
666: *
667: * @return 1 if released, 0 if still required
668: */
669: static int release_listener(struct listener *l)
670: {
671: if (l->used > 1)
672: {
673: struct irec *iface;
674: for (iface = daemon->interfaces; iface; iface = iface->next)
675: if (iface->done && sockaddr_isequal(&l->addr, &iface->addr))
676: {
677: if (iface->found)
678: {
679: /* update listener to point to active interface instead */
680: if (!l->iface->found)
681: l->iface = iface;
682: }
683: else
684: {
685: l->used--;
686: iface->done = 0;
687: }
688: }
689:
690: /* Someone is still using this listener, skip its deletion */
691: if (l->used > 0)
692: return 0;
693: }
694:
695: if (l->iface->done)
696: {
697: int port;
698:
699: port = prettyprint_addr(&l->iface->addr, daemon->addrbuff);
1.1.1.5 ! misho 700: my_syslog(LOG_DEBUG|MS_DEBUG, _("stopped listening on %s(#%d): %s port %d"),
1.1.1.4 misho 701: l->iface->name, l->iface->index, daemon->addrbuff, port);
702: /* In case it ever returns */
703: l->iface->done = 0;
704: }
705:
706: if (l->fd != -1)
707: close(l->fd);
708: if (l->tcpfd != -1)
709: close(l->tcpfd);
710: if (l->tftpfd != -1)
711: close(l->tftpfd);
712:
713: free(l);
714: return 1;
715: }
716:
1.1.1.2 misho 717: int enumerate_interfaces(int reset)
1.1 misho 718: {
1.1.1.2 misho 719: static struct addrlist *spare = NULL;
1.1.1.3 misho 720: static int done = 0;
1.1.1.2 misho 721: struct iface_param param;
722: int errsave, ret = 1;
723: struct addrlist *addr, *tmp;
724: struct interface_name *intname;
1.1.1.5 ! misho 725: struct cond_domain *cond;
1.1.1.2 misho 726: struct irec *iface;
727: #ifdef HAVE_AUTH
728: struct auth_zone *zone;
729: #endif
1.1.1.5 ! misho 730: struct server *serv;
! 731:
1.1.1.2 misho 732: /* Do this max once per select cycle - also inhibits netlink socket use
733: in TCP child processes. */
734:
735: if (reset)
736: {
737: done = 0;
738: return 1;
739: }
740:
1.1.1.3 misho 741: if (done)
1.1.1.2 misho 742: return 1;
743:
744: done = 1;
745:
746: if ((param.fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
747: return 0;
1.1.1.5 ! misho 748:
! 749: /* iface indexes can change when interfaces are created/destroyed.
! 750: We use them in the main forwarding control path, when the path
! 751: to a server is specified by an interface, so cache them.
! 752: Update the cache here. */
! 753: for (serv = daemon->servers; serv; serv = serv->next)
! 754: if (serv->interface[0] != 0)
! 755: {
! 756: #ifdef HAVE_LINUX_NETWORK
! 757: struct ifreq ifr;
! 758:
! 759: safe_strncpy(ifr.ifr_name, serv->interface, IF_NAMESIZE);
! 760: if (ioctl(param.fd, SIOCGIFINDEX, &ifr) != -1)
! 761: serv->ifindex = ifr.ifr_ifindex;
! 762: #else
! 763: serv->ifindex = if_nametoindex(serv->interface);
! 764: #endif
! 765: }
! 766:
! 767: again:
1.1.1.2 misho 768: /* Mark interfaces for garbage collection */
769: for (iface = daemon->interfaces; iface; iface = iface->next)
770: iface->found = 0;
771:
772: /* remove addresses stored against interface_names */
773: for (intname = daemon->int_names; intname; intname = intname->next)
774: {
775: for (addr = intname->addr; addr; addr = tmp)
776: {
777: tmp = addr->next;
778: addr->next = spare;
779: spare = addr;
780: }
781:
782: intname->addr = NULL;
783: }
784:
1.1.1.5 ! misho 785: /* remove addresses stored against cond-domains. */
! 786: for (cond = daemon->cond_domain; cond; cond = cond->next)
! 787: {
! 788: for (addr = cond->al; addr; addr = tmp)
! 789: {
! 790: tmp = addr->next;
! 791: addr->next = spare;
! 792: spare = addr;
! 793: }
! 794:
! 795: cond->al = NULL;
! 796: }
! 797:
1.1.1.2 misho 798: /* Remove list of addresses of local interfaces */
799: for (addr = daemon->interface_addrs; addr; addr = tmp)
800: {
801: tmp = addr->next;
802: addr->next = spare;
803: spare = addr;
804: }
805: daemon->interface_addrs = NULL;
806:
807: #ifdef HAVE_AUTH
808: /* remove addresses stored against auth_zone subnets, but not
809: ones configured as address literals */
810: for (zone = daemon->auth_zones; zone; zone = zone->next)
811: if (zone->interface_names)
812: {
813: struct addrlist **up;
814: for (up = &zone->subnet, addr = zone->subnet; addr; addr = tmp)
815: {
816: tmp = addr->next;
817: if (addr->flags & ADDRLIST_LITERAL)
818: up = &addr->next;
819: else
820: {
821: *up = addr->next;
822: addr->next = spare;
823: spare = addr;
824: }
825: }
826: }
827: #endif
828:
829: param.spare = spare;
830:
831: ret = iface_enumerate(AF_INET6, ¶m, iface_allowed_v6);
1.1.1.5 ! misho 832: if (ret < 0)
! 833: goto again;
! 834: else if (ret)
! 835: {
! 836: ret = iface_enumerate(AF_INET, ¶m, iface_allowed_v4);
! 837: if (ret < 0)
! 838: goto again;
! 839: }
1.1.1.2 misho 840:
841: errsave = errno;
842: close(param.fd);
843:
844: if (option_bool(OPT_CLEVERBIND))
845: {
846: /* Garbage-collect listeners listening on addresses that no longer exist.
847: Does nothing when not binding interfaces or for listeners on localhost,
848: since the ->iface field is NULL. Note that this needs the protections
1.1.1.4 misho 849: against reentrancy, hence it's here. It also means there's a possibility,
1.1.1.2 misho 850: in OPT_CLEVERBIND mode, that at listener will just disappear after
851: a call to enumerate_interfaces, this is checked OK on all calls. */
852: struct listener *l, *tmp, **up;
1.1.1.4 misho 853: int freed = 0;
1.1.1.2 misho 854:
855: for (up = &daemon->listeners, l = daemon->listeners; l; l = tmp)
856: {
857: tmp = l->next;
858:
859: if (!l->iface || l->iface->found)
860: up = &l->next;
1.1.1.4 misho 861: else if (release_listener(l))
1.1.1.2 misho 862: {
1.1.1.4 misho 863: *up = tmp;
864: freed = 1;
1.1.1.2 misho 865: }
866: }
1.1.1.4 misho 867:
868: if (freed)
869: clean_interfaces();
1.1.1.2 misho 870: }
1.1.1.4 misho 871:
1.1.1.2 misho 872: errno = errsave;
873: spare = param.spare;
1.1.1.5 ! misho 874:
1.1.1.2 misho 875: return ret;
1.1 misho 876: }
877:
878: /* set NONBLOCK bit on fd: See Stevens 16.6 */
879: int fix_fd(int fd)
880: {
881: int flags;
882:
883: if ((flags = fcntl(fd, F_GETFL)) == -1 ||
884: fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
885: return 0;
886:
887: return 1;
888: }
889:
890: static int make_sock(union mysockaddr *addr, int type, int dienow)
891: {
892: int family = addr->sa.sa_family;
893: int fd, rc, opt = 1;
894:
895: if ((fd = socket(family, type, 0)) == -1)
896: {
1.1.1.4 misho 897: int port, errsave;
1.1 misho 898: char *s;
899:
900: /* No error if the kernel just doesn't support this IP flavour */
901: if (errno == EPROTONOSUPPORT ||
902: errno == EAFNOSUPPORT ||
903: errno == EINVAL)
904: return -1;
905:
906: err:
1.1.1.4 misho 907: errsave = errno;
1.1 misho 908: port = prettyprint_addr(addr, daemon->addrbuff);
909: if (!option_bool(OPT_NOWILD) && !option_bool(OPT_CLEVERBIND))
910: sprintf(daemon->addrbuff, "port %d", port);
911: s = _("failed to create listening socket for %s: %s");
912:
913: if (fd != -1)
914: close (fd);
1.1.1.2 misho 915:
1.1.1.4 misho 916: errno = errsave;
1.1.1.2 misho 917:
1.1 misho 918: if (dienow)
919: {
920: /* failure to bind addresses given by --listen-address at this point
921: is OK if we're doing bind-dynamic */
922: if (!option_bool(OPT_CLEVERBIND))
923: die(s, daemon->addrbuff, EC_BADNET);
924: }
925: else
926: my_syslog(LOG_WARNING, s, daemon->addrbuff, strerror(errno));
927:
928: return -1;
929: }
930:
931: if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || !fix_fd(fd))
932: goto err;
933:
934: if (family == AF_INET6 && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)) == -1)
935: goto err;
936:
937: if ((rc = bind(fd, (struct sockaddr *)addr, sa_len(addr))) == -1)
938: goto err;
939:
940: if (type == SOCK_STREAM)
941: {
1.1.1.4 misho 942: #ifdef TCP_FASTOPEN
943: int qlen = 5;
944: setsockopt(fd, IPPROTO_TCP, TCP_FASTOPEN, &qlen, sizeof(qlen));
945: #endif
946:
947: if (listen(fd, TCP_BACKLOG) == -1)
1.1 misho 948: goto err;
949: }
1.1.1.2 misho 950: else if (family == AF_INET)
1.1 misho 951: {
1.1.1.2 misho 952: if (!option_bool(OPT_NOWILD))
1.1 misho 953: {
954: #if defined(HAVE_LINUX_NETWORK)
955: if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) == -1)
956: goto err;
957: #elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
958: if (setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt)) == -1 ||
959: setsockopt(fd, IPPROTO_IP, IP_RECVIF, &opt, sizeof(opt)) == -1)
960: goto err;
961: #endif
962: }
1.1.1.2 misho 963: }
964: else if (!set_ipv6pktinfo(fd))
965: goto err;
1.1 misho 966:
967: return fd;
968: }
969:
970: int set_ipv6pktinfo(int fd)
971: {
972: int opt = 1;
973:
974: /* The API changed around Linux 2.6.14 but the old ABI is still supported:
975: handle all combinations of headers and kernel.
976: OpenWrt note that this fixes the problem addressed by your very broken patch. */
977: daemon->v6pktinfo = IPV6_PKTINFO;
978:
979: #ifdef IPV6_RECVPKTINFO
980: if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &opt, sizeof(opt)) != -1)
981: return 1;
982: # ifdef IPV6_2292PKTINFO
983: else if (errno == ENOPROTOOPT && setsockopt(fd, IPPROTO_IPV6, IPV6_2292PKTINFO, &opt, sizeof(opt)) != -1)
984: {
985: daemon->v6pktinfo = IPV6_2292PKTINFO;
986: return 1;
987: }
988: # endif
989: #else
990: if (setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &opt, sizeof(opt)) != -1)
991: return 1;
992: #endif
993:
994: return 0;
995: }
996:
997:
998: /* Find the interface on which a TCP connection arrived, if possible, or zero otherwise. */
999: int tcp_interface(int fd, int af)
1000: {
1.1.1.4 misho 1001: (void)fd; /* suppress potential unused warning */
1002: (void)af; /* suppress potential unused warning */
1.1 misho 1003: int if_index = 0;
1004:
1005: #ifdef HAVE_LINUX_NETWORK
1006: int opt = 1;
1007: struct cmsghdr *cmptr;
1008: struct msghdr msg;
1.1.1.3 misho 1009: socklen_t len;
1.1 misho 1010:
1.1.1.3 misho 1011: /* use mshdr so that the CMSDG_* macros are available */
1.1 misho 1012: msg.msg_control = daemon->packet;
1.1.1.3 misho 1013: msg.msg_controllen = len = daemon->packet_buff_sz;
1.1.1.5 ! misho 1014:
1.1 misho 1015: /* we overwrote the buffer... */
1.1.1.5 ! misho 1016: daemon->srv_save = NULL;
! 1017:
1.1 misho 1018: if (af == AF_INET)
1019: {
1020: if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) != -1 &&
1.1.1.3 misho 1021: getsockopt(fd, IPPROTO_IP, IP_PKTOPTIONS, msg.msg_control, &len) != -1)
1022: {
1023: msg.msg_controllen = len;
1024: for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
1025: if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
1026: {
1027: union {
1028: unsigned char *c;
1029: struct in_pktinfo *p;
1030: } p;
1031:
1032: p.c = CMSG_DATA(cmptr);
1033: if_index = p.p->ipi_ifindex;
1034: }
1035: }
1.1 misho 1036: }
1037: else
1038: {
1039: /* Only the RFC-2292 API has the ability to find the interface for TCP connections,
1040: it was removed in RFC-3542 !!!!
1041:
1042: Fortunately, Linux kept the 2292 ABI when it moved to 3542. The following code always
1043: uses the old ABI, and should work with pre- and post-3542 kernel headers */
1044:
1045: #ifdef IPV6_2292PKTOPTIONS
1046: # define PKTOPTIONS IPV6_2292PKTOPTIONS
1047: #else
1048: # define PKTOPTIONS IPV6_PKTOPTIONS
1049: #endif
1050:
1051: if (set_ipv6pktinfo(fd) &&
1.1.1.3 misho 1052: getsockopt(fd, IPPROTO_IPV6, PKTOPTIONS, msg.msg_control, &len) != -1)
1.1 misho 1053: {
1.1.1.3 misho 1054: msg.msg_controllen = len;
1055: for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
1.1 misho 1056: if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
1057: {
1058: union {
1059: unsigned char *c;
1060: struct in6_pktinfo *p;
1061: } p;
1062: p.c = CMSG_DATA(cmptr);
1063:
1064: if_index = p.p->ipi6_ifindex;
1065: }
1066: }
1067: }
1068: #endif /* Linux */
1069:
1070: return if_index;
1071: }
1072:
1073: static struct listener *create_listeners(union mysockaddr *addr, int do_tftp, int dienow)
1074: {
1075: struct listener *l = NULL;
1076: int fd = -1, tcpfd = -1, tftpfd = -1;
1077:
1.1.1.2 misho 1078: (void)do_tftp;
1079:
1.1 misho 1080: if (daemon->port != 0)
1081: {
1082: fd = make_sock(addr, SOCK_DGRAM, dienow);
1083: tcpfd = make_sock(addr, SOCK_STREAM, dienow);
1084: }
1085:
1086: #ifdef HAVE_TFTP
1087: if (do_tftp)
1088: {
1089: if (addr->sa.sa_family == AF_INET)
1090: {
1091: /* port must be restored to DNS port for TCP code */
1092: short save = addr->in.sin_port;
1093: addr->in.sin_port = htons(TFTP_PORT);
1094: tftpfd = make_sock(addr, SOCK_DGRAM, dienow);
1095: addr->in.sin_port = save;
1096: }
1097: else
1098: {
1099: short save = addr->in6.sin6_port;
1100: addr->in6.sin6_port = htons(TFTP_PORT);
1101: tftpfd = make_sock(addr, SOCK_DGRAM, dienow);
1102: addr->in6.sin6_port = save;
1103: }
1104: }
1105: #endif
1106:
1107: if (fd != -1 || tcpfd != -1 || tftpfd != -1)
1108: {
1109: l = safe_malloc(sizeof(struct listener));
1110: l->next = NULL;
1111: l->fd = fd;
1112: l->tcpfd = tcpfd;
1.1.1.4 misho 1113: l->tftpfd = tftpfd;
1114: l->addr = *addr;
1115: l->used = 1;
1.1.1.2 misho 1116: l->iface = NULL;
1.1 misho 1117: }
1118:
1119: return l;
1120: }
1121:
1122: void create_wildcard_listeners(void)
1123: {
1124: union mysockaddr addr;
1125: struct listener *l, *l6;
1126:
1127: memset(&addr, 0, sizeof(addr));
1128: #ifdef HAVE_SOCKADDR_SA_LEN
1129: addr.in.sin_len = sizeof(addr.in);
1130: #endif
1131: addr.in.sin_family = AF_INET;
1132: addr.in.sin_addr.s_addr = INADDR_ANY;
1133: addr.in.sin_port = htons(daemon->port);
1134:
1135: l = create_listeners(&addr, !!option_bool(OPT_TFTP), 1);
1136:
1137: memset(&addr, 0, sizeof(addr));
1.1.1.4 misho 1138: #ifdef HAVE_SOCKADDR_SA_LEN
1.1 misho 1139: addr.in6.sin6_len = sizeof(addr.in6);
1.1.1.4 misho 1140: #endif
1.1 misho 1141: addr.in6.sin6_family = AF_INET6;
1142: addr.in6.sin6_addr = in6addr_any;
1143: addr.in6.sin6_port = htons(daemon->port);
1144:
1145: l6 = create_listeners(&addr, !!option_bool(OPT_TFTP), 1);
1146: if (l)
1147: l->next = l6;
1148: else
1149: l = l6;
1150:
1151: daemon->listeners = l;
1152: }
1153:
1.1.1.4 misho 1154: static struct listener *find_listener(union mysockaddr *addr)
1155: {
1156: struct listener *l;
1157: for (l = daemon->listeners; l; l = l->next)
1158: if (sockaddr_isequal(&l->addr, addr))
1159: return l;
1160: return NULL;
1161: }
1162:
1.1 misho 1163: void create_bound_listeners(int dienow)
1164: {
1165: struct listener *new;
1166: struct irec *iface;
1167: struct iname *if_tmp;
1.1.1.4 misho 1168: struct listener *existing;
1.1 misho 1169:
1170: for (iface = daemon->interfaces; iface; iface = iface->next)
1.1.1.4 misho 1171: if (!iface->done && !iface->dad && iface->found)
1.1 misho 1172: {
1.1.1.4 misho 1173: existing = find_listener(&iface->addr);
1174: if (existing)
1175: {
1176: iface->done = 1;
1177: existing->used++; /* increase usage counter */
1178: }
1179: else if ((new = create_listeners(&iface->addr, iface->tftp_ok, dienow)))
1180: {
1181: new->iface = iface;
1182: new->next = daemon->listeners;
1183: daemon->listeners = new;
1184: iface->done = 1;
1185:
1186: /* Don't log the initial set of listen addresses created
1187: at startup, since this is happening before the logging
1188: system is initialised and the sign-on printed. */
1189: if (!dienow)
1190: {
1191: int port = prettyprint_addr(&iface->addr, daemon->addrbuff);
1.1.1.5 ! misho 1192: my_syslog(LOG_DEBUG|MS_DEBUG, _("listening on %s(#%d): %s port %d"),
1.1.1.4 misho 1193: iface->name, iface->index, daemon->addrbuff, port);
1194: }
1195: }
1.1 misho 1196: }
1197:
1198: /* Check for --listen-address options that haven't been used because there's
1199: no interface with a matching address. These may be valid: eg it's possible
1200: to listen on 127.0.1.1 even if the loopback interface is 127.0.0.1
1201:
1202: If the address isn't valid the bind() will fail and we'll die()
1203: (except in bind-dynamic mode, when we'll complain but keep trying.)
1204:
1205: The resulting listeners have the ->iface field NULL, and this has to be
1206: handled by the DNS and TFTP code. It disables --localise-queries processing
1207: (no netmask) and some MTU login the tftp code. */
1208:
1209: for (if_tmp = daemon->if_addrs; if_tmp; if_tmp = if_tmp->next)
1210: if (!if_tmp->used &&
1211: (new = create_listeners(&if_tmp->addr, !!option_bool(OPT_TFTP), dienow)))
1212: {
1213: new->next = daemon->listeners;
1214: daemon->listeners = new;
1.1.1.4 misho 1215:
1216: if (!dienow)
1217: {
1218: int port = prettyprint_addr(&if_tmp->addr, daemon->addrbuff);
1.1.1.5 ! misho 1219: my_syslog(LOG_DEBUG|MS_DEBUG, _("listening on %s port %d"), daemon->addrbuff, port);
1.1.1.4 misho 1220: }
1.1 misho 1221: }
1222: }
1223:
1.1.1.2 misho 1224: /* In --bind-interfaces, the only access control is the addresses we're listening on.
1225: There's nothing to avoid a query to the address of an internal interface arriving via
1226: an external interface where we don't want to accept queries, except that in the usual
1227: case the addresses of internal interfaces are RFC1918. When bind-interfaces in use,
1228: and we listen on an address that looks like it's probably globally routeable, shout.
1229:
1230: The fix is to use --bind-dynamic, which actually checks the arrival interface too.
1231: Tough if your platform doesn't support this.
1232:
1233: Note that checking the arrival interface is supported in the standard IPv6 API and
1234: always done, so we don't warn about any IPv6 addresses here.
1235: */
1236:
1237: void warn_bound_listeners(void)
1238: {
1239: struct irec *iface;
1240: int advice = 0;
1241:
1242: for (iface = daemon->interfaces; iface; iface = iface->next)
1243: if (!iface->dns_auth)
1244: {
1245: if (iface->addr.sa.sa_family == AF_INET)
1246: {
1247: if (!private_net(iface->addr.in.sin_addr, 1))
1248: {
1249: inet_ntop(AF_INET, &iface->addr.in.sin_addr, daemon->addrbuff, ADDRSTRLEN);
1250: iface->warned = advice = 1;
1251: my_syslog(LOG_WARNING,
1252: _("LOUD WARNING: listening on %s may accept requests via interfaces other than %s"),
1253: daemon->addrbuff, iface->name);
1254: }
1255: }
1256: }
1257:
1258: if (advice)
1259: my_syslog(LOG_WARNING, _("LOUD WARNING: use --bind-dynamic rather than --bind-interfaces to avoid DNS amplification attacks via these interface(s)"));
1260: }
1261:
1.1.1.4 misho 1262: void warn_wild_labels(void)
1263: {
1264: struct irec *iface;
1265:
1266: for (iface = daemon->interfaces; iface; iface = iface->next)
1267: if (iface->found && iface->name && iface->label)
1268: my_syslog(LOG_WARNING, _("warning: using interface %s instead"), iface->name);
1269: }
1270:
1.1.1.2 misho 1271: void warn_int_names(void)
1272: {
1273: struct interface_name *intname;
1274:
1275: for (intname = daemon->int_names; intname; intname = intname->next)
1276: if (!intname->addr)
1277: my_syslog(LOG_WARNING, _("warning: no addresses found for interface %s"), intname->intr);
1278: }
1279:
1.1 misho 1280: int is_dad_listeners(void)
1281: {
1282: struct irec *iface;
1283:
1284: if (option_bool(OPT_NOWILD))
1285: for (iface = daemon->interfaces; iface; iface = iface->next)
1286: if (iface->dad && !iface->done)
1287: return 1;
1288:
1289: return 0;
1290: }
1291:
1292: #ifdef HAVE_DHCP6
1293: void join_multicast(int dienow)
1294: {
1295: struct irec *iface, *tmp;
1296:
1297: for (iface = daemon->interfaces; iface; iface = iface->next)
1298: if (iface->addr.sa.sa_family == AF_INET6 && iface->dhcp_ok && !iface->multicast_done)
1299: {
1300: /* There's an irec per address but we only want to join for multicast
1301: once per interface. Weed out duplicates. */
1302: for (tmp = daemon->interfaces; tmp; tmp = tmp->next)
1303: if (tmp->multicast_done && tmp->index == iface->index)
1304: break;
1305:
1306: iface->multicast_done = 1;
1307:
1308: if (!tmp)
1309: {
1310: struct ipv6_mreq mreq;
1311: int err = 0;
1312:
1313: mreq.ipv6mr_interface = iface->index;
1314:
1315: inet_pton(AF_INET6, ALL_RELAY_AGENTS_AND_SERVERS, &mreq.ipv6mr_multiaddr);
1316:
1.1.1.2 misho 1317: if ((daemon->doing_dhcp6 || daemon->relay6) &&
1.1 misho 1318: setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
1.1.1.3 misho 1319: err = errno;
1.1 misho 1320:
1321: inet_pton(AF_INET6, ALL_SERVERS, &mreq.ipv6mr_multiaddr);
1322:
1323: if (daemon->doing_dhcp6 &&
1324: setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
1.1.1.3 misho 1325: err = errno;
1.1 misho 1326:
1327: inet_pton(AF_INET6, ALL_ROUTERS, &mreq.ipv6mr_multiaddr);
1328:
1329: if (daemon->doing_ra &&
1330: setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
1.1.1.3 misho 1331: err = errno;
1.1 misho 1332:
1333: if (err)
1334: {
1335: char *s = _("interface %s failed to join DHCPv6 multicast group: %s");
1.1.1.3 misho 1336: errno = err;
1337:
1338: #ifdef HAVE_LINUX_NETWORK
1339: if (errno == ENOMEM)
1340: my_syslog(LOG_ERR, _("try increasing /proc/sys/net/core/optmem_max"));
1341: #endif
1342:
1.1 misho 1343: if (dienow)
1344: die(s, iface->name, EC_BADNET);
1345: else
1346: my_syslog(LOG_ERR, s, iface->name, strerror(errno));
1347: }
1348: }
1349: }
1350: }
1351: #endif
1352:
1.1.1.4 misho 1353: int local_bind(int fd, union mysockaddr *addr, char *intname, unsigned int ifindex, int is_tcp)
1.1 misho 1354: {
1355: union mysockaddr addr_copy = *addr;
1.1.1.4 misho 1356: unsigned short port;
1.1.1.5 ! misho 1357: int tries = 1;
! 1358: unsigned short ports_avail = 1;
! 1359:
1.1.1.4 misho 1360: if (addr_copy.sa.sa_family == AF_INET)
1361: port = addr_copy.in.sin_port;
1362: else
1363: port = addr_copy.in6.sin6_port;
1.1 misho 1364:
1365: /* cannot set source _port_ for TCP connections. */
1366: if (is_tcp)
1.1.1.4 misho 1367: port = 0;
1.1.1.5 ! misho 1368: else if (port == 0 && daemon->max_port != 0)
1.1.1.4 misho 1369: {
1.1.1.5 ! misho 1370: /* Bind a random port within the range given by min-port and max-port if either
! 1371: or both are set. Otherwise use the OS's random ephemeral port allocation by
! 1372: leaving port == 0 and tries == 1 */
! 1373: ports_avail = daemon->max_port - daemon->min_port + 1;
! 1374: tries = (ports_avail < SMALL_PORT_RANGE) ? ports_avail : 100;
! 1375: port = htons(daemon->min_port + (rand16() % ports_avail));
1.1.1.4 misho 1376: }
1377:
1.1.1.5 ! misho 1378: while (1)
1.1 misho 1379: {
1.1.1.5 ! misho 1380: /* elide bind() call if it's to port 0, address 0 */
1.1 misho 1381: if (addr_copy.sa.sa_family == AF_INET)
1.1.1.5 ! misho 1382: {
! 1383: if (port == 0 && addr_copy.in.sin_addr.s_addr == 0)
! 1384: break;
! 1385: addr_copy.in.sin_port = port;
! 1386: }
1.1 misho 1387: else
1.1.1.4 misho 1388: {
1.1.1.5 ! misho 1389: if (port == 0 && IN6_IS_ADDR_UNSPECIFIED(&addr_copy.in6.sin6_addr))
! 1390: break;
! 1391: addr_copy.in6.sin6_port = port;
1.1.1.4 misho 1392: }
1393:
1.1.1.5 ! misho 1394: if (bind(fd, (struct sockaddr *)&addr_copy, sa_len(&addr_copy)) != -1)
! 1395: break;
1.1.1.4 misho 1396:
1.1.1.5 ! misho 1397: if (errno != EADDRINUSE && errno != EACCES)
! 1398: return 0;
1.1.1.4 misho 1399:
1.1.1.5 ! misho 1400: if (--tries == 0)
! 1401: return 0;
! 1402:
! 1403: /* For small ranges, do a systematic search, not a random one. */
! 1404: if (ports_avail < SMALL_PORT_RANGE)
! 1405: {
! 1406: unsigned short hport = ntohs(port);
! 1407: if (hport++ == daemon->max_port)
! 1408: hport = daemon->min_port;
! 1409: port = htons(hport);
! 1410: }
! 1411: else
! 1412: port = htons(daemon->min_port + (rand16() % ports_avail));
! 1413: }
1.1.1.4 misho 1414:
1415: if (!is_tcp && ifindex > 0)
1416: {
1417: #if defined(IP_UNICAST_IF)
1418: if (addr_copy.sa.sa_family == AF_INET)
1419: {
1420: uint32_t ifindex_opt = htonl(ifindex);
1421: return setsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex_opt, sizeof(ifindex_opt)) == 0;
1422: }
1423: #endif
1424: #if defined (IPV6_UNICAST_IF)
1425: if (addr_copy.sa.sa_family == AF_INET6)
1426: {
1427: uint32_t ifindex_opt = htonl(ifindex);
1428: return setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_IF, &ifindex_opt, sizeof(ifindex_opt)) == 0;
1429: }
1430: #endif
1431: }
1432:
1433: (void)intname; /* suppress potential unused warning */
1.1 misho 1434: #if defined(SO_BINDTODEVICE)
1435: if (intname[0] != 0 &&
1436: setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, intname, IF_NAMESIZE) == -1)
1437: return 0;
1438: #endif
1439:
1440: return 1;
1441: }
1442:
1.1.1.5 ! misho 1443: static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname, unsigned int ifindex)
1.1 misho 1444: {
1445: struct serverfd *sfd;
1446: int errsave;
1.1.1.4 misho 1447: int opt = 1;
1448:
1.1 misho 1449: /* when using random ports, servers which would otherwise use
1.1.1.5 ! misho 1450: the INADDR_ANY/port0 socket have sfd set to NULL, this is
! 1451: anything without an explictly set source port. */
! 1452: if (!daemon->osport)
1.1 misho 1453: {
1454: errno = 0;
1455:
1456: if (addr->sa.sa_family == AF_INET &&
1457: addr->in.sin_port == htons(0))
1458: return NULL;
1459:
1460: if (addr->sa.sa_family == AF_INET6 &&
1461: addr->in6.sin6_port == htons(0))
1462: return NULL;
1463: }
1.1.1.4 misho 1464:
1.1 misho 1465: /* may have a suitable one already */
1466: for (sfd = daemon->sfds; sfd; sfd = sfd->next )
1.1.1.5 ! misho 1467: if (ifindex == sfd->ifindex &&
! 1468: sockaddr_isequal(&sfd->source_addr, addr) &&
! 1469: strcmp(intname, sfd->interface) == 0)
1.1 misho 1470: return sfd;
1471:
1472: /* need to make a new one. */
1473: errno = ENOMEM; /* in case malloc fails. */
1474: if (!(sfd = whine_malloc(sizeof(struct serverfd))))
1475: return NULL;
1476:
1477: if ((sfd->fd = socket(addr->sa.sa_family, SOCK_DGRAM, 0)) == -1)
1478: {
1479: free(sfd);
1480: return NULL;
1481: }
1.1.1.4 misho 1482:
1483: if ((addr->sa.sa_family == AF_INET6 && setsockopt(sfd->fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)) == -1) ||
1484: !local_bind(sfd->fd, addr, intname, ifindex, 0) || !fix_fd(sfd->fd))
1.1 misho 1485: {
1.1.1.4 misho 1486: errsave = errno; /* save error from bind/setsockopt. */
1.1 misho 1487: close(sfd->fd);
1488: free(sfd);
1489: errno = errsave;
1490: return NULL;
1491: }
1.1.1.4 misho 1492:
1493: safe_strncpy(sfd->interface, intname, sizeof(sfd->interface));
1.1 misho 1494: sfd->source_addr = *addr;
1495: sfd->next = daemon->sfds;
1.1.1.4 misho 1496: sfd->ifindex = ifindex;
1497: sfd->preallocated = 0;
1.1 misho 1498: daemon->sfds = sfd;
1.1.1.4 misho 1499:
1.1 misho 1500: return sfd;
1501: }
1502:
1503: /* create upstream sockets during startup, before root is dropped which may be needed
1504: this allows query_port to be a low port and interface binding */
1505: void pre_allocate_sfds(void)
1506: {
1507: struct server *srv;
1.1.1.4 misho 1508: struct serverfd *sfd;
1.1 misho 1509:
1510: if (daemon->query_port != 0)
1511: {
1512: union mysockaddr addr;
1513: memset(&addr, 0, sizeof(addr));
1514: addr.in.sin_family = AF_INET;
1515: addr.in.sin_addr.s_addr = INADDR_ANY;
1516: addr.in.sin_port = htons(daemon->query_port);
1517: #ifdef HAVE_SOCKADDR_SA_LEN
1518: addr.in.sin_len = sizeof(struct sockaddr_in);
1519: #endif
1.1.1.5 ! misho 1520: if ((sfd = allocate_sfd(&addr, "", 0)))
1.1.1.4 misho 1521: sfd->preallocated = 1;
1522:
1.1 misho 1523: memset(&addr, 0, sizeof(addr));
1524: addr.in6.sin6_family = AF_INET6;
1525: addr.in6.sin6_addr = in6addr_any;
1526: addr.in6.sin6_port = htons(daemon->query_port);
1527: #ifdef HAVE_SOCKADDR_SA_LEN
1528: addr.in6.sin6_len = sizeof(struct sockaddr_in6);
1529: #endif
1.1.1.5 ! misho 1530: if ((sfd = allocate_sfd(&addr, "", 0)))
1.1.1.4 misho 1531: sfd->preallocated = 1;
1.1 misho 1532: }
1533:
1534: for (srv = daemon->servers; srv; srv = srv->next)
1.1.1.5 ! misho 1535: if (!allocate_sfd(&srv->source_addr, srv->interface, srv->ifindex) &&
1.1 misho 1536: errno != 0 &&
1537: option_bool(OPT_NOWILD))
1538: {
1.1.1.4 misho 1539: (void)prettyprint_addr(&srv->source_addr, daemon->namebuff);
1.1 misho 1540: if (srv->interface[0] != 0)
1541: {
1542: strcat(daemon->namebuff, " ");
1543: strcat(daemon->namebuff, srv->interface);
1544: }
1545: die(_("failed to bind server socket for %s: %s"),
1546: daemon->namebuff, EC_BADNET);
1547: }
1548: }
1549:
1.1.1.5 ! misho 1550: void check_servers(int no_loop_check)
1.1 misho 1551: {
1552: struct irec *iface;
1.1.1.2 misho 1553: struct server *serv;
1.1.1.4 misho 1554: struct serverfd *sfd, *tmp, **up;
1.1.1.3 misho 1555: int port = 0, count;
1.1.1.4 misho 1556: int locals = 0;
1.1.1.5 ! misho 1557:
! 1558: #ifdef HAVE_LOOP
! 1559: if (!no_loop_check)
! 1560: loop_send_probes();
! 1561: #endif
1.1 misho 1562:
1.1.1.5 ! misho 1563: /* clear all marks. */
! 1564: mark_servers(0);
! 1565:
! 1566: /* interface may be new since startup */
1.1 misho 1567: if (!option_bool(OPT_NOWILD))
1.1.1.2 misho 1568: enumerate_interfaces(0);
1.1.1.4 misho 1569:
1570: /* don't garbage collect pre-allocated sfds. */
1571: for (sfd = daemon->sfds; sfd; sfd = sfd->next)
1572: sfd->used = sfd->preallocated;
1.1.1.3 misho 1573:
1574: for (count = 0, serv = daemon->servers; serv; serv = serv->next)
1.1 misho 1575: {
1.1.1.5 ! misho 1576: /* Init edns_pktsz for newly created server records. */
! 1577: if (serv->edns_pktsz == 0)
! 1578: serv->edns_pktsz = daemon->edns_pktsz;
! 1579:
1.1.1.3 misho 1580: #ifdef HAVE_DNSSEC
1.1.1.5 ! misho 1581: if (option_bool(OPT_DNSSEC_VALID))
! 1582: {
! 1583: if (!(serv->flags & SERV_FOR_NODOTS))
! 1584: serv->flags |= SERV_DO_DNSSEC;
1.1.1.3 misho 1585:
1.1.1.5 ! misho 1586: /* Disable DNSSEC validation when using server=/domain/.... servers
! 1587: unless there's a configured trust anchor. */
! 1588: if (strlen(serv->domain) != 0)
1.1 misho 1589: {
1.1.1.5 ! misho 1590: struct ds_config *ds;
! 1591: char *domain = serv->domain;
! 1592:
! 1593: /* .example.com is valid */
! 1594: while (*domain == '.')
! 1595: domain++;
! 1596:
! 1597: for (ds = daemon->ds; ds; ds = ds->next)
! 1598: if (ds->name[0] != 0 && hostname_isequal(domain, ds->name))
! 1599: break;
! 1600:
! 1601: if (!ds)
! 1602: serv->flags &= ~SERV_DO_DNSSEC;
1.1 misho 1603: }
1604: }
1.1.1.5 ! misho 1605: #endif
1.1 misho 1606:
1.1.1.5 ! misho 1607: port = prettyprint_addr(&serv->addr, daemon->namebuff);
! 1608:
! 1609: /* 0.0.0.0 is nothing, the stack treats it like 127.0.0.1 */
! 1610: if (serv->addr.sa.sa_family == AF_INET &&
! 1611: serv->addr.in.sin_addr.s_addr == 0)
1.1 misho 1612: {
1.1.1.5 ! misho 1613: serv->flags |= SERV_MARK;
! 1614: continue;
! 1615: }
! 1616:
! 1617: for (iface = daemon->interfaces; iface; iface = iface->next)
! 1618: if (sockaddr_isequal(&serv->addr, &iface->addr))
! 1619: break;
! 1620: if (iface)
! 1621: {
! 1622: my_syslog(LOG_WARNING, _("ignoring nameserver %s - local interface"), daemon->namebuff);
! 1623: serv->flags |= SERV_MARK;
! 1624: continue;
! 1625: }
! 1626:
! 1627: /* Do we need a socket set? */
! 1628: if (!serv->sfd &&
! 1629: !(serv->sfd = allocate_sfd(&serv->source_addr, serv->interface, serv->ifindex)) &&
! 1630: errno != 0)
! 1631: {
! 1632: my_syslog(LOG_WARNING,
! 1633: _("ignoring nameserver %s - cannot make/bind socket: %s"),
! 1634: daemon->namebuff, strerror(errno));
! 1635: serv->flags |= SERV_MARK;
! 1636: continue;
! 1637: }
! 1638:
! 1639: if (serv->sfd)
! 1640: serv->sfd->used = 1;
! 1641:
! 1642: if (count == SERVERS_LOGGED)
! 1643: my_syslog(LOG_INFO, _("more servers are defined but not logged"));
! 1644:
! 1645: if (++count > SERVERS_LOGGED)
! 1646: continue;
! 1647:
! 1648: if (strlen(serv->domain) != 0 || (serv->flags & SERV_FOR_NODOTS))
! 1649: {
! 1650: char *s1, *s2, *s3 = "", *s4 = "";
! 1651:
1.1.1.3 misho 1652: #ifdef HAVE_DNSSEC
1.1.1.5 ! misho 1653: if (option_bool(OPT_DNSSEC_VALID) && !(serv->flags & SERV_DO_DNSSEC))
! 1654: s3 = _("(no DNSSEC)");
1.1.1.3 misho 1655: #endif
1.1.1.5 ! misho 1656: if (serv->flags & SERV_FOR_NODOTS)
! 1657: s1 = _("unqualified"), s2 = _("names");
! 1658: else if (strlen(serv->domain) == 0)
! 1659: s1 = _("default"), s2 = "";
1.1 misho 1660: else
1.1.1.5 ! misho 1661: s1 = _("domain"), s2 = serv->domain, s4 = (serv->flags & SERV_WILDCARD) ? "*" : "";
! 1662:
! 1663: my_syslog(LOG_INFO, _("using nameserver %s#%d for %s %s%s %s"), daemon->namebuff, port, s1, s4, s2, s3);
1.1 misho 1664: }
1.1.1.5 ! misho 1665: #ifdef HAVE_LOOP
! 1666: else if (serv->flags & SERV_LOOP)
! 1667: my_syslog(LOG_INFO, _("NOT using nameserver %s#%d - query loop detected"), daemon->namebuff, port);
! 1668: #endif
! 1669: else if (serv->interface[0] != 0)
! 1670: my_syslog(LOG_INFO, _("using nameserver %s#%d(via %s)"), daemon->namebuff, port, serv->interface);
! 1671: else
! 1672: my_syslog(LOG_INFO, _("using nameserver %s#%d"), daemon->namebuff, port);
! 1673:
! 1674: }
! 1675:
! 1676: for (count = 0, serv = daemon->local_domains; serv; serv = serv->next)
! 1677: {
! 1678: if (++count > SERVERS_LOGGED)
! 1679: continue;
! 1680:
! 1681: if ((serv->flags & SERV_LITERAL_ADDRESS) &&
! 1682: !(serv->flags & (SERV_6ADDR | SERV_4ADDR | SERV_ALL_ZEROS)) &&
! 1683: strlen(serv->domain))
! 1684: {
! 1685: count--;
! 1686: if (++locals <= LOCALS_LOGGED)
! 1687: my_syslog(LOG_INFO, _("using only locally-known addresses for %s"), serv->domain);
! 1688: }
! 1689: else if (serv->flags & SERV_USE_RESOLV)
! 1690: my_syslog(LOG_INFO, _("using standard nameservers for %s"), serv->domain);
1.1 misho 1691: }
1.1.1.3 misho 1692:
1.1.1.4 misho 1693: if (locals > LOCALS_LOGGED)
1694: my_syslog(LOG_INFO, _("using %d more local addresses"), locals - LOCALS_LOGGED);
1.1.1.3 misho 1695: if (count - 1 > SERVERS_LOGGED)
1696: my_syslog(LOG_INFO, _("using %d more nameservers"), count - SERVERS_LOGGED - 1);
1.1.1.2 misho 1697:
1.1.1.4 misho 1698: /* Remove unused sfds */
1699: for (sfd = daemon->sfds, up = &daemon->sfds; sfd; sfd = tmp)
1700: {
1701: tmp = sfd->next;
1702: if (!sfd->used)
1703: {
1704: *up = sfd->next;
1705: close(sfd->fd);
1706: free(sfd);
1707: }
1708: else
1709: up = &sfd->next;
1710: }
1711:
1.1.1.5 ! misho 1712: cleanup_servers(); /* remove servers we just deleted. */
! 1713: build_server_array();
1.1 misho 1714: }
1715:
1716: /* Return zero if no servers found, in that case we keep polling.
1717: This is a protection against an update-time/write race on resolv.conf */
1718: int reload_servers(char *fname)
1719: {
1720: FILE *f;
1721: char *line;
1722: int gotone = 0;
1723:
1724: /* buff happens to be MAXDNAME long... */
1725: if (!(f = fopen(fname, "r")))
1726: {
1727: my_syslog(LOG_ERR, _("failed to read %s: %s"), fname, strerror(errno));
1728: return 0;
1729: }
1.1.1.2 misho 1730:
1731: mark_servers(SERV_FROM_RESOLV);
1732:
1.1 misho 1733: while ((line = fgets(daemon->namebuff, MAXDNAME, f)))
1734: {
1735: union mysockaddr addr, source_addr;
1736: char *token = strtok(line, " \t\n\r");
1737:
1738: if (!token)
1739: continue;
1740: if (strcmp(token, "nameserver") != 0 && strcmp(token, "server") != 0)
1741: continue;
1742: if (!(token = strtok(NULL, " \t\n\r")))
1743: continue;
1744:
1745: memset(&addr, 0, sizeof(addr));
1746: memset(&source_addr, 0, sizeof(source_addr));
1747:
1.1.1.5 ! misho 1748: if (inet_pton(AF_INET, token, &addr.in.sin_addr) > 0)
1.1 misho 1749: {
1750: #ifdef HAVE_SOCKADDR_SA_LEN
1751: source_addr.in.sin_len = addr.in.sin_len = sizeof(source_addr.in);
1752: #endif
1753: source_addr.in.sin_family = addr.in.sin_family = AF_INET;
1754: addr.in.sin_port = htons(NAMESERVER_PORT);
1755: source_addr.in.sin_addr.s_addr = INADDR_ANY;
1756: source_addr.in.sin_port = htons(daemon->query_port);
1757: }
1758: else
1759: {
1760: int scope_index = 0;
1761: char *scope_id = strchr(token, '%');
1762:
1763: if (scope_id)
1764: {
1765: *(scope_id++) = 0;
1766: scope_index = if_nametoindex(scope_id);
1767: }
1768:
1769: if (inet_pton(AF_INET6, token, &addr.in6.sin6_addr) > 0)
1770: {
1771: #ifdef HAVE_SOCKADDR_SA_LEN
1772: source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(source_addr.in6);
1773: #endif
1774: source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6;
1775: source_addr.in6.sin6_flowinfo = addr.in6.sin6_flowinfo = 0;
1776: addr.in6.sin6_port = htons(NAMESERVER_PORT);
1777: addr.in6.sin6_scope_id = scope_index;
1778: source_addr.in6.sin6_addr = in6addr_any;
1779: source_addr.in6.sin6_port = htons(daemon->query_port);
1780: source_addr.in6.sin6_scope_id = 0;
1781: }
1782: else
1783: continue;
1784: }
1785:
1.1.1.5 ! misho 1786: add_update_server(SERV_FROM_RESOLV, &addr, &source_addr, NULL, NULL, NULL);
1.1 misho 1787: gotone = 1;
1788: }
1789:
1790: fclose(f);
1.1.1.2 misho 1791: cleanup_servers();
1.1 misho 1792:
1793: return gotone;
1794: }
1795:
1.1.1.2 misho 1796: /* Called when addresses are added or deleted from an interface */
1797: void newaddress(time_t now)
1798: {
1.1.1.5 ! misho 1799: struct dhcp_relay *relay;
! 1800:
1.1.1.2 misho 1801: (void)now;
1802:
1803: if (option_bool(OPT_CLEVERBIND) || option_bool(OPT_LOCAL_SERVICE) ||
1804: daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
1805: enumerate_interfaces(0);
1.1 misho 1806:
1.1.1.2 misho 1807: if (option_bool(OPT_CLEVERBIND))
1808: create_bound_listeners(0);
1.1.1.5 ! misho 1809:
! 1810: #ifdef HAVE_DHCP
! 1811: /* clear cache of subnet->relay index */
! 1812: for (relay = daemon->relay4; relay; relay = relay->next)
! 1813: relay->iface_index = 0;
! 1814: #endif
1.1 misho 1815:
1.1.1.2 misho 1816: #ifdef HAVE_DHCP6
1817: if (daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
1818: join_multicast(0);
1.1 misho 1819:
1.1.1.2 misho 1820: if (daemon->doing_dhcp6 || daemon->doing_ra)
1821: dhcp_construct_contexts(now);
1.1 misho 1822:
1.1.1.2 misho 1823: if (daemon->doing_dhcp6)
1824: lease_find_interfaces(now);
1.1.1.5 ! misho 1825:
! 1826: for (relay = daemon->relay6; relay; relay = relay->next)
! 1827: relay->iface_index = 0;
1.1.1.2 misho 1828: #endif
1.1 misho 1829: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>