1 /*
2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3  *
4  * SPDX-License-Identifier: MPL-2.0
5  *
6  * This Source Code Form is subject to the terms of the Mozilla Public
7  * License, v. 2.0. If a copy of the MPL was not distributed with this
8  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
9  *
10  * See the COPYRIGHT file distributed with this work for additional
11  * information regarding copyright ownership.
12  */
13 
14 /*! \file */
15 
16 #include <stdbool.h>
17 
18 #include <isc/interfaceiter.h>
19 #include <isc/netmgr.h>
20 #include <isc/os.h>
21 #include <isc/random.h>
22 #include <isc/string.h>
23 #include <isc/task.h>
24 #include <isc/util.h>
25 
26 #include <dns/acl.h>
27 #include <dns/dispatch.h>
28 
29 #include <ns/client.h>
30 #include <ns/interfacemgr.h>
31 #include <ns/log.h>
32 #include <ns/server.h>
33 #include <ns/stats.h>
34 
35 #ifdef HAVE_NET_ROUTE_H
36 #include <net/route.h>
37 #if defined(RTM_VERSION) && defined(RTM_NEWADDR) && defined(RTM_DELADDR)
38 #define USE_ROUTE_SOCKET      1
39 #define ROUTE_SOCKET_PROTOCOL PF_ROUTE
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 #include <linux/netlink.h>
48 #include <linux/rtnetlink.h>
49 #if defined(RTM_NEWADDR) && defined(RTM_DELADDR)
50 #define USE_ROUTE_SOCKET      1
51 #define ROUTE_SOCKET_PROTOCOL PF_NETLINK
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 #ifdef TUNE_LARGE
59 #define UDPBUFFERS 32768
60 #else /* ifdef TUNE_LARGE */
61 #define UDPBUFFERS 1000
62 #endif /* TUNE_LARGE */
63 
64 #define IFMGR_MAGIC		 ISC_MAGIC('I', 'F', 'M', 'G')
65 #define NS_INTERFACEMGR_VALID(t) ISC_MAGIC_VALID(t, IFMGR_MAGIC)
66 
67 #define IFMGR_COMMON_LOGARGS \
68 	ns_lctx, NS_LOGCATEGORY_NETWORK, NS_LOGMODULE_INTERFACEMGR
69 
70 /*% nameserver interface manager structure */
71 struct ns_interfacemgr {
72 	unsigned int magic; /*%< Magic number. */
73 	isc_refcount_t references;
74 	isc_mutex_t lock;
75 	isc_mem_t *mctx;	    /*%< Memory context. */
76 	ns_server_t *sctx;	    /*%< Server context. */
77 	isc_taskmgr_t *taskmgr;	    /*%< Task manager. */
78 	isc_task_t *excl;	    /*%< Exclusive task. */
79 	isc_timermgr_t *timermgr;   /*%< Timer manager. */
80 	isc_socketmgr_t *socketmgr; /*%< Socket 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 	unsigned int udpdisp;	  /*%< UDP dispatch count */
92 	atomic_bool shuttingdown; /*%< Interfacemgr is shutting
93 				   * down */
94 #ifdef USE_ROUTE_SOCKET
95 	isc_task_t *task;
96 	isc_socket_t *route;
97 	unsigned char buf[2048];
98 #endif /* ifdef USE_ROUTE_SOCKET */
99 };
100 
101 static void
102 purge_old_interfaces(ns_interfacemgr_t *mgr);
103 
104 static void
105 clearlistenon(ns_interfacemgr_t *mgr);
106 
107 #ifdef USE_ROUTE_SOCKET
108 static void
route_event(isc_task_t * task,isc_event_t * event)109 route_event(isc_task_t *task, isc_event_t *event) {
110 	isc_socketevent_t *sevent = NULL;
111 	ns_interfacemgr_t *mgr = NULL;
112 	isc_region_t r;
113 	isc_result_t result;
114 	struct MSGHDR *rtm;
115 	bool done = true;
116 
117 	UNUSED(task);
118 
119 	REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE);
120 	mgr = event->ev_arg;
121 	sevent = (isc_socketevent_t *)event;
122 
123 	if (sevent->result != ISC_R_SUCCESS) {
124 		if (sevent->result != ISC_R_CANCELED) {
125 			isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
126 				      "automatic interface scanning "
127 				      "terminated: %s",
128 				      isc_result_totext(sevent->result));
129 		}
130 		ns_interfacemgr_detach(&mgr);
131 		isc_event_free(&event);
132 		return;
133 	}
134 
135 	rtm = (struct MSGHDR *)mgr->buf;
136 #ifdef RTM_VERSION
137 	if (rtm->rtm_version != RTM_VERSION) {
138 		isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
139 			      "automatic interface rescanning disabled: "
140 			      "rtm->rtm_version mismatch (%u != %u) "
141 			      "recompile required",
142 			      rtm->rtm_version, RTM_VERSION);
143 		ns_interfacemgr_detach(&mgr);
144 		isc_event_free(&event);
145 		return;
146 	}
147 #endif /* ifdef RTM_VERSION */
148 
149 	switch (rtm->MSGTYPE) {
150 	case RTM_NEWADDR:
151 	case RTM_DELADDR:
152 		if (mgr->route != NULL && mgr->sctx->interface_auto) {
153 			ns_interfacemgr_scan(mgr, false);
154 		}
155 		break;
156 	default:
157 		break;
158 	}
159 
160 	LOCK(&mgr->lock);
161 	if (mgr->route != NULL) {
162 		/*
163 		 * Look for next route event.
164 		 */
165 		r.base = mgr->buf;
166 		r.length = sizeof(mgr->buf);
167 		result = isc_socket_recv(mgr->route, &r, 1, mgr->task,
168 					 route_event, mgr);
169 		if (result == ISC_R_SUCCESS) {
170 			done = false;
171 		}
172 	}
173 	UNLOCK(&mgr->lock);
174 
175 	if (done) {
176 		ns_interfacemgr_detach(&mgr);
177 	}
178 	isc_event_free(&event);
179 	return;
180 }
181 #endif /* ifdef USE_ROUTE_SOCKET */
182 
183 isc_result_t
ns_interfacemgr_create(isc_mem_t * mctx,ns_server_t * sctx,isc_taskmgr_t * taskmgr,isc_timermgr_t * timermgr,isc_socketmgr_t * socketmgr,isc_nm_t * nm,dns_dispatchmgr_t * dispatchmgr,isc_task_t * task,unsigned int udpdisp,dns_geoip_databases_t * geoip,int ncpus,ns_interfacemgr_t ** mgrp)184 ns_interfacemgr_create(isc_mem_t *mctx, ns_server_t *sctx,
185 		       isc_taskmgr_t *taskmgr, isc_timermgr_t *timermgr,
186 		       isc_socketmgr_t *socketmgr, isc_nm_t *nm,
187 		       dns_dispatchmgr_t *dispatchmgr, isc_task_t *task,
188 		       unsigned int udpdisp, dns_geoip_databases_t *geoip,
189 		       int ncpus, ns_interfacemgr_t **mgrp) {
190 	isc_result_t result;
191 	ns_interfacemgr_t *mgr;
192 
193 #ifndef USE_ROUTE_SOCKET
194 	UNUSED(task);
195 #endif /* ifndef USE_ROUTE_SOCKET */
196 
197 	REQUIRE(mctx != NULL);
198 	REQUIRE(mgrp != NULL);
199 	REQUIRE(*mgrp == NULL);
200 
201 	mgr = isc_mem_get(mctx, sizeof(*mgr));
202 
203 	mgr->mctx = NULL;
204 	isc_mem_attach(mctx, &mgr->mctx);
205 
206 	mgr->sctx = NULL;
207 	ns_server_attach(sctx, &mgr->sctx);
208 
209 	isc_mutex_init(&mgr->lock);
210 
211 	mgr->excl = NULL;
212 	result = isc_taskmgr_excltask(taskmgr, &mgr->excl);
213 	if (result != ISC_R_SUCCESS) {
214 		goto cleanup_lock;
215 	}
216 
217 	mgr->taskmgr = taskmgr;
218 	mgr->timermgr = timermgr;
219 	mgr->socketmgr = socketmgr;
220 	mgr->nm = nm;
221 	mgr->dispatchmgr = dispatchmgr;
222 	mgr->generation = 1;
223 	mgr->listenon4 = NULL;
224 	mgr->listenon6 = NULL;
225 	mgr->udpdisp = udpdisp;
226 	mgr->ncpus = ncpus;
227 	atomic_init(&mgr->shuttingdown, false);
228 
229 	ISC_LIST_INIT(mgr->interfaces);
230 	ISC_LIST_INIT(mgr->listenon);
231 
232 	/*
233 	 * The listen-on lists are initially empty.
234 	 */
235 	result = ns_listenlist_create(mctx, &mgr->listenon4);
236 	if (result != ISC_R_SUCCESS) {
237 		goto cleanup_ctx;
238 	}
239 	ns_listenlist_attach(mgr->listenon4, &mgr->listenon6);
240 
241 	result = dns_aclenv_init(mctx, &mgr->aclenv);
242 	if (result != ISC_R_SUCCESS) {
243 		goto cleanup_listenon;
244 	}
245 #if defined(HAVE_GEOIP2)
246 	mgr->aclenv.geoip = geoip;
247 #else  /* if defined(HAVE_GEOIP2) */
248 	UNUSED(geoip);
249 #endif /* if defined(HAVE_GEOIP2) */
250 
251 #ifdef USE_ROUTE_SOCKET
252 	mgr->route = NULL;
253 	result = isc_socket_create(mgr->socketmgr, ROUTE_SOCKET_PROTOCOL,
254 				   isc_sockettype_raw, &mgr->route);
255 	switch (result) {
256 	case ISC_R_NOPERM:
257 	case ISC_R_SUCCESS:
258 	case ISC_R_NOTIMPLEMENTED:
259 	case ISC_R_FAMILYNOSUPPORT:
260 		break;
261 	default:
262 		goto cleanup_aclenv;
263 	}
264 
265 	mgr->task = NULL;
266 	if (mgr->route != NULL) {
267 		isc_task_attach(task, &mgr->task);
268 	}
269 	isc_refcount_init(&mgr->references, (mgr->route != NULL) ? 2 : 1);
270 #else  /* ifdef USE_ROUTE_SOCKET */
271 	isc_refcount_init(&mgr->references, 1);
272 #endif /* ifdef USE_ROUTE_SOCKET */
273 	mgr->magic = IFMGR_MAGIC;
274 	*mgrp = mgr;
275 
276 #ifdef USE_ROUTE_SOCKET
277 	if (mgr->route != NULL) {
278 		isc_region_t r = { mgr->buf, sizeof(mgr->buf) };
279 
280 		result = isc_socket_recv(mgr->route, &r, 1, mgr->task,
281 					 route_event, mgr);
282 		if (result != ISC_R_SUCCESS) {
283 			isc_task_detach(&mgr->task);
284 			isc_socket_detach(&mgr->route);
285 			ns_interfacemgr_detach(&mgr);
286 		}
287 	}
288 #endif /* ifdef USE_ROUTE_SOCKET */
289 	return (ISC_R_SUCCESS);
290 
291 #ifdef USE_ROUTE_SOCKET
292 cleanup_aclenv:
293 	dns_aclenv_destroy(&mgr->aclenv);
294 #endif /* ifdef USE_ROUTE_SOCKET */
295 cleanup_listenon:
296 	ns_listenlist_detach(&mgr->listenon4);
297 	ns_listenlist_detach(&mgr->listenon6);
298 cleanup_lock:
299 	isc_mutex_destroy(&mgr->lock);
300 cleanup_ctx:
301 	ns_server_detach(&mgr->sctx);
302 	isc_mem_putanddetach(&mgr->mctx, mgr, sizeof(*mgr));
303 	return (result);
304 }
305 
306 static void
ns_interfacemgr_destroy(ns_interfacemgr_t * mgr)307 ns_interfacemgr_destroy(ns_interfacemgr_t *mgr) {
308 	REQUIRE(NS_INTERFACEMGR_VALID(mgr));
309 
310 	isc_refcount_destroy(&mgr->references);
311 
312 #ifdef USE_ROUTE_SOCKET
313 	if (mgr->route != NULL) {
314 		isc_socket_detach(&mgr->route);
315 	}
316 	if (mgr->task != NULL) {
317 		isc_task_detach(&mgr->task);
318 	}
319 #endif /* ifdef USE_ROUTE_SOCKET */
320 	dns_aclenv_destroy(&mgr->aclenv);
321 	ns_listenlist_detach(&mgr->listenon4);
322 	ns_listenlist_detach(&mgr->listenon6);
323 	clearlistenon(mgr);
324 	isc_mutex_destroy(&mgr->lock);
325 	if (mgr->sctx != NULL) {
326 		ns_server_detach(&mgr->sctx);
327 	}
328 	if (mgr->excl != NULL) {
329 		isc_task_detach(&mgr->excl);
330 	}
331 	mgr->magic = 0;
332 	isc_mem_putanddetach(&mgr->mctx, mgr, sizeof(*mgr));
333 }
334 
335 void
ns_interfacemgr_setbacklog(ns_interfacemgr_t * mgr,int backlog)336 ns_interfacemgr_setbacklog(ns_interfacemgr_t *mgr, int backlog) {
337 	REQUIRE(NS_INTERFACEMGR_VALID(mgr));
338 	LOCK(&mgr->lock);
339 	mgr->backlog = backlog;
340 	UNLOCK(&mgr->lock);
341 }
342 
343 dns_aclenv_t *
ns_interfacemgr_getaclenv(ns_interfacemgr_t * mgr)344 ns_interfacemgr_getaclenv(ns_interfacemgr_t *mgr) {
345 	REQUIRE(NS_INTERFACEMGR_VALID(mgr));
346 
347 	return (&mgr->aclenv);
348 }
349 
350 void
ns_interfacemgr_attach(ns_interfacemgr_t * source,ns_interfacemgr_t ** target)351 ns_interfacemgr_attach(ns_interfacemgr_t *source, ns_interfacemgr_t **target) {
352 	REQUIRE(NS_INTERFACEMGR_VALID(source));
353 	isc_refcount_increment(&source->references);
354 	*target = source;
355 }
356 
357 void
ns_interfacemgr_detach(ns_interfacemgr_t ** targetp)358 ns_interfacemgr_detach(ns_interfacemgr_t **targetp) {
359 	ns_interfacemgr_t *target = *targetp;
360 	*targetp = NULL;
361 	REQUIRE(target != NULL);
362 	REQUIRE(NS_INTERFACEMGR_VALID(target));
363 	if (isc_refcount_decrement(&target->references) == 1) {
364 		ns_interfacemgr_destroy(target);
365 	}
366 }
367 
368 void
ns_interfacemgr_shutdown(ns_interfacemgr_t * mgr)369 ns_interfacemgr_shutdown(ns_interfacemgr_t *mgr) {
370 	REQUIRE(NS_INTERFACEMGR_VALID(mgr));
371 
372 	/*%
373 	 * Shut down and detach all interfaces.
374 	 * By incrementing the generation count, we make purge_old_interfaces()
375 	 * consider all interfaces "old".
376 	 */
377 	mgr->generation++;
378 	atomic_store(&mgr->shuttingdown, true);
379 #ifdef USE_ROUTE_SOCKET
380 	LOCK(&mgr->lock);
381 	if (mgr->route != NULL) {
382 		isc_socket_cancel(mgr->route, mgr->task, ISC_SOCKCANCEL_RECV);
383 		isc_socket_detach(&mgr->route);
384 		isc_task_detach(&mgr->task);
385 	}
386 	UNLOCK(&mgr->lock);
387 #endif /* ifdef USE_ROUTE_SOCKET */
388 	purge_old_interfaces(mgr);
389 }
390 
391 static isc_result_t
ns_interface_create(ns_interfacemgr_t * mgr,isc_sockaddr_t * addr,const char * name,ns_interface_t ** ifpret)392 ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
393 		    const char *name, ns_interface_t **ifpret) {
394 	ns_interface_t *ifp;
395 	isc_result_t result;
396 	int disp;
397 
398 	REQUIRE(NS_INTERFACEMGR_VALID(mgr));
399 
400 	ifp = isc_mem_get(mgr->mctx, sizeof(*ifp));
401 	*ifp = (ns_interface_t){ .generation = mgr->generation,
402 				 .addr = *addr,
403 				 .dscp = -1 };
404 
405 	strlcpy(ifp->name, name, sizeof(ifp->name));
406 
407 	isc_mutex_init(&ifp->lock);
408 
409 	for (disp = 0; disp < MAX_UDP_DISPATCH; disp++) {
410 		ifp->udpdispatch[disp] = NULL;
411 	}
412 
413 	/*
414 	 * Create a single TCP client object.  It will replace itself
415 	 * with a new one as soon as it gets a connection, so the actual
416 	 * connections will be handled in parallel even though there is
417 	 * only one client initially.
418 	 */
419 	isc_refcount_init(&ifp->ntcpaccepting, 0);
420 	isc_refcount_init(&ifp->ntcpactive, 0);
421 
422 	ISC_LINK_INIT(ifp, link);
423 
424 	ns_interfacemgr_attach(mgr, &ifp->mgr);
425 	LOCK(&mgr->lock);
426 	ISC_LIST_APPEND(mgr->interfaces, ifp, link);
427 	UNLOCK(&mgr->lock);
428 
429 	isc_refcount_init(&ifp->references, 1);
430 	ifp->magic = IFACE_MAGIC;
431 
432 	result = ns_clientmgr_create(mgr->mctx, mgr->sctx, mgr->taskmgr,
433 				     mgr->timermgr, ifp, mgr->ncpus,
434 				     &ifp->clientmgr);
435 	if (result != ISC_R_SUCCESS) {
436 		isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
437 			      "ns_clientmgr_create() failed: %s",
438 			      isc_result_totext(result));
439 		goto failure;
440 	}
441 
442 	*ifpret = ifp;
443 
444 	return (ISC_R_SUCCESS);
445 
446 failure:
447 	isc_mutex_destroy(&ifp->lock);
448 
449 	ifp->magic = 0;
450 	isc_mem_put(mgr->mctx, ifp, sizeof(*ifp));
451 
452 	return (ISC_R_UNEXPECTED);
453 }
454 
455 static isc_result_t
ns_interface_listenudp(ns_interface_t * ifp)456 ns_interface_listenudp(ns_interface_t *ifp) {
457 	isc_result_t result;
458 
459 	/* Reserve space for an ns_client_t with the netmgr handle */
460 	result = isc_nm_listenudp(ifp->mgr->nm, &ifp->addr, ns__client_request,
461 				  ifp, sizeof(ns_client_t),
462 				  &ifp->udplistensocket);
463 	return (result);
464 }
465 
466 static isc_result_t
ns_interface_listentcp(ns_interface_t * ifp)467 ns_interface_listentcp(ns_interface_t *ifp) {
468 	isc_result_t result;
469 
470 	result = isc_nm_listentcpdns(
471 		ifp->mgr->nm, &ifp->addr, ns__client_request, ifp,
472 		ns__client_tcpconn, ifp, sizeof(ns_client_t), ifp->mgr->backlog,
473 		&ifp->mgr->sctx->tcpquota, &ifp->tcplistensocket);
474 	if (result != ISC_R_SUCCESS) {
475 		isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
476 			      "creating TCP socket: %s",
477 			      isc_result_totext(result));
478 	}
479 
480 	/*
481 	 * We call this now to update the tcp-highwater statistic:
482 	 * this is necessary because we are adding to the TCP quota just
483 	 * by listening.
484 	 */
485 	result = ns__client_tcpconn(NULL, ISC_R_SUCCESS, ifp);
486 	if (result != ISC_R_SUCCESS) {
487 		isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
488 			      "connecting TCP socket: %s",
489 			      isc_result_totext(result));
490 	}
491 
492 #if 0
493 #ifndef ISC_ALLOW_MAPPED
494 	isc_socket_ipv6only(ifp->tcpsocket,true);
495 #endif /* ifndef ISC_ALLOW_MAPPED */
496 
497 	if (ifp->dscp != -1) {
498 		isc_socket_dscp(ifp->tcpsocket,ifp->dscp);
499 	}
500 
501 	(void)isc_socket_filter(ifp->tcpsocket,"dataready");
502 #endif /* if 0 */
503 	return (result);
504 }
505 
506 static isc_result_t
ns_interface_setup(ns_interfacemgr_t * mgr,isc_sockaddr_t * addr,const char * name,ns_interface_t ** ifpret,isc_dscp_t dscp,bool * addr_in_use)507 ns_interface_setup(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
508 		   const char *name, ns_interface_t **ifpret, isc_dscp_t dscp,
509 		   bool *addr_in_use) {
510 	isc_result_t result;
511 	ns_interface_t *ifp = NULL;
512 	REQUIRE(ifpret != NULL && *ifpret == NULL);
513 	REQUIRE(addr_in_use == NULL || !*addr_in_use);
514 
515 	result = ns_interface_create(mgr, addr, name, &ifp);
516 	if (result != ISC_R_SUCCESS) {
517 		return (result);
518 	}
519 
520 	ifp->dscp = dscp;
521 
522 	result = ns_interface_listenudp(ifp);
523 	if (result != ISC_R_SUCCESS) {
524 		if ((result == ISC_R_ADDRINUSE) && (addr_in_use != NULL)) {
525 			*addr_in_use = true;
526 		}
527 		goto cleanup_interface;
528 	}
529 
530 	if (((mgr->sctx->options & NS_SERVER_NOTCP) == 0)) {
531 		result = ns_interface_listentcp(ifp);
532 		if (result != ISC_R_SUCCESS) {
533 			if ((result == ISC_R_ADDRINUSE) &&
534 			    (addr_in_use != NULL)) {
535 				*addr_in_use = true;
536 			}
537 
538 			/*
539 			 * XXXRTH We don't currently have a way to easily stop
540 			 * dispatch service, so we currently return
541 			 * ISC_R_SUCCESS (the UDP stuff will work even if TCP
542 			 * creation failed).  This will be fixed later.
543 			 */
544 			result = ISC_R_SUCCESS;
545 		}
546 	}
547 	*ifpret = ifp;
548 	return (result);
549 
550 cleanup_interface:
551 	LOCK(&ifp->mgr->lock);
552 	ISC_LIST_UNLINK(ifp->mgr->interfaces, ifp, link);
553 	UNLOCK(&ifp->mgr->lock);
554 	ns_interface_shutdown(ifp);
555 	ns_interface_detach(&ifp);
556 	return (result);
557 }
558 
559 void
ns_interface_shutdown(ns_interface_t * ifp)560 ns_interface_shutdown(ns_interface_t *ifp) {
561 	if (ifp->udplistensocket != NULL) {
562 		isc_nm_stoplistening(ifp->udplistensocket);
563 		isc_nmsocket_close(&ifp->udplistensocket);
564 	}
565 	if (ifp->tcplistensocket != NULL) {
566 		isc_nm_stoplistening(ifp->tcplistensocket);
567 		isc_nmsocket_close(&ifp->tcplistensocket);
568 	}
569 	if (ifp->clientmgr != NULL) {
570 		ns_clientmgr_destroy(&ifp->clientmgr);
571 	}
572 }
573 
574 static void
ns_interface_destroy(ns_interface_t * ifp)575 ns_interface_destroy(ns_interface_t *ifp) {
576 	REQUIRE(NS_INTERFACE_VALID(ifp));
577 
578 	isc_mem_t *mctx = ifp->mgr->mctx;
579 
580 	ns_interface_shutdown(ifp);
581 
582 	for (int disp = 0; disp < ifp->nudpdispatch; disp++) {
583 		if (ifp->udpdispatch[disp] != NULL) {
584 			dns_dispatch_changeattributes(
585 				ifp->udpdispatch[disp], 0,
586 				DNS_DISPATCHATTR_NOLISTEN);
587 			dns_dispatch_detach(&(ifp->udpdispatch[disp]));
588 		}
589 	}
590 
591 	if (ifp->tcpsocket != NULL) {
592 		isc_socket_detach(&ifp->tcpsocket);
593 	}
594 
595 	isc_mutex_destroy(&ifp->lock);
596 
597 	ns_interfacemgr_detach(&ifp->mgr);
598 
599 	isc_refcount_destroy(&ifp->ntcpactive);
600 	isc_refcount_destroy(&ifp->ntcpaccepting);
601 
602 	ifp->magic = 0;
603 
604 	isc_mem_put(mctx, ifp, sizeof(*ifp));
605 }
606 
607 void
ns_interface_attach(ns_interface_t * source,ns_interface_t ** target)608 ns_interface_attach(ns_interface_t *source, ns_interface_t **target) {
609 	REQUIRE(NS_INTERFACE_VALID(source));
610 	isc_refcount_increment(&source->references);
611 	*target = source;
612 }
613 
614 void
ns_interface_detach(ns_interface_t ** targetp)615 ns_interface_detach(ns_interface_t **targetp) {
616 	ns_interface_t *target = *targetp;
617 	*targetp = NULL;
618 	REQUIRE(target != NULL);
619 	REQUIRE(NS_INTERFACE_VALID(target));
620 	if (isc_refcount_decrement(&target->references) == 1) {
621 		ns_interface_destroy(target);
622 	}
623 }
624 
625 /*%
626  * Search the interface list for an interface whose address and port
627  * both match those of 'addr'.  Return a pointer to it, or NULL if not found.
628  */
629 static ns_interface_t *
find_matching_interface(ns_interfacemgr_t * mgr,isc_sockaddr_t * addr)630 find_matching_interface(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr) {
631 	ns_interface_t *ifp;
632 	LOCK(&mgr->lock);
633 	for (ifp = ISC_LIST_HEAD(mgr->interfaces); ifp != NULL;
634 	     ifp = ISC_LIST_NEXT(ifp, link))
635 	{
636 		if (isc_sockaddr_equal(&ifp->addr, addr)) {
637 			break;
638 		}
639 	}
640 	UNLOCK(&mgr->lock);
641 	return (ifp);
642 }
643 
644 /*%
645  * Remove any interfaces whose generation number is not the current one.
646  */
647 static void
purge_old_interfaces(ns_interfacemgr_t * mgr)648 purge_old_interfaces(ns_interfacemgr_t *mgr) {
649 	ns_interface_t *ifp, *next;
650 	LOCK(&mgr->lock);
651 	for (ifp = ISC_LIST_HEAD(mgr->interfaces); ifp != NULL; ifp = next) {
652 		INSIST(NS_INTERFACE_VALID(ifp));
653 		next = ISC_LIST_NEXT(ifp, link);
654 		if (ifp->generation != mgr->generation) {
655 			char sabuf[256];
656 			ISC_LIST_UNLINK(ifp->mgr->interfaces, ifp, link);
657 			isc_sockaddr_format(&ifp->addr, sabuf, sizeof(sabuf));
658 			isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_INFO,
659 				      "no longer listening on %s", sabuf);
660 			ns_interface_shutdown(ifp);
661 			ns_interface_detach(&ifp);
662 		}
663 	}
664 	UNLOCK(&mgr->lock);
665 }
666 
667 static isc_result_t
clearacl(isc_mem_t * mctx,dns_acl_t ** aclp)668 clearacl(isc_mem_t *mctx, dns_acl_t **aclp) {
669 	dns_acl_t *newacl = NULL;
670 	isc_result_t result;
671 	result = dns_acl_create(mctx, 0, &newacl);
672 	if (result != ISC_R_SUCCESS) {
673 		return (result);
674 	}
675 	dns_acl_detach(aclp);
676 	dns_acl_attach(newacl, aclp);
677 	dns_acl_detach(&newacl);
678 	return (ISC_R_SUCCESS);
679 }
680 
681 static bool
listenon_is_ip6_any(ns_listenelt_t * elt)682 listenon_is_ip6_any(ns_listenelt_t *elt) {
683 	REQUIRE(elt && elt->acl);
684 	return (dns_acl_isany(elt->acl));
685 }
686 
687 static isc_result_t
setup_locals(ns_interfacemgr_t * mgr,isc_interface_t * interface)688 setup_locals(ns_interfacemgr_t *mgr, isc_interface_t *interface) {
689 	isc_result_t result;
690 	unsigned int prefixlen;
691 	isc_netaddr_t *netaddr;
692 
693 	netaddr = &interface->address;
694 
695 	/* First add localhost address */
696 	prefixlen = (netaddr->family == AF_INET) ? 32 : 128;
697 	result = dns_iptable_addprefix(mgr->aclenv.localhost->iptable, netaddr,
698 				       prefixlen, true);
699 	if (result != ISC_R_SUCCESS) {
700 		return (result);
701 	}
702 
703 	/* Then add localnets prefix */
704 	result = isc_netaddr_masktoprefixlen(&interface->netmask, &prefixlen);
705 
706 	/* Non contiguous netmasks not allowed by IPv6 arch. */
707 	if (result != ISC_R_SUCCESS && netaddr->family == AF_INET6) {
708 		return (result);
709 	}
710 
711 	if (result != ISC_R_SUCCESS) {
712 		isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING,
713 			      "omitting IPv4 interface %s from "
714 			      "localnets ACL: %s",
715 			      interface->name, isc_result_totext(result));
716 		return (ISC_R_SUCCESS);
717 	}
718 
719 	if (prefixlen == 0U) {
720 		isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING,
721 			      "omitting %s interface %s from localnets ACL: "
722 			      "zero prefix length detected",
723 			      (netaddr->family == AF_INET) ? "IPv4" : "IPv6",
724 			      interface->name);
725 		return (ISC_R_SUCCESS);
726 	}
727 
728 	result = dns_iptable_addprefix(mgr->aclenv.localnets->iptable, netaddr,
729 				       prefixlen, true);
730 	if (result != ISC_R_SUCCESS) {
731 		return (result);
732 	}
733 
734 	return (ISC_R_SUCCESS);
735 }
736 
737 static void
setup_listenon(ns_interfacemgr_t * mgr,isc_interface_t * interface,in_port_t port)738 setup_listenon(ns_interfacemgr_t *mgr, isc_interface_t *interface,
739 	       in_port_t port) {
740 	isc_sockaddr_t *addr;
741 	isc_sockaddr_t *old;
742 
743 	addr = isc_mem_get(mgr->mctx, sizeof(*addr));
744 
745 	isc_sockaddr_fromnetaddr(addr, &interface->address, port);
746 
747 	LOCK(&mgr->lock);
748 	for (old = ISC_LIST_HEAD(mgr->listenon); old != NULL;
749 	     old = ISC_LIST_NEXT(old, link))
750 	{
751 		if (isc_sockaddr_equal(addr, old)) {
752 			break;
753 		}
754 	}
755 
756 	if (old != NULL) {
757 		isc_mem_put(mgr->mctx, addr, sizeof(*addr));
758 	} else {
759 		ISC_LIST_APPEND(mgr->listenon, addr, link);
760 	}
761 	UNLOCK(&mgr->lock);
762 }
763 
764 static void
clearlistenon(ns_interfacemgr_t * mgr)765 clearlistenon(ns_interfacemgr_t *mgr) {
766 	isc_sockaddr_t *old;
767 
768 	LOCK(&mgr->lock);
769 	old = ISC_LIST_HEAD(mgr->listenon);
770 	while (old != NULL) {
771 		ISC_LIST_UNLINK(mgr->listenon, old, link);
772 		isc_mem_put(mgr->mctx, old, sizeof(*old));
773 		old = ISC_LIST_HEAD(mgr->listenon);
774 	}
775 	UNLOCK(&mgr->lock);
776 }
777 
778 static isc_result_t
do_scan(ns_interfacemgr_t * mgr,bool verbose)779 do_scan(ns_interfacemgr_t *mgr, bool verbose) {
780 	isc_interfaceiter_t *iter = NULL;
781 	bool scan_ipv4 = false;
782 	bool scan_ipv6 = false;
783 	bool ipv6only = true;
784 	bool ipv6pktinfo = true;
785 	isc_result_t result;
786 	isc_netaddr_t zero_address, zero_address6;
787 	ns_listenelt_t *le;
788 	isc_sockaddr_t listen_addr;
789 	ns_interface_t *ifp;
790 	bool log_explicit = false;
791 	bool dolistenon;
792 	char sabuf[ISC_SOCKADDR_FORMATSIZE];
793 	bool tried_listening;
794 	bool all_addresses_in_use;
795 
796 	if (isc_net_probeipv6() == ISC_R_SUCCESS) {
797 		scan_ipv6 = true;
798 	} else if ((mgr->sctx->options & NS_SERVER_DISABLE6) == 0) {
799 		isc_log_write(IFMGR_COMMON_LOGARGS,
800 			      verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1),
801 			      "no IPv6 interfaces found");
802 	}
803 
804 	if (isc_net_probeipv4() == ISC_R_SUCCESS) {
805 		scan_ipv4 = true;
806 	} else if ((mgr->sctx->options & NS_SERVER_DISABLE4) == 0) {
807 		isc_log_write(IFMGR_COMMON_LOGARGS,
808 			      verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1),
809 			      "no IPv4 interfaces found");
810 	}
811 
812 	/*
813 	 * A special, but typical case; listen-on-v6 { any; }.
814 	 * When we can make the socket IPv6-only, open a single wildcard
815 	 * socket for IPv6 communication.  Otherwise, make separate
816 	 * socket for each IPv6 address in order to avoid accepting IPv4
817 	 * packets as the form of mapped addresses unintentionally
818 	 * unless explicitly allowed.
819 	 */
820 #ifndef ISC_ALLOW_MAPPED
821 	if (scan_ipv6 && isc_net_probe_ipv6only() != ISC_R_SUCCESS) {
822 		ipv6only = false;
823 		log_explicit = true;
824 	}
825 #endif /* ifndef ISC_ALLOW_MAPPED */
826 	if (scan_ipv6 && isc_net_probe_ipv6pktinfo() != ISC_R_SUCCESS) {
827 		ipv6pktinfo = false;
828 		log_explicit = true;
829 	}
830 	if (scan_ipv6 && ipv6only && ipv6pktinfo) {
831 		for (le = ISC_LIST_HEAD(mgr->listenon6->elts); le != NULL;
832 		     le = ISC_LIST_NEXT(le, link))
833 		{
834 			struct in6_addr in6a;
835 
836 			if (!listenon_is_ip6_any(le)) {
837 				continue;
838 			}
839 
840 			in6a = in6addr_any;
841 			isc_sockaddr_fromin6(&listen_addr, &in6a, le->port);
842 
843 			ifp = find_matching_interface(mgr, &listen_addr);
844 			if (ifp != NULL) {
845 				ifp->generation = mgr->generation;
846 				if (le->dscp != -1 && ifp->dscp == -1) {
847 					ifp->dscp = le->dscp;
848 				} else if (le->dscp != ifp->dscp) {
849 					isc_sockaddr_format(&listen_addr, sabuf,
850 							    sizeof(sabuf));
851 					isc_log_write(IFMGR_COMMON_LOGARGS,
852 						      ISC_LOG_WARNING,
853 						      "%s: conflicting DSCP "
854 						      "values, using %d",
855 						      sabuf, ifp->dscp);
856 				}
857 			} else {
858 				isc_log_write(IFMGR_COMMON_LOGARGS,
859 					      ISC_LOG_INFO,
860 					      "listening on IPv6 "
861 					      "interfaces, port %u",
862 					      le->port);
863 				result = ns_interface_setup(mgr, &listen_addr,
864 							    "<any>", &ifp,
865 							    le->dscp, NULL);
866 				if (result == ISC_R_SUCCESS) {
867 					ifp->flags |= NS_INTERFACEFLAG_ANYADDR;
868 				} else {
869 					isc_log_write(IFMGR_COMMON_LOGARGS,
870 						      ISC_LOG_ERROR,
871 						      "listening on all IPv6 "
872 						      "interfaces failed");
873 				}
874 				/* Continue. */
875 			}
876 		}
877 	}
878 
879 	isc_netaddr_any(&zero_address);
880 	isc_netaddr_any6(&zero_address6);
881 
882 	result = isc_interfaceiter_create(mgr->mctx, &iter);
883 	if (result != ISC_R_SUCCESS) {
884 		return (result);
885 	}
886 
887 	result = clearacl(mgr->mctx, &mgr->aclenv.localhost);
888 	if (result != ISC_R_SUCCESS) {
889 		goto cleanup_iter;
890 	}
891 	result = clearacl(mgr->mctx, &mgr->aclenv.localnets);
892 	if (result != ISC_R_SUCCESS) {
893 		goto cleanup_iter;
894 	}
895 	clearlistenon(mgr);
896 
897 	tried_listening = false;
898 	all_addresses_in_use = true;
899 	for (result = isc_interfaceiter_first(iter); result == ISC_R_SUCCESS;
900 	     result = isc_interfaceiter_next(iter))
901 	{
902 		isc_interface_t interface;
903 		ns_listenlist_t *ll;
904 		unsigned int family;
905 
906 		result = isc_interfaceiter_current(iter, &interface);
907 		if (result != ISC_R_SUCCESS) {
908 			break;
909 		}
910 
911 		family = interface.address.family;
912 		if (family != AF_INET && family != AF_INET6) {
913 			continue;
914 		}
915 		if (!scan_ipv4 && family == AF_INET) {
916 			continue;
917 		}
918 		if (!scan_ipv6 && family == AF_INET6) {
919 			continue;
920 		}
921 
922 		/*
923 		 * Test for the address being nonzero rather than testing
924 		 * INTERFACE_F_UP, because on some systems the latter
925 		 * follows the media state and we could end up ignoring
926 		 * the interface for an entire rescan interval due to
927 		 * a temporary media glitch at rescan time.
928 		 */
929 		if (family == AF_INET &&
930 		    isc_netaddr_equal(&interface.address, &zero_address)) {
931 			continue;
932 		}
933 		if (family == AF_INET6 &&
934 		    isc_netaddr_equal(&interface.address, &zero_address6)) {
935 			continue;
936 		}
937 
938 		/*
939 		 * If running with -T fixedlocal, then we only
940 		 * want 127.0.0.1 and ::1 in the localhost ACL.
941 		 */
942 		if (((mgr->sctx->options & NS_SERVER_FIXEDLOCAL) != 0) &&
943 		    !isc_netaddr_isloopback(&interface.address))
944 		{
945 			goto listenon;
946 		}
947 
948 		result = setup_locals(mgr, &interface);
949 		if (result != ISC_R_SUCCESS) {
950 			goto ignore_interface;
951 		}
952 
953 	listenon:
954 		ll = (family == AF_INET) ? mgr->listenon4 : mgr->listenon6;
955 		dolistenon = true;
956 		for (le = ISC_LIST_HEAD(ll->elts); le != NULL;
957 		     le = ISC_LIST_NEXT(le, link)) {
958 			int match;
959 			bool ipv6_wildcard = false;
960 			isc_netaddr_t listen_netaddr;
961 			isc_sockaddr_t listen_sockaddr;
962 
963 			/*
964 			 * Construct a socket address for this IP/port
965 			 * combination.
966 			 */
967 			if (family == AF_INET) {
968 				isc_netaddr_fromin(&listen_netaddr,
969 						   &interface.address.type.in);
970 			} else {
971 				isc_netaddr_fromin6(
972 					&listen_netaddr,
973 					&interface.address.type.in6);
974 				isc_netaddr_setzone(&listen_netaddr,
975 						    interface.address.zone);
976 			}
977 			isc_sockaddr_fromnetaddr(&listen_sockaddr,
978 						 &listen_netaddr, le->port);
979 
980 			/*
981 			 * See if the address matches the listen-on statement;
982 			 * if not, ignore the interface.
983 			 */
984 			(void)dns_acl_match(&listen_netaddr, NULL, le->acl,
985 					    &mgr->aclenv, &match, NULL);
986 			if (match <= 0) {
987 				continue;
988 			}
989 
990 			if (dolistenon) {
991 				setup_listenon(mgr, &interface, le->port);
992 				dolistenon = false;
993 			}
994 
995 			/*
996 			 * The case of "any" IPv6 address will require
997 			 * special considerations later, so remember it.
998 			 */
999 			if (family == AF_INET6 && ipv6only && ipv6pktinfo &&
1000 			    listenon_is_ip6_any(le)) {
1001 				ipv6_wildcard = true;
1002 			}
1003 
1004 			ifp = find_matching_interface(mgr, &listen_sockaddr);
1005 			if (ifp != NULL) {
1006 				ifp->generation = mgr->generation;
1007 				if (le->dscp != -1 && ifp->dscp == -1) {
1008 					ifp->dscp = le->dscp;
1009 				} else if (le->dscp != ifp->dscp) {
1010 					isc_sockaddr_format(&listen_sockaddr,
1011 							    sabuf,
1012 							    sizeof(sabuf));
1013 					isc_log_write(IFMGR_COMMON_LOGARGS,
1014 						      ISC_LOG_WARNING,
1015 						      "%s: conflicting DSCP "
1016 						      "values, using %d",
1017 						      sabuf, ifp->dscp);
1018 				}
1019 			} else {
1020 				bool addr_in_use = false;
1021 
1022 				if (ipv6_wildcard) {
1023 					continue;
1024 				}
1025 
1026 				if (log_explicit && family == AF_INET6 &&
1027 				    listenon_is_ip6_any(le)) {
1028 					isc_log_write(
1029 						IFMGR_COMMON_LOGARGS,
1030 						verbose ? ISC_LOG_INFO
1031 							: ISC_LOG_DEBUG(1),
1032 						"IPv6 socket API is "
1033 						"incomplete; explicitly "
1034 						"binding to each IPv6 "
1035 						"address separately");
1036 					log_explicit = false;
1037 				}
1038 				isc_sockaddr_format(&listen_sockaddr, sabuf,
1039 						    sizeof(sabuf));
1040 				isc_log_write(
1041 					IFMGR_COMMON_LOGARGS, ISC_LOG_INFO,
1042 					"listening on %s interface "
1043 					"%s, %s",
1044 					(family == AF_INET) ? "IPv4" : "IPv6",
1045 					interface.name, sabuf);
1046 
1047 				result = ns_interface_setup(
1048 					mgr, &listen_sockaddr, interface.name,
1049 					&ifp, le->dscp, &addr_in_use);
1050 
1051 				tried_listening = true;
1052 				if (!addr_in_use) {
1053 					all_addresses_in_use = false;
1054 				}
1055 
1056 				if (result != ISC_R_SUCCESS) {
1057 					isc_log_write(IFMGR_COMMON_LOGARGS,
1058 						      ISC_LOG_ERROR,
1059 						      "creating %s interface "
1060 						      "%s failed; interface "
1061 						      "ignored",
1062 						      (family == AF_INET) ? "IP"
1063 									    "v4"
1064 									  : "IP"
1065 									    "v"
1066 									    "6",
1067 						      interface.name);
1068 				}
1069 				/* Continue. */
1070 			}
1071 		}
1072 		continue;
1073 
1074 	ignore_interface:
1075 		isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
1076 			      "ignoring %s interface %s: %s",
1077 			      (family == AF_INET) ? "IPv4" : "IPv6",
1078 			      interface.name, isc_result_totext(result));
1079 		continue;
1080 	}
1081 	if (result != ISC_R_NOMORE) {
1082 		UNEXPECTED_ERROR(__FILE__, __LINE__,
1083 				 "interface iteration failed: %s",
1084 				 isc_result_totext(result));
1085 	} else {
1086 		result = ((tried_listening && all_addresses_in_use)
1087 				  ? ISC_R_ADDRINUSE
1088 				  : ISC_R_SUCCESS);
1089 	}
1090 cleanup_iter:
1091 	isc_interfaceiter_destroy(&iter);
1092 	return (result);
1093 }
1094 
1095 static isc_result_t
ns_interfacemgr_scan0(ns_interfacemgr_t * mgr,bool verbose)1096 ns_interfacemgr_scan0(ns_interfacemgr_t *mgr, bool verbose) {
1097 	isc_result_t result;
1098 	bool purge = true;
1099 
1100 	REQUIRE(NS_INTERFACEMGR_VALID(mgr));
1101 
1102 	mgr->generation++; /* Increment the generation count. */
1103 
1104 	result = do_scan(mgr, verbose);
1105 	if ((result != ISC_R_SUCCESS) && (result != ISC_R_ADDRINUSE)) {
1106 		purge = false;
1107 	}
1108 
1109 	/*
1110 	 * Now go through the interface list and delete anything that
1111 	 * does not have the current generation number.  This is
1112 	 * how we catch interfaces that go away or change their
1113 	 * addresses.
1114 	 */
1115 	if (purge) {
1116 		purge_old_interfaces(mgr);
1117 	}
1118 
1119 	/*
1120 	 * Warn if we are not listening on any interface.
1121 	 */
1122 	if (ISC_LIST_EMPTY(mgr->interfaces)) {
1123 		isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING,
1124 			      "not listening on any interfaces");
1125 	}
1126 
1127 	return (result);
1128 }
1129 
1130 bool
ns_interfacemgr_islistening(ns_interfacemgr_t * mgr)1131 ns_interfacemgr_islistening(ns_interfacemgr_t *mgr) {
1132 	REQUIRE(NS_INTERFACEMGR_VALID(mgr));
1133 
1134 	return (ISC_LIST_EMPTY(mgr->interfaces) ? false : true);
1135 }
1136 
1137 isc_result_t
ns_interfacemgr_scan(ns_interfacemgr_t * mgr,bool verbose)1138 ns_interfacemgr_scan(ns_interfacemgr_t *mgr, bool verbose) {
1139 	isc_result_t result;
1140 	bool unlock = false;
1141 
1142 	/*
1143 	 * Check for success because we may already be task-exclusive
1144 	 * at this point.  Only if we succeed at obtaining an exclusive
1145 	 * lock now will we need to relinquish it later.
1146 	 */
1147 	result = isc_task_beginexclusive(mgr->excl);
1148 	if (result == ISC_R_SUCCESS) {
1149 		unlock = true;
1150 	}
1151 
1152 	result = ns_interfacemgr_scan0(mgr, verbose);
1153 
1154 	if (unlock) {
1155 		isc_task_endexclusive(mgr->excl);
1156 	}
1157 
1158 	return (result);
1159 }
1160 
1161 void
ns_interfacemgr_setlistenon4(ns_interfacemgr_t * mgr,ns_listenlist_t * value)1162 ns_interfacemgr_setlistenon4(ns_interfacemgr_t *mgr, ns_listenlist_t *value) {
1163 	REQUIRE(NS_INTERFACEMGR_VALID(mgr));
1164 
1165 	LOCK(&mgr->lock);
1166 	ns_listenlist_detach(&mgr->listenon4);
1167 	ns_listenlist_attach(value, &mgr->listenon4);
1168 	UNLOCK(&mgr->lock);
1169 }
1170 
1171 void
ns_interfacemgr_setlistenon6(ns_interfacemgr_t * mgr,ns_listenlist_t * value)1172 ns_interfacemgr_setlistenon6(ns_interfacemgr_t *mgr, ns_listenlist_t *value) {
1173 	REQUIRE(NS_INTERFACEMGR_VALID(mgr));
1174 
1175 	LOCK(&mgr->lock);
1176 	ns_listenlist_detach(&mgr->listenon6);
1177 	ns_listenlist_attach(value, &mgr->listenon6);
1178 	UNLOCK(&mgr->lock);
1179 }
1180 
1181 void
ns_interfacemgr_dumprecursing(FILE * f,ns_interfacemgr_t * mgr)1182 ns_interfacemgr_dumprecursing(FILE *f, ns_interfacemgr_t *mgr) {
1183 	ns_interface_t *interface;
1184 
1185 	REQUIRE(NS_INTERFACEMGR_VALID(mgr));
1186 
1187 	LOCK(&mgr->lock);
1188 	interface = ISC_LIST_HEAD(mgr->interfaces);
1189 	while (interface != NULL) {
1190 		if (interface->clientmgr != NULL) {
1191 			ns_client_dumprecursing(f, interface->clientmgr);
1192 		}
1193 		interface = ISC_LIST_NEXT(interface, link);
1194 	}
1195 	UNLOCK(&mgr->lock);
1196 }
1197 
1198 bool
ns_interfacemgr_listeningon(ns_interfacemgr_t * mgr,const isc_sockaddr_t * addr)1199 ns_interfacemgr_listeningon(ns_interfacemgr_t *mgr,
1200 			    const isc_sockaddr_t *addr) {
1201 	isc_sockaddr_t *old;
1202 	bool result = false;
1203 
1204 	REQUIRE(NS_INTERFACEMGR_VALID(mgr));
1205 	/*
1206 	 * If the manager is shutting down it's safer to
1207 	 * return true.
1208 	 */
1209 	if (atomic_load(&mgr->shuttingdown)) {
1210 		return (true);
1211 	}
1212 	LOCK(&mgr->lock);
1213 	for (old = ISC_LIST_HEAD(mgr->listenon); old != NULL;
1214 	     old = ISC_LIST_NEXT(old, link))
1215 	{
1216 		if (isc_sockaddr_equal(old, addr)) {
1217 			result = true;
1218 			break;
1219 		}
1220 	}
1221 	UNLOCK(&mgr->lock);
1222 
1223 	return (result);
1224 }
1225 
1226 ns_server_t *
ns_interfacemgr_getserver(ns_interfacemgr_t * mgr)1227 ns_interfacemgr_getserver(ns_interfacemgr_t *mgr) {
1228 	REQUIRE(NS_INTERFACEMGR_VALID(mgr));
1229 
1230 	return (mgr->sctx);
1231 }
1232 
1233 ns_interface_t *
ns__interfacemgr_getif(ns_interfacemgr_t * mgr)1234 ns__interfacemgr_getif(ns_interfacemgr_t *mgr) {
1235 	ns_interface_t *head;
1236 	REQUIRE(NS_INTERFACEMGR_VALID(mgr));
1237 	LOCK(&mgr->lock);
1238 	head = ISC_LIST_HEAD(mgr->interfaces);
1239 	UNLOCK(&mgr->lock);
1240 	return (head);
1241 }
1242 
1243 ns_interface_t *
ns__interfacemgr_nextif(ns_interface_t * ifp)1244 ns__interfacemgr_nextif(ns_interface_t *ifp) {
1245 	ns_interface_t *next;
1246 	LOCK(&ifp->lock);
1247 	next = ISC_LIST_NEXT(ifp, link);
1248 	UNLOCK(&ifp->lock);
1249 	return (next);
1250 }
1251