4 * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1999-2002 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: interfacemgr.c,v 1.95 2009/01/17 23:47:42 tbox Exp */
26 #include <isc/interfaceiter.h>
27 #include <isc/string.h>
32 #include <dns/dispatch.h>
34 #include <named/client.h>
35 #include <named/log.h>
36 #include <named/interfacemgr.h>
38 #define IFMGR_MAGIC ISC_MAGIC('I', 'F', 'M', 'G')
39 #define NS_INTERFACEMGR_VALID(t) ISC_MAGIC_VALID(t, IFMGR_MAGIC)
41 #define IFMGR_COMMON_LOGARGS \
42 ns_g_lctx, NS_LOGCATEGORY_NETWORK, NS_LOGMODULE_INTERFACEMGR
44 /*% nameserver interface manager structure */
45 struct ns_interfacemgr
{
46 unsigned int magic
; /*%< Magic number. */
49 isc_mem_t
* mctx
; /*%< Memory context. */
50 isc_taskmgr_t
* taskmgr
; /*%< Task manager. */
51 isc_socketmgr_t
* socketmgr
; /*%< Socket manager. */
52 dns_dispatchmgr_t
* dispatchmgr
;
53 unsigned int generation
; /*%< Current generation no. */
54 ns_listenlist_t
* listenon4
;
55 ns_listenlist_t
* listenon6
;
56 dns_aclenv_t aclenv
; /*%< Localhost/localnets ACLs */
57 ISC_LIST(ns_interface_t
) interfaces
; /*%< List of interfaces. */
58 ISC_LIST(isc_sockaddr_t
) listenon
;
62 purge_old_interfaces(ns_interfacemgr_t
*mgr
);
65 clearlistenon(ns_interfacemgr_t
*mgr
);
68 ns_interfacemgr_create(isc_mem_t
*mctx
, isc_taskmgr_t
*taskmgr
,
69 isc_socketmgr_t
*socketmgr
,
70 dns_dispatchmgr_t
*dispatchmgr
,
71 ns_interfacemgr_t
**mgrp
)
74 ns_interfacemgr_t
*mgr
;
76 REQUIRE(mctx
!= NULL
);
77 REQUIRE(mgrp
!= NULL
);
78 REQUIRE(*mgrp
== NULL
);
80 mgr
= isc_mem_get(mctx
, sizeof(*mgr
));
82 return (ISC_R_NOMEMORY
);
84 result
= isc_mutex_init(&mgr
->lock
);
85 if (result
!= ISC_R_SUCCESS
)
89 mgr
->taskmgr
= taskmgr
;
90 mgr
->socketmgr
= socketmgr
;
91 mgr
->dispatchmgr
= dispatchmgr
;
93 mgr
->listenon4
= NULL
;
94 mgr
->listenon6
= NULL
;
96 ISC_LIST_INIT(mgr
->interfaces
);
97 ISC_LIST_INIT(mgr
->listenon
);
100 * The listen-on lists are initially empty.
102 result
= ns_listenlist_create(mctx
, &mgr
->listenon4
);
103 if (result
!= ISC_R_SUCCESS
)
105 ns_listenlist_attach(mgr
->listenon4
, &mgr
->listenon6
);
107 result
= dns_aclenv_init(mctx
, &mgr
->aclenv
);
108 if (result
!= ISC_R_SUCCESS
)
109 goto cleanup_listenon
;
112 mgr
->magic
= IFMGR_MAGIC
;
114 return (ISC_R_SUCCESS
);
117 ns_listenlist_detach(&mgr
->listenon4
);
118 ns_listenlist_detach(&mgr
->listenon6
);
120 isc_mem_put(mctx
, mgr
, sizeof(*mgr
));
125 ns_interfacemgr_destroy(ns_interfacemgr_t
*mgr
) {
126 REQUIRE(NS_INTERFACEMGR_VALID(mgr
));
127 dns_aclenv_destroy(&mgr
->aclenv
);
128 ns_listenlist_detach(&mgr
->listenon4
);
129 ns_listenlist_detach(&mgr
->listenon6
);
131 DESTROYLOCK(&mgr
->lock
);
133 isc_mem_put(mgr
->mctx
, mgr
, sizeof(*mgr
));
137 ns_interfacemgr_getaclenv(ns_interfacemgr_t
*mgr
) {
138 return (&mgr
->aclenv
);
142 ns_interfacemgr_attach(ns_interfacemgr_t
*source
, ns_interfacemgr_t
**target
) {
143 REQUIRE(NS_INTERFACEMGR_VALID(source
));
145 INSIST(source
->references
> 0);
146 source
->references
++;
147 UNLOCK(&source
->lock
);
152 ns_interfacemgr_detach(ns_interfacemgr_t
**targetp
) {
153 isc_result_t need_destroy
= ISC_FALSE
;
154 ns_interfacemgr_t
*target
= *targetp
;
155 REQUIRE(target
!= NULL
);
156 REQUIRE(NS_INTERFACEMGR_VALID(target
));
158 REQUIRE(target
->references
> 0);
159 target
->references
--;
160 if (target
->references
== 0)
161 need_destroy
= ISC_TRUE
;
162 UNLOCK(&target
->lock
);
164 ns_interfacemgr_destroy(target
);
169 ns_interfacemgr_shutdown(ns_interfacemgr_t
*mgr
) {
170 REQUIRE(NS_INTERFACEMGR_VALID(mgr
));
173 * Shut down and detach all interfaces.
174 * By incrementing the generation count, we make purge_old_interfaces()
175 * consider all interfaces "old".
178 purge_old_interfaces(mgr
);
183 ns_interface_create(ns_interfacemgr_t
*mgr
, isc_sockaddr_t
*addr
,
184 const char *name
, ns_interface_t
**ifpret
)
189 REQUIRE(NS_INTERFACEMGR_VALID(mgr
));
190 ifp
= isc_mem_get(mgr
->mctx
, sizeof(*ifp
));
192 return (ISC_R_NOMEMORY
);
194 ifp
->generation
= mgr
->generation
;
197 strncpy(ifp
->name
, name
, sizeof(ifp
->name
));
198 ifp
->name
[sizeof(ifp
->name
)-1] = '\0';
199 ifp
->clientmgr
= NULL
;
201 result
= isc_mutex_init(&ifp
->lock
);
202 if (result
!= ISC_R_SUCCESS
)
203 goto lock_create_failure
;
205 result
= ns_clientmgr_create(mgr
->mctx
, mgr
->taskmgr
,
208 if (result
!= ISC_R_SUCCESS
) {
209 isc_log_write(IFMGR_COMMON_LOGARGS
, ISC_LOG_ERROR
,
210 "ns_clientmgr_create() failed: %s",
211 isc_result_totext(result
));
212 goto clientmgr_create_failure
;
215 ifp
->udpdispatch
= NULL
;
217 ifp
->tcpsocket
= NULL
;
219 * Create a single TCP client object. It will replace itself
220 * with a new one as soon as it gets a connection, so the actual
221 * connections will be handled in parallel even though there is
222 * only one client initially.
225 ifp
->ntcpcurrent
= 0;
227 ISC_LINK_INIT(ifp
, link
);
229 ns_interfacemgr_attach(mgr
, &ifp
->mgr
);
230 ISC_LIST_APPEND(mgr
->interfaces
, ifp
, link
);
233 ifp
->magic
= IFACE_MAGIC
;
236 return (ISC_R_SUCCESS
);
238 clientmgr_create_failure
:
239 DESTROYLOCK(&ifp
->lock
);
242 isc_mem_put(mgr
->mctx
, ifp
, sizeof(*ifp
));
244 return (ISC_R_UNEXPECTED
);
248 ns_interface_listenudp(ns_interface_t
*ifp
) {
251 unsigned int attrmask
;
254 attrs
|= DNS_DISPATCHATTR_UDP
;
255 if (isc_sockaddr_pf(&ifp
->addr
) == AF_INET
)
256 attrs
|= DNS_DISPATCHATTR_IPV4
;
258 attrs
|= DNS_DISPATCHATTR_IPV6
;
259 attrs
|= DNS_DISPATCHATTR_NOLISTEN
;
261 attrmask
|= DNS_DISPATCHATTR_UDP
| DNS_DISPATCHATTR_TCP
;
262 attrmask
|= DNS_DISPATCHATTR_IPV4
| DNS_DISPATCHATTR_IPV6
;
263 result
= dns_dispatch_getudp(ifp
->mgr
->dispatchmgr
, ns_g_socketmgr
,
264 ns_g_taskmgr
, &ifp
->addr
,
265 4096, 1000, 32768, 8219, 8237,
266 attrs
, attrmask
, &ifp
->udpdispatch
);
267 if (result
!= ISC_R_SUCCESS
) {
268 isc_log_write(IFMGR_COMMON_LOGARGS
, ISC_LOG_ERROR
,
269 "could not listen on UDP socket: %s",
270 isc_result_totext(result
));
271 goto udp_dispatch_failure
;
274 result
= ns_clientmgr_createclients(ifp
->clientmgr
, ns_g_cpus
,
276 if (result
!= ISC_R_SUCCESS
) {
277 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
278 "UDP ns_clientmgr_createclients(): %s",
279 isc_result_totext(result
));
280 goto addtodispatch_failure
;
282 return (ISC_R_SUCCESS
);
284 addtodispatch_failure
:
285 dns_dispatch_changeattributes(ifp
->udpdispatch
, 0,
286 DNS_DISPATCHATTR_NOLISTEN
);
287 dns_dispatch_detach(&ifp
->udpdispatch
);
288 udp_dispatch_failure
:
293 ns_interface_accepttcp(ns_interface_t
*ifp
) {
299 result
= isc_socket_create(ifp
->mgr
->socketmgr
,
300 isc_sockaddr_pf(&ifp
->addr
),
303 if (result
!= ISC_R_SUCCESS
) {
304 isc_log_write(IFMGR_COMMON_LOGARGS
, ISC_LOG_ERROR
,
305 "creating TCP socket: %s",
306 isc_result_totext(result
));
307 goto tcp_socket_failure
;
309 isc_socket_setname(ifp
->tcpsocket
, "dispatcher", NULL
);
310 #ifndef ISC_ALLOW_MAPPED
311 isc_socket_ipv6only(ifp
->tcpsocket
, ISC_TRUE
);
313 result
= isc_socket_bind(ifp
->tcpsocket
, &ifp
->addr
,
314 ISC_SOCKET_REUSEADDRESS
);
315 if (result
!= ISC_R_SUCCESS
) {
316 isc_log_write(IFMGR_COMMON_LOGARGS
, ISC_LOG_ERROR
,
317 "binding TCP socket: %s",
318 isc_result_totext(result
));
319 goto tcp_bind_failure
;
321 result
= isc_socket_listen(ifp
->tcpsocket
, ns_g_listen
);
322 if (result
!= ISC_R_SUCCESS
) {
323 isc_log_write(IFMGR_COMMON_LOGARGS
, ISC_LOG_ERROR
,
324 "listening on TCP socket: %s",
325 isc_result_totext(result
));
326 goto tcp_listen_failure
;
330 * If/when there a multiple filters listen to the
333 (void)isc_socket_filter(ifp
->tcpsocket
, "dataready");
335 result
= ns_clientmgr_createclients(ifp
->clientmgr
,
336 ifp
->ntcptarget
, ifp
,
338 if (result
!= ISC_R_SUCCESS
) {
339 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
340 "TCP ns_clientmgr_createclients(): %s",
341 isc_result_totext(result
));
342 goto accepttcp_failure
;
344 return (ISC_R_SUCCESS
);
349 isc_socket_detach(&ifp
->tcpsocket
);
351 return (ISC_R_SUCCESS
);
355 ns_interface_setup(ns_interfacemgr_t
*mgr
, isc_sockaddr_t
*addr
,
356 const char *name
, ns_interface_t
**ifpret
,
357 isc_boolean_t accept_tcp
)
360 ns_interface_t
*ifp
= NULL
;
361 REQUIRE(ifpret
!= NULL
&& *ifpret
== NULL
);
363 result
= ns_interface_create(mgr
, addr
, name
, &ifp
);
364 if (result
!= ISC_R_SUCCESS
)
367 result
= ns_interface_listenudp(ifp
);
368 if (result
!= ISC_R_SUCCESS
)
369 goto cleanup_interface
;
371 if (accept_tcp
== ISC_TRUE
) {
372 result
= ns_interface_accepttcp(ifp
);
373 if (result
!= ISC_R_SUCCESS
) {
375 * XXXRTH We don't currently have a way to easily stop
376 * dispatch service, so we currently return
377 * ISC_R_SUCCESS (the UDP stuff will work even if TCP
378 * creation failed). This will be fixed later.
380 result
= ISC_R_SUCCESS
;
384 return (ISC_R_SUCCESS
);
387 ISC_LIST_UNLINK(ifp
->mgr
->interfaces
, ifp
, link
);
388 ns_interface_detach(&ifp
);
393 ns_interface_shutdown(ns_interface_t
*ifp
) {
394 if (ifp
->clientmgr
!= NULL
)
395 ns_clientmgr_destroy(&ifp
->clientmgr
);
399 ns_interface_destroy(ns_interface_t
*ifp
) {
400 isc_mem_t
*mctx
= ifp
->mgr
->mctx
;
401 REQUIRE(NS_INTERFACE_VALID(ifp
));
403 ns_interface_shutdown(ifp
);
405 if (ifp
->udpdispatch
!= NULL
) {
406 dns_dispatch_changeattributes(ifp
->udpdispatch
, 0,
407 DNS_DISPATCHATTR_NOLISTEN
);
408 dns_dispatch_detach(&ifp
->udpdispatch
);
410 if (ifp
->tcpsocket
!= NULL
)
411 isc_socket_detach(&ifp
->tcpsocket
);
413 DESTROYLOCK(&ifp
->lock
);
415 ns_interfacemgr_detach(&ifp
->mgr
);
418 isc_mem_put(mctx
, ifp
, sizeof(*ifp
));
422 ns_interface_attach(ns_interface_t
*source
, ns_interface_t
**target
) {
423 REQUIRE(NS_INTERFACE_VALID(source
));
425 INSIST(source
->references
> 0);
426 source
->references
++;
427 UNLOCK(&source
->lock
);
432 ns_interface_detach(ns_interface_t
**targetp
) {
433 isc_result_t need_destroy
= ISC_FALSE
;
434 ns_interface_t
*target
= *targetp
;
435 REQUIRE(target
!= NULL
);
436 REQUIRE(NS_INTERFACE_VALID(target
));
438 REQUIRE(target
->references
> 0);
439 target
->references
--;
440 if (target
->references
== 0)
441 need_destroy
= ISC_TRUE
;
442 UNLOCK(&target
->lock
);
444 ns_interface_destroy(target
);
449 * Search the interface list for an interface whose address and port
450 * both match those of 'addr'. Return a pointer to it, or NULL if not found.
452 static ns_interface_t
*
453 find_matching_interface(ns_interfacemgr_t
*mgr
, isc_sockaddr_t
*addr
) {
455 for (ifp
= ISC_LIST_HEAD(mgr
->interfaces
); ifp
!= NULL
;
456 ifp
= ISC_LIST_NEXT(ifp
, link
)) {
457 if (isc_sockaddr_equal(&ifp
->addr
, addr
))
464 * Remove any interfaces whose generation number is not the current one.
467 purge_old_interfaces(ns_interfacemgr_t
*mgr
) {
468 ns_interface_t
*ifp
, *next
;
469 for (ifp
= ISC_LIST_HEAD(mgr
->interfaces
); ifp
!= NULL
; ifp
= next
) {
470 INSIST(NS_INTERFACE_VALID(ifp
));
471 next
= ISC_LIST_NEXT(ifp
, link
);
472 if (ifp
->generation
!= mgr
->generation
) {
474 ISC_LIST_UNLINK(ifp
->mgr
->interfaces
, ifp
, link
);
475 isc_sockaddr_format(&ifp
->addr
, sabuf
, sizeof(sabuf
));
476 isc_log_write(IFMGR_COMMON_LOGARGS
,
478 "no longer listening on %s", sabuf
);
479 ns_interface_shutdown(ifp
);
480 ns_interface_detach(&ifp
);
486 clearacl(isc_mem_t
*mctx
, dns_acl_t
**aclp
) {
487 dns_acl_t
*newacl
= NULL
;
489 result
= dns_acl_create(mctx
, 0, &newacl
);
490 if (result
!= ISC_R_SUCCESS
)
492 dns_acl_detach(aclp
);
493 dns_acl_attach(newacl
, aclp
);
494 dns_acl_detach(&newacl
);
495 return (ISC_R_SUCCESS
);
499 listenon_is_ip6_any(ns_listenelt_t
*elt
) {
500 REQUIRE(elt
&& elt
->acl
);
501 return dns_acl_isany(elt
->acl
);
505 setup_locals(ns_interfacemgr_t
*mgr
, isc_interface_t
*interface
) {
507 unsigned int prefixlen
;
508 isc_netaddr_t
*netaddr
;
510 netaddr
= &interface
->address
;
512 /* First add localhost address */
513 prefixlen
= (netaddr
->family
== AF_INET
) ? 32 : 128;
514 result
= dns_iptable_addprefix(mgr
->aclenv
.localhost
->iptable
,
515 netaddr
, prefixlen
, ISC_TRUE
);
516 if (result
!= ISC_R_SUCCESS
)
519 /* Then add localnets prefix */
520 result
= isc_netaddr_masktoprefixlen(&interface
->netmask
,
523 /* Non contiguous netmasks not allowed by IPv6 arch. */
524 if (result
!= ISC_R_SUCCESS
&& netaddr
->family
== AF_INET6
)
527 if (result
!= ISC_R_SUCCESS
) {
528 isc_log_write(IFMGR_COMMON_LOGARGS
,
530 "omitting IPv4 interface %s from "
533 isc_result_totext(result
));
534 return (ISC_R_SUCCESS
);
537 result
= dns_iptable_addprefix(mgr
->aclenv
.localnets
->iptable
,
538 netaddr
, prefixlen
, ISC_TRUE
);
539 if (result
!= ISC_R_SUCCESS
)
542 return (ISC_R_SUCCESS
);
546 setup_listenon(ns_interfacemgr_t
*mgr
, isc_interface_t
*interface
,
549 isc_sockaddr_t
*addr
;
552 addr
= isc_mem_get(mgr
->mctx
, sizeof(*addr
));
556 isc_sockaddr_fromnetaddr(addr
, &interface
->address
, port
);
558 for (old
= ISC_LIST_HEAD(mgr
->listenon
);
560 old
= ISC_LIST_NEXT(old
, link
))
561 if (isc_sockaddr_equal(addr
, old
))
565 isc_mem_put(mgr
->mctx
, addr
, sizeof(*addr
));
567 ISC_LIST_APPEND(mgr
->listenon
, addr
, link
);
571 clearlistenon(ns_interfacemgr_t
*mgr
) {
574 old
= ISC_LIST_HEAD(mgr
->listenon
);
575 while (old
!= NULL
) {
576 ISC_LIST_UNLINK(mgr
->listenon
, old
, link
);
577 isc_mem_put(mgr
->mctx
, old
, sizeof(*old
));
578 old
= ISC_LIST_HEAD(mgr
->listenon
);
583 do_scan(ns_interfacemgr_t
*mgr
, ns_listenlist_t
*ext_listen
,
584 isc_boolean_t verbose
)
586 isc_interfaceiter_t
*iter
= NULL
;
587 isc_boolean_t scan_ipv4
= ISC_FALSE
;
588 isc_boolean_t scan_ipv6
= ISC_FALSE
;
589 isc_boolean_t adjusting
= ISC_FALSE
;
590 isc_boolean_t ipv6only
= ISC_TRUE
;
591 isc_boolean_t ipv6pktinfo
= ISC_TRUE
;
593 isc_netaddr_t zero_address
, zero_address6
;
595 isc_sockaddr_t listen_addr
;
597 isc_boolean_t log_explicit
= ISC_FALSE
;
598 isc_boolean_t dolistenon
;
600 if (ext_listen
!= NULL
)
601 adjusting
= ISC_TRUE
;
603 if (isc_net_probeipv6() == ISC_R_SUCCESS
)
604 scan_ipv6
= ISC_TRUE
;
607 isc_log_write(IFMGR_COMMON_LOGARGS
,
608 verbose
? ISC_LOG_INFO
: ISC_LOG_DEBUG(1),
609 "no IPv6 interfaces found");
612 if (isc_net_probeipv4() == ISC_R_SUCCESS
)
613 scan_ipv4
= ISC_TRUE
;
615 isc_log_write(IFMGR_COMMON_LOGARGS
,
616 verbose
? ISC_LOG_INFO
: ISC_LOG_DEBUG(1),
617 "no IPv4 interfaces found");
620 * A special, but typical case; listen-on-v6 { any; }.
621 * When we can make the socket IPv6-only, open a single wildcard
622 * socket for IPv6 communication. Otherwise, make separate socket
623 * for each IPv6 address in order to avoid accepting IPv4 packets
624 * as the form of mapped addresses unintentionally unless explicitly
627 #ifndef ISC_ALLOW_MAPPED
628 if (scan_ipv6
== ISC_TRUE
&&
629 isc_net_probe_ipv6only() != ISC_R_SUCCESS
) {
630 ipv6only
= ISC_FALSE
;
631 log_explicit
= ISC_TRUE
;
634 if (scan_ipv6
== ISC_TRUE
&&
635 isc_net_probe_ipv6pktinfo() != ISC_R_SUCCESS
) {
636 ipv6pktinfo
= ISC_FALSE
;
637 log_explicit
= ISC_TRUE
;
639 if (scan_ipv6
== ISC_TRUE
&& ipv6only
&& ipv6pktinfo
) {
640 for (le
= ISC_LIST_HEAD(mgr
->listenon6
->elts
);
642 le
= ISC_LIST_NEXT(le
, link
)) {
643 struct in6_addr in6a
;
645 if (!listenon_is_ip6_any(le
))
649 isc_sockaddr_fromin6(&listen_addr
, &in6a
, le
->port
);
651 ifp
= find_matching_interface(mgr
, &listen_addr
);
653 ifp
->generation
= mgr
->generation
;
655 isc_log_write(IFMGR_COMMON_LOGARGS
,
658 "interfaces, port %u",
660 result
= ns_interface_setup(mgr
, &listen_addr
,
663 if (result
== ISC_R_SUCCESS
)
664 ifp
->flags
|= NS_INTERFACEFLAG_ANYADDR
;
666 isc_log_write(IFMGR_COMMON_LOGARGS
,
668 "listening on all IPv6 "
669 "interfaces failed");
675 isc_netaddr_any(&zero_address
);
676 isc_netaddr_any6(&zero_address6
);
678 result
= isc_interfaceiter_create(mgr
->mctx
, &iter
);
679 if (result
!= ISC_R_SUCCESS
)
682 if (adjusting
== ISC_FALSE
) {
683 result
= clearacl(mgr
->mctx
, &mgr
->aclenv
.localhost
);
684 if (result
!= ISC_R_SUCCESS
)
686 result
= clearacl(mgr
->mctx
, &mgr
->aclenv
.localnets
);
687 if (result
!= ISC_R_SUCCESS
)
692 for (result
= isc_interfaceiter_first(iter
);
693 result
== ISC_R_SUCCESS
;
694 result
= isc_interfaceiter_next(iter
))
696 isc_interface_t interface
;
700 result
= isc_interfaceiter_current(iter
, &interface
);
701 if (result
!= ISC_R_SUCCESS
)
704 family
= interface
.address
.family
;
705 if (family
!= AF_INET
&& family
!= AF_INET6
)
707 if (scan_ipv4
== ISC_FALSE
&& family
== AF_INET
)
709 if (scan_ipv6
== ISC_FALSE
&& family
== AF_INET6
)
713 * Test for the address being nonzero rather than testing
714 * INTERFACE_F_UP, because on some systems the latter
715 * follows the media state and we could end up ignoring
716 * the interface for an entire rescan interval due to
717 * a temporary media glitch at rescan time.
719 if (family
== AF_INET
&&
720 isc_netaddr_equal(&interface
.address
, &zero_address
)) {
723 if (family
== AF_INET6
&&
724 isc_netaddr_equal(&interface
.address
, &zero_address6
)) {
728 if (adjusting
== ISC_FALSE
) {
729 result
= setup_locals(mgr
, &interface
);
730 if (result
!= ISC_R_SUCCESS
)
731 goto ignore_interface
;
734 ll
= (family
== AF_INET
) ? mgr
->listenon4
: mgr
->listenon6
;
735 dolistenon
= ISC_TRUE
;
736 for (le
= ISC_LIST_HEAD(ll
->elts
);
738 le
= ISC_LIST_NEXT(le
, link
))
741 isc_boolean_t ipv6_wildcard
= ISC_FALSE
;
742 isc_netaddr_t listen_netaddr
;
743 isc_sockaddr_t listen_sockaddr
;
746 * Construct a socket address for this IP/port
749 if (family
== AF_INET
) {
750 isc_netaddr_fromin(&listen_netaddr
,
751 &interface
.address
.type
.in
);
753 isc_netaddr_fromin6(&listen_netaddr
,
754 &interface
.address
.type
.in6
);
755 isc_netaddr_setzone(&listen_netaddr
,
756 interface
.address
.zone
);
758 isc_sockaddr_fromnetaddr(&listen_sockaddr
,
763 * See if the address matches the listen-on statement;
764 * if not, ignore the interface.
766 (void)dns_acl_match(&listen_netaddr
, NULL
, le
->acl
,
767 &mgr
->aclenv
, &match
, NULL
);
771 if (adjusting
== ISC_FALSE
&& dolistenon
== ISC_TRUE
) {
772 setup_listenon(mgr
, &interface
, le
->port
);
773 dolistenon
= ISC_FALSE
;
777 * The case of "any" IPv6 address will require
778 * special considerations later, so remember it.
780 if (family
== AF_INET6
&& ipv6only
&& ipv6pktinfo
&&
781 listenon_is_ip6_any(le
))
782 ipv6_wildcard
= ISC_TRUE
;
785 * When adjusting interfaces with extra a listening
786 * list, see if the address matches the extra list.
787 * If it does, and is also covered by a wildcard
788 * interface, we need to listen on the address
791 if (adjusting
== ISC_TRUE
) {
795 for (ele
= ISC_LIST_HEAD(ext_listen
->elts
);
797 ele
= ISC_LIST_NEXT(ele
, link
)) {
798 (void)dns_acl_match(&listen_netaddr
,
802 (ele
->port
== le
->port
||
808 if (ipv6_wildcard
== ISC_TRUE
&& match
== 0)
812 ifp
= find_matching_interface(mgr
, &listen_sockaddr
);
814 ifp
->generation
= mgr
->generation
;
816 char sabuf
[ISC_SOCKADDR_FORMATSIZE
];
818 if (adjusting
== ISC_FALSE
&&
819 ipv6_wildcard
== ISC_TRUE
)
822 if (log_explicit
&& family
== AF_INET6
&&
823 !adjusting
&& listenon_is_ip6_any(le
)) {
824 isc_log_write(IFMGR_COMMON_LOGARGS
,
825 verbose
? ISC_LOG_INFO
:
827 "IPv6 socket API is "
828 "incomplete; explicitly "
829 "binding to each IPv6 "
830 "address separately");
831 log_explicit
= ISC_FALSE
;
833 isc_sockaddr_format(&listen_sockaddr
,
834 sabuf
, sizeof(sabuf
));
835 isc_log_write(IFMGR_COMMON_LOGARGS
,
838 "listening on %s interface "
840 (adjusting
== ISC_TRUE
) ?
841 "additionally " : "",
842 (family
== AF_INET
) ?
844 interface
.name
, sabuf
);
846 result
= ns_interface_setup(mgr
,
850 (adjusting
== ISC_TRUE
) ?
854 if (result
!= ISC_R_SUCCESS
) {
855 isc_log_write(IFMGR_COMMON_LOGARGS
,
857 "creating %s interface "
858 "%s failed; interface "
860 (family
== AF_INET
) ?
871 isc_log_write(IFMGR_COMMON_LOGARGS
,
873 "ignoring %s interface %s: %s",
874 (family
== AF_INET
) ? "IPv4" : "IPv6",
875 interface
.name
, isc_result_totext(result
));
878 if (result
!= ISC_R_NOMORE
)
879 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
880 "interface iteration failed: %s",
881 isc_result_totext(result
));
883 result
= ISC_R_SUCCESS
;
885 isc_interfaceiter_destroy(&iter
);
890 ns_interfacemgr_scan0(ns_interfacemgr_t
*mgr
, ns_listenlist_t
*ext_listen
,
891 isc_boolean_t verbose
)
893 isc_boolean_t purge
= ISC_TRUE
;
895 REQUIRE(NS_INTERFACEMGR_VALID(mgr
));
897 mgr
->generation
++; /* Increment the generation count. */
899 if (do_scan(mgr
, ext_listen
, verbose
) != ISC_R_SUCCESS
)
903 * Now go through the interface list and delete anything that
904 * does not have the current generation number. This is
905 * how we catch interfaces that go away or change their
909 purge_old_interfaces(mgr
);
912 * Warn if we are not listening on any interface, unless
913 * we're in lwresd-only mode, in which case that is to
916 if (ext_listen
== NULL
&&
917 ISC_LIST_EMPTY(mgr
->interfaces
) && ! ns_g_lwresdonly
) {
918 isc_log_write(IFMGR_COMMON_LOGARGS
, ISC_LOG_WARNING
,
919 "not listening on any interfaces");
924 ns_interfacemgr_scan(ns_interfacemgr_t
*mgr
, isc_boolean_t verbose
) {
925 ns_interfacemgr_scan0(mgr
, NULL
, verbose
);
929 ns_interfacemgr_adjust(ns_interfacemgr_t
*mgr
, ns_listenlist_t
*list
,
930 isc_boolean_t verbose
)
932 ns_interfacemgr_scan0(mgr
, list
, verbose
);
936 ns_interfacemgr_setlistenon4(ns_interfacemgr_t
*mgr
, ns_listenlist_t
*value
) {
938 ns_listenlist_detach(&mgr
->listenon4
);
939 ns_listenlist_attach(value
, &mgr
->listenon4
);
944 ns_interfacemgr_setlistenon6(ns_interfacemgr_t
*mgr
, ns_listenlist_t
*value
) {
946 ns_listenlist_detach(&mgr
->listenon6
);
947 ns_listenlist_attach(value
, &mgr
->listenon6
);
952 ns_interfacemgr_dumprecursing(FILE *f
, ns_interfacemgr_t
*mgr
) {
953 ns_interface_t
*interface
;
956 interface
= ISC_LIST_HEAD(mgr
->interfaces
);
957 while (interface
!= NULL
) {
958 if (interface
->clientmgr
!= NULL
)
959 ns_client_dumprecursing(f
, interface
->clientmgr
);
960 interface
= ISC_LIST_NEXT(interface
, link
);
966 ns_interfacemgr_listeningon(ns_interfacemgr_t
*mgr
, isc_sockaddr_t
*addr
) {
969 old
= ISC_LIST_HEAD(mgr
->listenon
);
970 for (old
= ISC_LIST_HEAD(mgr
->listenon
);
972 old
= ISC_LIST_NEXT(old
, link
))
973 if (isc_sockaddr_equal(old
, addr
))