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