Home | History | Annotate | Line # | Download | only in ns
      1 /*	$NetBSD: interfacemgr.c,v 1.19 2026/08/29 14:55:19 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
      5  *
      6  * SPDX-License-Identifier: MPL-2.0
      7  *
      8  * This Source Code Form is subject to the terms of the Mozilla Public
      9  * License, v. 2.0. If a copy of the MPL was not distributed with this
     10  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
     11  *
     12  * See the COPYRIGHT file distributed with this work for additional
     13  * information regarding copyright ownership.
     14  */
     15 
     16 /*! \file */
     17 
     18 #include <stdbool.h>
     19 
     20 #include <isc/interfaceiter.h>
     21 #include <isc/loop.h>
     22 #include <isc/netmgr.h>
     23 #include <isc/os.h>
     24 #include <isc/random.h>
     25 #include <isc/string.h>
     26 #include <isc/tid.h>
     27 #include <isc/util.h>
     28 
     29 #include <dns/acl.h>
     30 #include <dns/dispatch.h>
     31 
     32 #include <ns/client.h>
     33 #include <ns/interfacemgr.h>
     34 #include <ns/log.h>
     35 #include <ns/server.h>
     36 #include <ns/stats.h>
     37 
     38 #ifdef HAVE_NET_ROUTE_H
     39 #include <net/route.h>
     40 #if defined(RTM_VERSION) && defined(RTM_NEWADDR) && defined(RTM_DELADDR)
     41 #define MSGHDR	rt_msghdr
     42 #define MSGTYPE rtm_type
     43 #endif /* if defined(RTM_VERSION) && defined(RTM_NEWADDR) && \
     44 	* defined(RTM_DELADDR) */
     45 #endif /* ifdef HAVE_NET_ROUTE_H */
     46 
     47 #if defined(HAVE_LINUX_NETLINK_H) && defined(HAVE_LINUX_RTNETLINK_H)
     48 #define LINUX_NETLINK_AVAILABLE
     49 #include <linux/netlink.h>
     50 #include <linux/rtnetlink.h>
     51 #if defined(RTM_NEWADDR) && defined(RTM_DELADDR)
     52 #define MSGHDR	nlmsghdr
     53 #define MSGTYPE nlmsg_type
     54 #endif /* if defined(RTM_NEWADDR) && defined(RTM_DELADDR) */
     55 #endif /* if defined(HAVE_LINUX_NETLINK_H) && defined(HAVE_LINUX_RTNETLINK_H) \
     56 	*/
     57 
     58 #define LISTENING(ifp) (((ifp)->flags & NS_INTERFACEFLAG_LISTENING) != 0)
     59 
     60 #define IFMGR_MAGIC		 ISC_MAGIC('I', 'F', 'M', 'G')
     61 #define NS_INTERFACEMGR_VALID(t) ISC_MAGIC_VALID(t, IFMGR_MAGIC)
     62 
     63 #define IFMGR_COMMON_LOGARGS \
     64 	ns_lctx, NS_LOGCATEGORY_NETWORK, NS_LOGMODULE_INTERFACEMGR
     65 
     66 /*% nameserver interface manager structure */
     67 struct ns_interfacemgr {
     68 	unsigned int magic; /*%< Magic number */
     69 	isc_refcount_t references;
     70 	isc_mutex_t lock;
     71 	isc_mem_t *mctx;	/*%< Memory context */
     72 	ns_server_t *sctx;	/*%< Server context */
     73 	isc_loopmgr_t *loopmgr; /*%< Loop manager */
     74 	isc_nm_t *nm;		/*%< Net manager */
     75 	uint32_t ncpus;		/*%< Number of workers */
     76 	dns_dispatchmgr_t *dispatchmgr;
     77 	unsigned int generation; /*%< Current generation no */
     78 	ns_listenlist_t *listenon4;
     79 	ns_listenlist_t *listenon6;
     80 	dns_aclenv_t *aclenv;		     /*%< Localhost/localnets ACLs */
     81 	ISC_LIST(ns_interface_t) interfaces; /*%< List of interfaces */
     82 	ISC_LIST(isc_sockaddr_t) listenon;
     83 	int backlog;		     /*%< Listen queue size */
     84 	atomic_bool shuttingdown;    /*%< Interfacemgr shutting down */
     85 	ns_clientmgr_t **clientmgrs; /*%< Client managers */
     86 	isc_nmhandle_t *route;
     87 };
     88 
     89 static void
     90 purge_old_interfaces(ns_interfacemgr_t *mgr);
     91 
     92 static void
     93 clearlistenon(ns_interfacemgr_t *mgr);
     94 
     95 #if defined(RTM_NEWADDR) && defined(RTM_DELADDR)
     96 static bool
     97 need_rescan(ns_interfacemgr_t *mgr, struct MSGHDR *rtm, size_t len) {
     98 	if (rtm->MSGTYPE != RTM_NEWADDR && rtm->MSGTYPE != RTM_DELADDR) {
     99 		return false;
    100 	}
    101 
    102 #ifndef LINUX_NETLINK_AVAILABLE
    103 	UNUSED(mgr);
    104 	UNUSED(len);
    105 	/* On most systems, any NEWADDR or DELADDR means we rescan */
    106 	return true;
    107 #else  /* LINUX_NETLINK_AVAILABLE */
    108 	/* ...but on linux we need to check the messages more carefully */
    109 	for (struct MSGHDR *nlh = rtm;
    110 	     NLMSG_OK(nlh, len) && nlh->nlmsg_type != NLMSG_DONE;
    111 	     nlh = NLMSG_NEXT(nlh, len))
    112 	{
    113 		struct ifaddrmsg *ifa = (struct ifaddrmsg *)NLMSG_DATA(nlh);
    114 		struct rtattr *rth = IFA_RTA(ifa);
    115 		size_t rtl = IFA_PAYLOAD(nlh);
    116 
    117 		while (rtl > 0 && RTA_OK(rth, rtl)) {
    118 			/*
    119 			 * Look for IFA_ADDRESS to detect IPv6 interface
    120 			 * state changes.
    121 			 */
    122 			if (rth->rta_type == IFA_ADDRESS &&
    123 			    ifa->ifa_family == AF_INET6)
    124 			{
    125 				bool existed = false;
    126 				bool was_listening = false;
    127 				isc_netaddr_t addr = { 0 };
    128 				ns_interface_t *ifp = NULL;
    129 
    130 				isc_netaddr_fromin6(&addr, RTA_DATA(rth));
    131 				INSIST(isc_netaddr_getzone(&addr) == 0);
    132 
    133 				/*
    134 				 * Check whether we were listening on the
    135 				 * address. We need to do this as the
    136 				 * Linux kernel seems to issue messages
    137 				 * containing IFA_ADDRESS far more often
    138 				 * than the actual state changes (on
    139 				 * router advertisements?)
    140 				 */
    141 				LOCK(&mgr->lock);
    142 				for (ifp = ISC_LIST_HEAD(mgr->interfaces);
    143 				     ifp != NULL;
    144 				     ifp = ISC_LIST_NEXT(ifp, link))
    145 				{
    146 					isc_netaddr_t tmp = { 0 };
    147 					isc_netaddr_fromsockaddr(&tmp,
    148 								 &ifp->addr);
    149 					if (tmp.family != AF_INET6) {
    150 						continue;
    151 					}
    152 
    153 					/*
    154 					 * We have to nullify the zone (IPv6
    155 					 * scope ID) because we haven't got one
    156 					 * from the kernel. Otherwise match
    157 					 * could fail even for an existing
    158 					 * address.
    159 					 */
    160 					isc_netaddr_setzone(&tmp, 0);
    161 					if (isc_netaddr_equal(&tmp, &addr)) {
    162 						was_listening = LISTENING(ifp);
    163 						existed = true;
    164 						break;
    165 					}
    166 				}
    167 				UNLOCK(&mgr->lock);
    168 
    169 				/*
    170 				 * Do rescan if the state of the interface
    171 				 * has changed.
    172 				 */
    173 				if ((!existed && rtm->MSGTYPE == RTM_NEWADDR) ||
    174 				    (existed && was_listening &&
    175 				     rtm->MSGTYPE == RTM_DELADDR))
    176 				{
    177 					return true;
    178 				}
    179 			} else if (rth->rta_type == IFA_ADDRESS &&
    180 				   ifa->ifa_family == AF_INET)
    181 			{
    182 				/*
    183 				 * It seems that the IPv4 P2P link state
    184 				 * has changed.
    185 				 */
    186 				return true;
    187 			} else if (rth->rta_type == IFA_LOCAL) {
    188 				/*
    189 				 * Local address state has changed - do
    190 				 * rescan.
    191 				 */
    192 				return true;
    193 			}
    194 			rth = RTA_NEXT(rth, rtl);
    195 		}
    196 	}
    197 #endif /* LINUX_NETLINK_AVAILABLE */
    198 
    199 	return false;
    200 }
    201 #endif /* if defined(RTM_NEWADDR) && defined(RTM_DELADDR) */
    202 
    203 static void
    204 route_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
    205 	   void *arg) {
    206 	ns_interfacemgr_t *mgr = (ns_interfacemgr_t *)arg;
    207 	struct MSGHDR *rtm = NULL;
    208 	size_t rtmlen;
    209 
    210 	isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_DEBUG(9), "route_recv: %s",
    211 		      isc_result_totext(eresult));
    212 
    213 	if (handle == NULL) {
    214 		return;
    215 	}
    216 
    217 	switch (eresult) {
    218 	case ISC_R_SUCCESS:
    219 		break;
    220 	default:
    221 		isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
    222 			      "automatic interface scanning terminated: %s",
    223 			      isc_result_totext(eresult));
    224 		FALLTHROUGH;
    225 	case ISC_R_CANCELED:
    226 	case ISC_R_SHUTTINGDOWN:
    227 	case ISC_R_EOF:
    228 		ns_interfacemgr_routedisconnect(mgr);
    229 		return;
    230 	}
    231 
    232 	rtm = (struct MSGHDR *)region->base;
    233 	rtmlen = region->length;
    234 
    235 #ifdef RTM_VERSION
    236 	if (rtm->rtm_version != RTM_VERSION) {
    237 		isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
    238 			      "automatic interface rescanning disabled: "
    239 			      "rtm->rtm_version mismatch (%u != %u) "
    240 			      "recompile required",
    241 			      rtm->rtm_version, RTM_VERSION);
    242 		isc_nmhandle_detach(&mgr->route);
    243 		ns_interfacemgr_detach(&mgr);
    244 		return;
    245 	}
    246 #endif /* ifdef RTM_VERSION */
    247 
    248 	REQUIRE(mgr->route != NULL);
    249 
    250 #if defined(RTM_NEWADDR) && defined(RTM_DELADDR)
    251 	if (need_rescan(mgr, rtm, rtmlen) && mgr->sctx->interface_auto) {
    252 		ns_interfacemgr_scan(mgr, false, false);
    253 	}
    254 #endif /* if defined(RTM_NEWADDR) && defined(RTM_DELADDR) */
    255 
    256 	isc_nm_read(handle, route_recv, mgr);
    257 	return;
    258 }
    259 
    260 static void
    261 route_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) {
    262 	ns_interfacemgr_t *mgr = (ns_interfacemgr_t *)arg;
    263 
    264 	isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_DEBUG(9),
    265 		      "route_connected: %s", isc_result_totext(eresult));
    266 
    267 	if (eresult != ISC_R_SUCCESS) {
    268 		ns_interfacemgr_detach(&mgr);
    269 		return;
    270 	}
    271 
    272 	INSIST(mgr->route == NULL);
    273 
    274 	isc_nmhandle_attach(handle, &mgr->route);
    275 	isc_nm_read(handle, route_recv, mgr);
    276 }
    277 
    278 isc_result_t
    279 ns_interfacemgr_create(isc_mem_t *mctx, ns_server_t *sctx,
    280 		       isc_loopmgr_t *loopmgr, isc_nm_t *nm,
    281 		       dns_dispatchmgr_t *dispatchmgr,
    282 		       dns_geoip_databases_t *geoip, ns_interfacemgr_t **mgrp) {
    283 	isc_result_t result;
    284 	ns_interfacemgr_t *mgr = NULL;
    285 
    286 	REQUIRE(mctx != NULL);
    287 	REQUIRE(mgrp != NULL);
    288 	REQUIRE(*mgrp == NULL);
    289 
    290 	mgr = isc_mem_get(mctx, sizeof(*mgr));
    291 	*mgr = (ns_interfacemgr_t){
    292 		.loopmgr = loopmgr,
    293 		.nm = nm,
    294 		.dispatchmgr = dispatchmgr,
    295 		.generation = 1,
    296 		.ncpus = isc_loopmgr_nloops(loopmgr),
    297 	};
    298 
    299 	isc_mem_attach(mctx, &mgr->mctx);
    300 	ns_server_attach(sctx, &mgr->sctx);
    301 
    302 	isc_mutex_init(&mgr->lock);
    303 
    304 	atomic_init(&mgr->shuttingdown, false);
    305 
    306 	ISC_LIST_INIT(mgr->interfaces);
    307 	ISC_LIST_INIT(mgr->listenon);
    308 
    309 	/*
    310 	 * The listen-on lists are initially empty.
    311 	 */
    312 	result = ns_listenlist_create(mctx, &mgr->listenon4);
    313 	if (result != ISC_R_SUCCESS) {
    314 		goto cleanup_lock;
    315 	}
    316 	ns_listenlist_attach(mgr->listenon4, &mgr->listenon6);
    317 
    318 	dns_aclenv_create(mctx, &mgr->aclenv);
    319 #if defined(HAVE_GEOIP2)
    320 	mgr->aclenv->geoip = geoip;
    321 #else  /* if defined(HAVE_GEOIP2) */
    322 	UNUSED(geoip);
    323 #endif /* if defined(HAVE_GEOIP2) */
    324 
    325 	isc_refcount_init(&mgr->references, 1);
    326 	mgr->magic = IFMGR_MAGIC;
    327 	*mgrp = mgr;
    328 
    329 	mgr->clientmgrs = isc_mem_cget(mgr->mctx, mgr->ncpus,
    330 				       sizeof(mgr->clientmgrs[0]));
    331 	for (size_t i = 0; i < mgr->ncpus; i++) {
    332 		result = ns_clientmgr_create(mgr->sctx, mgr->loopmgr,
    333 					     mgr->aclenv, (int)i,
    334 					     &mgr->clientmgrs[i]);
    335 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
    336 	}
    337 
    338 	return ISC_R_SUCCESS;
    339 
    340 cleanup_lock:
    341 	isc_mutex_destroy(&mgr->lock);
    342 	ns_server_detach(&mgr->sctx);
    343 	isc_mem_putanddetach(&mgr->mctx, mgr, sizeof(*mgr));
    344 	return result;
    345 }
    346 
    347 void
    348 ns_interfacemgr_routeconnect(ns_interfacemgr_t *mgr) {
    349 	REQUIRE(NS_INTERFACEMGR_VALID(mgr));
    350 	REQUIRE(isc_tid() == 0);
    351 
    352 	if (mgr->route != NULL) {
    353 		return;
    354 	}
    355 
    356 	ns_interfacemgr_ref(mgr);
    357 
    358 	isc_result_t result = isc_nm_routeconnect(mgr->nm, route_connected,
    359 						  mgr);
    360 	if (result != ISC_R_SUCCESS) {
    361 		isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_INFO,
    362 			      "unable to open route socket: %s",
    363 			      isc_result_totext(result));
    364 		ns_interfacemgr_unref(mgr);
    365 	}
    366 }
    367 
    368 void
    369 ns_interfacemgr_routedisconnect(ns_interfacemgr_t *mgr) {
    370 	REQUIRE(NS_INTERFACEMGR_VALID(mgr));
    371 	REQUIRE(isc_tid() == 0);
    372 
    373 	if (mgr->route == NULL) {
    374 		return;
    375 	}
    376 
    377 	isc_nmhandle_close(mgr->route);
    378 	isc_nmhandle_detach(&mgr->route);
    379 	ns_interfacemgr_detach(&mgr);
    380 }
    381 
    382 static void
    383 ns_interfacemgr__destroy(ns_interfacemgr_t *mgr) {
    384 	REQUIRE(NS_INTERFACEMGR_VALID(mgr));
    385 
    386 	isc_refcount_destroy(&mgr->references);
    387 
    388 	dns_aclenv_detach(&mgr->aclenv);
    389 	ns_listenlist_detach(&mgr->listenon4);
    390 	ns_listenlist_detach(&mgr->listenon6);
    391 	clearlistenon(mgr);
    392 	isc_mutex_destroy(&mgr->lock);
    393 	for (size_t i = 0; i < mgr->ncpus; i++) {
    394 		ns_clientmgr_detach(&mgr->clientmgrs[i]);
    395 	}
    396 	isc_mem_cput(mgr->mctx, mgr->clientmgrs, mgr->ncpus,
    397 		     sizeof(mgr->clientmgrs[0]));
    398 
    399 	if (mgr->sctx != NULL) {
    400 		ns_server_detach(&mgr->sctx);
    401 	}
    402 	mgr->magic = 0;
    403 	isc_mem_putanddetach(&mgr->mctx, mgr, sizeof(*mgr));
    404 }
    405 
    406 void
    407 ns_interfacemgr_setbacklog(ns_interfacemgr_t *mgr, int backlog) {
    408 	REQUIRE(NS_INTERFACEMGR_VALID(mgr));
    409 	LOCK(&mgr->lock);
    410 	mgr->backlog = backlog;
    411 	UNLOCK(&mgr->lock);
    412 }
    413 
    414 dns_aclenv_t *
    415 ns_interfacemgr_getaclenv(ns_interfacemgr_t *mgr) {
    416 	dns_aclenv_t *aclenv = NULL;
    417 
    418 	REQUIRE(NS_INTERFACEMGR_VALID(mgr));
    419 
    420 	LOCK(&mgr->lock);
    421 	aclenv = mgr->aclenv;
    422 	UNLOCK(&mgr->lock);
    423 
    424 	return aclenv;
    425 }
    426 
    427 ISC_REFCOUNT_IMPL(ns_interfacemgr, ns_interfacemgr__destroy);
    428 
    429 void
    430 ns_interfacemgr_shutdown(ns_interfacemgr_t *mgr) {
    431 	REQUIRE(NS_INTERFACEMGR_VALID(mgr));
    432 
    433 	/*%
    434 	 * Shut down and detach all interfaces.
    435 	 * By incrementing the generation count, we make
    436 	 * purge_old_interfaces() consider all interfaces "old".
    437 	 */
    438 	mgr->generation++;
    439 	atomic_store(&mgr->shuttingdown, true);
    440 
    441 	purge_old_interfaces(mgr);
    442 
    443 	if (mgr->route != NULL) {
    444 		isc_nm_cancelread(mgr->route);
    445 	}
    446 
    447 	for (size_t i = 0; i < mgr->ncpus; i++) {
    448 		ns_clientmgr_shutdown(mgr->clientmgrs[i]);
    449 	}
    450 }
    451 
    452 void
    453 ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
    454 		    const char *name, ns_interface_t **ifpret) {
    455 	ns_interface_t *ifp = NULL;
    456 	const char *default_name = "default";
    457 
    458 	REQUIRE(NS_INTERFACEMGR_VALID(mgr));
    459 
    460 	ifp = isc_mem_get(mgr->mctx, sizeof(*ifp));
    461 	*ifp = (ns_interface_t){ .generation = mgr->generation,
    462 				 .addr = *addr,
    463 				 .proxy_type = ISC_NM_PROXY_NONE };
    464 
    465 	if (name == NULL) {
    466 		name = default_name;
    467 	}
    468 	strlcpy(ifp->name, name, sizeof(ifp->name));
    469 
    470 	isc_mutex_init(&ifp->lock);
    471 
    472 	isc_refcount_init(&ifp->ntcpaccepting, 0);
    473 	isc_refcount_init(&ifp->ntcpactive, 0);
    474 
    475 	ISC_LINK_INIT(ifp, link);
    476 
    477 	ns_interfacemgr_attach(mgr, &ifp->mgr);
    478 	ifp->magic = IFACE_MAGIC;
    479 
    480 	LOCK(&mgr->lock);
    481 	ISC_LIST_APPEND(mgr->interfaces, ifp, link);
    482 	UNLOCK(&mgr->lock);
    483 
    484 	*ifpret = ifp;
    485 }
    486 
    487 static isc_result_t
    488 ns_interface_listenudp(ns_interface_t *ifp, isc_nm_proxy_type_t proxy) {
    489 	isc_result_t result;
    490 
    491 	/* Reserve space for an ns_client_t with the netmgr handle */
    492 	if (proxy == ISC_NM_PROXY_NONE) {
    493 		result = isc_nm_listenudp(ifp->mgr->nm, ISC_NM_LISTEN_ALL,
    494 					  &ifp->addr, ns_client_request, ifp,
    495 					  &ifp->udplistensocket);
    496 	} else {
    497 		INSIST(proxy == ISC_NM_PROXY_PLAIN);
    498 		result = isc_nm_listenproxyudp(ifp->mgr->nm, ISC_NM_LISTEN_ALL,
    499 					       &ifp->addr, ns_client_request,
    500 					       ifp, &ifp->udplistensocket);
    501 	}
    502 	return result;
    503 }
    504 
    505 static isc_result_t
    506 ns_interface_listentcp(ns_interface_t *ifp, isc_nm_proxy_type_t proxy) {
    507 	isc_result_t result;
    508 
    509 	result = isc_nm_listenstreamdns(
    510 		ifp->mgr->nm, ISC_NM_LISTEN_ALL, &ifp->addr, ns_client_request,
    511 		ifp, ns__client_tcpconn, ifp, ifp->mgr->backlog,
    512 		&ifp->mgr->sctx->tcpquota, NULL, proxy, &ifp->tcplistensocket);
    513 	if (result != ISC_R_SUCCESS) {
    514 		isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
    515 			      "creating TCP socket: %s",
    516 			      isc_result_totext(result));
    517 	}
    518 
    519 	/*
    520 	 * We call this now to update the tcp-highwater statistic:
    521 	 * this is necessary because we are adding to the TCP quota just
    522 	 * by listening.
    523 	 */
    524 	result = ns__client_tcpconn(NULL, ISC_R_SUCCESS, ifp);
    525 	if (result != ISC_R_SUCCESS) {
    526 		isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
    527 			      "connecting TCP socket: %s",
    528 			      isc_result_totext(result));
    529 	}
    530 
    531 	return result;
    532 }
    533 
    534 /*
    535  * XXXWPK we should probably pass a complete object with key, cert, and other
    536  * TLS related options.
    537  */
    538 static isc_result_t
    539 ns_interface_listentls(ns_interface_t *ifp, isc_nm_proxy_type_t proxy,
    540 		       isc_tlsctx_t *sslctx) {
    541 	isc_result_t result;
    542 
    543 	result = isc_nm_listenstreamdns(
    544 		ifp->mgr->nm, ISC_NM_LISTEN_ALL, &ifp->addr, ns_client_request,
    545 		ifp, ns__client_tcpconn, ifp, ifp->mgr->backlog,
    546 		&ifp->mgr->sctx->tcpquota, sslctx, proxy,
    547 		&ifp->tlslistensocket);
    548 
    549 	if (result != ISC_R_SUCCESS) {
    550 		isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
    551 			      "creating TLS socket: %s",
    552 			      isc_result_totext(result));
    553 		return result;
    554 	}
    555 
    556 	/*
    557 	 * We call this now to update the tcp-highwater statistic:
    558 	 * this is necessary because we are adding to the TCP quota just
    559 	 * by listening.
    560 	 */
    561 	result = ns__client_tcpconn(NULL, ISC_R_SUCCESS, ifp);
    562 	if (result != ISC_R_SUCCESS) {
    563 		isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
    564 			      "updating TCP stats: %s",
    565 			      isc_result_totext(result));
    566 	}
    567 
    568 	return result;
    569 }
    570 
    571 #ifdef HAVE_LIBNGHTTP2
    572 static isc_result_t
    573 load_http_endpoints(isc_nm_http_endpoints_t *epset, ns_interface_t *ifp,
    574 		    char **eps, size_t neps) {
    575 	isc_result_t result = ISC_R_FAILURE;
    576 
    577 	for (size_t i = 0; i < neps; i++) {
    578 		result = isc_nm_http_endpoints_add(epset, eps[i],
    579 						   ns_client_request, ifp);
    580 		if (result != ISC_R_SUCCESS) {
    581 			break;
    582 		}
    583 	}
    584 
    585 	return result;
    586 }
    587 #endif /* HAVE_LIBNGHTTP2 */
    588 
    589 static isc_result_t
    590 ns_interface_listenhttp(ns_interface_t *ifp, isc_nm_proxy_type_t proxy,
    591 			isc_tlsctx_t *sslctx, char **eps, size_t neps,
    592 			uint32_t max_clients, uint32_t max_concurrent_streams) {
    593 #if HAVE_LIBNGHTTP2
    594 	isc_result_t result = ISC_R_FAILURE;
    595 	isc_nmsocket_t *sock = NULL;
    596 	isc_nm_http_endpoints_t *epset = NULL;
    597 	isc_quota_t *quota = NULL;
    598 
    599 	epset = isc_nm_http_endpoints_new(ifp->mgr->mctx);
    600 
    601 	result = load_http_endpoints(epset, ifp, eps, neps);
    602 
    603 	if (result == ISC_R_SUCCESS) {
    604 		quota = isc_mem_get(ifp->mgr->mctx, sizeof(*quota));
    605 		isc_quota_init(quota, max_clients);
    606 		result = isc_nm_listenhttp(
    607 			ifp->mgr->nm, ISC_NM_LISTEN_ALL, &ifp->addr,
    608 			ifp->mgr->backlog, quota, sslctx, epset,
    609 			max_concurrent_streams, proxy, &sock);
    610 	}
    611 
    612 	isc_nm_http_endpoints_detach(&epset);
    613 
    614 	if (quota != NULL) {
    615 		if (result != ISC_R_SUCCESS) {
    616 			isc_quota_destroy(quota);
    617 			isc_mem_put(ifp->mgr->mctx, quota, sizeof(*quota));
    618 		} else {
    619 			ifp->http_quota = quota;
    620 			ns_server_append_http_quota(ifp->mgr->sctx, quota);
    621 		}
    622 	}
    623 
    624 	if (result != ISC_R_SUCCESS) {
    625 		isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
    626 			      "creating %s socket: %s",
    627 			      sslctx ? "HTTPS" : "HTTP",
    628 			      isc_result_totext(result));
    629 		return result;
    630 	}
    631 
    632 	if (sslctx) {
    633 		ifp->http_secure_listensocket = sock;
    634 	} else {
    635 		ifp->http_listensocket = sock;
    636 	}
    637 
    638 	/*
    639 	 * We call this now to update the tcp-highwater statistic:
    640 	 * this is necessary because we are adding to the TCP quota just
    641 	 * by listening.
    642 	 */
    643 	result = ns__client_tcpconn(NULL, ISC_R_SUCCESS, ifp);
    644 	if (result != ISC_R_SUCCESS) {
    645 		isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
    646 			      "updating TCP stats: %s",
    647 			      isc_result_totext(result));
    648 	}
    649 
    650 	return result;
    651 #else
    652 	UNUSED(ifp);
    653 	UNUSED(proxy);
    654 	UNUSED(sslctx);
    655 	UNUSED(eps);
    656 	UNUSED(neps);
    657 	UNUSED(max_clients);
    658 	UNUSED(max_concurrent_streams);
    659 	return ISC_R_NOTIMPLEMENTED;
    660 #endif
    661 }
    662 
    663 static isc_result_t
    664 interface_setup(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr, const char *name,
    665 		ns_interface_t **ifpret, ns_listenelt_t *elt,
    666 		bool *addr_in_use) {
    667 	isc_result_t result;
    668 	ns_interface_t *ifp = NULL;
    669 
    670 	REQUIRE(ifpret != NULL);
    671 	REQUIRE(addr_in_use == NULL || !*addr_in_use);
    672 
    673 	ifp = *ifpret;
    674 
    675 	if (ifp == NULL) {
    676 		ns_interface_create(mgr, addr, name, &ifp);
    677 	} else {
    678 		REQUIRE(!LISTENING(ifp));
    679 		LOCK(&mgr->lock);
    680 		ifp->generation = mgr->generation;
    681 		UNLOCK(&mgr->lock);
    682 	}
    683 
    684 	ifp->flags |= NS_INTERFACEFLAG_LISTENING;
    685 	ifp->proxy_type = elt->proxy;
    686 
    687 	if (elt->is_http) {
    688 		result = ns_interface_listenhttp(
    689 			ifp, elt->proxy, elt->sslctx, elt->http_endpoints,
    690 			elt->http_endpoints_number, elt->http_max_clients,
    691 			elt->max_concurrent_streams);
    692 		if (result != ISC_R_SUCCESS) {
    693 			goto cleanup_interface;
    694 		}
    695 		*ifpret = ifp;
    696 		return result;
    697 	}
    698 
    699 	if (elt->sslctx != NULL) {
    700 		result = ns_interface_listentls(ifp, elt->proxy, elt->sslctx);
    701 		if (result != ISC_R_SUCCESS) {
    702 			goto cleanup_interface;
    703 		}
    704 		*ifpret = ifp;
    705 		return result;
    706 	}
    707 
    708 	result = ns_interface_listenudp(ifp, elt->proxy);
    709 	if (result != ISC_R_SUCCESS) {
    710 		if ((result == ISC_R_ADDRINUSE) && (addr_in_use != NULL)) {
    711 			*addr_in_use = true;
    712 		}
    713 		goto cleanup_interface;
    714 	}
    715 
    716 	if ((mgr->sctx->options & NS_SERVER_NOTCP) == 0) {
    717 		result = ns_interface_listentcp(ifp, elt->proxy);
    718 		if (result != ISC_R_SUCCESS) {
    719 			if ((result == ISC_R_ADDRINUSE) &&
    720 			    (addr_in_use != NULL))
    721 			{
    722 				*addr_in_use = true;
    723 			}
    724 
    725 			/*
    726 			 * XXXRTH We don't currently have a way to easily stop
    727 			 * dispatch service, so we currently return
    728 			 * ISC_R_SUCCESS (the UDP stuff will work even if TCP
    729 			 * creation failed).  This will be fixed later.
    730 			 */
    731 			result = ISC_R_SUCCESS;
    732 		}
    733 	}
    734 	*ifpret = ifp;
    735 	return result;
    736 
    737 cleanup_interface:
    738 	ns_interface_shutdown(ifp);
    739 	return result;
    740 }
    741 
    742 void
    743 ns_interface_shutdown(ns_interface_t *ifp) {
    744 	ifp->flags &= ~NS_INTERFACEFLAG_LISTENING;
    745 
    746 	if (ifp->udplistensocket != NULL) {
    747 		isc_nm_stoplistening(ifp->udplistensocket);
    748 		isc_nmsocket_close(&ifp->udplistensocket);
    749 	}
    750 	if (ifp->tcplistensocket != NULL) {
    751 		isc_nm_stoplistening(ifp->tcplistensocket);
    752 		isc_nmsocket_close(&ifp->tcplistensocket);
    753 	}
    754 	if (ifp->tlslistensocket != NULL) {
    755 		isc_nm_stoplistening(ifp->tlslistensocket);
    756 		isc_nmsocket_close(&ifp->tlslistensocket);
    757 	}
    758 	if (ifp->http_listensocket != NULL) {
    759 		isc_nm_stoplistening(ifp->http_listensocket);
    760 		isc_nmsocket_close(&ifp->http_listensocket);
    761 	}
    762 	if (ifp->http_secure_listensocket != NULL) {
    763 		isc_nm_stoplistening(ifp->http_secure_listensocket);
    764 		isc_nmsocket_close(&ifp->http_secure_listensocket);
    765 	}
    766 	ifp->http_quota = NULL;
    767 }
    768 
    769 static void
    770 interface_destroy(ns_interface_t **interfacep) {
    771 	ns_interface_t *ifp = NULL;
    772 	ns_interfacemgr_t *mgr = NULL;
    773 
    774 	REQUIRE(interfacep != NULL);
    775 
    776 	ifp = *interfacep;
    777 	*interfacep = NULL;
    778 
    779 	REQUIRE(NS_INTERFACE_VALID(ifp));
    780 
    781 	mgr = ifp->mgr;
    782 
    783 	ns_interface_shutdown(ifp);
    784 
    785 	ifp->magic = 0;
    786 	isc_mutex_destroy(&ifp->lock);
    787 	ns_interfacemgr_detach(&ifp->mgr);
    788 	isc_refcount_destroy(&ifp->ntcpactive);
    789 	isc_refcount_destroy(&ifp->ntcpaccepting);
    790 
    791 	isc_mem_put(mgr->mctx, ifp, sizeof(*ifp));
    792 }
    793 
    794 /*%
    795  * Search the interface list for an interface whose address and port
    796  * both match those of 'addr'.  Return a pointer to it, or NULL if not found.
    797  */
    798 static ns_interface_t *
    799 find_matching_interface(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr) {
    800 	ns_interface_t *ifp;
    801 	LOCK(&mgr->lock);
    802 	for (ifp = ISC_LIST_HEAD(mgr->interfaces); ifp != NULL;
    803 	     ifp = ISC_LIST_NEXT(ifp, link))
    804 	{
    805 		if (isc_sockaddr_equal(&ifp->addr, addr)) {
    806 			break;
    807 		}
    808 	}
    809 	UNLOCK(&mgr->lock);
    810 	return ifp;
    811 }
    812 
    813 static void
    814 log_interface_shutdown(const ns_interface_t *ifp) {
    815 	char sabuf[ISC_SOCKADDR_FORMATSIZE];
    816 	isc_sockaddr_format(&ifp->addr, sabuf, sizeof(sabuf));
    817 	isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_INFO,
    818 		      "no longer listening on %s", sabuf);
    819 }
    820 
    821 /*%
    822  * Remove any interfaces whose generation number is not the current one.
    823  */
    824 static void
    825 purge_old_interfaces(ns_interfacemgr_t *mgr) {
    826 	ns_interface_t *ifp = NULL, *next = NULL;
    827 	ISC_LIST(ns_interface_t) interfaces;
    828 
    829 	ISC_LIST_INIT(interfaces);
    830 
    831 	LOCK(&mgr->lock);
    832 	for (ifp = ISC_LIST_HEAD(mgr->interfaces); ifp != NULL; ifp = next) {
    833 		INSIST(NS_INTERFACE_VALID(ifp));
    834 		next = ISC_LIST_NEXT(ifp, link);
    835 		if (ifp->generation != mgr->generation) {
    836 			ISC_LIST_UNLINK(ifp->mgr->interfaces, ifp, link);
    837 			ISC_LIST_APPEND(interfaces, ifp, link);
    838 		}
    839 	}
    840 	UNLOCK(&mgr->lock);
    841 
    842 	for (ifp = ISC_LIST_HEAD(interfaces); ifp != NULL; ifp = next) {
    843 		next = ISC_LIST_NEXT(ifp, link);
    844 		if (LISTENING(ifp)) {
    845 			log_interface_shutdown(ifp);
    846 			ns_interface_shutdown(ifp);
    847 		}
    848 		ISC_LIST_UNLINK(interfaces, ifp, link);
    849 		interface_destroy(&ifp);
    850 	}
    851 }
    852 
    853 static bool
    854 listenon_is_ip6_any(ns_listenelt_t *elt) {
    855 	REQUIRE(elt && elt->acl);
    856 	return dns_acl_isany(elt->acl);
    857 }
    858 
    859 static isc_result_t
    860 setup_locals(isc_interface_t *interface, dns_acl_t *localhost,
    861 	     dns_acl_t *localnets) {
    862 	isc_result_t result;
    863 	unsigned int prefixlen;
    864 	isc_netaddr_t *netaddr;
    865 
    866 	netaddr = &interface->address;
    867 
    868 	/* First add localhost address */
    869 	prefixlen = (netaddr->family == AF_INET) ? 32 : 128;
    870 	result = dns_iptable_addprefix(localhost->iptable, netaddr, prefixlen,
    871 				       true);
    872 	if (result != ISC_R_SUCCESS) {
    873 		return result;
    874 	}
    875 
    876 	/* Then add localnets prefix */
    877 	result = isc_netaddr_masktoprefixlen(&interface->netmask, &prefixlen);
    878 
    879 	/* Non contiguous netmasks not allowed by IPv6 arch. */
    880 	if (result != ISC_R_SUCCESS && netaddr->family == AF_INET6) {
    881 		return result;
    882 	}
    883 
    884 	if (result != ISC_R_SUCCESS) {
    885 		isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING,
    886 			      "omitting IPv4 interface %s from "
    887 			      "localnets ACL: %s",
    888 			      interface->name, isc_result_totext(result));
    889 		return ISC_R_SUCCESS;
    890 	}
    891 
    892 	if (prefixlen == 0U) {
    893 		isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING,
    894 			      "omitting %s interface %s from localnets ACL: "
    895 			      "zero prefix length detected",
    896 			      (netaddr->family == AF_INET) ? "IPv4" : "IPv6",
    897 			      interface->name);
    898 		return ISC_R_SUCCESS;
    899 	}
    900 
    901 	result = dns_iptable_addprefix(localnets->iptable, netaddr, prefixlen,
    902 				       true);
    903 	if (result != ISC_R_SUCCESS) {
    904 		return result;
    905 	}
    906 
    907 	return ISC_R_SUCCESS;
    908 }
    909 
    910 static void
    911 setup_listenon(ns_interfacemgr_t *mgr, isc_interface_t *interface,
    912 	       in_port_t port) {
    913 	isc_sockaddr_t *addr;
    914 	isc_sockaddr_t *old;
    915 
    916 	addr = isc_mem_get(mgr->mctx, sizeof(*addr));
    917 
    918 	isc_sockaddr_fromnetaddr(addr, &interface->address, port);
    919 
    920 	LOCK(&mgr->lock);
    921 	for (old = ISC_LIST_HEAD(mgr->listenon); old != NULL;
    922 	     old = ISC_LIST_NEXT(old, link))
    923 	{
    924 		if (isc_sockaddr_equal(addr, old)) {
    925 			/* We found an existing address */
    926 			isc_mem_put(mgr->mctx, addr, sizeof(*addr));
    927 			goto unlock;
    928 		}
    929 	}
    930 
    931 	ISC_LIST_APPEND(mgr->listenon, addr, link);
    932 unlock:
    933 	UNLOCK(&mgr->lock);
    934 }
    935 
    936 static void
    937 clearlistenon(ns_interfacemgr_t *mgr) {
    938 	ISC_LIST(isc_sockaddr_t) listenon;
    939 	isc_sockaddr_t *old;
    940 
    941 	ISC_LIST_INIT(listenon);
    942 
    943 	LOCK(&mgr->lock);
    944 	ISC_LIST_MOVE(listenon, mgr->listenon);
    945 	UNLOCK(&mgr->lock);
    946 
    947 	old = ISC_LIST_HEAD(listenon);
    948 	while (old != NULL) {
    949 		ISC_LIST_UNLINK(listenon, old, link);
    950 		isc_mem_put(mgr->mctx, old, sizeof(*old));
    951 		old = ISC_LIST_HEAD(listenon);
    952 	}
    953 }
    954 
    955 static void
    956 replace_listener_tlsctx(ns_interface_t *ifp, isc_tlsctx_t *newctx) {
    957 	char sabuf[ISC_SOCKADDR_FORMATSIZE];
    958 
    959 	isc_sockaddr_format(&ifp->addr, sabuf, sizeof(sabuf));
    960 	isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_INFO,
    961 		      "updating TLS context on %s", sabuf);
    962 	if (ifp->tlslistensocket != NULL) {
    963 		isc_nmsocket_set_tlsctx(ifp->tlslistensocket, newctx);
    964 	} else if (ifp->http_secure_listensocket != NULL) {
    965 		isc_nmsocket_set_tlsctx(ifp->http_secure_listensocket, newctx);
    966 	}
    967 }
    968 
    969 #ifdef HAVE_LIBNGHTTP2
    970 static void
    971 update_http_settings(ns_interface_t *ifp, ns_listenelt_t *le) {
    972 	isc_result_t result;
    973 	isc_nmsocket_t *listener;
    974 	isc_nm_http_endpoints_t *epset;
    975 
    976 	REQUIRE(le->is_http);
    977 
    978 	INSIST(ifp->http_quota != NULL);
    979 	isc_quota_max(ifp->http_quota, le->http_max_clients);
    980 
    981 	if (ifp->http_secure_listensocket != NULL) {
    982 		listener = ifp->http_secure_listensocket;
    983 	} else {
    984 		INSIST(ifp->http_listensocket != NULL);
    985 		listener = ifp->http_listensocket;
    986 	}
    987 
    988 	isc_nmsocket_set_max_streams(listener, le->max_concurrent_streams);
    989 
    990 	epset = isc_nm_http_endpoints_new(ifp->mgr->mctx);
    991 
    992 	result = load_http_endpoints(epset, ifp, le->http_endpoints,
    993 				     le->http_endpoints_number);
    994 
    995 	if (result == ISC_R_SUCCESS) {
    996 		isc_nm_http_set_endpoints(listener, epset);
    997 	}
    998 
    999 	isc_nm_http_endpoints_detach(&epset);
   1000 }
   1001 #endif /* HAVE_LIBNGHTTP2 */
   1002 
   1003 static void
   1004 update_listener_configuration(ns_interfacemgr_t *mgr, ns_interface_t *ifp,
   1005 			      ns_listenelt_t *le) {
   1006 	REQUIRE(NS_INTERFACEMGR_VALID(mgr));
   1007 	REQUIRE(NS_INTERFACE_VALID(ifp));
   1008 	REQUIRE(le != NULL);
   1009 
   1010 	LOCK(&mgr->lock);
   1011 	/*
   1012 	 * We need to update the TLS contexts
   1013 	 * inside the TLS/HTTPS listeners during
   1014 	 * a reconfiguration because the
   1015 	 * certificates could have been changed.
   1016 	 */
   1017 	if (le->sslctx != NULL) {
   1018 		replace_listener_tlsctx(ifp, le->sslctx);
   1019 	}
   1020 
   1021 #ifdef HAVE_LIBNGHTTP2
   1022 	/*
   1023 	 * Let's update HTTP listener settings
   1024 	 * on reconfiguration.
   1025 	 */
   1026 	if (le->is_http) {
   1027 		update_http_settings(ifp, le);
   1028 	}
   1029 #endif /* HAVE_LIBNGHTTP2 */
   1030 
   1031 	UNLOCK(&mgr->lock);
   1032 }
   1033 
   1034 static bool
   1035 same_listener_type(ns_interface_t *ifp, ns_listenelt_t *new_le) {
   1036 	bool same_transport_type = false;
   1037 
   1038 	/* See 'interface_setup()' above */
   1039 	if (new_le->is_http) {
   1040 		/* HTTP/DoH */
   1041 		same_transport_type = (new_le->sslctx != NULL &&
   1042 				       ifp->http_secure_listensocket != NULL) ||
   1043 				      (new_le->sslctx == NULL &&
   1044 				       ifp->http_listensocket != NULL);
   1045 	} else if (new_le->sslctx != NULL && ifp->tlslistensocket != NULL) {
   1046 		/* TLS/DoT */
   1047 		same_transport_type = true;
   1048 	} else if (new_le->sslctx == NULL && (ifp->udplistensocket != NULL ||
   1049 					      ifp->tcplistensocket != NULL))
   1050 	{
   1051 		/* "plain" DNS/Do53 */
   1052 		same_transport_type = true;
   1053 	}
   1054 
   1055 	/*
   1056 	 * Check if transport type of the listener has not changed. That
   1057 	 * implies that PROXY type has not been changed as well.
   1058 	 */
   1059 	return same_transport_type && new_le->proxy == ifp->proxy_type;
   1060 }
   1061 
   1062 static bool
   1063 interface_update_or_shutdown(ns_interfacemgr_t *mgr, ns_interface_t *ifp,
   1064 			     ns_listenelt_t *le, const bool config) {
   1065 	if (LISTENING(ifp) && config && !same_listener_type(ifp, le)) {
   1066 		/*
   1067 		 * DNS listener type has been changed on re-configuration. We
   1068 		 * will need to recreate the listener anew.
   1069 		 */
   1070 		log_interface_shutdown(ifp);
   1071 		ns_interface_shutdown(ifp);
   1072 	} else {
   1073 		LOCK(&mgr->lock);
   1074 		ifp->generation = mgr->generation;
   1075 		UNLOCK(&mgr->lock);
   1076 		if (LISTENING(ifp)) {
   1077 			if (config) {
   1078 				update_listener_configuration(mgr, ifp, le);
   1079 			}
   1080 			return true;
   1081 		}
   1082 	}
   1083 	return false;
   1084 }
   1085 
   1086 static isc_result_t
   1087 do_scan(ns_interfacemgr_t *mgr, bool verbose, bool config) {
   1088 	isc_interfaceiter_t *iter = NULL;
   1089 	bool scan_ipv4 = false;
   1090 	bool scan_ipv6 = false;
   1091 	bool ipv6only = true;
   1092 	bool ipv6pktinfo = true;
   1093 	isc_result_t result;
   1094 	isc_netaddr_t zero_address, zero_address6;
   1095 	ns_listenelt_t *le = NULL;
   1096 	isc_sockaddr_t listen_addr;
   1097 	ns_interface_t *ifp = NULL;
   1098 	bool log_explicit = false;
   1099 	bool dolistenon;
   1100 	char sabuf[ISC_SOCKADDR_FORMATSIZE];
   1101 	bool tried_listening;
   1102 	bool all_addresses_in_use;
   1103 	dns_acl_t *localhost = NULL;
   1104 	dns_acl_t *localnets = NULL;
   1105 
   1106 	if (isc_net_probeipv6() == ISC_R_SUCCESS) {
   1107 		scan_ipv6 = true;
   1108 	} else if ((mgr->sctx->options & NS_SERVER_DISABLE6) == 0) {
   1109 		isc_log_write(IFMGR_COMMON_LOGARGS,
   1110 			      verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1),
   1111 			      "no IPv6 interfaces found");
   1112 	}
   1113 
   1114 	if (isc_net_probeipv4() == ISC_R_SUCCESS) {
   1115 		scan_ipv4 = true;
   1116 	} else if ((mgr->sctx->options & NS_SERVER_DISABLE4) == 0) {
   1117 		isc_log_write(IFMGR_COMMON_LOGARGS,
   1118 			      verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1),
   1119 			      "no IPv4 interfaces found");
   1120 	}
   1121 
   1122 	/*
   1123 	 * A special, but typical case; listen-on-v6 { any; }.
   1124 	 * When we can make the socket IPv6-only, open a single wildcard
   1125 	 * socket for IPv6 communication.  Otherwise, make separate
   1126 	 * socket for each IPv6 address in order to avoid accepting IPv4
   1127 	 * packets as the form of mapped addresses unintentionally
   1128 	 * unless explicitly allowed.
   1129 	 */
   1130 	if (scan_ipv6 && isc_net_probe_ipv6only() != ISC_R_SUCCESS) {
   1131 		ipv6only = false;
   1132 		log_explicit = true;
   1133 	}
   1134 	if (scan_ipv6 && isc_net_probe_ipv6pktinfo() != ISC_R_SUCCESS) {
   1135 		ipv6pktinfo = false;
   1136 		log_explicit = true;
   1137 	}
   1138 	if (scan_ipv6 && ipv6only && ipv6pktinfo) {
   1139 		for (le = ISC_LIST_HEAD(mgr->listenon6->elts); le != NULL;
   1140 		     le = ISC_LIST_NEXT(le, link))
   1141 		{
   1142 			struct in6_addr in6a;
   1143 
   1144 			if (!listenon_is_ip6_any(le)) {
   1145 				continue;
   1146 			}
   1147 
   1148 			in6a = in6addr_any;
   1149 			isc_sockaddr_fromin6(&listen_addr, &in6a, le->port);
   1150 
   1151 			ifp = find_matching_interface(mgr, &listen_addr);
   1152 			if (ifp != NULL) {
   1153 				bool cont = interface_update_or_shutdown(
   1154 					mgr, ifp, le, config);
   1155 				if (cont) {
   1156 					continue;
   1157 				}
   1158 			}
   1159 
   1160 			isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_INFO,
   1161 				      "listening on IPv6 "
   1162 				      "interfaces, port %u",
   1163 				      le->port);
   1164 			result = interface_setup(mgr, &listen_addr, "<any>",
   1165 						 &ifp, le, NULL);
   1166 			if (result == ISC_R_SUCCESS) {
   1167 				ifp->flags |= NS_INTERFACEFLAG_ANYADDR;
   1168 			} else {
   1169 				isc_log_write(IFMGR_COMMON_LOGARGS,
   1170 					      ISC_LOG_ERROR,
   1171 					      "listening on all IPv6 "
   1172 					      "interfaces failed");
   1173 			}
   1174 			/* Continue. */
   1175 		}
   1176 	}
   1177 
   1178 	isc_netaddr_any(&zero_address);
   1179 	isc_netaddr_any6(&zero_address6);
   1180 
   1181 	result = isc_interfaceiter_create(mgr->mctx, &iter);
   1182 	if (result != ISC_R_SUCCESS) {
   1183 		return result;
   1184 	}
   1185 
   1186 	dns_acl_create(mgr->mctx, 0, &localhost);
   1187 	dns_acl_create(mgr->mctx, 0, &localnets);
   1188 
   1189 	clearlistenon(mgr);
   1190 
   1191 	tried_listening = false;
   1192 	all_addresses_in_use = true;
   1193 	for (result = isc_interfaceiter_first(iter); result == ISC_R_SUCCESS;
   1194 	     result = isc_interfaceiter_next(iter))
   1195 	{
   1196 		isc_interface_t interface;
   1197 		ns_listenlist_t *ll = NULL;
   1198 		unsigned int family;
   1199 
   1200 		result = isc_interfaceiter_current(iter, &interface);
   1201 		if (result != ISC_R_SUCCESS) {
   1202 			break;
   1203 		}
   1204 
   1205 		family = interface.address.family;
   1206 		if (family != AF_INET && family != AF_INET6) {
   1207 			continue;
   1208 		}
   1209 		if (!scan_ipv4 && family == AF_INET) {
   1210 			continue;
   1211 		}
   1212 		if (!scan_ipv6 && family == AF_INET6) {
   1213 			continue;
   1214 		}
   1215 
   1216 		/*
   1217 		 * Test for the address being nonzero rather than testing
   1218 		 * INTERFACE_F_UP, because on some systems the latter
   1219 		 * follows the media state and we could end up ignoring
   1220 		 * the interface for an entire rescan interval due to
   1221 		 * a temporary media glitch at rescan time.
   1222 		 */
   1223 		if (family == AF_INET &&
   1224 		    isc_netaddr_equal(&interface.address, &zero_address))
   1225 		{
   1226 			continue;
   1227 		}
   1228 		if (family == AF_INET6 &&
   1229 		    isc_netaddr_equal(&interface.address, &zero_address6))
   1230 		{
   1231 			continue;
   1232 		}
   1233 
   1234 		/*
   1235 		 * If running with -T fixedlocal, then we only
   1236 		 * want 127.0.0.1 and ::1 in the localhost ACL.
   1237 		 */
   1238 		if (((mgr->sctx->options & NS_SERVER_FIXEDLOCAL) != 0) &&
   1239 		    !isc_netaddr_isloopback(&interface.address))
   1240 		{
   1241 			goto listenon;
   1242 		}
   1243 
   1244 		result = setup_locals(&interface, localhost, localnets);
   1245 		if (result != ISC_R_SUCCESS) {
   1246 			goto ignore_interface;
   1247 		}
   1248 
   1249 	listenon:
   1250 		ll = (family == AF_INET) ? mgr->listenon4 : mgr->listenon6;
   1251 		dolistenon = true;
   1252 		for (le = ISC_LIST_HEAD(ll->elts); le != NULL;
   1253 		     le = ISC_LIST_NEXT(le, link))
   1254 		{
   1255 			int match;
   1256 			bool addr_in_use = false;
   1257 			bool ipv6_wildcard = false;
   1258 			isc_sockaddr_t listen_sockaddr;
   1259 
   1260 			isc_sockaddr_fromnetaddr(&listen_sockaddr,
   1261 						 &interface.address, le->port);
   1262 
   1263 			/*
   1264 			 * See if the address matches the listen-on statement;
   1265 			 * if not, ignore the interface, but store it in
   1266 			 * the interface table so we know we've seen it
   1267 			 * before.
   1268 			 */
   1269 			(void)dns_acl_match(&interface.address, NULL, le->acl,
   1270 					    mgr->aclenv, &match, NULL);
   1271 			if (match <= 0) {
   1272 				ns_interface_t *new = NULL;
   1273 				ns_interface_create(mgr, &listen_sockaddr,
   1274 						    interface.name, &new);
   1275 				continue;
   1276 			}
   1277 
   1278 			if (dolistenon) {
   1279 				setup_listenon(mgr, &interface, le->port);
   1280 				dolistenon = false;
   1281 			}
   1282 
   1283 			/*
   1284 			 * The case of "any" IPv6 address will require
   1285 			 * special considerations later, so remember it.
   1286 			 */
   1287 			if (family == AF_INET6 && ipv6only && ipv6pktinfo &&
   1288 			    listenon_is_ip6_any(le))
   1289 			{
   1290 				ipv6_wildcard = true;
   1291 			}
   1292 
   1293 			ifp = find_matching_interface(mgr, &listen_sockaddr);
   1294 			if (ifp != NULL) {
   1295 				bool cont = interface_update_or_shutdown(
   1296 					mgr, ifp, le, config);
   1297 				if (cont) {
   1298 					continue;
   1299 				}
   1300 			}
   1301 
   1302 			if (ipv6_wildcard) {
   1303 				continue;
   1304 			}
   1305 
   1306 			if (log_explicit && family == AF_INET6 &&
   1307 			    listenon_is_ip6_any(le))
   1308 			{
   1309 				isc_log_write(IFMGR_COMMON_LOGARGS,
   1310 					      verbose ? ISC_LOG_INFO
   1311 						      : ISC_LOG_DEBUG(1),
   1312 					      "IPv6 socket API is "
   1313 					      "incomplete; explicitly "
   1314 					      "binding to each IPv6 "
   1315 					      "address separately");
   1316 				log_explicit = false;
   1317 			}
   1318 			isc_sockaddr_format(&listen_sockaddr, sabuf,
   1319 					    sizeof(sabuf));
   1320 			isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_INFO,
   1321 				      "listening on %s interface "
   1322 				      "%s, %s",
   1323 				      (family == AF_INET) ? "IPv4" : "IPv6",
   1324 				      interface.name, sabuf);
   1325 
   1326 			result = interface_setup(mgr, &listen_sockaddr,
   1327 						 interface.name, &ifp, le,
   1328 						 &addr_in_use);
   1329 
   1330 			tried_listening = true;
   1331 			if (!addr_in_use) {
   1332 				all_addresses_in_use = false;
   1333 			}
   1334 
   1335 			if (result != ISC_R_SUCCESS) {
   1336 				isc_log_write(
   1337 					IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
   1338 					"creating %s interface "
   1339 					"%s failed; interface ignored",
   1340 					(family == AF_INET) ? "IPv4" : "IPv6",
   1341 					interface.name);
   1342 			}
   1343 			/* Continue. */
   1344 		}
   1345 		continue;
   1346 
   1347 	ignore_interface:
   1348 		isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
   1349 			      "ignoring %s interface %s: %s",
   1350 			      (family == AF_INET) ? "IPv4" : "IPv6",
   1351 			      interface.name, isc_result_totext(result));
   1352 		continue;
   1353 	}
   1354 	if (result != ISC_R_NOMORE) {
   1355 		UNEXPECTED_ERROR("interface iteration failed: %s",
   1356 				 isc_result_totext(result));
   1357 	} else {
   1358 		result = ((tried_listening && all_addresses_in_use)
   1359 				  ? ISC_R_ADDRINUSE
   1360 				  : ISC_R_SUCCESS);
   1361 	}
   1362 
   1363 	dns_aclenv_set(mgr->aclenv, localhost, localnets);
   1364 
   1365 	dns_acl_detach(&localnets);
   1366 	dns_acl_detach(&localhost);
   1367 
   1368 	isc_interfaceiter_destroy(&iter);
   1369 	return result;
   1370 }
   1371 
   1372 isc_result_t
   1373 ns_interfacemgr_scan(ns_interfacemgr_t *mgr, bool verbose, bool config) {
   1374 	isc_result_t result;
   1375 	bool purge = true;
   1376 
   1377 	REQUIRE(NS_INTERFACEMGR_VALID(mgr));
   1378 	REQUIRE(isc_tid() == 0);
   1379 
   1380 	mgr->generation++; /* Increment the generation count. */
   1381 
   1382 	result = do_scan(mgr, verbose, config);
   1383 	if ((result != ISC_R_SUCCESS) && (result != ISC_R_ADDRINUSE)) {
   1384 		purge = false;
   1385 	}
   1386 
   1387 	/*
   1388 	 * Now go through the interface list and delete anything that
   1389 	 * does not have the current generation number.  This is
   1390 	 * how we catch interfaces that go away or change their
   1391 	 * addresses.
   1392 	 */
   1393 	if (purge) {
   1394 		purge_old_interfaces(mgr);
   1395 	}
   1396 
   1397 	/*
   1398 	 * Warn if we are not listening on any interface.
   1399 	 */
   1400 	if (ISC_LIST_EMPTY(mgr->interfaces)) {
   1401 		isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING,
   1402 			      "not listening on any interfaces");
   1403 	}
   1404 
   1405 	return result;
   1406 }
   1407 
   1408 void
   1409 ns_interfacemgr_setlistenon4(ns_interfacemgr_t *mgr, ns_listenlist_t *value) {
   1410 	REQUIRE(NS_INTERFACEMGR_VALID(mgr));
   1411 
   1412 	LOCK(&mgr->lock);
   1413 	ns_listenlist_detach(&mgr->listenon4);
   1414 	ns_listenlist_attach(value, &mgr->listenon4);
   1415 	UNLOCK(&mgr->lock);
   1416 }
   1417 
   1418 void
   1419 ns_interfacemgr_setlistenon6(ns_interfacemgr_t *mgr, ns_listenlist_t *value) {
   1420 	REQUIRE(NS_INTERFACEMGR_VALID(mgr));
   1421 
   1422 	LOCK(&mgr->lock);
   1423 	ns_listenlist_detach(&mgr->listenon6);
   1424 	ns_listenlist_attach(value, &mgr->listenon6);
   1425 	UNLOCK(&mgr->lock);
   1426 }
   1427 
   1428 void
   1429 ns_interfacemgr_dumprecursing(FILE *f, ns_interfacemgr_t *mgr) {
   1430 	REQUIRE(NS_INTERFACEMGR_VALID(mgr));
   1431 
   1432 	LOCK(&mgr->lock);
   1433 	for (size_t i = 0; i < mgr->ncpus; i++) {
   1434 		ns_client_dumprecursing(f, mgr->clientmgrs[i]);
   1435 	}
   1436 	UNLOCK(&mgr->lock);
   1437 }
   1438 
   1439 bool
   1440 ns_interfacemgr_listeningon(ns_interfacemgr_t *mgr,
   1441 			    const isc_sockaddr_t *addr) {
   1442 	isc_sockaddr_t *old;
   1443 	bool result = false;
   1444 
   1445 	REQUIRE(NS_INTERFACEMGR_VALID(mgr));
   1446 	/*
   1447 	 * If the manager is shutting down it's safer to
   1448 	 * return true.
   1449 	 */
   1450 	if (atomic_load(&mgr->shuttingdown)) {
   1451 		return true;
   1452 	}
   1453 	LOCK(&mgr->lock);
   1454 	for (old = ISC_LIST_HEAD(mgr->listenon); old != NULL;
   1455 	     old = ISC_LIST_NEXT(old, link))
   1456 	{
   1457 		if (isc_sockaddr_equal(old, addr)) {
   1458 			result = true;
   1459 			break;
   1460 		}
   1461 	}
   1462 	UNLOCK(&mgr->lock);
   1463 
   1464 	return result;
   1465 }
   1466 
   1467 ns_server_t *
   1468 ns_interfacemgr_getserver(ns_interfacemgr_t *mgr) {
   1469 	REQUIRE(NS_INTERFACEMGR_VALID(mgr));
   1470 
   1471 	return mgr->sctx;
   1472 }
   1473 
   1474 ns_clientmgr_t *
   1475 ns_interfacemgr_getclientmgr(ns_interfacemgr_t *mgr) {
   1476 	int tid = isc_tid();
   1477 
   1478 	REQUIRE(NS_INTERFACEMGR_VALID(mgr));
   1479 	REQUIRE(tid >= 0);
   1480 	REQUIRE((uint32_t)tid < mgr->ncpus);
   1481 
   1482 	return mgr->clientmgrs[tid];
   1483 }
   1484 
   1485 bool
   1486 ns_interfacemgr_dynamic_updates_are_reliable(void) {
   1487 #if defined(LINUX_NETLINK_AVAILABLE)
   1488 	/*
   1489 	 * Let's disable periodic interface rescans on Linux, as there a
   1490 	 * reliable kernel-based mechanism for tracking interface state
   1491 	 * changes is available.
   1492 	 */
   1493 	return true;
   1494 #else
   1495 	return false;
   1496 #endif /* LINUX_NETLINK_AVAILABLE */
   1497 }
   1498