summaryrefslogtreecommitdiffstats
path: root/contrib/bind9/bin/named/interfacemgr.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/bind9/bin/named/interfacemgr.c')
-rw-r--r--contrib/bind9/bin/named/interfacemgr.c978
1 files changed, 0 insertions, 978 deletions
diff --git a/contrib/bind9/bin/named/interfacemgr.c b/contrib/bind9/bin/named/interfacemgr.c
deleted file mode 100644
index db41031..0000000
--- a/contrib/bind9/bin/named/interfacemgr.c
+++ /dev/null
@@ -1,978 +0,0 @@
-/*
- * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
- * Copyright (C) 1999-2002 Internet Software Consortium.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
- * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
- * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
- * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
-
-/* $Id: interfacemgr.c,v 1.76.18.8 2006/07/20 01:10:30 marka Exp $ */
-
-/*! \file */
-
-#include <config.h>
-
-#include <isc/interfaceiter.h>
-#include <isc/string.h>
-#include <isc/task.h>
-#include <isc/util.h>
-
-#include <dns/acl.h>
-#include <dns/dispatch.h>
-
-#include <named/client.h>
-#include <named/log.h>
-#include <named/interfacemgr.h>
-
-#define IFMGR_MAGIC ISC_MAGIC('I', 'F', 'M', 'G')
-#define NS_INTERFACEMGR_VALID(t) ISC_MAGIC_VALID(t, IFMGR_MAGIC)
-
-#define IFMGR_COMMON_LOGARGS \
- ns_g_lctx, NS_LOGCATEGORY_NETWORK, NS_LOGMODULE_INTERFACEMGR
-
-/*% nameserver interface manager structure */
-struct ns_interfacemgr {
- unsigned int magic; /*%< Magic number. */
- int references;
- isc_mutex_t lock;
- isc_mem_t * mctx; /*%< Memory context. */
- isc_taskmgr_t * taskmgr; /*%< Task manager. */
- isc_socketmgr_t * socketmgr; /*%< Socket manager. */
- dns_dispatchmgr_t * dispatchmgr;
- unsigned int generation; /*%< Current generation no. */
- ns_listenlist_t * listenon4;
- ns_listenlist_t * listenon6;
- dns_aclenv_t aclenv; /*%< Localhost/localnets ACLs */
- ISC_LIST(ns_interface_t) interfaces; /*%< List of interfaces. */
- ISC_LIST(isc_sockaddr_t) listenon;
-};
-
-static void
-purge_old_interfaces(ns_interfacemgr_t *mgr);
-
-static void
-clearlistenon(ns_interfacemgr_t *mgr);
-
-isc_result_t
-ns_interfacemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
- isc_socketmgr_t *socketmgr,
- dns_dispatchmgr_t *dispatchmgr,
- ns_interfacemgr_t **mgrp)
-{
- isc_result_t result;
- ns_interfacemgr_t *mgr;
-
- REQUIRE(mctx != NULL);
- REQUIRE(mgrp != NULL);
- REQUIRE(*mgrp == NULL);
-
- mgr = isc_mem_get(mctx, sizeof(*mgr));
- if (mgr == NULL)
- return (ISC_R_NOMEMORY);
-
- result = isc_mutex_init(&mgr->lock);
- if (result != ISC_R_SUCCESS)
- goto cleanup_mem;
-
- mgr->mctx = mctx;
- mgr->taskmgr = taskmgr;
- mgr->socketmgr = socketmgr;
- mgr->dispatchmgr = dispatchmgr;
- mgr->generation = 1;
- mgr->listenon4 = NULL;
- mgr->listenon6 = NULL;
-
- ISC_LIST_INIT(mgr->interfaces);
- ISC_LIST_INIT(mgr->listenon);
-
- /*
- * The listen-on lists are initially empty.
- */
- result = ns_listenlist_create(mctx, &mgr->listenon4);
- if (result != ISC_R_SUCCESS)
- goto cleanup_mem;
- ns_listenlist_attach(mgr->listenon4, &mgr->listenon6);
-
- result = dns_aclenv_init(mctx, &mgr->aclenv);
- if (result != ISC_R_SUCCESS)
- goto cleanup_listenon;
-
- mgr->references = 1;
- mgr->magic = IFMGR_MAGIC;
- *mgrp = mgr;
- return (ISC_R_SUCCESS);
-
- cleanup_listenon:
- ns_listenlist_detach(&mgr->listenon4);
- ns_listenlist_detach(&mgr->listenon6);
- cleanup_mem:
- isc_mem_put(mctx, mgr, sizeof(*mgr));
- return (result);
-}
-
-static void
-ns_interfacemgr_destroy(ns_interfacemgr_t *mgr) {
- REQUIRE(NS_INTERFACEMGR_VALID(mgr));
- dns_aclenv_destroy(&mgr->aclenv);
- ns_listenlist_detach(&mgr->listenon4);
- ns_listenlist_detach(&mgr->listenon6);
- clearlistenon(mgr);
- DESTROYLOCK(&mgr->lock);
- mgr->magic = 0;
- isc_mem_put(mgr->mctx, mgr, sizeof(*mgr));
-}
-
-dns_aclenv_t *
-ns_interfacemgr_getaclenv(ns_interfacemgr_t *mgr) {
- return (&mgr->aclenv);
-}
-
-void
-ns_interfacemgr_attach(ns_interfacemgr_t *source, ns_interfacemgr_t **target) {
- REQUIRE(NS_INTERFACEMGR_VALID(source));
- LOCK(&source->lock);
- INSIST(source->references > 0);
- source->references++;
- UNLOCK(&source->lock);
- *target = source;
-}
-
-void
-ns_interfacemgr_detach(ns_interfacemgr_t **targetp) {
- isc_result_t need_destroy = ISC_FALSE;
- ns_interfacemgr_t *target = *targetp;
- REQUIRE(target != NULL);
- REQUIRE(NS_INTERFACEMGR_VALID(target));
- LOCK(&target->lock);
- REQUIRE(target->references > 0);
- target->references--;
- if (target->references == 0)
- need_destroy = ISC_TRUE;
- UNLOCK(&target->lock);
- if (need_destroy)
- ns_interfacemgr_destroy(target);
- *targetp = NULL;
-}
-
-void
-ns_interfacemgr_shutdown(ns_interfacemgr_t *mgr) {
- REQUIRE(NS_INTERFACEMGR_VALID(mgr));
-
- /*%
- * Shut down and detach all interfaces.
- * By incrementing the generation count, we make purge_old_interfaces()
- * consider all interfaces "old".
- */
- mgr->generation++;
- purge_old_interfaces(mgr);
-}
-
-
-static isc_result_t
-ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
- const char *name, ns_interface_t **ifpret)
-{
- ns_interface_t *ifp;
- isc_result_t result;
-
- REQUIRE(NS_INTERFACEMGR_VALID(mgr));
- ifp = isc_mem_get(mgr->mctx, sizeof(*ifp));
- if (ifp == NULL)
- return (ISC_R_NOMEMORY);
- ifp->mgr = NULL;
- ifp->generation = mgr->generation;
- ifp->addr = *addr;
- ifp->flags = 0;
- strncpy(ifp->name, name, sizeof(ifp->name));
- ifp->name[sizeof(ifp->name)-1] = '\0';
- ifp->clientmgr = NULL;
-
- result = isc_mutex_init(&ifp->lock);
- if (result != ISC_R_SUCCESS)
- goto lock_create_failure;
-
- result = ns_clientmgr_create(mgr->mctx, mgr->taskmgr,
- ns_g_timermgr,
- &ifp->clientmgr);
- if (result != ISC_R_SUCCESS) {
- isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
- "ns_clientmgr_create() failed: %s",
- isc_result_totext(result));
- goto clientmgr_create_failure;
- }
-
- ifp->udpdispatch = NULL;
-
- ifp->tcpsocket = NULL;
- /*
- * Create a single TCP client object. It will replace itself
- * with a new one as soon as it gets a connection, so the actual
- * connections will be handled in parallel even though there is
- * only one client initially.
- */
- ifp->ntcptarget = 1;
- ifp->ntcpcurrent = 0;
-
- ISC_LINK_INIT(ifp, link);
-
- ns_interfacemgr_attach(mgr, &ifp->mgr);
- ISC_LIST_APPEND(mgr->interfaces, ifp, link);
-
- ifp->references = 1;
- ifp->magic = IFACE_MAGIC;
- *ifpret = ifp;
-
- return (ISC_R_SUCCESS);
-
- clientmgr_create_failure:
- DESTROYLOCK(&ifp->lock);
- lock_create_failure:
- ifp->magic = 0;
- isc_mem_put(mgr->mctx, ifp, sizeof(*ifp));
-
- return (ISC_R_UNEXPECTED);
-}
-
-static isc_result_t
-ns_interface_listenudp(ns_interface_t *ifp) {
- isc_result_t result;
- unsigned int attrs;
- unsigned int attrmask;
-
- attrs = 0;
- attrs |= DNS_DISPATCHATTR_UDP;
- if (isc_sockaddr_pf(&ifp->addr) == AF_INET)
- attrs |= DNS_DISPATCHATTR_IPV4;
- else
- attrs |= DNS_DISPATCHATTR_IPV6;
- attrs |= DNS_DISPATCHATTR_NOLISTEN;
- attrmask = 0;
- attrmask |= DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_TCP;
- attrmask |= DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_IPV6;
- result = dns_dispatch_getudp(ifp->mgr->dispatchmgr, ns_g_socketmgr,
- ns_g_taskmgr, &ifp->addr,
- 4096, 1000, 32768, 8219, 8237,
- attrs, attrmask, &ifp->udpdispatch);
- if (result != ISC_R_SUCCESS) {
- isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
- "could not listen on UDP socket: %s",
- isc_result_totext(result));
- goto udp_dispatch_failure;
- }
-
- result = ns_clientmgr_createclients(ifp->clientmgr, ns_g_cpus,
- ifp, ISC_FALSE);
- if (result != ISC_R_SUCCESS) {
- UNEXPECTED_ERROR(__FILE__, __LINE__,
- "UDP ns_clientmgr_createclients(): %s",
- isc_result_totext(result));
- goto addtodispatch_failure;
- }
- return (ISC_R_SUCCESS);
-
- addtodispatch_failure:
- dns_dispatch_changeattributes(ifp->udpdispatch, 0,
- DNS_DISPATCHATTR_NOLISTEN);
- dns_dispatch_detach(&ifp->udpdispatch);
- udp_dispatch_failure:
- return (result);
-}
-
-static isc_result_t
-ns_interface_accepttcp(ns_interface_t *ifp) {
- isc_result_t result;
-
- /*
- * Open a TCP socket.
- */
- result = isc_socket_create(ifp->mgr->socketmgr,
- isc_sockaddr_pf(&ifp->addr),
- isc_sockettype_tcp,
- &ifp->tcpsocket);
- if (result != ISC_R_SUCCESS) {
- isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
- "creating TCP socket: %s",
- isc_result_totext(result));
- goto tcp_socket_failure;
- }
-#ifndef ISC_ALLOW_MAPPED
- isc_socket_ipv6only(ifp->tcpsocket, ISC_TRUE);
-#endif
- result = isc_socket_bind(ifp->tcpsocket, &ifp->addr);
- if (result != ISC_R_SUCCESS) {
- isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
- "binding TCP socket: %s",
- isc_result_totext(result));
- goto tcp_bind_failure;
- }
- result = isc_socket_listen(ifp->tcpsocket, ns_g_listen);
- if (result != ISC_R_SUCCESS) {
- isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
- "listening on TCP socket: %s",
- isc_result_totext(result));
- goto tcp_listen_failure;
- }
-
- /*
- * If/when there a multiple filters listen to the
- * result.
- */
- (void)isc_socket_filter(ifp->tcpsocket, "dataready");
-
- result = ns_clientmgr_createclients(ifp->clientmgr,
- ifp->ntcptarget, ifp,
- ISC_TRUE);
- if (result != ISC_R_SUCCESS) {
- UNEXPECTED_ERROR(__FILE__, __LINE__,
- "TCP ns_clientmgr_createclients(): %s",
- isc_result_totext(result));
- goto accepttcp_failure;
- }
- return (ISC_R_SUCCESS);
-
- accepttcp_failure:
- tcp_listen_failure:
- tcp_bind_failure:
- isc_socket_detach(&ifp->tcpsocket);
- tcp_socket_failure:
- return (ISC_R_SUCCESS);
-}
-
-static isc_result_t
-ns_interface_setup(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
- const char *name, ns_interface_t **ifpret,
- isc_boolean_t accept_tcp)
-{
- isc_result_t result;
- ns_interface_t *ifp = NULL;
- REQUIRE(ifpret != NULL && *ifpret == NULL);
-
- result = ns_interface_create(mgr, addr, name, &ifp);
- if (result != ISC_R_SUCCESS)
- return (result);
-
- result = ns_interface_listenudp(ifp);
- if (result != ISC_R_SUCCESS)
- goto cleanup_interface;
-
- if (accept_tcp == ISC_TRUE) {
- result = ns_interface_accepttcp(ifp);
- if (result != ISC_R_SUCCESS) {
- /*
- * XXXRTH We don't currently have a way to easily stop
- * dispatch service, so we currently return
- * ISC_R_SUCCESS (the UDP stuff will work even if TCP
- * creation failed). This will be fixed later.
- */
- result = ISC_R_SUCCESS;
- }
- }
- *ifpret = ifp;
- return (ISC_R_SUCCESS);
-
- cleanup_interface:
- ISC_LIST_UNLINK(ifp->mgr->interfaces, ifp, link);
- ns_interface_detach(&ifp);
- return (result);
-}
-
-void
-ns_interface_shutdown(ns_interface_t *ifp) {
- if (ifp->clientmgr != NULL)
- ns_clientmgr_destroy(&ifp->clientmgr);
-}
-
-static void
-ns_interface_destroy(ns_interface_t *ifp) {
- isc_mem_t *mctx = ifp->mgr->mctx;
- REQUIRE(NS_INTERFACE_VALID(ifp));
-
- ns_interface_shutdown(ifp);
-
- if (ifp->udpdispatch != NULL) {
- dns_dispatch_changeattributes(ifp->udpdispatch, 0,
- DNS_DISPATCHATTR_NOLISTEN);
- dns_dispatch_detach(&ifp->udpdispatch);
- }
- if (ifp->tcpsocket != NULL)
- isc_socket_detach(&ifp->tcpsocket);
-
- DESTROYLOCK(&ifp->lock);
-
- ns_interfacemgr_detach(&ifp->mgr);
-
- ifp->magic = 0;
- isc_mem_put(mctx, ifp, sizeof(*ifp));
-}
-
-void
-ns_interface_attach(ns_interface_t *source, ns_interface_t **target) {
- REQUIRE(NS_INTERFACE_VALID(source));
- LOCK(&source->lock);
- INSIST(source->references > 0);
- source->references++;
- UNLOCK(&source->lock);
- *target = source;
-}
-
-void
-ns_interface_detach(ns_interface_t **targetp) {
- isc_result_t need_destroy = ISC_FALSE;
- ns_interface_t *target = *targetp;
- REQUIRE(target != NULL);
- REQUIRE(NS_INTERFACE_VALID(target));
- LOCK(&target->lock);
- REQUIRE(target->references > 0);
- target->references--;
- if (target->references == 0)
- need_destroy = ISC_TRUE;
- UNLOCK(&target->lock);
- if (need_destroy)
- ns_interface_destroy(target);
- *targetp = NULL;
-}
-
-/*%
- * Search the interface list for an interface whose address and port
- * both match those of 'addr'. Return a pointer to it, or NULL if not found.
- */
-static ns_interface_t *
-find_matching_interface(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr) {
- ns_interface_t *ifp;
- for (ifp = ISC_LIST_HEAD(mgr->interfaces); ifp != NULL;
- ifp = ISC_LIST_NEXT(ifp, link)) {
- if (isc_sockaddr_equal(&ifp->addr, addr))
- break;
- }
- return (ifp);
-}
-
-/*%
- * Remove any interfaces whose generation number is not the current one.
- */
-static void
-purge_old_interfaces(ns_interfacemgr_t *mgr) {
- ns_interface_t *ifp, *next;
- for (ifp = ISC_LIST_HEAD(mgr->interfaces); ifp != NULL; ifp = next) {
- INSIST(NS_INTERFACE_VALID(ifp));
- next = ISC_LIST_NEXT(ifp, link);
- if (ifp->generation != mgr->generation) {
- char sabuf[256];
- ISC_LIST_UNLINK(ifp->mgr->interfaces, ifp, link);
- isc_sockaddr_format(&ifp->addr, sabuf, sizeof(sabuf));
- isc_log_write(IFMGR_COMMON_LOGARGS,
- ISC_LOG_INFO,
- "no longer listening on %s", sabuf);
- ns_interface_shutdown(ifp);
- ns_interface_detach(&ifp);
- }
- }
-}
-
-static isc_result_t
-clearacl(isc_mem_t *mctx, dns_acl_t **aclp) {
- dns_acl_t *newacl = NULL;
- isc_result_t result;
- result = dns_acl_create(mctx, 10, &newacl);
- if (result != ISC_R_SUCCESS)
- return (result);
- dns_acl_detach(aclp);
- dns_acl_attach(newacl, aclp);
- dns_acl_detach(&newacl);
- return (ISC_R_SUCCESS);
-}
-
-static isc_boolean_t
-listenon_is_ip6_any(ns_listenelt_t *elt) {
- if (elt->acl->length != 1)
- return (ISC_FALSE);
- if (elt->acl->elements[0].negative == ISC_FALSE &&
- elt->acl->elements[0].type == dns_aclelementtype_any)
- return (ISC_TRUE); /* listen-on-v6 { any; } */
- return (ISC_FALSE); /* All others */
-}
-
-static isc_result_t
-setup_locals(ns_interfacemgr_t *mgr, isc_interface_t *interface) {
- isc_result_t result;
- dns_aclelement_t elt;
- unsigned int family;
- unsigned int prefixlen;
-
- family = interface->address.family;
-
- elt.type = dns_aclelementtype_ipprefix;
- elt.negative = ISC_FALSE;
- elt.u.ip_prefix.address = interface->address;
- elt.u.ip_prefix.prefixlen = (family == AF_INET) ? 32 : 128;
- result = dns_acl_appendelement(mgr->aclenv.localhost, &elt);
- if (result != ISC_R_SUCCESS)
- return (result);
-
- result = isc_netaddr_masktoprefixlen(&interface->netmask,
- &prefixlen);
-
- /* Non contigious netmasks not allowed by IPv6 arch. */
- if (result != ISC_R_SUCCESS && family == AF_INET6)
- return (result);
-
- if (result != ISC_R_SUCCESS) {
- isc_log_write(IFMGR_COMMON_LOGARGS,
- ISC_LOG_WARNING,
- "omitting IPv4 interface %s from "
- "localnets ACL: %s",
- interface->name,
- isc_result_totext(result));
- } else {
- elt.u.ip_prefix.prefixlen = prefixlen;
- if (dns_acl_elementmatch(mgr->aclenv.localnets, &elt,
- NULL) == ISC_R_NOTFOUND) {
- result = dns_acl_appendelement(mgr->aclenv.localnets,
- &elt);
- if (result != ISC_R_SUCCESS)
- return (result);
- }
- }
-
- return (ISC_R_SUCCESS);
-}
-
-static void
-setup_listenon(ns_interfacemgr_t *mgr, isc_interface_t *interface,
- in_port_t port)
-{
- isc_sockaddr_t *addr;
- isc_sockaddr_t *old;
-
- addr = isc_mem_get(mgr->mctx, sizeof(*addr));
- if (addr == NULL)
- return;
-
- isc_sockaddr_fromnetaddr(addr, &interface->address, port);
-
- for (old = ISC_LIST_HEAD(mgr->listenon);
- old != NULL;
- old = ISC_LIST_NEXT(old, link))
- if (isc_sockaddr_equal(addr, old))
- break;
-
- if (old != NULL)
- isc_mem_put(mgr->mctx, addr, sizeof(*addr));
- else
- ISC_LIST_APPEND(mgr->listenon, addr, link);
-}
-
-static void
-clearlistenon(ns_interfacemgr_t *mgr) {
- isc_sockaddr_t *old;
-
- old = ISC_LIST_HEAD(mgr->listenon);
- while (old != NULL) {
- ISC_LIST_UNLINK(mgr->listenon, old, link);
- isc_mem_put(mgr->mctx, old, sizeof(*old));
- old = ISC_LIST_HEAD(mgr->listenon);
- }
-}
-
-static isc_result_t
-do_scan(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen,
- isc_boolean_t verbose)
-{
- isc_interfaceiter_t *iter = NULL;
- isc_boolean_t scan_ipv4 = ISC_FALSE;
- isc_boolean_t scan_ipv6 = ISC_FALSE;
- isc_boolean_t adjusting = ISC_FALSE;
- isc_boolean_t ipv6only = ISC_TRUE;
- isc_boolean_t ipv6pktinfo = ISC_TRUE;
- isc_result_t result;
- isc_netaddr_t zero_address, zero_address6;
- ns_listenelt_t *le;
- isc_sockaddr_t listen_addr;
- ns_interface_t *ifp;
- isc_boolean_t log_explicit = ISC_FALSE;
- isc_boolean_t dolistenon;
-
- if (ext_listen != NULL)
- adjusting = ISC_TRUE;
-
- if (isc_net_probeipv6() == ISC_R_SUCCESS)
- scan_ipv6 = ISC_TRUE;
-#ifdef WANT_IPV6
- else
- isc_log_write(IFMGR_COMMON_LOGARGS,
- verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1),
- "no IPv6 interfaces found");
-#endif
-
- if (isc_net_probeipv4() == ISC_R_SUCCESS)
- scan_ipv4 = ISC_TRUE;
- else
- isc_log_write(IFMGR_COMMON_LOGARGS,
- verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1),
- "no IPv4 interfaces found");
-
- /*
- * A special, but typical case; listen-on-v6 { any; }.
- * When we can make the socket IPv6-only, open a single wildcard
- * socket for IPv6 communication. Otherwise, make separate socket
- * for each IPv6 address in order to avoid accepting IPv4 packets
- * as the form of mapped addresses unintentionally unless explicitly
- * allowed.
- */
-#ifndef ISC_ALLOW_MAPPED
- if (scan_ipv6 == ISC_TRUE &&
- isc_net_probe_ipv6only() != ISC_R_SUCCESS) {
- ipv6only = ISC_FALSE;
- log_explicit = ISC_TRUE;
- }
-#endif
- if (scan_ipv6 == ISC_TRUE &&
- isc_net_probe_ipv6pktinfo() != ISC_R_SUCCESS) {
- ipv6pktinfo = ISC_FALSE;
- log_explicit = ISC_TRUE;
- }
- if (scan_ipv6 == ISC_TRUE && ipv6only && ipv6pktinfo) {
- for (le = ISC_LIST_HEAD(mgr->listenon6->elts);
- le != NULL;
- le = ISC_LIST_NEXT(le, link)) {
- struct in6_addr in6a;
-
- if (!listenon_is_ip6_any(le))
- continue;
-
- in6a = in6addr_any;
- isc_sockaddr_fromin6(&listen_addr, &in6a, le->port);
-
- ifp = find_matching_interface(mgr, &listen_addr);
- if (ifp != NULL) {
- ifp->generation = mgr->generation;
- } else {
- isc_log_write(IFMGR_COMMON_LOGARGS,
- ISC_LOG_INFO,
- "listening on IPv6 "
- "interfaces, port %u",
- le->port);
- result = ns_interface_setup(mgr, &listen_addr,
- "<any>", &ifp,
- ISC_TRUE);
- if (result == ISC_R_SUCCESS)
- ifp->flags |= NS_INTERFACEFLAG_ANYADDR;
- else
- isc_log_write(IFMGR_COMMON_LOGARGS,
- ISC_LOG_ERROR,
- "listening on all IPv6 "
- "interfaces failed");
- /* Continue. */
- }
- }
- }
-
- isc_netaddr_any(&zero_address);
- isc_netaddr_any6(&zero_address6);
-
- result = isc_interfaceiter_create(mgr->mctx, &iter);
- if (result != ISC_R_SUCCESS)
- return (result);
-
- if (adjusting == ISC_FALSE) {
- result = clearacl(mgr->mctx, &mgr->aclenv.localhost);
- if (result != ISC_R_SUCCESS)
- goto cleanup_iter;
- result = clearacl(mgr->mctx, &mgr->aclenv.localnets);
- if (result != ISC_R_SUCCESS)
- goto cleanup_iter;
- clearlistenon(mgr);
- }
-
- for (result = isc_interfaceiter_first(iter);
- result == ISC_R_SUCCESS;
- result = isc_interfaceiter_next(iter))
- {
- isc_interface_t interface;
- ns_listenlist_t *ll;
- unsigned int family;
-
- result = isc_interfaceiter_current(iter, &interface);
- if (result != ISC_R_SUCCESS)
- break;
-
- family = interface.address.family;
- if (family != AF_INET && family != AF_INET6)
- continue;
- if (scan_ipv4 == ISC_FALSE && family == AF_INET)
- continue;
- if (scan_ipv6 == ISC_FALSE && family == AF_INET6)
- continue;
-
- /*
- * Test for the address being nonzero rather than testing
- * INTERFACE_F_UP, because on some systems the latter
- * follows the media state and we could end up ignoring
- * the interface for an entire rescan interval due to
- * a temporary media glitch at rescan time.
- */
- if (family == AF_INET &&
- isc_netaddr_equal(&interface.address, &zero_address)) {
- continue;
- }
- if (family == AF_INET6 &&
- isc_netaddr_equal(&interface.address, &zero_address6)) {
- continue;
- }
-
- if (adjusting == ISC_FALSE) {
- result = setup_locals(mgr, &interface);
- if (result != ISC_R_SUCCESS)
- goto ignore_interface;
- }
-
- ll = (family == AF_INET) ? mgr->listenon4 : mgr->listenon6;
- dolistenon = ISC_TRUE;
- for (le = ISC_LIST_HEAD(ll->elts);
- le != NULL;
- le = ISC_LIST_NEXT(le, link))
- {
- int match;
- isc_boolean_t ipv6_wildcard = ISC_FALSE;
- isc_netaddr_t listen_netaddr;
- isc_sockaddr_t listen_sockaddr;
-
- /*
- * Construct a socket address for this IP/port
- * combination.
- */
- if (family == AF_INET) {
- isc_netaddr_fromin(&listen_netaddr,
- &interface.address.type.in);
- } else {
- isc_netaddr_fromin6(&listen_netaddr,
- &interface.address.type.in6);
- isc_netaddr_setzone(&listen_netaddr,
- interface.address.zone);
- }
- isc_sockaddr_fromnetaddr(&listen_sockaddr,
- &listen_netaddr,
- le->port);
-
- /*
- * See if the address matches the listen-on statement;
- * if not, ignore the interface.
- */
- (void)dns_acl_match(&listen_netaddr, NULL, le->acl,
- &mgr->aclenv, &match, NULL);
- if (match <= 0)
- continue;
-
- if (adjusting == ISC_FALSE && dolistenon == ISC_TRUE) {
- setup_listenon(mgr, &interface, le->port);
- dolistenon = ISC_FALSE;
- }
-
- /*
- * The case of "any" IPv6 address will require
- * special considerations later, so remember it.
- */
- if (family == AF_INET6 && ipv6only && ipv6pktinfo &&
- listenon_is_ip6_any(le))
- ipv6_wildcard = ISC_TRUE;
-
- /*
- * When adjusting interfaces with extra a listening
- * list, see if the address matches the extra list.
- * If it does, and is also covered by a wildcard
- * interface, we need to listen on the address
- * explicitly.
- */
- if (adjusting == ISC_TRUE) {
- ns_listenelt_t *ele;
-
- match = 0;
- for (ele = ISC_LIST_HEAD(ext_listen->elts);
- ele != NULL;
- ele = ISC_LIST_NEXT(ele, link)) {
- (void)dns_acl_match(&listen_netaddr,
- NULL, ele->acl,
- NULL, &match, NULL);
- if (match > 0 && ele->port == le->port)
- break;
- else
- match = 0;
- }
- if (ipv6_wildcard == ISC_TRUE && match == 0)
- continue;
- }
-
- ifp = find_matching_interface(mgr, &listen_sockaddr);
- if (ifp != NULL) {
- ifp->generation = mgr->generation;
- } else {
- char sabuf[ISC_SOCKADDR_FORMATSIZE];
-
- if (adjusting == ISC_FALSE &&
- ipv6_wildcard == ISC_TRUE)
- continue;
-
- if (log_explicit && family == AF_INET6 &&
- !adjusting && listenon_is_ip6_any(le)) {
- isc_log_write(IFMGR_COMMON_LOGARGS,
- verbose ? ISC_LOG_INFO :
- ISC_LOG_DEBUG(1),
- "IPv6 socket API is "
- "incomplete; explicitly "
- "binding to each IPv6 "
- "address separately");
- log_explicit = ISC_FALSE;
- }
- isc_sockaddr_format(&listen_sockaddr,
- sabuf, sizeof(sabuf));
- isc_log_write(IFMGR_COMMON_LOGARGS,
- ISC_LOG_INFO,
- "%s"
- "listening on %s interface "
- "%s, %s",
- (adjusting == ISC_TRUE) ?
- "additionally " : "",
- (family == AF_INET) ?
- "IPv4" : "IPv6",
- interface.name, sabuf);
-
- result = ns_interface_setup(mgr,
- &listen_sockaddr,
- interface.name,
- &ifp,
- (adjusting == ISC_TRUE) ?
- ISC_FALSE :
- ISC_TRUE);
-
- if (result != ISC_R_SUCCESS) {
- isc_log_write(IFMGR_COMMON_LOGARGS,
- ISC_LOG_ERROR,
- "creating %s interface "
- "%s failed; interface "
- "ignored",
- (family == AF_INET) ?
- "IPv4" : "IPv6",
- interface.name);
- }
- /* Continue. */
- }
-
- }
- continue;
-
- ignore_interface:
- isc_log_write(IFMGR_COMMON_LOGARGS,
- ISC_LOG_ERROR,
- "ignoring %s interface %s: %s",
- (family == AF_INET) ? "IPv4" : "IPv6",
- interface.name, isc_result_totext(result));
- continue;
- }
- if (result != ISC_R_NOMORE)
- UNEXPECTED_ERROR(__FILE__, __LINE__,
- "interface iteration failed: %s",
- isc_result_totext(result));
- else
- result = ISC_R_SUCCESS;
- cleanup_iter:
- isc_interfaceiter_destroy(&iter);
- return (result);
-}
-
-static void
-ns_interfacemgr_scan0(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen,
- isc_boolean_t verbose)
-{
- isc_boolean_t purge = ISC_TRUE;
-
- REQUIRE(NS_INTERFACEMGR_VALID(mgr));
-
- mgr->generation++; /* Increment the generation count. */
-
- if (do_scan(mgr, ext_listen, verbose) != ISC_R_SUCCESS)
- purge = ISC_FALSE;
-
- /*
- * Now go through the interface list and delete anything that
- * does not have the current generation number. This is
- * how we catch interfaces that go away or change their
- * addresses.
- */
- if (purge)
- purge_old_interfaces(mgr);
-
- /*
- * Warn if we are not listening on any interface, unless
- * we're in lwresd-only mode, in which case that is to
- * be expected.
- */
- if (ext_listen == NULL &&
- ISC_LIST_EMPTY(mgr->interfaces) && ! ns_g_lwresdonly) {
- isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING,
- "not listening on any interfaces");
- }
-}
-
-void
-ns_interfacemgr_scan(ns_interfacemgr_t *mgr, isc_boolean_t verbose) {
- ns_interfacemgr_scan0(mgr, NULL, verbose);
-}
-
-void
-ns_interfacemgr_adjust(ns_interfacemgr_t *mgr, ns_listenlist_t *list,
- isc_boolean_t verbose)
-{
- ns_interfacemgr_scan0(mgr, list, verbose);
-}
-
-void
-ns_interfacemgr_setlistenon4(ns_interfacemgr_t *mgr, ns_listenlist_t *value) {
- LOCK(&mgr->lock);
- ns_listenlist_detach(&mgr->listenon4);
- ns_listenlist_attach(value, &mgr->listenon4);
- UNLOCK(&mgr->lock);
-}
-
-void
-ns_interfacemgr_setlistenon6(ns_interfacemgr_t *mgr, ns_listenlist_t *value) {
- LOCK(&mgr->lock);
- ns_listenlist_detach(&mgr->listenon6);
- ns_listenlist_attach(value, &mgr->listenon6);
- UNLOCK(&mgr->lock);
-}
-
-void
-ns_interfacemgr_dumprecursing(FILE *f, ns_interfacemgr_t *mgr) {
- ns_interface_t *interface;
-
- LOCK(&mgr->lock);
- interface = ISC_LIST_HEAD(mgr->interfaces);
- while (interface != NULL) {
- if (interface->clientmgr != NULL)
- ns_client_dumprecursing(f, interface->clientmgr);
- interface = ISC_LIST_NEXT(interface, link);
- }
- UNLOCK(&mgr->lock);
-}
-
-isc_boolean_t
-ns_interfacemgr_listeningon(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr) {
- isc_sockaddr_t *old;
-
- old = ISC_LIST_HEAD(mgr->listenon);
- for (old = ISC_LIST_HEAD(mgr->listenon);
- old != NULL;
- old = ISC_LIST_NEXT(old, link))
- if (isc_sockaddr_equal(old, addr))
- return (ISC_TRUE);
- return (ISC_FALSE);
-}
OpenPOWER on IntegriCloud