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.59.2.5.8.18 2006/07/19 00:16:28 marka 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;
186 strncpy(ifp->name, name, sizeof(ifp->name));
187 ifp->name[sizeof(ifp->name)-1] = '\0';
188 ifp->clientmgr = NULL;
190 result = isc_mutex_init(&ifp->lock);
191 if (result != ISC_R_SUCCESS)
192 goto lock_create_failure;
194 result = ns_clientmgr_create(mgr->mctx, mgr->taskmgr,
197 if (result != ISC_R_SUCCESS) {
198 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
199 "ns_clientmgr_create() failed: %s",
200 isc_result_totext(result));
201 goto clientmgr_create_failure;
204 ifp->udpdispatch = NULL;
206 ifp->tcpsocket = NULL;
208 * Create a single TCP client object. It will replace itself
209 * with a new one as soon as it gets a connection, so the actual
210 * connections will be handled in parallel even though there is
211 * only one client initially.
214 ifp->ntcpcurrent = 0;
216 ISC_LINK_INIT(ifp, link);
218 ns_interfacemgr_attach(mgr, &ifp->mgr);
219 ISC_LIST_APPEND(mgr->interfaces, ifp, link);
222 ifp->magic = IFACE_MAGIC;
225 return (ISC_R_SUCCESS);
227 clientmgr_create_failure:
228 DESTROYLOCK(&ifp->lock);
231 isc_mem_put(mgr->mctx, ifp, sizeof(*ifp));
233 return (ISC_R_UNEXPECTED);
237 ns_interface_listenudp(ns_interface_t *ifp) {
240 unsigned int attrmask;
243 attrs |= DNS_DISPATCHATTR_UDP;
244 if (isc_sockaddr_pf(&ifp->addr) == AF_INET)
245 attrs |= DNS_DISPATCHATTR_IPV4;
247 attrs |= DNS_DISPATCHATTR_IPV6;
248 attrs |= DNS_DISPATCHATTR_NOLISTEN;
250 attrmask |= DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_TCP;
251 attrmask |= DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_IPV6;
252 result = dns_dispatch_getudp(ifp->mgr->dispatchmgr, ns_g_socketmgr,
253 ns_g_taskmgr, &ifp->addr,
254 4096, 1000, 32768, 8219, 8237,
255 attrs, attrmask, &ifp->udpdispatch);
256 if (result != ISC_R_SUCCESS) {
257 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
258 "could not listen on UDP socket: %s",
259 isc_result_totext(result));
260 goto udp_dispatch_failure;
263 result = ns_clientmgr_createclients(ifp->clientmgr, ns_g_cpus,
265 if (result != ISC_R_SUCCESS) {
266 UNEXPECTED_ERROR(__FILE__, __LINE__,
267 "UDP ns_clientmgr_createclients(): %s",
268 isc_result_totext(result));
269 goto addtodispatch_failure;
271 return (ISC_R_SUCCESS);
273 addtodispatch_failure:
274 dns_dispatch_changeattributes(ifp->udpdispatch, 0,
275 DNS_DISPATCHATTR_NOLISTEN);
276 dns_dispatch_detach(&ifp->udpdispatch);
277 udp_dispatch_failure:
282 ns_interface_accepttcp(ns_interface_t *ifp) {
288 result = isc_socket_create(ifp->mgr->socketmgr,
289 isc_sockaddr_pf(&ifp->addr),
292 if (result != ISC_R_SUCCESS) {
293 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
294 "creating TCP socket: %s",
295 isc_result_totext(result));
296 goto tcp_socket_failure;
298 #ifndef ISC_ALLOW_MAPPED
299 isc_socket_ipv6only(ifp->tcpsocket, ISC_TRUE);
301 result = isc_socket_bind(ifp->tcpsocket, &ifp->addr);
302 if (result != ISC_R_SUCCESS) {
303 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
304 "binding TCP socket: %s",
305 isc_result_totext(result));
306 goto tcp_bind_failure;
308 result = isc_socket_listen(ifp->tcpsocket, ns_g_listen);
309 if (result != ISC_R_SUCCESS) {
310 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
311 "listening on TCP socket: %s",
312 isc_result_totext(result));
313 goto tcp_listen_failure;
317 * If/when there a multiple filters listen to the
320 (void)isc_socket_filter(ifp->tcpsocket, "dataready");
322 result = ns_clientmgr_createclients(ifp->clientmgr,
323 ifp->ntcptarget, ifp,
325 if (result != ISC_R_SUCCESS) {
326 UNEXPECTED_ERROR(__FILE__, __LINE__,
327 "TCP ns_clientmgr_createclients(): %s",
328 isc_result_totext(result));
329 goto accepttcp_failure;
331 return (ISC_R_SUCCESS);
336 isc_socket_detach(&ifp->tcpsocket);
338 return (ISC_R_SUCCESS);
342 ns_interface_setup(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
343 const char *name, ns_interface_t **ifpret,
344 isc_boolean_t accept_tcp)
347 ns_interface_t *ifp = NULL;
348 REQUIRE(ifpret != NULL && *ifpret == NULL);
350 result = ns_interface_create(mgr, addr, name, &ifp);
351 if (result != ISC_R_SUCCESS)
354 result = ns_interface_listenudp(ifp);
355 if (result != ISC_R_SUCCESS)
356 goto cleanup_interface;
358 if (accept_tcp == ISC_TRUE) {
359 result = ns_interface_accepttcp(ifp);
360 if (result != ISC_R_SUCCESS) {
362 * XXXRTH We don't currently have a way to easily stop
363 * dispatch service, so we currently return
364 * ISC_R_SUCCESS (the UDP stuff will work even if TCP
365 * creation failed). This will be fixed later.
367 result = ISC_R_SUCCESS;
371 return (ISC_R_SUCCESS);
374 ISC_LIST_UNLINK(ifp->mgr->interfaces, ifp, link);
375 ns_interface_detach(&ifp);
380 ns_interface_shutdown(ns_interface_t *ifp) {
381 if (ifp->clientmgr != NULL)
382 ns_clientmgr_destroy(&ifp->clientmgr);
386 ns_interface_destroy(ns_interface_t *ifp) {
387 isc_mem_t *mctx = ifp->mgr->mctx;
388 REQUIRE(NS_INTERFACE_VALID(ifp));
390 ns_interface_shutdown(ifp);
392 if (ifp->udpdispatch != NULL) {
393 dns_dispatch_changeattributes(ifp->udpdispatch, 0,
394 DNS_DISPATCHATTR_NOLISTEN);
395 dns_dispatch_detach(&ifp->udpdispatch);
397 if (ifp->tcpsocket != NULL)
398 isc_socket_detach(&ifp->tcpsocket);
400 DESTROYLOCK(&ifp->lock);
402 ns_interfacemgr_detach(&ifp->mgr);
405 isc_mem_put(mctx, ifp, sizeof(*ifp));
409 ns_interface_attach(ns_interface_t *source, ns_interface_t **target) {
410 REQUIRE(NS_INTERFACE_VALID(source));
412 INSIST(source->references > 0);
413 source->references++;
414 UNLOCK(&source->lock);
419 ns_interface_detach(ns_interface_t **targetp) {
420 isc_result_t need_destroy = ISC_FALSE;
421 ns_interface_t *target = *targetp;
422 REQUIRE(target != NULL);
423 REQUIRE(NS_INTERFACE_VALID(target));
425 REQUIRE(target->references > 0);
426 target->references--;
427 if (target->references == 0)
428 need_destroy = ISC_TRUE;
429 UNLOCK(&target->lock);
431 ns_interface_destroy(target);
436 * Search the interface list for an interface whose address and port
437 * both match those of 'addr'. Return a pointer to it, or NULL if not found.
439 static ns_interface_t *
440 find_matching_interface(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr) {
442 for (ifp = ISC_LIST_HEAD(mgr->interfaces); ifp != NULL;
443 ifp = ISC_LIST_NEXT(ifp, link)) {
444 if (isc_sockaddr_equal(&ifp->addr, addr))
451 * Remove any interfaces whose generation number is not the current one.
454 purge_old_interfaces(ns_interfacemgr_t *mgr) {
455 ns_interface_t *ifp, *next;
456 for (ifp = ISC_LIST_HEAD(mgr->interfaces); ifp != NULL; ifp = next) {
457 INSIST(NS_INTERFACE_VALID(ifp));
458 next = ISC_LIST_NEXT(ifp, link);
459 if (ifp->generation != mgr->generation) {
461 ISC_LIST_UNLINK(ifp->mgr->interfaces, ifp, link);
462 isc_sockaddr_format(&ifp->addr, sabuf, sizeof(sabuf));
463 isc_log_write(IFMGR_COMMON_LOGARGS,
465 "no longer listening on %s", sabuf);
466 ns_interface_shutdown(ifp);
467 ns_interface_detach(&ifp);
473 clearacl(isc_mem_t *mctx, dns_acl_t **aclp) {
474 dns_acl_t *newacl = NULL;
476 result = dns_acl_create(mctx, 10, &newacl);
477 if (result != ISC_R_SUCCESS)
479 dns_acl_detach(aclp);
480 dns_acl_attach(newacl, aclp);
481 dns_acl_detach(&newacl);
482 return (ISC_R_SUCCESS);
486 listenon_is_ip6_any(ns_listenelt_t *elt) {
487 if (elt->acl->length != 1)
489 if (elt->acl->elements[0].negative == ISC_FALSE &&
490 elt->acl->elements[0].type == dns_aclelementtype_any)
491 return (ISC_TRUE); /* listen-on-v6 { any; } */
492 return (ISC_FALSE); /* All others */
496 setup_locals(ns_interfacemgr_t *mgr, isc_interface_t *interface) {
498 dns_aclelement_t elt;
500 unsigned int prefixlen;
502 family = interface->address.family;
504 elt.type = dns_aclelementtype_ipprefix;
505 elt.negative = ISC_FALSE;
506 elt.u.ip_prefix.address = interface->address;
507 elt.u.ip_prefix.prefixlen = (family == AF_INET) ? 32 : 128;
508 result = dns_acl_appendelement(mgr->aclenv.localhost, &elt);
509 if (result != ISC_R_SUCCESS)
512 result = isc_netaddr_masktoprefixlen(&interface->netmask,
515 /* Non contigious netmasks not allowed by IPv6 arch. */
516 if (result != ISC_R_SUCCESS && family == AF_INET6)
519 if (result != ISC_R_SUCCESS) {
520 isc_log_write(IFMGR_COMMON_LOGARGS,
522 "omitting IPv4 interface %s from "
525 isc_result_totext(result));
527 elt.u.ip_prefix.prefixlen = prefixlen;
528 if (dns_acl_elementmatch(mgr->aclenv.localnets, &elt,
529 NULL) == ISC_R_NOTFOUND) {
530 result = dns_acl_appendelement(mgr->aclenv.localnets,
532 if (result != ISC_R_SUCCESS)
537 return (ISC_R_SUCCESS);
541 do_scan(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen,
542 isc_boolean_t verbose)
544 isc_interfaceiter_t *iter = NULL;
545 isc_boolean_t scan_ipv4 = ISC_FALSE;
546 isc_boolean_t scan_ipv6 = ISC_FALSE;
547 isc_boolean_t adjusting = ISC_FALSE;
548 isc_boolean_t ipv6only = ISC_TRUE;
549 isc_boolean_t ipv6pktinfo = ISC_TRUE;
551 isc_netaddr_t zero_address, zero_address6;
553 isc_sockaddr_t listen_addr;
555 isc_boolean_t log_explicit = ISC_FALSE;
557 if (ext_listen != NULL)
558 adjusting = ISC_TRUE;
560 if (isc_net_probeipv6() == ISC_R_SUCCESS)
561 scan_ipv6 = ISC_TRUE;
564 isc_log_write(IFMGR_COMMON_LOGARGS,
565 verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1),
566 "no IPv6 interfaces found");
569 if (isc_net_probeipv4() == ISC_R_SUCCESS)
570 scan_ipv4 = ISC_TRUE;
572 isc_log_write(IFMGR_COMMON_LOGARGS,
573 verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1),
574 "no IPv4 interfaces found");
577 * A special, but typical case; listen-on-v6 { any; }.
578 * When we can make the socket IPv6-only, open a single wildcard
579 * socket for IPv6 communication. Otherwise, make separate socket
580 * for each IPv6 address in order to avoid accepting IPv4 packets
581 * as the form of mapped addresses unintentionally unless explicitly
584 #ifndef ISC_ALLOW_MAPPED
585 if (scan_ipv6 == ISC_TRUE &&
586 isc_net_probe_ipv6only() != ISC_R_SUCCESS) {
587 ipv6only = ISC_FALSE;
588 log_explicit = ISC_TRUE;
591 if (scan_ipv6 == ISC_TRUE &&
592 isc_net_probe_ipv6pktinfo() != ISC_R_SUCCESS) {
593 ipv6pktinfo = ISC_FALSE;
594 log_explicit = ISC_TRUE;
596 if (scan_ipv6 == ISC_TRUE && ipv6only && ipv6pktinfo) {
597 for (le = ISC_LIST_HEAD(mgr->listenon6->elts);
599 le = ISC_LIST_NEXT(le, link)) {
600 struct in6_addr in6a;
602 if (!listenon_is_ip6_any(le))
606 isc_sockaddr_fromin6(&listen_addr, &in6a, le->port);
608 ifp = find_matching_interface(mgr, &listen_addr);
610 ifp->generation = mgr->generation;
612 isc_log_write(IFMGR_COMMON_LOGARGS,
615 "interfaces, port %u",
617 result = ns_interface_setup(mgr, &listen_addr,
620 if (result == ISC_R_SUCCESS)
621 ifp->flags |= NS_INTERFACEFLAG_ANYADDR;
623 isc_log_write(IFMGR_COMMON_LOGARGS,
625 "listening on all IPv6 "
626 "interfaces failed");
632 isc_netaddr_any(&zero_address);
633 isc_netaddr_any6(&zero_address6);
635 result = isc_interfaceiter_create(mgr->mctx, &iter);
636 if (result != ISC_R_SUCCESS)
639 if (adjusting == ISC_FALSE) {
640 result = clearacl(mgr->mctx, &mgr->aclenv.localhost);
641 if (result != ISC_R_SUCCESS)
643 result = clearacl(mgr->mctx, &mgr->aclenv.localnets);
644 if (result != ISC_R_SUCCESS)
648 for (result = isc_interfaceiter_first(iter);
649 result == ISC_R_SUCCESS;
650 result = isc_interfaceiter_next(iter))
652 isc_interface_t interface;
656 result = isc_interfaceiter_current(iter, &interface);
657 if (result != ISC_R_SUCCESS)
660 family = interface.address.family;
661 if (family != AF_INET && family != AF_INET6)
663 if (scan_ipv4 == ISC_FALSE && family == AF_INET)
665 if (scan_ipv6 == ISC_FALSE && family == AF_INET6)
669 * Test for the address being nonzero rather than testing
670 * INTERFACE_F_UP, because on some systems the latter
671 * follows the media state and we could end up ignoring
672 * the interface for an entire rescan interval due to
673 * a temporary media glitch at rescan time.
675 if (family == AF_INET &&
676 isc_netaddr_equal(&interface.address, &zero_address)) {
679 if (family == AF_INET6 &&
680 isc_netaddr_equal(&interface.address, &zero_address6)) {
684 if (adjusting == ISC_FALSE) {
685 result = setup_locals(mgr, &interface);
686 if (result != ISC_R_SUCCESS)
687 goto ignore_interface;
690 ll = (family == AF_INET) ? mgr->listenon4 : mgr->listenon6;
691 for (le = ISC_LIST_HEAD(ll->elts);
693 le = ISC_LIST_NEXT(le, link))
696 isc_boolean_t ipv6_wildcard = ISC_FALSE;
697 isc_netaddr_t listen_netaddr;
698 isc_sockaddr_t listen_sockaddr;
701 * Construct a socket address for this IP/port
704 if (family == AF_INET) {
705 isc_netaddr_fromin(&listen_netaddr,
706 &interface.address.type.in);
708 isc_netaddr_fromin6(&listen_netaddr,
709 &interface.address.type.in6);
710 isc_netaddr_setzone(&listen_netaddr,
711 interface.address.zone);
713 isc_sockaddr_fromnetaddr(&listen_sockaddr,
718 * See if the address matches the listen-on statement;
719 * if not, ignore the interface.
721 (void)dns_acl_match(&listen_netaddr, NULL, le->acl,
722 &mgr->aclenv, &match, NULL);
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 (void)dns_acl_match(&listen_netaddr,
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);