2 * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2002 Internet Software Consortium.
5 * Permission to use, copy, modify, and 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.8 2006/07/20 01:10:30 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 if (result != ISC_R_SUCCESS) {
312 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
313 "binding TCP socket: %s",
314 isc_result_totext(result));
315 goto tcp_bind_failure;
317 result = isc_socket_listen(ifp->tcpsocket, ns_g_listen);
318 if (result != ISC_R_SUCCESS) {
319 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
320 "listening on TCP socket: %s",
321 isc_result_totext(result));
322 goto tcp_listen_failure;
326 * If/when there a multiple filters listen to the
329 (void)isc_socket_filter(ifp->tcpsocket, "dataready");
331 result = ns_clientmgr_createclients(ifp->clientmgr,
332 ifp->ntcptarget, ifp,
334 if (result != ISC_R_SUCCESS) {
335 UNEXPECTED_ERROR(__FILE__, __LINE__,
336 "TCP ns_clientmgr_createclients(): %s",
337 isc_result_totext(result));
338 goto accepttcp_failure;
340 return (ISC_R_SUCCESS);
345 isc_socket_detach(&ifp->tcpsocket);
347 return (ISC_R_SUCCESS);
351 ns_interface_setup(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
352 const char *name, ns_interface_t **ifpret,
353 isc_boolean_t accept_tcp)
356 ns_interface_t *ifp = NULL;
357 REQUIRE(ifpret != NULL && *ifpret == NULL);
359 result = ns_interface_create(mgr, addr, name, &ifp);
360 if (result != ISC_R_SUCCESS)
363 result = ns_interface_listenudp(ifp);
364 if (result != ISC_R_SUCCESS)
365 goto cleanup_interface;
367 if (accept_tcp == ISC_TRUE) {
368 result = ns_interface_accepttcp(ifp);
369 if (result != ISC_R_SUCCESS) {
371 * XXXRTH We don't currently have a way to easily stop
372 * dispatch service, so we currently return
373 * ISC_R_SUCCESS (the UDP stuff will work even if TCP
374 * creation failed). This will be fixed later.
376 result = ISC_R_SUCCESS;
380 return (ISC_R_SUCCESS);
383 ISC_LIST_UNLINK(ifp->mgr->interfaces, ifp, link);
384 ns_interface_detach(&ifp);
389 ns_interface_shutdown(ns_interface_t *ifp) {
390 if (ifp->clientmgr != NULL)
391 ns_clientmgr_destroy(&ifp->clientmgr);
395 ns_interface_destroy(ns_interface_t *ifp) {
396 isc_mem_t *mctx = ifp->mgr->mctx;
397 REQUIRE(NS_INTERFACE_VALID(ifp));
399 ns_interface_shutdown(ifp);
401 if (ifp->udpdispatch != NULL) {
402 dns_dispatch_changeattributes(ifp->udpdispatch, 0,
403 DNS_DISPATCHATTR_NOLISTEN);
404 dns_dispatch_detach(&ifp->udpdispatch);
406 if (ifp->tcpsocket != NULL)
407 isc_socket_detach(&ifp->tcpsocket);
409 DESTROYLOCK(&ifp->lock);
411 ns_interfacemgr_detach(&ifp->mgr);
414 isc_mem_put(mctx, ifp, sizeof(*ifp));
418 ns_interface_attach(ns_interface_t *source, ns_interface_t **target) {
419 REQUIRE(NS_INTERFACE_VALID(source));
421 INSIST(source->references > 0);
422 source->references++;
423 UNLOCK(&source->lock);
428 ns_interface_detach(ns_interface_t **targetp) {
429 isc_result_t need_destroy = ISC_FALSE;
430 ns_interface_t *target = *targetp;
431 REQUIRE(target != NULL);
432 REQUIRE(NS_INTERFACE_VALID(target));
434 REQUIRE(target->references > 0);
435 target->references--;
436 if (target->references == 0)
437 need_destroy = ISC_TRUE;
438 UNLOCK(&target->lock);
440 ns_interface_destroy(target);
445 * Search the interface list for an interface whose address and port
446 * both match those of 'addr'. Return a pointer to it, or NULL if not found.
448 static ns_interface_t *
449 find_matching_interface(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr) {
451 for (ifp = ISC_LIST_HEAD(mgr->interfaces); ifp != NULL;
452 ifp = ISC_LIST_NEXT(ifp, link)) {
453 if (isc_sockaddr_equal(&ifp->addr, addr))
460 * Remove any interfaces whose generation number is not the current one.
463 purge_old_interfaces(ns_interfacemgr_t *mgr) {
464 ns_interface_t *ifp, *next;
465 for (ifp = ISC_LIST_HEAD(mgr->interfaces); ifp != NULL; ifp = next) {
466 INSIST(NS_INTERFACE_VALID(ifp));
467 next = ISC_LIST_NEXT(ifp, link);
468 if (ifp->generation != mgr->generation) {
470 ISC_LIST_UNLINK(ifp->mgr->interfaces, ifp, link);
471 isc_sockaddr_format(&ifp->addr, sabuf, sizeof(sabuf));
472 isc_log_write(IFMGR_COMMON_LOGARGS,
474 "no longer listening on %s", sabuf);
475 ns_interface_shutdown(ifp);
476 ns_interface_detach(&ifp);
482 clearacl(isc_mem_t *mctx, dns_acl_t **aclp) {
483 dns_acl_t *newacl = NULL;
485 result = dns_acl_create(mctx, 10, &newacl);
486 if (result != ISC_R_SUCCESS)
488 dns_acl_detach(aclp);
489 dns_acl_attach(newacl, aclp);
490 dns_acl_detach(&newacl);
491 return (ISC_R_SUCCESS);
495 listenon_is_ip6_any(ns_listenelt_t *elt) {
496 if (elt->acl->length != 1)
498 if (elt->acl->elements[0].negative == ISC_FALSE &&
499 elt->acl->elements[0].type == dns_aclelementtype_any)
500 return (ISC_TRUE); /* listen-on-v6 { any; } */
501 return (ISC_FALSE); /* All others */
505 setup_locals(ns_interfacemgr_t *mgr, isc_interface_t *interface) {
507 dns_aclelement_t elt;
509 unsigned int prefixlen;
511 family = interface->address.family;
513 elt.type = dns_aclelementtype_ipprefix;
514 elt.negative = ISC_FALSE;
515 elt.u.ip_prefix.address = interface->address;
516 elt.u.ip_prefix.prefixlen = (family == AF_INET) ? 32 : 128;
517 result = dns_acl_appendelement(mgr->aclenv.localhost, &elt);
518 if (result != ISC_R_SUCCESS)
521 result = isc_netaddr_masktoprefixlen(&interface->netmask,
524 /* Non contigious netmasks not allowed by IPv6 arch. */
525 if (result != ISC_R_SUCCESS && family == AF_INET6)
528 if (result != ISC_R_SUCCESS) {
529 isc_log_write(IFMGR_COMMON_LOGARGS,
531 "omitting IPv4 interface %s from "
534 isc_result_totext(result));
536 elt.u.ip_prefix.prefixlen = prefixlen;
537 if (dns_acl_elementmatch(mgr->aclenv.localnets, &elt,
538 NULL) == ISC_R_NOTFOUND) {
539 result = dns_acl_appendelement(mgr->aclenv.localnets,
541 if (result != ISC_R_SUCCESS)
546 return (ISC_R_SUCCESS);
550 setup_listenon(ns_interfacemgr_t *mgr, isc_interface_t *interface,
553 isc_sockaddr_t *addr;
556 addr = isc_mem_get(mgr->mctx, sizeof(*addr));
560 isc_sockaddr_fromnetaddr(addr, &interface->address, port);
562 for (old = ISC_LIST_HEAD(mgr->listenon);
564 old = ISC_LIST_NEXT(old, link))
565 if (isc_sockaddr_equal(addr, old))
569 isc_mem_put(mgr->mctx, addr, sizeof(*addr));
571 ISC_LIST_APPEND(mgr->listenon, addr, link);
575 clearlistenon(ns_interfacemgr_t *mgr) {
578 old = ISC_LIST_HEAD(mgr->listenon);
579 while (old != NULL) {
580 ISC_LIST_UNLINK(mgr->listenon, old, link);
581 isc_mem_put(mgr->mctx, old, sizeof(*old));
582 old = ISC_LIST_HEAD(mgr->listenon);
587 do_scan(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen,
588 isc_boolean_t verbose)
590 isc_interfaceiter_t *iter = NULL;
591 isc_boolean_t scan_ipv4 = ISC_FALSE;
592 isc_boolean_t scan_ipv6 = ISC_FALSE;
593 isc_boolean_t adjusting = ISC_FALSE;
594 isc_boolean_t ipv6only = ISC_TRUE;
595 isc_boolean_t ipv6pktinfo = ISC_TRUE;
597 isc_netaddr_t zero_address, zero_address6;
599 isc_sockaddr_t listen_addr;
601 isc_boolean_t log_explicit = ISC_FALSE;
602 isc_boolean_t dolistenon;
604 if (ext_listen != NULL)
605 adjusting = ISC_TRUE;
607 if (isc_net_probeipv6() == ISC_R_SUCCESS)
608 scan_ipv6 = ISC_TRUE;
611 isc_log_write(IFMGR_COMMON_LOGARGS,
612 verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1),
613 "no IPv6 interfaces found");
616 if (isc_net_probeipv4() == ISC_R_SUCCESS)
617 scan_ipv4 = ISC_TRUE;
619 isc_log_write(IFMGR_COMMON_LOGARGS,
620 verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1),
621 "no IPv4 interfaces found");
624 * A special, but typical case; listen-on-v6 { any; }.
625 * When we can make the socket IPv6-only, open a single wildcard
626 * socket for IPv6 communication. Otherwise, make separate socket
627 * for each IPv6 address in order to avoid accepting IPv4 packets
628 * as the form of mapped addresses unintentionally unless explicitly
631 #ifndef ISC_ALLOW_MAPPED
632 if (scan_ipv6 == ISC_TRUE &&
633 isc_net_probe_ipv6only() != ISC_R_SUCCESS) {
634 ipv6only = ISC_FALSE;
635 log_explicit = ISC_TRUE;
638 if (scan_ipv6 == ISC_TRUE &&
639 isc_net_probe_ipv6pktinfo() != ISC_R_SUCCESS) {
640 ipv6pktinfo = ISC_FALSE;
641 log_explicit = ISC_TRUE;
643 if (scan_ipv6 == ISC_TRUE && ipv6only && ipv6pktinfo) {
644 for (le = ISC_LIST_HEAD(mgr->listenon6->elts);
646 le = ISC_LIST_NEXT(le, link)) {
647 struct in6_addr in6a;
649 if (!listenon_is_ip6_any(le))
653 isc_sockaddr_fromin6(&listen_addr, &in6a, le->port);
655 ifp = find_matching_interface(mgr, &listen_addr);
657 ifp->generation = mgr->generation;
659 isc_log_write(IFMGR_COMMON_LOGARGS,
662 "interfaces, port %u",
664 result = ns_interface_setup(mgr, &listen_addr,
667 if (result == ISC_R_SUCCESS)
668 ifp->flags |= NS_INTERFACEFLAG_ANYADDR;
670 isc_log_write(IFMGR_COMMON_LOGARGS,
672 "listening on all IPv6 "
673 "interfaces failed");
679 isc_netaddr_any(&zero_address);
680 isc_netaddr_any6(&zero_address6);
682 result = isc_interfaceiter_create(mgr->mctx, &iter);
683 if (result != ISC_R_SUCCESS)
686 if (adjusting == ISC_FALSE) {
687 result = clearacl(mgr->mctx, &mgr->aclenv.localhost);
688 if (result != ISC_R_SUCCESS)
690 result = clearacl(mgr->mctx, &mgr->aclenv.localnets);
691 if (result != ISC_R_SUCCESS)
696 for (result = isc_interfaceiter_first(iter);
697 result == ISC_R_SUCCESS;
698 result = isc_interfaceiter_next(iter))
700 isc_interface_t interface;
704 result = isc_interfaceiter_current(iter, &interface);
705 if (result != ISC_R_SUCCESS)
708 family = interface.address.family;
709 if (family != AF_INET && family != AF_INET6)
711 if (scan_ipv4 == ISC_FALSE && family == AF_INET)
713 if (scan_ipv6 == ISC_FALSE && family == AF_INET6)
717 * Test for the address being nonzero rather than testing
718 * INTERFACE_F_UP, because on some systems the latter
719 * follows the media state and we could end up ignoring
720 * the interface for an entire rescan interval due to
721 * a temporary media glitch at rescan time.
723 if (family == AF_INET &&
724 isc_netaddr_equal(&interface.address, &zero_address)) {
727 if (family == AF_INET6 &&
728 isc_netaddr_equal(&interface.address, &zero_address6)) {
732 if (adjusting == ISC_FALSE) {
733 result = setup_locals(mgr, &interface);
734 if (result != ISC_R_SUCCESS)
735 goto ignore_interface;
738 ll = (family == AF_INET) ? mgr->listenon4 : mgr->listenon6;
739 dolistenon = ISC_TRUE;
740 for (le = ISC_LIST_HEAD(ll->elts);
742 le = ISC_LIST_NEXT(le, link))
745 isc_boolean_t ipv6_wildcard = ISC_FALSE;
746 isc_netaddr_t listen_netaddr;
747 isc_sockaddr_t listen_sockaddr;
750 * Construct a socket address for this IP/port
753 if (family == AF_INET) {
754 isc_netaddr_fromin(&listen_netaddr,
755 &interface.address.type.in);
757 isc_netaddr_fromin6(&listen_netaddr,
758 &interface.address.type.in6);
759 isc_netaddr_setzone(&listen_netaddr,
760 interface.address.zone);
762 isc_sockaddr_fromnetaddr(&listen_sockaddr,
767 * See if the address matches the listen-on statement;
768 * if not, ignore the interface.
770 (void)dns_acl_match(&listen_netaddr, NULL, le->acl,
771 &mgr->aclenv, &match, NULL);
775 if (adjusting == ISC_FALSE && dolistenon == ISC_TRUE) {
776 setup_listenon(mgr, &interface, le->port);
777 dolistenon = ISC_FALSE;
781 * The case of "any" IPv6 address will require
782 * special considerations later, so remember it.
784 if (family == AF_INET6 && ipv6only && ipv6pktinfo &&
785 listenon_is_ip6_any(le))
786 ipv6_wildcard = ISC_TRUE;
789 * When adjusting interfaces with extra a listening
790 * list, see if the address matches the extra list.
791 * If it does, and is also covered by a wildcard
792 * interface, we need to listen on the address
795 if (adjusting == ISC_TRUE) {
799 for (ele = ISC_LIST_HEAD(ext_listen->elts);
801 ele = ISC_LIST_NEXT(ele, link)) {
802 (void)dns_acl_match(&listen_netaddr,
805 if (match > 0 && ele->port == le->port)
810 if (ipv6_wildcard == ISC_TRUE && match == 0)
814 ifp = find_matching_interface(mgr, &listen_sockaddr);
816 ifp->generation = mgr->generation;
818 char sabuf[ISC_SOCKADDR_FORMATSIZE];
820 if (adjusting == ISC_FALSE &&
821 ipv6_wildcard == ISC_TRUE)
824 if (log_explicit && family == AF_INET6 &&
825 !adjusting && listenon_is_ip6_any(le)) {
826 isc_log_write(IFMGR_COMMON_LOGARGS,
827 verbose ? ISC_LOG_INFO :
829 "IPv6 socket API is "
830 "incomplete; explicitly "
831 "binding to each IPv6 "
832 "address separately");
833 log_explicit = ISC_FALSE;
835 isc_sockaddr_format(&listen_sockaddr,
836 sabuf, sizeof(sabuf));
837 isc_log_write(IFMGR_COMMON_LOGARGS,
840 "listening on %s interface "
842 (adjusting == ISC_TRUE) ?
843 "additionally " : "",
844 (family == AF_INET) ?
846 interface.name, sabuf);
848 result = ns_interface_setup(mgr,
852 (adjusting == ISC_TRUE) ?
856 if (result != ISC_R_SUCCESS) {
857 isc_log_write(IFMGR_COMMON_LOGARGS,
859 "creating %s interface "
860 "%s failed; interface "
862 (family == AF_INET) ?
873 isc_log_write(IFMGR_COMMON_LOGARGS,
875 "ignoring %s interface %s: %s",
876 (family == AF_INET) ? "IPv4" : "IPv6",
877 interface.name, isc_result_totext(result));
880 if (result != ISC_R_NOMORE)
881 UNEXPECTED_ERROR(__FILE__, __LINE__,
882 "interface iteration failed: %s",
883 isc_result_totext(result));
885 result = ISC_R_SUCCESS;
887 isc_interfaceiter_destroy(&iter);
892 ns_interfacemgr_scan0(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen,
893 isc_boolean_t verbose)
895 isc_boolean_t purge = ISC_TRUE;
897 REQUIRE(NS_INTERFACEMGR_VALID(mgr));
899 mgr->generation++; /* Increment the generation count. */
901 if (do_scan(mgr, ext_listen, verbose) != ISC_R_SUCCESS)
905 * Now go through the interface list and delete anything that
906 * does not have the current generation number. This is
907 * how we catch interfaces that go away or change their
911 purge_old_interfaces(mgr);
914 * Warn if we are not listening on any interface, unless
915 * we're in lwresd-only mode, in which case that is to
918 if (ext_listen == NULL &&
919 ISC_LIST_EMPTY(mgr->interfaces) && ! ns_g_lwresdonly) {
920 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING,
921 "not listening on any interfaces");
926 ns_interfacemgr_scan(ns_interfacemgr_t *mgr, isc_boolean_t verbose) {
927 ns_interfacemgr_scan0(mgr, NULL, verbose);
931 ns_interfacemgr_adjust(ns_interfacemgr_t *mgr, ns_listenlist_t *list,
932 isc_boolean_t verbose)
934 ns_interfacemgr_scan0(mgr, list, verbose);
938 ns_interfacemgr_setlistenon4(ns_interfacemgr_t *mgr, ns_listenlist_t *value) {
940 ns_listenlist_detach(&mgr->listenon4);
941 ns_listenlist_attach(value, &mgr->listenon4);
946 ns_interfacemgr_setlistenon6(ns_interfacemgr_t *mgr, ns_listenlist_t *value) {
948 ns_listenlist_detach(&mgr->listenon6);
949 ns_listenlist_attach(value, &mgr->listenon6);
954 ns_interfacemgr_dumprecursing(FILE *f, ns_interfacemgr_t *mgr) {
955 ns_interface_t *interface;
958 interface = ISC_LIST_HEAD(mgr->interfaces);
959 while (interface != NULL) {
960 if (interface->clientmgr != NULL)
961 ns_client_dumprecursing(f, interface->clientmgr);
962 interface = ISC_LIST_NEXT(interface, link);
968 ns_interfacemgr_listeningon(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr) {
971 old = ISC_LIST_HEAD(mgr->listenon);
972 for (old = ISC_LIST_HEAD(mgr->listenon);
974 old = ISC_LIST_NEXT(old, link))
975 if (isc_sockaddr_equal(old, addr))