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