2 * Copyright (C) 2004-2006, 2008 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.76.18.11 2008/07/23 23:33:02 marka 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 #ifndef ISC_ALLOW_MAPPED
308 isc_socket_ipv6only(ifp->tcpsocket, ISC_TRUE);
310 result = isc_socket_bind(ifp->tcpsocket, &ifp->addr,
311 ISC_SOCKET_REUSEADDRESS);
312 if (result != ISC_R_SUCCESS) {
313 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
314 "binding TCP socket: %s",
315 isc_result_totext(result));
316 goto tcp_bind_failure;
318 result = isc_socket_listen(ifp->tcpsocket, ns_g_listen);
319 if (result != ISC_R_SUCCESS) {
320 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
321 "listening on TCP socket: %s",
322 isc_result_totext(result));
323 goto tcp_listen_failure;
327 * If/when there a multiple filters listen to the
330 (void)isc_socket_filter(ifp->tcpsocket, "dataready");
332 result = ns_clientmgr_createclients(ifp->clientmgr,
333 ifp->ntcptarget, ifp,
335 if (result != ISC_R_SUCCESS) {
336 UNEXPECTED_ERROR(__FILE__, __LINE__,
337 "TCP ns_clientmgr_createclients(): %s",
338 isc_result_totext(result));
339 goto accepttcp_failure;
341 return (ISC_R_SUCCESS);
346 isc_socket_detach(&ifp->tcpsocket);
348 return (ISC_R_SUCCESS);
352 ns_interface_setup(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
353 const char *name, ns_interface_t **ifpret,
354 isc_boolean_t accept_tcp)
357 ns_interface_t *ifp = NULL;
358 REQUIRE(ifpret != NULL && *ifpret == NULL);
360 result = ns_interface_create(mgr, addr, name, &ifp);
361 if (result != ISC_R_SUCCESS)
364 result = ns_interface_listenudp(ifp);
365 if (result != ISC_R_SUCCESS)
366 goto cleanup_interface;
368 if (accept_tcp == ISC_TRUE) {
369 result = ns_interface_accepttcp(ifp);
370 if (result != ISC_R_SUCCESS) {
372 * XXXRTH We don't currently have a way to easily stop
373 * dispatch service, so we currently return
374 * ISC_R_SUCCESS (the UDP stuff will work even if TCP
375 * creation failed). This will be fixed later.
377 result = ISC_R_SUCCESS;
381 return (ISC_R_SUCCESS);
384 ISC_LIST_UNLINK(ifp->mgr->interfaces, ifp, link);
385 ns_interface_detach(&ifp);
390 ns_interface_shutdown(ns_interface_t *ifp) {
391 if (ifp->clientmgr != NULL)
392 ns_clientmgr_destroy(&ifp->clientmgr);
396 ns_interface_destroy(ns_interface_t *ifp) {
397 isc_mem_t *mctx = ifp->mgr->mctx;
398 REQUIRE(NS_INTERFACE_VALID(ifp));
400 ns_interface_shutdown(ifp);
402 if (ifp->udpdispatch != NULL) {
403 dns_dispatch_changeattributes(ifp->udpdispatch, 0,
404 DNS_DISPATCHATTR_NOLISTEN);
405 dns_dispatch_detach(&ifp->udpdispatch);
407 if (ifp->tcpsocket != NULL)
408 isc_socket_detach(&ifp->tcpsocket);
410 DESTROYLOCK(&ifp->lock);
412 ns_interfacemgr_detach(&ifp->mgr);
415 isc_mem_put(mctx, ifp, sizeof(*ifp));
419 ns_interface_attach(ns_interface_t *source, ns_interface_t **target) {
420 REQUIRE(NS_INTERFACE_VALID(source));
422 INSIST(source->references > 0);
423 source->references++;
424 UNLOCK(&source->lock);
429 ns_interface_detach(ns_interface_t **targetp) {
430 isc_result_t need_destroy = ISC_FALSE;
431 ns_interface_t *target = *targetp;
432 REQUIRE(target != NULL);
433 REQUIRE(NS_INTERFACE_VALID(target));
435 REQUIRE(target->references > 0);
436 target->references--;
437 if (target->references == 0)
438 need_destroy = ISC_TRUE;
439 UNLOCK(&target->lock);
441 ns_interface_destroy(target);
446 * Search the interface list for an interface whose address and port
447 * both match those of 'addr'. Return a pointer to it, or NULL if not found.
449 static ns_interface_t *
450 find_matching_interface(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr) {
452 for (ifp = ISC_LIST_HEAD(mgr->interfaces); ifp != NULL;
453 ifp = ISC_LIST_NEXT(ifp, link)) {
454 if (isc_sockaddr_equal(&ifp->addr, addr))
461 * Remove any interfaces whose generation number is not the current one.
464 purge_old_interfaces(ns_interfacemgr_t *mgr) {
465 ns_interface_t *ifp, *next;
466 for (ifp = ISC_LIST_HEAD(mgr->interfaces); ifp != NULL; ifp = next) {
467 INSIST(NS_INTERFACE_VALID(ifp));
468 next = ISC_LIST_NEXT(ifp, link);
469 if (ifp->generation != mgr->generation) {
471 ISC_LIST_UNLINK(ifp->mgr->interfaces, ifp, link);
472 isc_sockaddr_format(&ifp->addr, sabuf, sizeof(sabuf));
473 isc_log_write(IFMGR_COMMON_LOGARGS,
475 "no longer listening on %s", sabuf);
476 ns_interface_shutdown(ifp);
477 ns_interface_detach(&ifp);
483 clearacl(isc_mem_t *mctx, dns_acl_t **aclp) {
484 dns_acl_t *newacl = NULL;
486 result = dns_acl_create(mctx, 10, &newacl);
487 if (result != ISC_R_SUCCESS)
489 dns_acl_detach(aclp);
490 dns_acl_attach(newacl, aclp);
491 dns_acl_detach(&newacl);
492 return (ISC_R_SUCCESS);
496 listenon_is_ip6_any(ns_listenelt_t *elt) {
497 if (elt->acl->length != 1)
499 if (elt->acl->elements[0].negative == ISC_FALSE &&
500 elt->acl->elements[0].type == dns_aclelementtype_any)
501 return (ISC_TRUE); /* listen-on-v6 { any; } */
502 return (ISC_FALSE); /* All others */
506 setup_locals(ns_interfacemgr_t *mgr, isc_interface_t *interface) {
508 dns_aclelement_t elt;
510 unsigned int prefixlen;
512 family = interface->address.family;
514 elt.type = dns_aclelementtype_ipprefix;
515 elt.negative = ISC_FALSE;
516 elt.u.ip_prefix.address = interface->address;
517 elt.u.ip_prefix.prefixlen = (family == AF_INET) ? 32 : 128;
518 result = dns_acl_appendelement(mgr->aclenv.localhost, &elt);
519 if (result != ISC_R_SUCCESS)
522 result = isc_netaddr_masktoprefixlen(&interface->netmask,
525 /* Non contigious netmasks not allowed by IPv6 arch. */
526 if (result != ISC_R_SUCCESS && family == AF_INET6)
529 if (result != ISC_R_SUCCESS) {
530 isc_log_write(IFMGR_COMMON_LOGARGS,
532 "omitting IPv4 interface %s from "
535 isc_result_totext(result));
537 elt.u.ip_prefix.prefixlen = prefixlen;
538 if (dns_acl_elementmatch(mgr->aclenv.localnets, &elt,
539 NULL) == ISC_R_NOTFOUND) {
540 result = dns_acl_appendelement(mgr->aclenv.localnets,
542 if (result != ISC_R_SUCCESS)
547 return (ISC_R_SUCCESS);
551 setup_listenon(ns_interfacemgr_t *mgr, isc_interface_t *interface,
554 isc_sockaddr_t *addr;
557 addr = isc_mem_get(mgr->mctx, sizeof(*addr));
561 isc_sockaddr_fromnetaddr(addr, &interface->address, port);
563 for (old = ISC_LIST_HEAD(mgr->listenon);
565 old = ISC_LIST_NEXT(old, link))
566 if (isc_sockaddr_equal(addr, old))
570 isc_mem_put(mgr->mctx, addr, sizeof(*addr));
572 ISC_LIST_APPEND(mgr->listenon, addr, link);
576 clearlistenon(ns_interfacemgr_t *mgr) {
579 old = ISC_LIST_HEAD(mgr->listenon);
580 while (old != NULL) {
581 ISC_LIST_UNLINK(mgr->listenon, old, link);
582 isc_mem_put(mgr->mctx, old, sizeof(*old));
583 old = ISC_LIST_HEAD(mgr->listenon);
588 do_scan(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen,
589 isc_boolean_t verbose)
591 isc_interfaceiter_t *iter = NULL;
592 isc_boolean_t scan_ipv4 = ISC_FALSE;
593 isc_boolean_t scan_ipv6 = ISC_FALSE;
594 isc_boolean_t adjusting = ISC_FALSE;
595 isc_boolean_t ipv6only = ISC_TRUE;
596 isc_boolean_t ipv6pktinfo = ISC_TRUE;
598 isc_netaddr_t zero_address, zero_address6;
600 isc_sockaddr_t listen_addr;
602 isc_boolean_t log_explicit = ISC_FALSE;
603 isc_boolean_t dolistenon;
605 if (ext_listen != NULL)
606 adjusting = ISC_TRUE;
608 if (isc_net_probeipv6() == ISC_R_SUCCESS)
609 scan_ipv6 = ISC_TRUE;
612 isc_log_write(IFMGR_COMMON_LOGARGS,
613 verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1),
614 "no IPv6 interfaces found");
617 if (isc_net_probeipv4() == ISC_R_SUCCESS)
618 scan_ipv4 = ISC_TRUE;
620 isc_log_write(IFMGR_COMMON_LOGARGS,
621 verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1),
622 "no IPv4 interfaces found");
625 * A special, but typical case; listen-on-v6 { any; }.
626 * When we can make the socket IPv6-only, open a single wildcard
627 * socket for IPv6 communication. Otherwise, make separate socket
628 * for each IPv6 address in order to avoid accepting IPv4 packets
629 * as the form of mapped addresses unintentionally unless explicitly
632 #ifndef ISC_ALLOW_MAPPED
633 if (scan_ipv6 == ISC_TRUE &&
634 isc_net_probe_ipv6only() != ISC_R_SUCCESS) {
635 ipv6only = ISC_FALSE;
636 log_explicit = ISC_TRUE;
639 if (scan_ipv6 == ISC_TRUE &&
640 isc_net_probe_ipv6pktinfo() != ISC_R_SUCCESS) {
641 ipv6pktinfo = ISC_FALSE;
642 log_explicit = ISC_TRUE;
644 if (scan_ipv6 == ISC_TRUE && ipv6only && ipv6pktinfo) {
645 for (le = ISC_LIST_HEAD(mgr->listenon6->elts);
647 le = ISC_LIST_NEXT(le, link)) {
648 struct in6_addr in6a;
650 if (!listenon_is_ip6_any(le))
654 isc_sockaddr_fromin6(&listen_addr, &in6a, le->port);
656 ifp = find_matching_interface(mgr, &listen_addr);
658 ifp->generation = mgr->generation;
660 isc_log_write(IFMGR_COMMON_LOGARGS,
663 "interfaces, port %u",
665 result = ns_interface_setup(mgr, &listen_addr,
668 if (result == ISC_R_SUCCESS)
669 ifp->flags |= NS_INTERFACEFLAG_ANYADDR;
671 isc_log_write(IFMGR_COMMON_LOGARGS,
673 "listening on all IPv6 "
674 "interfaces failed");
680 isc_netaddr_any(&zero_address);
681 isc_netaddr_any6(&zero_address6);
683 result = isc_interfaceiter_create(mgr->mctx, &iter);
684 if (result != ISC_R_SUCCESS)
687 if (adjusting == ISC_FALSE) {
688 result = clearacl(mgr->mctx, &mgr->aclenv.localhost);
689 if (result != ISC_R_SUCCESS)
691 result = clearacl(mgr->mctx, &mgr->aclenv.localnets);
692 if (result != ISC_R_SUCCESS)
697 for (result = isc_interfaceiter_first(iter);
698 result == ISC_R_SUCCESS;
699 result = isc_interfaceiter_next(iter))
701 isc_interface_t interface;
705 result = isc_interfaceiter_current(iter, &interface);
706 if (result != ISC_R_SUCCESS)
709 family = interface.address.family;
710 if (family != AF_INET && family != AF_INET6)
712 if (scan_ipv4 == ISC_FALSE && family == AF_INET)
714 if (scan_ipv6 == ISC_FALSE && family == AF_INET6)
718 * Test for the address being nonzero rather than testing
719 * INTERFACE_F_UP, because on some systems the latter
720 * follows the media state and we could end up ignoring
721 * the interface for an entire rescan interval due to
722 * a temporary media glitch at rescan time.
724 if (family == AF_INET &&
725 isc_netaddr_equal(&interface.address, &zero_address)) {
728 if (family == AF_INET6 &&
729 isc_netaddr_equal(&interface.address, &zero_address6)) {
733 if (adjusting == ISC_FALSE) {
734 result = setup_locals(mgr, &interface);
735 if (result != ISC_R_SUCCESS)
736 goto ignore_interface;
739 ll = (family == AF_INET) ? mgr->listenon4 : mgr->listenon6;
740 dolistenon = ISC_TRUE;
741 for (le = ISC_LIST_HEAD(ll->elts);
743 le = ISC_LIST_NEXT(le, link))
746 isc_boolean_t ipv6_wildcard = ISC_FALSE;
747 isc_netaddr_t listen_netaddr;
748 isc_sockaddr_t listen_sockaddr;
751 * Construct a socket address for this IP/port
754 if (family == AF_INET) {
755 isc_netaddr_fromin(&listen_netaddr,
756 &interface.address.type.in);
758 isc_netaddr_fromin6(&listen_netaddr,
759 &interface.address.type.in6);
760 isc_netaddr_setzone(&listen_netaddr,
761 interface.address.zone);
763 isc_sockaddr_fromnetaddr(&listen_sockaddr,
768 * See if the address matches the listen-on statement;
769 * if not, ignore the interface.
771 (void)dns_acl_match(&listen_netaddr, NULL, le->acl,
772 &mgr->aclenv, &match, NULL);
776 if (adjusting == ISC_FALSE && dolistenon == ISC_TRUE) {
777 setup_listenon(mgr, &interface, le->port);
778 dolistenon = ISC_FALSE;
782 * The case of "any" IPv6 address will require
783 * special considerations later, so remember it.
785 if (family == AF_INET6 && ipv6only && ipv6pktinfo &&
786 listenon_is_ip6_any(le))
787 ipv6_wildcard = ISC_TRUE;
790 * When adjusting interfaces with extra a listening
791 * list, see if the address matches the extra list.
792 * If it does, and is also covered by a wildcard
793 * interface, we need to listen on the address
796 if (adjusting == ISC_TRUE) {
800 for (ele = ISC_LIST_HEAD(ext_listen->elts);
802 ele = ISC_LIST_NEXT(ele, link)) {
803 (void)dns_acl_match(&listen_netaddr,
806 if (match > 0 && ele->port == le->port)
811 if (ipv6_wildcard == ISC_TRUE && match == 0)
815 ifp = find_matching_interface(mgr, &listen_sockaddr);
817 ifp->generation = mgr->generation;
819 char sabuf[ISC_SOCKADDR_FORMATSIZE];
821 if (adjusting == ISC_FALSE &&
822 ipv6_wildcard == ISC_TRUE)
825 if (log_explicit && family == AF_INET6 &&
826 !adjusting && listenon_is_ip6_any(le)) {
827 isc_log_write(IFMGR_COMMON_LOGARGS,
828 verbose ? ISC_LOG_INFO :
830 "IPv6 socket API is "
831 "incomplete; explicitly "
832 "binding to each IPv6 "
833 "address separately");
834 log_explicit = ISC_FALSE;
836 isc_sockaddr_format(&listen_sockaddr,
837 sabuf, sizeof(sabuf));
838 isc_log_write(IFMGR_COMMON_LOGARGS,
841 "listening on %s interface "
843 (adjusting == ISC_TRUE) ?
844 "additionally " : "",
845 (family == AF_INET) ?
847 interface.name, sabuf);
849 result = ns_interface_setup(mgr,
853 (adjusting == ISC_TRUE) ?
857 if (result != ISC_R_SUCCESS) {
858 isc_log_write(IFMGR_COMMON_LOGARGS,
860 "creating %s interface "
861 "%s failed; interface "
863 (family == AF_INET) ?
874 isc_log_write(IFMGR_COMMON_LOGARGS,
876 "ignoring %s interface %s: %s",
877 (family == AF_INET) ? "IPv4" : "IPv6",
878 interface.name, isc_result_totext(result));
881 if (result != ISC_R_NOMORE)
882 UNEXPECTED_ERROR(__FILE__, __LINE__,
883 "interface iteration failed: %s",
884 isc_result_totext(result));
886 result = ISC_R_SUCCESS;
888 isc_interfaceiter_destroy(&iter);
893 ns_interfacemgr_scan0(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen,
894 isc_boolean_t verbose)
896 isc_boolean_t purge = ISC_TRUE;
898 REQUIRE(NS_INTERFACEMGR_VALID(mgr));
900 mgr->generation++; /* Increment the generation count. */
902 if (do_scan(mgr, ext_listen, verbose) != ISC_R_SUCCESS)
906 * Now go through the interface list and delete anything that
907 * does not have the current generation number. This is
908 * how we catch interfaces that go away or change their
912 purge_old_interfaces(mgr);
915 * Warn if we are not listening on any interface, unless
916 * we're in lwresd-only mode, in which case that is to
919 if (ext_listen == NULL &&
920 ISC_LIST_EMPTY(mgr->interfaces) && ! ns_g_lwresdonly) {
921 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING,
922 "not listening on any interfaces");
927 ns_interfacemgr_scan(ns_interfacemgr_t *mgr, isc_boolean_t verbose) {
928 ns_interfacemgr_scan0(mgr, NULL, verbose);
932 ns_interfacemgr_adjust(ns_interfacemgr_t *mgr, ns_listenlist_t *list,
933 isc_boolean_t verbose)
935 ns_interfacemgr_scan0(mgr, list, verbose);
939 ns_interfacemgr_setlistenon4(ns_interfacemgr_t *mgr, ns_listenlist_t *value) {
941 ns_listenlist_detach(&mgr->listenon4);
942 ns_listenlist_attach(value, &mgr->listenon4);
947 ns_interfacemgr_setlistenon6(ns_interfacemgr_t *mgr, ns_listenlist_t *value) {
949 ns_listenlist_detach(&mgr->listenon6);
950 ns_listenlist_attach(value, &mgr->listenon6);
955 ns_interfacemgr_dumprecursing(FILE *f, ns_interfacemgr_t *mgr) {
956 ns_interface_t *interface;
959 interface = ISC_LIST_HEAD(mgr->interfaces);
960 while (interface != NULL) {
961 if (interface->clientmgr != NULL)
962 ns_client_dumprecursing(f, interface->clientmgr);
963 interface = ISC_LIST_NEXT(interface, link);
969 ns_interfacemgr_listeningon(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr) {
972 old = ISC_LIST_HEAD(mgr->listenon);
973 for (old = ISC_LIST_HEAD(mgr->listenon);
975 old = ISC_LIST_NEXT(old, link))
976 if (isc_sockaddr_equal(old, addr))