2 * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2002 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: interfacemgr.c,v 1.93.70.2 2009/01/18 23:47:34 tbox Exp $ */
24 #include <isc/interfaceiter.h>
25 #include <isc/string.h>
30 #include <dns/dispatch.h>
32 #include <named/client.h>
33 #include <named/log.h>
34 #include <named/interfacemgr.h>
36 #define IFMGR_MAGIC ISC_MAGIC('I', 'F', 'M', 'G')
37 #define NS_INTERFACEMGR_VALID(t) ISC_MAGIC_VALID(t, IFMGR_MAGIC)
39 #define IFMGR_COMMON_LOGARGS \
40 ns_g_lctx, NS_LOGCATEGORY_NETWORK, NS_LOGMODULE_INTERFACEMGR
42 /*% nameserver interface manager structure */
43 struct ns_interfacemgr {
44 unsigned int magic; /*%< Magic number. */
47 isc_mem_t * mctx; /*%< Memory context. */
48 isc_taskmgr_t * taskmgr; /*%< Task manager. */
49 isc_socketmgr_t * socketmgr; /*%< Socket manager. */
50 dns_dispatchmgr_t * dispatchmgr;
51 unsigned int generation; /*%< Current generation no. */
52 ns_listenlist_t * listenon4;
53 ns_listenlist_t * listenon6;
54 dns_aclenv_t aclenv; /*%< Localhost/localnets ACLs */
55 ISC_LIST(ns_interface_t) interfaces; /*%< List of interfaces. */
56 ISC_LIST(isc_sockaddr_t) listenon;
60 purge_old_interfaces(ns_interfacemgr_t *mgr);
63 clearlistenon(ns_interfacemgr_t *mgr);
66 ns_interfacemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
67 isc_socketmgr_t *socketmgr,
68 dns_dispatchmgr_t *dispatchmgr,
69 ns_interfacemgr_t **mgrp)
72 ns_interfacemgr_t *mgr;
74 REQUIRE(mctx != NULL);
75 REQUIRE(mgrp != NULL);
76 REQUIRE(*mgrp == NULL);
78 mgr = isc_mem_get(mctx, sizeof(*mgr));
80 return (ISC_R_NOMEMORY);
82 result = isc_mutex_init(&mgr->lock);
83 if (result != ISC_R_SUCCESS)
87 mgr->taskmgr = taskmgr;
88 mgr->socketmgr = socketmgr;
89 mgr->dispatchmgr = dispatchmgr;
91 mgr->listenon4 = NULL;
92 mgr->listenon6 = NULL;
94 ISC_LIST_INIT(mgr->interfaces);
95 ISC_LIST_INIT(mgr->listenon);
98 * The listen-on lists are initially empty.
100 result = ns_listenlist_create(mctx, &mgr->listenon4);
101 if (result != ISC_R_SUCCESS)
103 ns_listenlist_attach(mgr->listenon4, &mgr->listenon6);
105 result = dns_aclenv_init(mctx, &mgr->aclenv);
106 if (result != ISC_R_SUCCESS)
107 goto cleanup_listenon;
110 mgr->magic = IFMGR_MAGIC;
112 return (ISC_R_SUCCESS);
115 ns_listenlist_detach(&mgr->listenon4);
116 ns_listenlist_detach(&mgr->listenon6);
118 isc_mem_put(mctx, mgr, sizeof(*mgr));
123 ns_interfacemgr_destroy(ns_interfacemgr_t *mgr) {
124 REQUIRE(NS_INTERFACEMGR_VALID(mgr));
125 dns_aclenv_destroy(&mgr->aclenv);
126 ns_listenlist_detach(&mgr->listenon4);
127 ns_listenlist_detach(&mgr->listenon6);
129 DESTROYLOCK(&mgr->lock);
131 isc_mem_put(mgr->mctx, mgr, sizeof(*mgr));
135 ns_interfacemgr_getaclenv(ns_interfacemgr_t *mgr) {
136 return (&mgr->aclenv);
140 ns_interfacemgr_attach(ns_interfacemgr_t *source, ns_interfacemgr_t **target) {
141 REQUIRE(NS_INTERFACEMGR_VALID(source));
143 INSIST(source->references > 0);
144 source->references++;
145 UNLOCK(&source->lock);
150 ns_interfacemgr_detach(ns_interfacemgr_t **targetp) {
151 isc_result_t need_destroy = ISC_FALSE;
152 ns_interfacemgr_t *target = *targetp;
153 REQUIRE(target != NULL);
154 REQUIRE(NS_INTERFACEMGR_VALID(target));
156 REQUIRE(target->references > 0);
157 target->references--;
158 if (target->references == 0)
159 need_destroy = ISC_TRUE;
160 UNLOCK(&target->lock);
162 ns_interfacemgr_destroy(target);
167 ns_interfacemgr_shutdown(ns_interfacemgr_t *mgr) {
168 REQUIRE(NS_INTERFACEMGR_VALID(mgr));
171 * Shut down and detach all interfaces.
172 * By incrementing the generation count, we make purge_old_interfaces()
173 * consider all interfaces "old".
176 purge_old_interfaces(mgr);
181 ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
182 const char *name, ns_interface_t **ifpret)
187 REQUIRE(NS_INTERFACEMGR_VALID(mgr));
188 ifp = isc_mem_get(mgr->mctx, sizeof(*ifp));
190 return (ISC_R_NOMEMORY);
192 ifp->generation = mgr->generation;
195 strncpy(ifp->name, name, sizeof(ifp->name));
196 ifp->name[sizeof(ifp->name)-1] = '\0';
197 ifp->clientmgr = NULL;
199 result = isc_mutex_init(&ifp->lock);
200 if (result != ISC_R_SUCCESS)
201 goto lock_create_failure;
203 result = ns_clientmgr_create(mgr->mctx, mgr->taskmgr,
206 if (result != ISC_R_SUCCESS) {
207 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
208 "ns_clientmgr_create() failed: %s",
209 isc_result_totext(result));
210 goto clientmgr_create_failure;
213 ifp->udpdispatch = NULL;
215 ifp->tcpsocket = NULL;
217 * Create a single TCP client object. It will replace itself
218 * with a new one as soon as it gets a connection, so the actual
219 * connections will be handled in parallel even though there is
220 * only one client initially.
223 ifp->ntcpcurrent = 0;
225 ISC_LINK_INIT(ifp, link);
227 ns_interfacemgr_attach(mgr, &ifp->mgr);
228 ISC_LIST_APPEND(mgr->interfaces, ifp, link);
231 ifp->magic = IFACE_MAGIC;
234 return (ISC_R_SUCCESS);
236 clientmgr_create_failure:
237 DESTROYLOCK(&ifp->lock);
240 isc_mem_put(mgr->mctx, ifp, sizeof(*ifp));
242 return (ISC_R_UNEXPECTED);
246 ns_interface_listenudp(ns_interface_t *ifp) {
249 unsigned int attrmask;
252 attrs |= DNS_DISPATCHATTR_UDP;
253 if (isc_sockaddr_pf(&ifp->addr) == AF_INET)
254 attrs |= DNS_DISPATCHATTR_IPV4;
256 attrs |= DNS_DISPATCHATTR_IPV6;
257 attrs |= DNS_DISPATCHATTR_NOLISTEN;
259 attrmask |= DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_TCP;
260 attrmask |= DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_IPV6;
261 result = dns_dispatch_getudp(ifp->mgr->dispatchmgr, ns_g_socketmgr,
262 ns_g_taskmgr, &ifp->addr,
263 4096, 1000, 32768, 8219, 8237,
264 attrs, attrmask, &ifp->udpdispatch);
265 if (result != ISC_R_SUCCESS) {
266 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
267 "could not listen on UDP socket: %s",
268 isc_result_totext(result));
269 goto udp_dispatch_failure;
272 result = ns_clientmgr_createclients(ifp->clientmgr, ns_g_cpus,
274 if (result != ISC_R_SUCCESS) {
275 UNEXPECTED_ERROR(__FILE__, __LINE__,
276 "UDP ns_clientmgr_createclients(): %s",
277 isc_result_totext(result));
278 goto addtodispatch_failure;
280 return (ISC_R_SUCCESS);
282 addtodispatch_failure:
283 dns_dispatch_changeattributes(ifp->udpdispatch, 0,
284 DNS_DISPATCHATTR_NOLISTEN);
285 dns_dispatch_detach(&ifp->udpdispatch);
286 udp_dispatch_failure:
291 ns_interface_accepttcp(ns_interface_t *ifp) {
297 result = isc_socket_create(ifp->mgr->socketmgr,
298 isc_sockaddr_pf(&ifp->addr),
301 if (result != ISC_R_SUCCESS) {
302 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
303 "creating TCP socket: %s",
304 isc_result_totext(result));
305 goto tcp_socket_failure;
307 isc_socket_setname(ifp->tcpsocket, "dispatcher", NULL);
308 #ifndef ISC_ALLOW_MAPPED
309 isc_socket_ipv6only(ifp->tcpsocket, ISC_TRUE);
311 result = isc_socket_bind(ifp->tcpsocket, &ifp->addr,
312 ISC_SOCKET_REUSEADDRESS);
313 if (result != ISC_R_SUCCESS) {
314 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
315 "binding TCP socket: %s",
316 isc_result_totext(result));
317 goto tcp_bind_failure;
319 result = isc_socket_listen(ifp->tcpsocket, ns_g_listen);
320 if (result != ISC_R_SUCCESS) {
321 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
322 "listening on TCP socket: %s",
323 isc_result_totext(result));
324 goto tcp_listen_failure;
328 * If/when there a multiple filters listen to the
331 (void)isc_socket_filter(ifp->tcpsocket, "dataready");
333 result = ns_clientmgr_createclients(ifp->clientmgr,
334 ifp->ntcptarget, ifp,
336 if (result != ISC_R_SUCCESS) {
337 UNEXPECTED_ERROR(__FILE__, __LINE__,
338 "TCP ns_clientmgr_createclients(): %s",
339 isc_result_totext(result));
340 goto accepttcp_failure;
342 return (ISC_R_SUCCESS);
347 isc_socket_detach(&ifp->tcpsocket);
349 return (ISC_R_SUCCESS);
353 ns_interface_setup(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
354 const char *name, ns_interface_t **ifpret,
355 isc_boolean_t accept_tcp)
358 ns_interface_t *ifp = NULL;
359 REQUIRE(ifpret != NULL && *ifpret == NULL);
361 result = ns_interface_create(mgr, addr, name, &ifp);
362 if (result != ISC_R_SUCCESS)
365 result = ns_interface_listenudp(ifp);
366 if (result != ISC_R_SUCCESS)
367 goto cleanup_interface;
369 if (accept_tcp == ISC_TRUE) {
370 result = ns_interface_accepttcp(ifp);
371 if (result != ISC_R_SUCCESS) {
373 * XXXRTH We don't currently have a way to easily stop
374 * dispatch service, so we currently return
375 * ISC_R_SUCCESS (the UDP stuff will work even if TCP
376 * creation failed). This will be fixed later.
378 result = ISC_R_SUCCESS;
382 return (ISC_R_SUCCESS);
385 ISC_LIST_UNLINK(ifp->mgr->interfaces, ifp, link);
386 ns_interface_detach(&ifp);
391 ns_interface_shutdown(ns_interface_t *ifp) {
392 if (ifp->clientmgr != NULL)
393 ns_clientmgr_destroy(&ifp->clientmgr);
397 ns_interface_destroy(ns_interface_t *ifp) {
398 isc_mem_t *mctx = ifp->mgr->mctx;
399 REQUIRE(NS_INTERFACE_VALID(ifp));
401 ns_interface_shutdown(ifp);
403 if (ifp->udpdispatch != NULL) {
404 dns_dispatch_changeattributes(ifp->udpdispatch, 0,
405 DNS_DISPATCHATTR_NOLISTEN);
406 dns_dispatch_detach(&ifp->udpdispatch);
408 if (ifp->tcpsocket != NULL)
409 isc_socket_detach(&ifp->tcpsocket);
411 DESTROYLOCK(&ifp->lock);
413 ns_interfacemgr_detach(&ifp->mgr);
416 isc_mem_put(mctx, ifp, sizeof(*ifp));
420 ns_interface_attach(ns_interface_t *source, ns_interface_t **target) {
421 REQUIRE(NS_INTERFACE_VALID(source));
423 INSIST(source->references > 0);
424 source->references++;
425 UNLOCK(&source->lock);
430 ns_interface_detach(ns_interface_t **targetp) {
431 isc_result_t need_destroy = ISC_FALSE;
432 ns_interface_t *target = *targetp;
433 REQUIRE(target != NULL);
434 REQUIRE(NS_INTERFACE_VALID(target));
436 REQUIRE(target->references > 0);
437 target->references--;
438 if (target->references == 0)
439 need_destroy = ISC_TRUE;
440 UNLOCK(&target->lock);
442 ns_interface_destroy(target);
447 * Search the interface list for an interface whose address and port
448 * both match those of 'addr'. Return a pointer to it, or NULL if not found.
450 static ns_interface_t *
451 find_matching_interface(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr) {
453 for (ifp = ISC_LIST_HEAD(mgr->interfaces); ifp != NULL;
454 ifp = ISC_LIST_NEXT(ifp, link)) {
455 if (isc_sockaddr_equal(&ifp->addr, addr))
462 * Remove any interfaces whose generation number is not the current one.
465 purge_old_interfaces(ns_interfacemgr_t *mgr) {
466 ns_interface_t *ifp, *next;
467 for (ifp = ISC_LIST_HEAD(mgr->interfaces); ifp != NULL; ifp = next) {
468 INSIST(NS_INTERFACE_VALID(ifp));
469 next = ISC_LIST_NEXT(ifp, link);
470 if (ifp->generation != mgr->generation) {
472 ISC_LIST_UNLINK(ifp->mgr->interfaces, ifp, link);
473 isc_sockaddr_format(&ifp->addr, sabuf, sizeof(sabuf));
474 isc_log_write(IFMGR_COMMON_LOGARGS,
476 "no longer listening on %s", sabuf);
477 ns_interface_shutdown(ifp);
478 ns_interface_detach(&ifp);
484 clearacl(isc_mem_t *mctx, dns_acl_t **aclp) {
485 dns_acl_t *newacl = NULL;
487 result = dns_acl_create(mctx, 0, &newacl);
488 if (result != ISC_R_SUCCESS)
490 dns_acl_detach(aclp);
491 dns_acl_attach(newacl, aclp);
492 dns_acl_detach(&newacl);
493 return (ISC_R_SUCCESS);
497 listenon_is_ip6_any(ns_listenelt_t *elt) {
498 REQUIRE(elt && elt->acl);
499 return dns_acl_isany(elt->acl);
503 setup_locals(ns_interfacemgr_t *mgr, isc_interface_t *interface) {
505 unsigned int prefixlen;
506 isc_netaddr_t *netaddr;
508 netaddr = &interface->address;
510 /* First add localhost address */
511 prefixlen = (netaddr->family == AF_INET) ? 32 : 128;
512 result = dns_iptable_addprefix(mgr->aclenv.localhost->iptable,
513 netaddr, prefixlen, ISC_TRUE);
514 if (result != ISC_R_SUCCESS)
517 /* Then add localnets prefix */
518 result = isc_netaddr_masktoprefixlen(&interface->netmask,
521 /* Non contiguous netmasks not allowed by IPv6 arch. */
522 if (result != ISC_R_SUCCESS && netaddr->family == AF_INET6)
525 if (result != ISC_R_SUCCESS) {
526 isc_log_write(IFMGR_COMMON_LOGARGS,
528 "omitting IPv4 interface %s from "
531 isc_result_totext(result));
532 return (ISC_R_SUCCESS);
535 result = dns_iptable_addprefix(mgr->aclenv.localnets->iptable,
536 netaddr, prefixlen, ISC_TRUE);
537 if (result != ISC_R_SUCCESS)
540 return (ISC_R_SUCCESS);
544 setup_listenon(ns_interfacemgr_t *mgr, isc_interface_t *interface,
547 isc_sockaddr_t *addr;
550 addr = isc_mem_get(mgr->mctx, sizeof(*addr));
554 isc_sockaddr_fromnetaddr(addr, &interface->address, port);
556 for (old = ISC_LIST_HEAD(mgr->listenon);
558 old = ISC_LIST_NEXT(old, link))
559 if (isc_sockaddr_equal(addr, old))
563 isc_mem_put(mgr->mctx, addr, sizeof(*addr));
565 ISC_LIST_APPEND(mgr->listenon, addr, link);
569 clearlistenon(ns_interfacemgr_t *mgr) {
572 old = ISC_LIST_HEAD(mgr->listenon);
573 while (old != NULL) {
574 ISC_LIST_UNLINK(mgr->listenon, old, link);
575 isc_mem_put(mgr->mctx, old, sizeof(*old));
576 old = ISC_LIST_HEAD(mgr->listenon);
581 do_scan(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen,
582 isc_boolean_t verbose)
584 isc_interfaceiter_t *iter = NULL;
585 isc_boolean_t scan_ipv4 = ISC_FALSE;
586 isc_boolean_t scan_ipv6 = ISC_FALSE;
587 isc_boolean_t adjusting = ISC_FALSE;
588 isc_boolean_t ipv6only = ISC_TRUE;
589 isc_boolean_t ipv6pktinfo = ISC_TRUE;
591 isc_netaddr_t zero_address, zero_address6;
593 isc_sockaddr_t listen_addr;
595 isc_boolean_t log_explicit = ISC_FALSE;
596 isc_boolean_t dolistenon;
598 if (ext_listen != NULL)
599 adjusting = ISC_TRUE;
601 if (isc_net_probeipv6() == ISC_R_SUCCESS)
602 scan_ipv6 = ISC_TRUE;
605 isc_log_write(IFMGR_COMMON_LOGARGS,
606 verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1),
607 "no IPv6 interfaces found");
610 if (isc_net_probeipv4() == ISC_R_SUCCESS)
611 scan_ipv4 = ISC_TRUE;
613 isc_log_write(IFMGR_COMMON_LOGARGS,
614 verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1),
615 "no IPv4 interfaces found");
618 * A special, but typical case; listen-on-v6 { any; }.
619 * When we can make the socket IPv6-only, open a single wildcard
620 * socket for IPv6 communication. Otherwise, make separate socket
621 * for each IPv6 address in order to avoid accepting IPv4 packets
622 * as the form of mapped addresses unintentionally unless explicitly
625 #ifndef ISC_ALLOW_MAPPED
626 if (scan_ipv6 == ISC_TRUE &&
627 isc_net_probe_ipv6only() != ISC_R_SUCCESS) {
628 ipv6only = ISC_FALSE;
629 log_explicit = ISC_TRUE;
632 if (scan_ipv6 == ISC_TRUE &&
633 isc_net_probe_ipv6pktinfo() != ISC_R_SUCCESS) {
634 ipv6pktinfo = ISC_FALSE;
635 log_explicit = ISC_TRUE;
637 if (scan_ipv6 == ISC_TRUE && ipv6only && ipv6pktinfo) {
638 for (le = ISC_LIST_HEAD(mgr->listenon6->elts);
640 le = ISC_LIST_NEXT(le, link)) {
641 struct in6_addr in6a;
643 if (!listenon_is_ip6_any(le))
647 isc_sockaddr_fromin6(&listen_addr, &in6a, le->port);
649 ifp = find_matching_interface(mgr, &listen_addr);
651 ifp->generation = mgr->generation;
653 isc_log_write(IFMGR_COMMON_LOGARGS,
656 "interfaces, port %u",
658 result = ns_interface_setup(mgr, &listen_addr,
661 if (result == ISC_R_SUCCESS)
662 ifp->flags |= NS_INTERFACEFLAG_ANYADDR;
664 isc_log_write(IFMGR_COMMON_LOGARGS,
666 "listening on all IPv6 "
667 "interfaces failed");
673 isc_netaddr_any(&zero_address);
674 isc_netaddr_any6(&zero_address6);
676 result = isc_interfaceiter_create(mgr->mctx, &iter);
677 if (result != ISC_R_SUCCESS)
680 if (adjusting == ISC_FALSE) {
681 result = clearacl(mgr->mctx, &mgr->aclenv.localhost);
682 if (result != ISC_R_SUCCESS)
684 result = clearacl(mgr->mctx, &mgr->aclenv.localnets);
685 if (result != ISC_R_SUCCESS)
690 for (result = isc_interfaceiter_first(iter);
691 result == ISC_R_SUCCESS;
692 result = isc_interfaceiter_next(iter))
694 isc_interface_t interface;
698 result = isc_interfaceiter_current(iter, &interface);
699 if (result != ISC_R_SUCCESS)
702 family = interface.address.family;
703 if (family != AF_INET && family != AF_INET6)
705 if (scan_ipv4 == ISC_FALSE && family == AF_INET)
707 if (scan_ipv6 == ISC_FALSE && family == AF_INET6)
711 * Test for the address being nonzero rather than testing
712 * INTERFACE_F_UP, because on some systems the latter
713 * follows the media state and we could end up ignoring
714 * the interface for an entire rescan interval due to
715 * a temporary media glitch at rescan time.
717 if (family == AF_INET &&
718 isc_netaddr_equal(&interface.address, &zero_address)) {
721 if (family == AF_INET6 &&
722 isc_netaddr_equal(&interface.address, &zero_address6)) {
726 if (adjusting == ISC_FALSE) {
727 result = setup_locals(mgr, &interface);
728 if (result != ISC_R_SUCCESS)
729 goto ignore_interface;
732 ll = (family == AF_INET) ? mgr->listenon4 : mgr->listenon6;
733 dolistenon = ISC_TRUE;
734 for (le = ISC_LIST_HEAD(ll->elts);
736 le = ISC_LIST_NEXT(le, link))
739 isc_boolean_t ipv6_wildcard = ISC_FALSE;
740 isc_netaddr_t listen_netaddr;
741 isc_sockaddr_t listen_sockaddr;
744 * Construct a socket address for this IP/port
747 if (family == AF_INET) {
748 isc_netaddr_fromin(&listen_netaddr,
749 &interface.address.type.in);
751 isc_netaddr_fromin6(&listen_netaddr,
752 &interface.address.type.in6);
753 isc_netaddr_setzone(&listen_netaddr,
754 interface.address.zone);
756 isc_sockaddr_fromnetaddr(&listen_sockaddr,
761 * See if the address matches the listen-on statement;
762 * if not, ignore the interface.
764 (void)dns_acl_match(&listen_netaddr, NULL, le->acl,
765 &mgr->aclenv, &match, NULL);
769 if (adjusting == ISC_FALSE && dolistenon == ISC_TRUE) {
770 setup_listenon(mgr, &interface, le->port);
771 dolistenon = ISC_FALSE;
775 * The case of "any" IPv6 address will require
776 * special considerations later, so remember it.
778 if (family == AF_INET6 && ipv6only && ipv6pktinfo &&
779 listenon_is_ip6_any(le))
780 ipv6_wildcard = ISC_TRUE;
783 * When adjusting interfaces with extra a listening
784 * list, see if the address matches the extra list.
785 * If it does, and is also covered by a wildcard
786 * interface, we need to listen on the address
789 if (adjusting == ISC_TRUE) {
793 for (ele = ISC_LIST_HEAD(ext_listen->elts);
795 ele = ISC_LIST_NEXT(ele, link)) {
796 (void)dns_acl_match(&listen_netaddr,
800 (ele->port == le->port ||
806 if (ipv6_wildcard == ISC_TRUE && match == 0)
810 ifp = find_matching_interface(mgr, &listen_sockaddr);
812 ifp->generation = mgr->generation;
814 char sabuf[ISC_SOCKADDR_FORMATSIZE];
816 if (adjusting == ISC_FALSE &&
817 ipv6_wildcard == ISC_TRUE)
820 if (log_explicit && family == AF_INET6 &&
821 !adjusting && listenon_is_ip6_any(le)) {
822 isc_log_write(IFMGR_COMMON_LOGARGS,
823 verbose ? ISC_LOG_INFO :
825 "IPv6 socket API is "
826 "incomplete; explicitly "
827 "binding to each IPv6 "
828 "address separately");
829 log_explicit = ISC_FALSE;
831 isc_sockaddr_format(&listen_sockaddr,
832 sabuf, sizeof(sabuf));
833 isc_log_write(IFMGR_COMMON_LOGARGS,
836 "listening on %s interface "
838 (adjusting == ISC_TRUE) ?
839 "additionally " : "",
840 (family == AF_INET) ?
842 interface.name, sabuf);
844 result = ns_interface_setup(mgr,
848 (adjusting == ISC_TRUE) ?
852 if (result != ISC_R_SUCCESS) {
853 isc_log_write(IFMGR_COMMON_LOGARGS,
855 "creating %s interface "
856 "%s failed; interface "
858 (family == AF_INET) ?
869 isc_log_write(IFMGR_COMMON_LOGARGS,
871 "ignoring %s interface %s: %s",
872 (family == AF_INET) ? "IPv4" : "IPv6",
873 interface.name, isc_result_totext(result));
876 if (result != ISC_R_NOMORE)
877 UNEXPECTED_ERROR(__FILE__, __LINE__,
878 "interface iteration failed: %s",
879 isc_result_totext(result));
881 result = ISC_R_SUCCESS;
883 isc_interfaceiter_destroy(&iter);
888 ns_interfacemgr_scan0(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen,
889 isc_boolean_t verbose)
891 isc_boolean_t purge = ISC_TRUE;
893 REQUIRE(NS_INTERFACEMGR_VALID(mgr));
895 mgr->generation++; /* Increment the generation count. */
897 if (do_scan(mgr, ext_listen, verbose) != ISC_R_SUCCESS)
901 * Now go through the interface list and delete anything that
902 * does not have the current generation number. This is
903 * how we catch interfaces that go away or change their
907 purge_old_interfaces(mgr);
910 * Warn if we are not listening on any interface, unless
911 * we're in lwresd-only mode, in which case that is to
914 if (ext_listen == NULL &&
915 ISC_LIST_EMPTY(mgr->interfaces) && ! ns_g_lwresdonly) {
916 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING,
917 "not listening on any interfaces");
922 ns_interfacemgr_scan(ns_interfacemgr_t *mgr, isc_boolean_t verbose) {
923 ns_interfacemgr_scan0(mgr, NULL, verbose);
927 ns_interfacemgr_adjust(ns_interfacemgr_t *mgr, ns_listenlist_t *list,
928 isc_boolean_t verbose)
930 ns_interfacemgr_scan0(mgr, list, verbose);
934 ns_interfacemgr_setlistenon4(ns_interfacemgr_t *mgr, ns_listenlist_t *value) {
936 ns_listenlist_detach(&mgr->listenon4);
937 ns_listenlist_attach(value, &mgr->listenon4);
942 ns_interfacemgr_setlistenon6(ns_interfacemgr_t *mgr, ns_listenlist_t *value) {
944 ns_listenlist_detach(&mgr->listenon6);
945 ns_listenlist_attach(value, &mgr->listenon6);
950 ns_interfacemgr_dumprecursing(FILE *f, ns_interfacemgr_t *mgr) {
951 ns_interface_t *interface;
954 interface = ISC_LIST_HEAD(mgr->interfaces);
955 while (interface != NULL) {
956 if (interface->clientmgr != NULL)
957 ns_client_dumprecursing(f, interface->clientmgr);
958 interface = ISC_LIST_NEXT(interface, link);
964 ns_interfacemgr_listeningon(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr) {
967 old = ISC_LIST_HEAD(mgr->listenon);
968 for (old = ISC_LIST_HEAD(mgr->listenon);
970 old = ISC_LIST_NEXT(old, link))
971 if (isc_sockaddr_equal(old, addr))