1 /* $NetBSD: interfacemgr.c,v 1.10 2015/07/08 17:28:55 christos Exp $ */
4 * Copyright (C) 2004-2009, 2011-2015 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.101 2011/11/09 18:44:03 each Exp */
26 #include <isc/interfaceiter.h>
28 #include <isc/string.h>
33 #include <dns/dispatch.h>
35 #include <named/client.h>
36 #include <named/log.h>
37 #include <named/interfacemgr.h>
38 #include <named/server.h>
40 #ifdef HAVE_NET_ROUTE_H
41 #include <net/route.h>
42 #if defined(RTM_VERSION) && defined(RTM_NEWADDR) && defined(RTM_DELADDR)
43 #define USE_ROUTE_SOCKET 1
44 #define ROUTE_SOCKET_PROTOCOL PF_ROUTE
45 #define MSGHDR rt_msghdr
46 #define MSGTYPE rtm_type
50 #if defined(HAVE_LINUX_NETLINK_H) && defined(HAVE_LINUX_RTNETLINK_H)
51 #include <linux/netlink.h>
52 #include <linux/rtnetlink.h>
53 #if defined(RTM_NEWADDR) && defined(RTM_DELADDR)
54 #define USE_ROUTE_SOCKET 1
55 #define ROUTE_SOCKET_PROTOCOL PF_NETLINK
56 #define MSGHDR nlmsghdr
57 #define MSGTYPE nlmsg_type
62 #define UDPBUFFERS 32768
64 #define UDPBUFFERS 1000
65 #endif /* TUNE_LARGE */
67 #define IFMGR_MAGIC ISC_MAGIC('I', 'F', 'M', 'G')
68 #define NS_INTERFACEMGR_VALID(t) ISC_MAGIC_VALID(t, IFMGR_MAGIC)
70 #define IFMGR_COMMON_LOGARGS \
71 ns_g_lctx, NS_LOGCATEGORY_NETWORK, NS_LOGMODULE_INTERFACEMGR
73 /*% nameserver interface manager structure */
74 struct ns_interfacemgr
{
75 unsigned int magic
; /*%< Magic number. */
78 isc_mem_t
* mctx
; /*%< Memory context. */
79 isc_taskmgr_t
* taskmgr
; /*%< Task manager. */
80 isc_socketmgr_t
* socketmgr
; /*%< Socket manager. */
81 dns_dispatchmgr_t
* dispatchmgr
;
82 unsigned int generation
; /*%< Current generation no. */
83 ns_listenlist_t
* listenon4
;
84 ns_listenlist_t
* listenon6
;
85 dns_aclenv_t aclenv
; /*%< Localhost/localnets ACLs */
86 ISC_LIST(ns_interface_t
) interfaces
; /*%< List of interfaces. */
87 ISC_LIST(isc_sockaddr_t
) listenon
;
88 #ifdef USE_ROUTE_SOCKET
91 unsigned char buf
[2048];
96 purge_old_interfaces(ns_interfacemgr_t
*mgr
);
99 clearlistenon(ns_interfacemgr_t
*mgr
);
101 #ifdef USE_ROUTE_SOCKET
103 route_event(isc_task_t
*task
, isc_event_t
*event
) {
104 isc_socketevent_t
*sevent
= NULL
;
105 ns_interfacemgr_t
*mgr
= NULL
;
109 isc_boolean_t done
= ISC_TRUE
;
113 REQUIRE(event
->ev_type
== ISC_SOCKEVENT_RECVDONE
);
115 sevent
= (isc_socketevent_t
*)event
;
117 if (sevent
->result
!= ISC_R_SUCCESS
) {
118 if (sevent
->result
!= ISC_R_CANCELED
)
119 isc_log_write(IFMGR_COMMON_LOGARGS
, ISC_LOG_ERROR
,
120 "automatic interface scanning "
122 isc_result_totext(sevent
->result
));
123 ns_interfacemgr_detach(&mgr
);
124 isc_event_free(&event
);
128 rtm
= (struct MSGHDR
*)mgr
->buf
;
130 if (rtm
->rtm_version
!= RTM_VERSION
) {
131 isc_log_write(IFMGR_COMMON_LOGARGS
, ISC_LOG_ERROR
,
132 "automatic interface rescanning disabled: "
133 "rtm->rtm_version mismatch (%u != %u) "
134 "recompile required", rtm
->rtm_version
,
136 ns_interfacemgr_detach(&mgr
);
137 isc_event_free(&event
);
142 switch (rtm
->MSGTYPE
) {
145 if (mgr
->route
!= NULL
&& ns_g_server
->interface_auto
)
146 ns_server_scan_interfaces(ns_g_server
);
153 if (mgr
->route
!= NULL
) {
155 * Look for next route event.
158 r
.length
= sizeof(mgr
->buf
);
159 result
= isc_socket_recv(mgr
->route
, &r
, 1, mgr
->task
,
161 if (result
== ISC_R_SUCCESS
)
167 ns_interfacemgr_detach(&mgr
);
168 isc_event_free(&event
);
174 ns_interfacemgr_create(isc_mem_t
*mctx
, isc_taskmgr_t
*taskmgr
,
175 isc_socketmgr_t
*socketmgr
,
176 dns_dispatchmgr_t
*dispatchmgr
,
177 isc_task_t
*task
, ns_interfacemgr_t
**mgrp
)
180 ns_interfacemgr_t
*mgr
;
182 #ifndef USE_ROUTE_SOCKET
186 REQUIRE(mctx
!= NULL
);
187 REQUIRE(mgrp
!= NULL
);
188 REQUIRE(*mgrp
== NULL
);
190 mgr
= isc_mem_get(mctx
, sizeof(*mgr
));
192 return (ISC_R_NOMEMORY
);
195 isc_mem_attach(mctx
, &mgr
->mctx
);
197 result
= isc_mutex_init(&mgr
->lock
);
198 if (result
!= ISC_R_SUCCESS
)
201 mgr
->taskmgr
= taskmgr
;
202 mgr
->socketmgr
= socketmgr
;
203 mgr
->dispatchmgr
= dispatchmgr
;
205 mgr
->listenon4
= NULL
;
206 mgr
->listenon6
= NULL
;
208 ISC_LIST_INIT(mgr
->interfaces
);
209 ISC_LIST_INIT(mgr
->listenon
);
212 * The listen-on lists are initially empty.
214 result
= ns_listenlist_create(mctx
, &mgr
->listenon4
);
215 if (result
!= ISC_R_SUCCESS
)
217 ns_listenlist_attach(mgr
->listenon4
, &mgr
->listenon6
);
219 result
= dns_aclenv_init(mctx
, &mgr
->aclenv
);
220 if (result
!= ISC_R_SUCCESS
)
221 goto cleanup_listenon
;
223 mgr
->aclenv
.geoip
= ns_g_geoip
;
226 #ifdef USE_ROUTE_SOCKET
228 result
= isc_socket_create(mgr
->socketmgr
, ROUTE_SOCKET_PROTOCOL
,
229 isc_sockettype_raw
, &mgr
->route
);
233 case ISC_R_NOTIMPLEMENTED
:
234 case ISC_R_FAMILYNOSUPPORT
:
241 if (mgr
->route
!= NULL
)
242 isc_task_attach(task
, &mgr
->task
);
243 mgr
->references
= (mgr
->route
!= NULL
) ? 2 : 1;
247 mgr
->magic
= IFMGR_MAGIC
;
250 #ifdef USE_ROUTE_SOCKET
251 if (mgr
->route
!= NULL
) {
252 isc_region_t r
= { mgr
->buf
, sizeof(mgr
->buf
) };
254 result
= isc_socket_recv(mgr
->route
, &r
, 1, mgr
->task
,
256 if (result
!= ISC_R_SUCCESS
) {
257 isc_task_detach(&mgr
->task
);
258 isc_socket_detach(&mgr
->route
);
259 ns_interfacemgr_detach(&mgr
);
263 return (ISC_R_SUCCESS
);
265 #ifdef USE_ROUTE_SOCKET
267 dns_aclenv_destroy(&mgr
->aclenv
);
270 ns_listenlist_detach(&mgr
->listenon4
);
271 ns_listenlist_detach(&mgr
->listenon6
);
273 isc_mem_putanddetach(&mgr
->mctx
, mgr
, sizeof(*mgr
));
278 ns_interfacemgr_destroy(ns_interfacemgr_t
*mgr
) {
279 REQUIRE(NS_INTERFACEMGR_VALID(mgr
));
281 #ifdef USE_ROUTE_SOCKET
282 if (mgr
->route
!= NULL
)
283 isc_socket_detach(&mgr
->route
);
284 if (mgr
->task
!= NULL
)
285 isc_task_detach(&mgr
->task
);
287 dns_aclenv_destroy(&mgr
->aclenv
);
288 ns_listenlist_detach(&mgr
->listenon4
);
289 ns_listenlist_detach(&mgr
->listenon6
);
291 DESTROYLOCK(&mgr
->lock
);
293 isc_mem_putanddetach(&mgr
->mctx
, mgr
, sizeof(*mgr
));
297 ns_interfacemgr_getaclenv(ns_interfacemgr_t
*mgr
) {
298 return (&mgr
->aclenv
);
302 ns_interfacemgr_attach(ns_interfacemgr_t
*source
, ns_interfacemgr_t
**target
) {
303 REQUIRE(NS_INTERFACEMGR_VALID(source
));
305 INSIST(source
->references
> 0);
306 source
->references
++;
307 UNLOCK(&source
->lock
);
312 ns_interfacemgr_detach(ns_interfacemgr_t
**targetp
) {
313 isc_result_t need_destroy
= ISC_FALSE
;
314 ns_interfacemgr_t
*target
= *targetp
;
315 REQUIRE(target
!= NULL
);
316 REQUIRE(NS_INTERFACEMGR_VALID(target
));
318 REQUIRE(target
->references
> 0);
319 target
->references
--;
320 if (target
->references
== 0)
321 need_destroy
= ISC_TRUE
;
322 UNLOCK(&target
->lock
);
324 ns_interfacemgr_destroy(target
);
329 ns_interfacemgr_shutdown(ns_interfacemgr_t
*mgr
) {
330 REQUIRE(NS_INTERFACEMGR_VALID(mgr
));
333 * Shut down and detach all interfaces.
334 * By incrementing the generation count, we make purge_old_interfaces()
335 * consider all interfaces "old".
338 #ifdef USE_ROUTE_SOCKET
340 if (mgr
->route
!= NULL
) {
341 isc_socket_cancel(mgr
->route
, mgr
->task
, ISC_SOCKCANCEL_RECV
);
342 isc_socket_detach(&mgr
->route
);
343 isc_task_detach(&mgr
->task
);
347 purge_old_interfaces(mgr
);
352 ns_interface_create(ns_interfacemgr_t
*mgr
, isc_sockaddr_t
*addr
,
353 const char *name
, ns_interface_t
**ifpret
)
359 REQUIRE(NS_INTERFACEMGR_VALID(mgr
));
361 ifp
= isc_mem_get(mgr
->mctx
, sizeof(*ifp
));
363 return (ISC_R_NOMEMORY
);
366 ifp
->generation
= mgr
->generation
;
369 strncpy(ifp
->name
, name
, sizeof(ifp
->name
));
370 ifp
->name
[sizeof(ifp
->name
)-1] = '\0';
371 ifp
->clientmgr
= NULL
;
373 result
= isc_mutex_init(&ifp
->lock
);
374 if (result
!= ISC_R_SUCCESS
)
375 goto lock_create_failure
;
377 result
= ns_clientmgr_create(mgr
->mctx
, mgr
->taskmgr
,
380 if (result
!= ISC_R_SUCCESS
) {
381 isc_log_write(IFMGR_COMMON_LOGARGS
, ISC_LOG_ERROR
,
382 "ns_clientmgr_create() failed: %s",
383 isc_result_totext(result
));
384 goto clientmgr_create_failure
;
387 for (disp
= 0; disp
< MAX_UDP_DISPATCH
; disp
++)
388 ifp
->udpdispatch
[disp
] = NULL
;
390 ifp
->tcpsocket
= NULL
;
393 * Create a single TCP client object. It will replace itself
394 * with a new one as soon as it gets a connection, so the actual
395 * connections will be handled in parallel even though there is
396 * only one client initially.
399 ifp
->ntcpcurrent
= 0;
400 ifp
->nudpdispatch
= 0;
404 ISC_LINK_INIT(ifp
, link
);
406 ns_interfacemgr_attach(mgr
, &ifp
->mgr
);
407 ISC_LIST_APPEND(mgr
->interfaces
, ifp
, link
);
410 ifp
->magic
= IFACE_MAGIC
;
413 return (ISC_R_SUCCESS
);
415 clientmgr_create_failure
:
416 DESTROYLOCK(&ifp
->lock
);
420 isc_mem_put(mgr
->mctx
, ifp
, sizeof(*ifp
));
422 return (ISC_R_UNEXPECTED
);
426 ns_interface_listenudp(ns_interface_t
*ifp
) {
429 unsigned int attrmask
;
433 attrs
|= DNS_DISPATCHATTR_UDP
;
434 if (isc_sockaddr_pf(&ifp
->addr
) == AF_INET
)
435 attrs
|= DNS_DISPATCHATTR_IPV4
;
437 attrs
|= DNS_DISPATCHATTR_IPV6
;
438 attrs
|= DNS_DISPATCHATTR_NOLISTEN
;
440 attrmask
|= DNS_DISPATCHATTR_UDP
| DNS_DISPATCHATTR_TCP
;
441 attrmask
|= DNS_DISPATCHATTR_IPV4
| DNS_DISPATCHATTR_IPV6
;
443 ifp
->nudpdispatch
= ISC_MIN(ns_g_udpdisp
, MAX_UDP_DISPATCH
);
444 for (disp
= 0; disp
< ifp
->nudpdispatch
; disp
++) {
445 result
= dns_dispatch_getudp_dup(ifp
->mgr
->dispatchmgr
,
447 ns_g_taskmgr
, &ifp
->addr
,
451 &ifp
->udpdispatch
[disp
],
454 : ifp
->udpdispatch
[0]);
455 if (result
!= ISC_R_SUCCESS
) {
456 isc_log_write(IFMGR_COMMON_LOGARGS
, ISC_LOG_ERROR
,
457 "could not listen on UDP socket: %s",
458 isc_result_totext(result
));
459 goto udp_dispatch_failure
;
464 result
= ns_clientmgr_createclients(ifp
->clientmgr
, ifp
->nudpdispatch
,
466 if (result
!= ISC_R_SUCCESS
) {
467 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
468 "UDP ns_clientmgr_createclients(): %s",
469 isc_result_totext(result
));
470 goto addtodispatch_failure
;
473 return (ISC_R_SUCCESS
);
475 addtodispatch_failure
:
476 for (i
= disp
- 1; i
<= 0; i
--) {
477 dns_dispatch_changeattributes(ifp
->udpdispatch
[i
], 0,
478 DNS_DISPATCHATTR_NOLISTEN
);
479 dns_dispatch_detach(&(ifp
->udpdispatch
[i
]));
481 ifp
->nudpdispatch
= 0;
483 udp_dispatch_failure
:
488 ns_interface_accepttcp(ns_interface_t
*ifp
) {
494 result
= isc_socket_create(ifp
->mgr
->socketmgr
,
495 isc_sockaddr_pf(&ifp
->addr
),
498 if (result
!= ISC_R_SUCCESS
) {
499 isc_log_write(IFMGR_COMMON_LOGARGS
, ISC_LOG_ERROR
,
500 "creating TCP socket: %s",
501 isc_result_totext(result
));
502 goto tcp_socket_failure
;
504 isc_socket_setname(ifp
->tcpsocket
, "dispatcher", NULL
);
505 #ifndef ISC_ALLOW_MAPPED
506 isc_socket_ipv6only(ifp
->tcpsocket
, ISC_TRUE
);
508 result
= isc_socket_bind(ifp
->tcpsocket
, &ifp
->addr
,
509 ISC_SOCKET_REUSEADDRESS
);
510 if (result
!= ISC_R_SUCCESS
) {
511 isc_log_write(IFMGR_COMMON_LOGARGS
, ISC_LOG_ERROR
,
512 "binding TCP socket: %s",
513 isc_result_totext(result
));
514 goto tcp_bind_failure
;
518 isc_socket_dscp(ifp
->tcpsocket
, ifp
->dscp
);
520 result
= isc_socket_listen(ifp
->tcpsocket
, ns_g_listen
);
521 if (result
!= ISC_R_SUCCESS
) {
522 isc_log_write(IFMGR_COMMON_LOGARGS
, ISC_LOG_ERROR
,
523 "listening on TCP socket: %s",
524 isc_result_totext(result
));
525 goto tcp_listen_failure
;
529 * If/when there a multiple filters listen to the
532 (void)isc_socket_filter(ifp
->tcpsocket
, "dataready");
534 result
= ns_clientmgr_createclients(ifp
->clientmgr
,
535 ifp
->ntcptarget
, ifp
,
537 if (result
!= ISC_R_SUCCESS
) {
538 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
539 "TCP ns_clientmgr_createclients(): %s",
540 isc_result_totext(result
));
541 goto accepttcp_failure
;
543 return (ISC_R_SUCCESS
);
548 isc_socket_detach(&ifp
->tcpsocket
);
550 return (ISC_R_SUCCESS
);
554 ns_interface_setup(ns_interfacemgr_t
*mgr
, isc_sockaddr_t
*addr
,
555 const char *name
, ns_interface_t
**ifpret
,
556 isc_boolean_t accept_tcp
, isc_dscp_t dscp
)
559 ns_interface_t
*ifp
= NULL
;
560 REQUIRE(ifpret
!= NULL
&& *ifpret
== NULL
);
562 result
= ns_interface_create(mgr
, addr
, name
, &ifp
);
563 if (result
!= ISC_R_SUCCESS
)
568 result
= ns_interface_listenudp(ifp
);
569 if (result
!= ISC_R_SUCCESS
)
570 goto cleanup_interface
;
572 if (!ns_g_notcp
&& accept_tcp
== ISC_TRUE
) {
573 result
= ns_interface_accepttcp(ifp
);
574 if (result
!= ISC_R_SUCCESS
) {
576 * XXXRTH We don't currently have a way to easily stop
577 * dispatch service, so we currently return
578 * ISC_R_SUCCESS (the UDP stuff will work even if TCP
579 * creation failed). This will be fixed later.
581 result
= ISC_R_SUCCESS
;
588 ISC_LIST_UNLINK(ifp
->mgr
->interfaces
, ifp
, link
);
589 ns_interface_detach(&ifp
);
594 ns_interface_shutdown(ns_interface_t
*ifp
) {
595 if (ifp
->clientmgr
!= NULL
)
596 ns_clientmgr_destroy(&ifp
->clientmgr
);
600 ns_interface_destroy(ns_interface_t
*ifp
) {
601 isc_mem_t
*mctx
= ifp
->mgr
->mctx
;
604 REQUIRE(NS_INTERFACE_VALID(ifp
));
606 ns_interface_shutdown(ifp
);
608 for (disp
= 0; disp
< ifp
->nudpdispatch
; disp
++)
609 if (ifp
->udpdispatch
[disp
] != NULL
) {
610 dns_dispatch_changeattributes(ifp
->udpdispatch
[disp
], 0,
611 DNS_DISPATCHATTR_NOLISTEN
);
612 dns_dispatch_detach(&(ifp
->udpdispatch
[disp
]));
615 if (ifp
->tcpsocket
!= NULL
)
616 isc_socket_detach(&ifp
->tcpsocket
);
618 DESTROYLOCK(&ifp
->lock
);
620 ns_interfacemgr_detach(&ifp
->mgr
);
623 isc_mem_put(mctx
, ifp
, sizeof(*ifp
));
627 ns_interface_attach(ns_interface_t
*source
, ns_interface_t
**target
) {
628 REQUIRE(NS_INTERFACE_VALID(source
));
630 INSIST(source
->references
> 0);
631 source
->references
++;
632 UNLOCK(&source
->lock
);
637 ns_interface_detach(ns_interface_t
**targetp
) {
638 isc_result_t need_destroy
= ISC_FALSE
;
639 ns_interface_t
*target
= *targetp
;
640 REQUIRE(target
!= NULL
);
641 REQUIRE(NS_INTERFACE_VALID(target
));
643 REQUIRE(target
->references
> 0);
644 target
->references
--;
645 if (target
->references
== 0)
646 need_destroy
= ISC_TRUE
;
647 UNLOCK(&target
->lock
);
649 ns_interface_destroy(target
);
654 * Search the interface list for an interface whose address and port
655 * both match those of 'addr'. Return a pointer to it, or NULL if not found.
657 static ns_interface_t
*
658 find_matching_interface(ns_interfacemgr_t
*mgr
, isc_sockaddr_t
*addr
) {
660 for (ifp
= ISC_LIST_HEAD(mgr
->interfaces
); ifp
!= NULL
;
661 ifp
= ISC_LIST_NEXT(ifp
, link
)) {
662 if (isc_sockaddr_equal(&ifp
->addr
, addr
))
669 * Remove any interfaces whose generation number is not the current one.
672 purge_old_interfaces(ns_interfacemgr_t
*mgr
) {
673 ns_interface_t
*ifp
, *next
;
674 for (ifp
= ISC_LIST_HEAD(mgr
->interfaces
); ifp
!= NULL
; ifp
= next
) {
675 INSIST(NS_INTERFACE_VALID(ifp
));
676 next
= ISC_LIST_NEXT(ifp
, link
);
677 if (ifp
->generation
!= mgr
->generation
) {
679 ISC_LIST_UNLINK(ifp
->mgr
->interfaces
, ifp
, link
);
680 isc_sockaddr_format(&ifp
->addr
, sabuf
, sizeof(sabuf
));
681 isc_log_write(IFMGR_COMMON_LOGARGS
,
683 "no longer listening on %s", sabuf
);
684 ns_interface_shutdown(ifp
);
685 ns_interface_detach(&ifp
);
691 clearacl(isc_mem_t
*mctx
, dns_acl_t
**aclp
) {
692 dns_acl_t
*newacl
= NULL
;
694 result
= dns_acl_create(mctx
, 0, &newacl
);
695 if (result
!= ISC_R_SUCCESS
)
697 dns_acl_detach(aclp
);
698 dns_acl_attach(newacl
, aclp
);
699 dns_acl_detach(&newacl
);
700 return (ISC_R_SUCCESS
);
704 listenon_is_ip6_any(ns_listenelt_t
*elt
) {
705 REQUIRE(elt
&& elt
->acl
);
706 return dns_acl_isany(elt
->acl
);
710 setup_locals(ns_interfacemgr_t
*mgr
, isc_interface_t
*interface
) {
712 unsigned int prefixlen
;
713 isc_netaddr_t
*netaddr
;
715 netaddr
= &interface
->address
;
717 /* First add localhost address */
718 prefixlen
= (netaddr
->family
== AF_INET
) ? 32 : 128;
719 result
= dns_iptable_addprefix(mgr
->aclenv
.localhost
->iptable
,
720 netaddr
, prefixlen
, ISC_TRUE
);
721 if (result
!= ISC_R_SUCCESS
)
724 /* Then add localnets prefix */
725 result
= isc_netaddr_masktoprefixlen(&interface
->netmask
,
728 /* Non contiguous netmasks not allowed by IPv6 arch. */
729 if (result
!= ISC_R_SUCCESS
&& netaddr
->family
== AF_INET6
)
732 if (result
!= ISC_R_SUCCESS
) {
733 isc_log_write(IFMGR_COMMON_LOGARGS
, ISC_LOG_WARNING
,
734 "omitting IPv4 interface %s from "
735 "localnets ACL: %s", interface
->name
,
736 isc_result_totext(result
));
737 return (ISC_R_SUCCESS
);
740 if (prefixlen
== 0U) {
741 isc_log_write(IFMGR_COMMON_LOGARGS
, ISC_LOG_WARNING
,
742 "omitting %s interface %s from localnets ACL: "
743 "zero prefix length detected",
744 (netaddr
->family
== AF_INET
) ? "IPv4" : "IPv6",
746 return (ISC_R_SUCCESS
);
749 result
= dns_iptable_addprefix(mgr
->aclenv
.localnets
->iptable
,
750 netaddr
, prefixlen
, ISC_TRUE
);
751 if (result
!= ISC_R_SUCCESS
)
754 return (ISC_R_SUCCESS
);
758 setup_listenon(ns_interfacemgr_t
*mgr
, isc_interface_t
*interface
,
761 isc_sockaddr_t
*addr
;
764 addr
= isc_mem_get(mgr
->mctx
, sizeof(*addr
));
768 isc_sockaddr_fromnetaddr(addr
, &interface
->address
, port
);
770 for (old
= ISC_LIST_HEAD(mgr
->listenon
);
772 old
= ISC_LIST_NEXT(old
, link
))
773 if (isc_sockaddr_equal(addr
, old
))
777 isc_mem_put(mgr
->mctx
, addr
, sizeof(*addr
));
779 ISC_LIST_APPEND(mgr
->listenon
, addr
, link
);
783 clearlistenon(ns_interfacemgr_t
*mgr
) {
786 old
= ISC_LIST_HEAD(mgr
->listenon
);
787 while (old
!= NULL
) {
788 ISC_LIST_UNLINK(mgr
->listenon
, old
, link
);
789 isc_mem_put(mgr
->mctx
, old
, sizeof(*old
));
790 old
= ISC_LIST_HEAD(mgr
->listenon
);
795 do_scan(ns_interfacemgr_t
*mgr
, ns_listenlist_t
*ext_listen
,
796 isc_boolean_t verbose
)
798 isc_interfaceiter_t
*iter
= NULL
;
799 isc_boolean_t scan_ipv4
= ISC_FALSE
;
800 isc_boolean_t scan_ipv6
= ISC_FALSE
;
801 isc_boolean_t adjusting
= ISC_FALSE
;
802 isc_boolean_t ipv6only
= ISC_TRUE
;
803 isc_boolean_t ipv6pktinfo
= ISC_TRUE
;
805 isc_netaddr_t zero_address
, zero_address6
;
807 isc_sockaddr_t listen_addr
;
809 isc_boolean_t log_explicit
= ISC_FALSE
;
810 isc_boolean_t dolistenon
;
811 char sabuf
[ISC_SOCKADDR_FORMATSIZE
];
813 if (ext_listen
!= NULL
)
814 adjusting
= ISC_TRUE
;
816 if (isc_net_probeipv6() == ISC_R_SUCCESS
)
817 scan_ipv6
= ISC_TRUE
;
819 else if (!ns_g_disable6
)
820 isc_log_write(IFMGR_COMMON_LOGARGS
,
821 verbose
? ISC_LOG_INFO
: ISC_LOG_DEBUG(1),
822 "no IPv6 interfaces found");
825 if (isc_net_probeipv4() == ISC_R_SUCCESS
)
826 scan_ipv4
= ISC_TRUE
;
827 else if (!ns_g_disable4
)
828 isc_log_write(IFMGR_COMMON_LOGARGS
,
829 verbose
? ISC_LOG_INFO
: ISC_LOG_DEBUG(1),
830 "no IPv4 interfaces found");
833 * A special, but typical case; listen-on-v6 { any; }.
834 * When we can make the socket IPv6-only, open a single wildcard
835 * socket for IPv6 communication. Otherwise, make separate socket
836 * for each IPv6 address in order to avoid accepting IPv4 packets
837 * as the form of mapped addresses unintentionally unless explicitly
840 #ifndef ISC_ALLOW_MAPPED
841 if (scan_ipv6
== ISC_TRUE
&&
842 isc_net_probe_ipv6only() != ISC_R_SUCCESS
) {
843 ipv6only
= ISC_FALSE
;
844 log_explicit
= ISC_TRUE
;
847 if (scan_ipv6
== ISC_TRUE
&&
848 isc_net_probe_ipv6pktinfo() != ISC_R_SUCCESS
) {
849 ipv6pktinfo
= ISC_FALSE
;
850 log_explicit
= ISC_TRUE
;
852 if (scan_ipv6
== ISC_TRUE
&& ipv6only
&& ipv6pktinfo
) {
853 for (le
= ISC_LIST_HEAD(mgr
->listenon6
->elts
);
855 le
= ISC_LIST_NEXT(le
, link
)) {
856 struct in6_addr in6a
;
858 if (!listenon_is_ip6_any(le
))
862 isc_sockaddr_fromin6(&listen_addr
, &in6a
, le
->port
);
864 ifp
= find_matching_interface(mgr
, &listen_addr
);
866 ifp
->generation
= mgr
->generation
;
867 if (le
->dscp
!= -1 && ifp
->dscp
== -1)
868 ifp
->dscp
= le
->dscp
;
869 else if (le
->dscp
!= ifp
->dscp
) {
870 isc_sockaddr_format(&listen_addr
,
873 isc_log_write(IFMGR_COMMON_LOGARGS
,
875 "%s: conflicting DSCP "
880 isc_log_write(IFMGR_COMMON_LOGARGS
,
883 "interfaces, port %u",
885 result
= ns_interface_setup(mgr
, &listen_addr
,
889 if (result
== ISC_R_SUCCESS
)
890 ifp
->flags
|= NS_INTERFACEFLAG_ANYADDR
;
892 isc_log_write(IFMGR_COMMON_LOGARGS
,
894 "listening on all IPv6 "
895 "interfaces failed");
901 isc_netaddr_any(&zero_address
);
902 isc_netaddr_any6(&zero_address6
);
904 result
= isc_interfaceiter_create(mgr
->mctx
, &iter
);
905 if (result
!= ISC_R_SUCCESS
)
908 if (adjusting
== ISC_FALSE
) {
909 result
= clearacl(mgr
->mctx
, &mgr
->aclenv
.localhost
);
910 if (result
!= ISC_R_SUCCESS
)
912 result
= clearacl(mgr
->mctx
, &mgr
->aclenv
.localnets
);
913 if (result
!= ISC_R_SUCCESS
)
918 for (result
= isc_interfaceiter_first(iter
);
919 result
== ISC_R_SUCCESS
;
920 result
= isc_interfaceiter_next(iter
))
922 isc_interface_t interface
;
926 result
= isc_interfaceiter_current(iter
, &interface
);
927 if (result
!= ISC_R_SUCCESS
)
930 family
= interface
.address
.family
;
931 if (family
!= AF_INET
&& family
!= AF_INET6
)
933 if (scan_ipv4
== ISC_FALSE
&& family
== AF_INET
)
935 if (scan_ipv6
== ISC_FALSE
&& family
== AF_INET6
)
939 * Test for the address being nonzero rather than testing
940 * INTERFACE_F_UP, because on some systems the latter
941 * follows the media state and we could end up ignoring
942 * the interface for an entire rescan interval due to
943 * a temporary media glitch at rescan time.
945 if (family
== AF_INET
&&
946 isc_netaddr_equal(&interface
.address
, &zero_address
)) {
949 if (family
== AF_INET6
&&
950 isc_netaddr_equal(&interface
.address
, &zero_address6
)) {
954 if (adjusting
== ISC_FALSE
) {
955 result
= setup_locals(mgr
, &interface
);
956 if (result
!= ISC_R_SUCCESS
)
957 goto ignore_interface
;
960 ll
= (family
== AF_INET
) ? mgr
->listenon4
: mgr
->listenon6
;
961 dolistenon
= ISC_TRUE
;
962 for (le
= ISC_LIST_HEAD(ll
->elts
);
964 le
= ISC_LIST_NEXT(le
, link
))
967 isc_boolean_t ipv6_wildcard
= ISC_FALSE
;
968 isc_netaddr_t listen_netaddr
;
969 isc_sockaddr_t listen_sockaddr
;
972 * Construct a socket address for this IP/port
975 if (family
== AF_INET
) {
976 isc_netaddr_fromin(&listen_netaddr
,
977 &interface
.address
.type
.in
);
979 isc_netaddr_fromin6(&listen_netaddr
,
980 &interface
.address
.type
.in6
);
981 isc_netaddr_setzone(&listen_netaddr
,
982 interface
.address
.zone
);
984 isc_sockaddr_fromnetaddr(&listen_sockaddr
,
989 * See if the address matches the listen-on statement;
990 * if not, ignore the interface.
992 (void)dns_acl_match(&listen_netaddr
, NULL
, le
->acl
,
993 &mgr
->aclenv
, &match
, NULL
);
997 if (adjusting
== ISC_FALSE
&& dolistenon
== ISC_TRUE
) {
998 setup_listenon(mgr
, &interface
, le
->port
);
999 dolistenon
= ISC_FALSE
;
1003 * The case of "any" IPv6 address will require
1004 * special considerations later, so remember it.
1006 if (family
== AF_INET6
&& ipv6only
&& ipv6pktinfo
&&
1007 listenon_is_ip6_any(le
))
1008 ipv6_wildcard
= ISC_TRUE
;
1011 * When adjusting interfaces with extra a listening
1012 * list, see if the address matches the extra list.
1013 * If it does, and is also covered by a wildcard
1014 * interface, we need to listen on the address
1017 if (adjusting
== ISC_TRUE
) {
1018 ns_listenelt_t
*ele
;
1021 for (ele
= ISC_LIST_HEAD(ext_listen
->elts
);
1023 ele
= ISC_LIST_NEXT(ele
, link
)) {
1024 (void)dns_acl_match(&listen_netaddr
,
1026 NULL
, &match
, NULL
);
1028 (ele
->port
== le
->port
||
1034 if (ipv6_wildcard
== ISC_TRUE
&& match
== 0)
1038 ifp
= find_matching_interface(mgr
, &listen_sockaddr
);
1040 ifp
->generation
= mgr
->generation
;
1041 if (le
->dscp
!= -1 && ifp
->dscp
== -1)
1042 ifp
->dscp
= le
->dscp
;
1043 else if (le
->dscp
!= ifp
->dscp
) {
1044 isc_sockaddr_format(&listen_sockaddr
,
1047 isc_log_write(IFMGR_COMMON_LOGARGS
,
1049 "%s: conflicting DSCP "
1054 if (adjusting
== ISC_FALSE
&&
1055 ipv6_wildcard
== ISC_TRUE
)
1058 if (log_explicit
&& family
== AF_INET6
&&
1059 !adjusting
&& listenon_is_ip6_any(le
)) {
1060 isc_log_write(IFMGR_COMMON_LOGARGS
,
1061 verbose
? ISC_LOG_INFO
:
1063 "IPv6 socket API is "
1064 "incomplete; explicitly "
1065 "binding to each IPv6 "
1066 "address separately");
1067 log_explicit
= ISC_FALSE
;
1069 isc_sockaddr_format(&listen_sockaddr
,
1070 sabuf
, sizeof(sabuf
));
1071 isc_log_write(IFMGR_COMMON_LOGARGS
,
1074 "listening on %s interface "
1076 (adjusting
== ISC_TRUE
) ?
1077 "additionally " : "",
1078 (family
== AF_INET
) ?
1080 interface
.name
, sabuf
);
1082 result
= ns_interface_setup(mgr
,
1086 (adjusting
== ISC_TRUE
) ?
1087 ISC_FALSE
: ISC_TRUE
,
1090 if (result
!= ISC_R_SUCCESS
) {
1091 isc_log_write(IFMGR_COMMON_LOGARGS
,
1093 "creating %s interface "
1094 "%s failed; interface "
1096 (family
== AF_INET
) ?
1107 isc_log_write(IFMGR_COMMON_LOGARGS
,
1109 "ignoring %s interface %s: %s",
1110 (family
== AF_INET
) ? "IPv4" : "IPv6",
1111 interface
.name
, isc_result_totext(result
));
1114 if (result
!= ISC_R_NOMORE
)
1115 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
1116 "interface iteration failed: %s",
1117 isc_result_totext(result
));
1119 result
= ISC_R_SUCCESS
;
1121 isc_interfaceiter_destroy(&iter
);
1126 ns_interfacemgr_scan0(ns_interfacemgr_t
*mgr
, ns_listenlist_t
*ext_listen
,
1127 isc_boolean_t verbose
)
1129 isc_boolean_t purge
= ISC_TRUE
;
1131 REQUIRE(NS_INTERFACEMGR_VALID(mgr
));
1133 mgr
->generation
++; /* Increment the generation count. */
1135 if (do_scan(mgr
, ext_listen
, verbose
) != ISC_R_SUCCESS
)
1139 * Now go through the interface list and delete anything that
1140 * does not have the current generation number. This is
1141 * how we catch interfaces that go away or change their
1145 purge_old_interfaces(mgr
);
1148 * Warn if we are not listening on any interface, unless
1149 * we're in lwresd-only mode, in which case that is to
1152 if (ext_listen
== NULL
&&
1153 ISC_LIST_EMPTY(mgr
->interfaces
) && ! ns_g_lwresdonly
) {
1154 isc_log_write(IFMGR_COMMON_LOGARGS
, ISC_LOG_WARNING
,
1155 "not listening on any interfaces");
1160 ns_interfacemgr_scan(ns_interfacemgr_t
*mgr
, isc_boolean_t verbose
) {
1161 ns_interfacemgr_scan0(mgr
, NULL
, verbose
);
1165 ns_interfacemgr_adjust(ns_interfacemgr_t
*mgr
, ns_listenlist_t
*list
,
1166 isc_boolean_t verbose
)
1168 ns_interfacemgr_scan0(mgr
, list
, verbose
);
1172 ns_interfacemgr_setlistenon4(ns_interfacemgr_t
*mgr
, ns_listenlist_t
*value
) {
1174 ns_listenlist_detach(&mgr
->listenon4
);
1175 ns_listenlist_attach(value
, &mgr
->listenon4
);
1180 ns_interfacemgr_setlistenon6(ns_interfacemgr_t
*mgr
, ns_listenlist_t
*value
) {
1182 ns_listenlist_detach(&mgr
->listenon6
);
1183 ns_listenlist_attach(value
, &mgr
->listenon6
);
1188 ns_interfacemgr_dumprecursing(FILE *f
, ns_interfacemgr_t
*mgr
) {
1189 ns_interface_t
*interface
;
1192 interface
= ISC_LIST_HEAD(mgr
->interfaces
);
1193 while (interface
!= NULL
) {
1194 if (interface
->clientmgr
!= NULL
)
1195 ns_client_dumprecursing(f
, interface
->clientmgr
);
1196 interface
= ISC_LIST_NEXT(interface
, link
);
1202 ns_interfacemgr_listeningon(ns_interfacemgr_t
*mgr
, isc_sockaddr_t
*addr
) {
1203 isc_sockaddr_t
*old
;
1205 for (old
= ISC_LIST_HEAD(mgr
->listenon
);
1207 old
= ISC_LIST_NEXT(old
, link
))
1208 if (isc_sockaddr_equal(old
, addr
))