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
);