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