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