2 * Copyright (C) 2004 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.59.2.5.8.15 2004/08/10 04:56:23 jinmei Exp $ */
22 #include <isc/interfaceiter.h>
23 #include <isc/string.h>
28 #include <dns/dispatch.h>
30 #include <named/client.h>
31 #include <named/log.h>
32 #include <named/interfacemgr.h>
34 #define IFMGR_MAGIC ISC_MAGIC('I', 'F', 'M', 'G')
35 #define NS_INTERFACEMGR_VALID(t) ISC_MAGIC_VALID(t, IFMGR_MAGIC)
37 #define IFMGR_COMMON_LOGARGS \
38 ns_g_lctx, NS_LOGCATEGORY_NETWORK, NS_LOGMODULE_INTERFACEMGR
40 struct ns_interfacemgr {
41 unsigned int magic; /* Magic number. */
44 isc_mem_t * mctx; /* Memory context. */
45 isc_taskmgr_t * taskmgr; /* Task manager. */
46 isc_socketmgr_t * socketmgr; /* Socket manager. */
47 dns_dispatchmgr_t * dispatchmgr;
48 unsigned int generation; /* Current generation no. */
49 ns_listenlist_t * listenon4;
50 ns_listenlist_t * listenon6;
51 dns_aclenv_t aclenv; /* Localhost/localnets ACLs */
52 ISC_LIST(ns_interface_t) interfaces; /* List of interfaces. */
56 purge_old_interfaces(ns_interfacemgr_t *mgr);
59 ns_interfacemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
60 isc_socketmgr_t *socketmgr,
61 dns_dispatchmgr_t *dispatchmgr,
62 ns_interfacemgr_t **mgrp)
65 ns_interfacemgr_t *mgr;
67 REQUIRE(mctx != NULL);
68 REQUIRE(mgrp != NULL);
69 REQUIRE(*mgrp == NULL);
71 mgr = isc_mem_get(mctx, sizeof(*mgr));
73 return (ISC_R_NOMEMORY);
75 result = isc_mutex_init(&mgr->lock);
76 if (result != ISC_R_SUCCESS)
80 mgr->taskmgr = taskmgr;
81 mgr->socketmgr = socketmgr;
82 mgr->dispatchmgr = dispatchmgr;
84 mgr->listenon4 = NULL;
85 mgr->listenon6 = NULL;
87 ISC_LIST_INIT(mgr->interfaces);
90 * The listen-on lists are initially empty.
92 result = ns_listenlist_create(mctx, &mgr->listenon4);
93 if (result != ISC_R_SUCCESS)
95 ns_listenlist_attach(mgr->listenon4, &mgr->listenon6);
97 result = dns_aclenv_init(mctx, &mgr->aclenv);
98 if (result != ISC_R_SUCCESS)
99 goto cleanup_listenon;
102 mgr->magic = IFMGR_MAGIC;
104 return (ISC_R_SUCCESS);
107 ns_listenlist_detach(&mgr->listenon4);
108 ns_listenlist_detach(&mgr->listenon6);
110 isc_mem_put(mctx, mgr, sizeof(*mgr));
115 ns_interfacemgr_destroy(ns_interfacemgr_t *mgr) {
116 REQUIRE(NS_INTERFACEMGR_VALID(mgr));
117 dns_aclenv_destroy(&mgr->aclenv);
118 ns_listenlist_detach(&mgr->listenon4);
119 ns_listenlist_detach(&mgr->listenon6);
120 DESTROYLOCK(&mgr->lock);
122 isc_mem_put(mgr->mctx, mgr, sizeof(*mgr));
126 ns_interfacemgr_getaclenv(ns_interfacemgr_t *mgr) {
127 return (&mgr->aclenv);
131 ns_interfacemgr_attach(ns_interfacemgr_t *source, ns_interfacemgr_t **target) {
132 REQUIRE(NS_INTERFACEMGR_VALID(source));
134 INSIST(source->references > 0);
135 source->references++;
136 UNLOCK(&source->lock);
141 ns_interfacemgr_detach(ns_interfacemgr_t **targetp) {
142 isc_result_t need_destroy = ISC_FALSE;
143 ns_interfacemgr_t *target = *targetp;
144 REQUIRE(target != NULL);
145 REQUIRE(NS_INTERFACEMGR_VALID(target));
147 REQUIRE(target->references > 0);
148 target->references--;
149 if (target->references == 0)
150 need_destroy = ISC_TRUE;
151 UNLOCK(&target->lock);
153 ns_interfacemgr_destroy(target);
158 ns_interfacemgr_shutdown(ns_interfacemgr_t *mgr) {
159 REQUIRE(NS_INTERFACEMGR_VALID(mgr));
162 * Shut down and detach all interfaces.
163 * By incrementing the generation count, we make purge_old_interfaces()
164 * consider all interfaces "old".
167 purge_old_interfaces(mgr);
172 ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
173 const char *name, ns_interface_t **ifpret)
178 REQUIRE(NS_INTERFACEMGR_VALID(mgr));
179 ifp = isc_mem_get(mgr->mctx, sizeof(*ifp));
181 return (ISC_R_NOMEMORY);
183 ifp->generation = mgr->generation;
185 strncpy(ifp->name, name, sizeof(ifp->name));
186 ifp->name[sizeof(ifp->name)-1] = '\0';
187 ifp->clientmgr = NULL;
189 result = isc_mutex_init(&ifp->lock);
190 if (result != ISC_R_SUCCESS)
191 goto lock_create_failure;
193 result = ns_clientmgr_create(mgr->mctx, mgr->taskmgr,
196 if (result != ISC_R_SUCCESS) {
197 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
198 "ns_clientmgr_create() failed: %s",
199 isc_result_totext(result));
200 goto clientmgr_create_failure;
203 ifp->udpdispatch = NULL;
205 ifp->tcpsocket = NULL;
207 * Create a single TCP client object. It will replace itself
208 * with a new one as soon as it gets a connection, so the actual
209 * connections will be handled in parallel even though there is
210 * only one client initially.
213 ifp->ntcpcurrent = 0;
215 ISC_LINK_INIT(ifp, link);
217 ns_interfacemgr_attach(mgr, &ifp->mgr);
218 ISC_LIST_APPEND(mgr->interfaces, ifp, link);
221 ifp->magic = IFACE_MAGIC;
224 return (ISC_R_SUCCESS);
226 clientmgr_create_failure:
227 DESTROYLOCK(&ifp->lock);
230 isc_mem_put(mgr->mctx, ifp, sizeof(*ifp));
232 return (ISC_R_UNEXPECTED);
236 ns_interface_listenudp(ns_interface_t *ifp) {
239 unsigned int attrmask;
242 attrs |= DNS_DISPATCHATTR_UDP;
243 if (isc_sockaddr_pf(&ifp->addr) == AF_INET)
244 attrs |= DNS_DISPATCHATTR_IPV4;
246 attrs |= DNS_DISPATCHATTR_IPV6;
247 attrs |= DNS_DISPATCHATTR_NOLISTEN;
249 attrmask |= DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_TCP;
250 attrmask |= DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_IPV6;
251 result = dns_dispatch_getudp(ifp->mgr->dispatchmgr, ns_g_socketmgr,
252 ns_g_taskmgr, &ifp->addr,
253 4096, 1000, 32768, 8219, 8237,
254 attrs, attrmask, &ifp->udpdispatch);
255 if (result != ISC_R_SUCCESS) {
256 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
257 "could not listen on UDP socket: %s",
258 isc_result_totext(result));
259 goto udp_dispatch_failure;
262 result = ns_clientmgr_createclients(ifp->clientmgr, ns_g_cpus,
264 if (result != ISC_R_SUCCESS) {
265 UNEXPECTED_ERROR(__FILE__, __LINE__,
266 "UDP ns_clientmgr_createclients(): %s",
267 isc_result_totext(result));
268 goto addtodispatch_failure;
270 return (ISC_R_SUCCESS);
272 addtodispatch_failure:
273 dns_dispatch_changeattributes(ifp->udpdispatch, 0,
274 DNS_DISPATCHATTR_NOLISTEN);
275 dns_dispatch_detach(&ifp->udpdispatch);
276 udp_dispatch_failure:
281 ns_interface_accepttcp(ns_interface_t *ifp) {
287 result = isc_socket_create(ifp->mgr->socketmgr,
288 isc_sockaddr_pf(&ifp->addr),
291 if (result != ISC_R_SUCCESS) {
292 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
293 "creating TCP socket: %s",
294 isc_result_totext(result));
295 goto tcp_socket_failure;
297 #ifndef ISC_ALLOW_MAPPED
298 isc_socket_ipv6only(ifp->tcpsocket, ISC_TRUE);
300 result = isc_socket_bind(ifp->tcpsocket, &ifp->addr);
301 if (result != ISC_R_SUCCESS) {
302 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
303 "binding TCP socket: %s",
304 isc_result_totext(result));
305 goto tcp_bind_failure;
307 result = isc_socket_listen(ifp->tcpsocket, ns_g_listen);
308 if (result != ISC_R_SUCCESS) {
309 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
310 "listening on TCP socket: %s",
311 isc_result_totext(result));
312 goto tcp_listen_failure;
316 * If/when there a multiple filters listen to the
319 (void)isc_socket_filter(ifp->tcpsocket, "dataready");
321 result = ns_clientmgr_createclients(ifp->clientmgr,
322 ifp->ntcptarget, ifp,
324 if (result != ISC_R_SUCCESS) {
325 UNEXPECTED_ERROR(__FILE__, __LINE__,
326 "TCP ns_clientmgr_createclients(): %s",
327 isc_result_totext(result));
328 goto accepttcp_failure;
330 return (ISC_R_SUCCESS);
335 isc_socket_detach(&ifp->tcpsocket);
337 return (ISC_R_SUCCESS);
341 ns_interface_setup(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
342 const char *name, ns_interface_t **ifpret,
343 isc_boolean_t accept_tcp)
346 ns_interface_t *ifp = NULL;
347 REQUIRE(ifpret != NULL && *ifpret == NULL);
349 result = ns_interface_create(mgr, addr, name, &ifp);
350 if (result != ISC_R_SUCCESS)
353 result = ns_interface_listenudp(ifp);
354 if (result != ISC_R_SUCCESS)
355 goto cleanup_interface;
357 if (accept_tcp == ISC_TRUE) {
358 result = ns_interface_accepttcp(ifp);
359 if (result != ISC_R_SUCCESS) {
361 * XXXRTH We don't currently have a way to easily stop
362 * dispatch service, so we currently return
363 * ISC_R_SUCCESS (the UDP stuff will work even if TCP
364 * creation failed). This will be fixed later.
366 result = ISC_R_SUCCESS;
370 return (ISC_R_SUCCESS);
373 ISC_LIST_UNLINK(ifp->mgr->interfaces, ifp, link);
374 ns_interface_detach(&ifp);
379 ns_interface_shutdown(ns_interface_t *ifp) {
380 if (ifp->clientmgr != NULL)
381 ns_clientmgr_destroy(&ifp->clientmgr);
385 ns_interface_destroy(ns_interface_t *ifp) {
386 isc_mem_t *mctx = ifp->mgr->mctx;
387 REQUIRE(NS_INTERFACE_VALID(ifp));
389 ns_interface_shutdown(ifp);
391 if (ifp->udpdispatch != NULL) {
392 dns_dispatch_changeattributes(ifp->udpdispatch, 0,
393 DNS_DISPATCHATTR_NOLISTEN);
394 dns_dispatch_detach(&ifp->udpdispatch);
396 if (ifp->tcpsocket != NULL)
397 isc_socket_detach(&ifp->tcpsocket);
399 DESTROYLOCK(&ifp->lock);
401 ns_interfacemgr_detach(&ifp->mgr);
404 isc_mem_put(mctx, ifp, sizeof(*ifp));
408 ns_interface_attach(ns_interface_t *source, ns_interface_t **target) {
409 REQUIRE(NS_INTERFACE_VALID(source));
411 INSIST(source->references > 0);
412 source->references++;
413 UNLOCK(&source->lock);
418 ns_interface_detach(ns_interface_t **targetp) {
419 isc_result_t need_destroy = ISC_FALSE;
420 ns_interface_t *target = *targetp;
421 REQUIRE(target != NULL);
422 REQUIRE(NS_INTERFACE_VALID(target));
424 REQUIRE(target->references > 0);
425 target->references--;
426 if (target->references == 0)
427 need_destroy = ISC_TRUE;
428 UNLOCK(&target->lock);
430 ns_interface_destroy(target);
435 * Search the interface list for an interface whose address and port
436 * both match those of 'addr'. Return a pointer to it, or NULL if not found.
438 static ns_interface_t *
439 find_matching_interface(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr) {
441 for (ifp = ISC_LIST_HEAD(mgr->interfaces); ifp != NULL;
442 ifp = ISC_LIST_NEXT(ifp, link)) {
443 if (isc_sockaddr_equal(&ifp->addr, addr))
450 * Remove any interfaces whose generation number is not the current one.
453 purge_old_interfaces(ns_interfacemgr_t *mgr) {
454 ns_interface_t *ifp, *next;
455 for (ifp = ISC_LIST_HEAD(mgr->interfaces); ifp != NULL; ifp = next) {
456 INSIST(NS_INTERFACE_VALID(ifp));
457 next = ISC_LIST_NEXT(ifp, link);
458 if (ifp->generation != mgr->generation) {
460 ISC_LIST_UNLINK(ifp->mgr->interfaces, ifp, link);
461 isc_sockaddr_format(&ifp->addr, sabuf, sizeof(sabuf));
462 isc_log_write(IFMGR_COMMON_LOGARGS,
464 "no longer listening on %s", sabuf);
465 ns_interface_shutdown(ifp);
466 ns_interface_detach(&ifp);
472 clearacl(isc_mem_t *mctx, dns_acl_t **aclp) {
473 dns_acl_t *newacl = NULL;
475 result = dns_acl_create(mctx, 10, &newacl);
476 if (result != ISC_R_SUCCESS)
478 dns_acl_detach(aclp);
479 dns_acl_attach(newacl, aclp);
480 dns_acl_detach(&newacl);
481 return (ISC_R_SUCCESS);
485 listenon_is_ip6_any(ns_listenelt_t *elt) {
486 if (elt->acl->length != 1)
488 if (elt->acl->elements[0].negative == ISC_FALSE &&
489 elt->acl->elements[0].type == dns_aclelementtype_any)
490 return (ISC_TRUE); /* listen-on-v6 { any; } */
491 return (ISC_FALSE); /* All others */
495 setup_locals(ns_interfacemgr_t *mgr, isc_interface_t *interface) {
497 dns_aclelement_t elt;
499 unsigned int prefixlen;
501 family = interface->address.family;
503 elt.type = dns_aclelementtype_ipprefix;
504 elt.negative = ISC_FALSE;
505 elt.u.ip_prefix.address = interface->address;
506 elt.u.ip_prefix.prefixlen = (family == AF_INET) ? 32 : 128;
507 result = dns_acl_appendelement(mgr->aclenv.localhost, &elt);
508 if (result != ISC_R_SUCCESS)
511 result = isc_netaddr_masktoprefixlen(&interface->netmask,
514 /* Non contigious netmasks not allowed by IPv6 arch. */
515 if (result != ISC_R_SUCCESS && family == AF_INET6)
518 if (result != ISC_R_SUCCESS) {
519 isc_log_write(IFMGR_COMMON_LOGARGS,
521 "omitting IPv4 interface %s from "
524 isc_result_totext(result));
526 elt.u.ip_prefix.prefixlen = prefixlen;
527 if (dns_acl_elementmatch(mgr->aclenv.localnets, &elt,
528 NULL) == ISC_R_NOTFOUND) {
529 result = dns_acl_appendelement(mgr->aclenv.localnets,
531 if (result != ISC_R_SUCCESS)
536 return (ISC_R_SUCCESS);
540 do_scan(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen,
541 isc_boolean_t verbose)
543 isc_interfaceiter_t *iter = NULL;
544 isc_boolean_t scan_ipv4 = ISC_FALSE;
545 isc_boolean_t scan_ipv6 = ISC_FALSE;
546 isc_boolean_t adjusting = ISC_FALSE;
547 isc_boolean_t ipv6only = ISC_TRUE;
548 isc_boolean_t ipv6pktinfo = ISC_TRUE;
550 isc_netaddr_t zero_address, zero_address6;
552 isc_sockaddr_t listen_addr;
554 isc_boolean_t log_explicit = ISC_FALSE;
556 if (ext_listen != NULL)
557 adjusting = ISC_TRUE;
559 if (isc_net_probeipv6() == ISC_R_SUCCESS)
560 scan_ipv6 = ISC_TRUE;
563 isc_log_write(IFMGR_COMMON_LOGARGS,
564 verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1),
565 "no IPv6 interfaces found");
568 if (isc_net_probeipv4() == ISC_R_SUCCESS)
569 scan_ipv4 = ISC_TRUE;
571 isc_log_write(IFMGR_COMMON_LOGARGS,
572 verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1),
573 "no IPv4 interfaces found");
576 * A special, but typical case; listen-on-v6 { any; }.
577 * When we can make the socket IPv6-only, open a single wildcard
578 * socket for IPv6 communication. Otherwise, make separate socket
579 * for each IPv6 address in order to avoid accepting IPv4 packets
580 * as the form of mapped addresses unintentionally unless explicitly
583 #ifndef ISC_ALLOW_MAPPED
584 if (scan_ipv6 == ISC_TRUE &&
585 isc_net_probe_ipv6only() != ISC_R_SUCCESS) {
586 ipv6only = ISC_FALSE;
587 log_explicit = ISC_TRUE;
590 if (scan_ipv6 == ISC_TRUE &&
591 isc_net_probe_ipv6pktinfo() != ISC_R_SUCCESS) {
592 ipv6pktinfo = ISC_FALSE;
593 log_explicit = ISC_TRUE;
595 if (scan_ipv6 == ISC_TRUE && ipv6only && ipv6pktinfo) {
596 for (le = ISC_LIST_HEAD(mgr->listenon6->elts);
598 le = ISC_LIST_NEXT(le, link)) {
599 struct in6_addr in6a;
601 if (!listenon_is_ip6_any(le))
605 isc_sockaddr_fromin6(&listen_addr, &in6a, le->port);
607 ifp = find_matching_interface(mgr, &listen_addr);
609 ifp->generation = mgr->generation;
611 isc_log_write(IFMGR_COMMON_LOGARGS,
614 "interfaces, port %u",
616 result = ns_interface_setup(mgr, &listen_addr,
619 if (result == ISC_R_SUCCESS)
620 ifp->flags |= NS_INTERFACEFLAG_ANYADDR;
622 isc_log_write(IFMGR_COMMON_LOGARGS,
624 "listening on all IPv6 "
625 "interfaces failed");
631 isc_netaddr_any(&zero_address);
632 isc_netaddr_any6(&zero_address6);
634 result = isc_interfaceiter_create(mgr->mctx, &iter);
635 if (result != ISC_R_SUCCESS)
638 if (adjusting == ISC_FALSE) {
639 result = clearacl(mgr->mctx, &mgr->aclenv.localhost);
640 if (result != ISC_R_SUCCESS)
642 result = clearacl(mgr->mctx, &mgr->aclenv.localnets);
643 if (result != ISC_R_SUCCESS)
647 for (result = isc_interfaceiter_first(iter);
648 result == ISC_R_SUCCESS;
649 result = isc_interfaceiter_next(iter))
651 isc_interface_t interface;
655 result = isc_interfaceiter_current(iter, &interface);
656 if (result != ISC_R_SUCCESS)
659 family = interface.address.family;
660 if (family != AF_INET && family != AF_INET6)
662 if (scan_ipv4 == ISC_FALSE && family == AF_INET)
664 if (scan_ipv6 == ISC_FALSE && family == AF_INET6)
668 * Test for the address being nonzero rather than testing
669 * INTERFACE_F_UP, because on some systems the latter
670 * follows the media state and we could end up ignoring
671 * the interface for an entire rescan interval due to
672 * a temporary media glitch at rescan time.
674 if (family == AF_INET &&
675 isc_netaddr_equal(&interface.address, &zero_address)) {
678 if (family == AF_INET6 &&
679 isc_netaddr_equal(&interface.address, &zero_address6)) {
683 if (adjusting == ISC_FALSE) {
684 result = setup_locals(mgr, &interface);
685 if (result != ISC_R_SUCCESS)
686 goto ignore_interface;
689 ll = (family == AF_INET) ? mgr->listenon4 : mgr->listenon6;
690 for (le = ISC_LIST_HEAD(ll->elts);
692 le = ISC_LIST_NEXT(le, link))
695 isc_boolean_t ipv6_wildcard = ISC_FALSE;
696 isc_netaddr_t listen_netaddr;
697 isc_sockaddr_t listen_sockaddr;
700 * Construct a socket address for this IP/port
703 if (family == AF_INET) {
704 isc_netaddr_fromin(&listen_netaddr,
705 &interface.address.type.in);
707 isc_netaddr_fromin6(&listen_netaddr,
708 &interface.address.type.in6);
709 isc_netaddr_setzone(&listen_netaddr,
710 interface.address.zone);
712 isc_sockaddr_fromnetaddr(&listen_sockaddr,
717 * See if the address matches the listen-on statement;
718 * if not, ignore the interface.
720 result = dns_acl_match(&listen_netaddr, NULL,
721 le->acl, &mgr->aclenv,
727 * The case of "any" IPv6 address will require
728 * special considerations later, so remember it.
730 if (family == AF_INET6 && ipv6only && ipv6pktinfo &&
731 listenon_is_ip6_any(le))
732 ipv6_wildcard = ISC_TRUE;
735 * When adjusting interfaces with extra a listening
736 * list, see if the address matches the extra list.
737 * If it does, and is also covered by a wildcard
738 * interface, we need to listen on the address
741 if (adjusting == ISC_TRUE) {
745 for (ele = ISC_LIST_HEAD(ext_listen->elts);
747 ele = ISC_LIST_NEXT(ele, link)) {
748 dns_acl_match(&listen_netaddr, NULL,
751 if (match > 0 && ele->port == le->port)
756 if (ipv6_wildcard == ISC_TRUE && match == 0)
760 ifp = find_matching_interface(mgr, &listen_sockaddr);
762 ifp->generation = mgr->generation;
764 char sabuf[ISC_SOCKADDR_FORMATSIZE];
766 if (adjusting == ISC_FALSE &&
767 ipv6_wildcard == ISC_TRUE)
770 if (log_explicit && family == AF_INET6 &&
771 !adjusting && listenon_is_ip6_any(le)) {
772 isc_log_write(IFMGR_COMMON_LOGARGS,
773 verbose ? ISC_LOG_INFO :
775 "IPv6 socket API is "
776 "incomplete; explicitly "
777 "binding to each IPv6 "
778 "address separately");
779 log_explicit = ISC_FALSE;
781 isc_sockaddr_format(&listen_sockaddr,
782 sabuf, sizeof(sabuf));
783 isc_log_write(IFMGR_COMMON_LOGARGS,
786 "listening on %s interface "
788 (adjusting == ISC_TRUE) ?
789 "additionally " : "",
790 (family == AF_INET) ?
792 interface.name, sabuf);
794 result = ns_interface_setup(mgr,
798 (adjusting == ISC_TRUE) ?
802 if (result != ISC_R_SUCCESS) {
803 isc_log_write(IFMGR_COMMON_LOGARGS,
805 "creating %s interface "
806 "%s failed; interface "
808 (family == AF_INET) ?
819 isc_log_write(IFMGR_COMMON_LOGARGS,
821 "ignoring %s interface %s: %s",
822 (family == AF_INET) ? "IPv4" : "IPv6",
823 interface.name, isc_result_totext(result));
826 if (result != ISC_R_NOMORE)
827 UNEXPECTED_ERROR(__FILE__, __LINE__,
828 "interface iteration failed: %s",
829 isc_result_totext(result));
831 result = ISC_R_SUCCESS;
833 isc_interfaceiter_destroy(&iter);
838 ns_interfacemgr_scan0(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen,
839 isc_boolean_t verbose)
841 isc_boolean_t purge = ISC_TRUE;
843 REQUIRE(NS_INTERFACEMGR_VALID(mgr));
845 mgr->generation++; /* Increment the generation count. */
847 if (do_scan(mgr, ext_listen, verbose) != ISC_R_SUCCESS)
851 * Now go through the interface list and delete anything that
852 * does not have the current generation number. This is
853 * how we catch interfaces that go away or change their
857 purge_old_interfaces(mgr);
860 * Warn if we are not listening on any interface, unless
861 * we're in lwresd-only mode, in which case that is to
864 if (ext_listen == NULL &&
865 ISC_LIST_EMPTY(mgr->interfaces) && ! ns_g_lwresdonly) {
866 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING,
867 "not listening on any interfaces");
872 ns_interfacemgr_scan(ns_interfacemgr_t *mgr, isc_boolean_t verbose) {
873 ns_interfacemgr_scan0(mgr, NULL, verbose);
877 ns_interfacemgr_adjust(ns_interfacemgr_t *mgr, ns_listenlist_t *list,
878 isc_boolean_t verbose)
880 ns_interfacemgr_scan0(mgr, list, verbose);
884 ns_interfacemgr_setlistenon4(ns_interfacemgr_t *mgr, ns_listenlist_t *value) {
886 ns_listenlist_detach(&mgr->listenon4);
887 ns_listenlist_attach(value, &mgr->listenon4);
892 ns_interfacemgr_setlistenon6(ns_interfacemgr_t *mgr, ns_listenlist_t *value) {
894 ns_listenlist_detach(&mgr->listenon6);
895 ns_listenlist_attach(value, &mgr->listenon6);
900 ns_interfacemgr_dumprecursing(FILE *f, ns_interfacemgr_t *mgr) {
901 ns_interface_t *interface;
904 interface = ISC_LIST_HEAD(mgr->interfaces);
905 while (interface != NULL) {
906 if (interface->clientmgr != NULL)
907 ns_client_dumprecursing(f, interface->clientmgr);
908 interface = ISC_LIST_NEXT(interface, link);