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