interfacemgr.c revision 1.10
1/*	$NetBSD: interfacemgr.c,v 1.10 2021/03/23 20:59:03 christos Exp $	*/
2
3/*
4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
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 */
71struct 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
101static void
102purge_old_interfaces(ns_interfacemgr_t *mgr);
103
104static void
105clearlistenon(ns_interfacemgr_t *mgr);
106
107#ifdef USE_ROUTE_SOCKET
108static void
109route_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
183isc_result_t
184ns_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
292cleanup_aclenv:
293	dns_aclenv_destroy(&mgr->aclenv);
294#endif /* ifdef USE_ROUTE_SOCKET */
295cleanup_listenon:
296	ns_listenlist_detach(&mgr->listenon4);
297	ns_listenlist_detach(&mgr->listenon6);
298cleanup_lock:
299	isc_mutex_destroy(&mgr->lock);
300cleanup_ctx:
301	ns_server_detach(&mgr->sctx);
302	isc_mem_putanddetach(&mgr->mctx, mgr, sizeof(*mgr));
303	return (result);
304}
305
306static void
307ns_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
335void
336ns_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
343dns_aclenv_t *
344ns_interfacemgr_getaclenv(ns_interfacemgr_t *mgr) {
345	REQUIRE(NS_INTERFACEMGR_VALID(mgr));
346
347	return (&mgr->aclenv);
348}
349
350void
351ns_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
357void
358ns_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
368void
369ns_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
391static isc_result_t
392ns_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#ifndef __lint__ // XXX: bug
402	*ifp = (ns_interface_t){ .generation = mgr->generation,
403				 .addr = *addr,
404				 .dscp = -1 };
405#endif
406
407	strlcpy(ifp->name, name, sizeof(ifp->name));
408
409	isc_mutex_init(&ifp->lock);
410
411	for (disp = 0; disp < MAX_UDP_DISPATCH; disp++) {
412		ifp->udpdispatch[disp] = NULL;
413	}
414
415	/*
416	 * Create a single TCP client object.  It will replace itself
417	 * with a new one as soon as it gets a connection, so the actual
418	 * connections will be handled in parallel even though there is
419	 * only one client initially.
420	 */
421	isc_refcount_init(&ifp->ntcpaccepting, 0);
422	isc_refcount_init(&ifp->ntcpactive, 0);
423
424	ISC_LINK_INIT(ifp, link);
425
426	ns_interfacemgr_attach(mgr, &ifp->mgr);
427	LOCK(&mgr->lock);
428	ISC_LIST_APPEND(mgr->interfaces, ifp, link);
429	UNLOCK(&mgr->lock);
430
431	isc_refcount_init(&ifp->references, 1);
432	ifp->magic = IFACE_MAGIC;
433
434	result = ns_clientmgr_create(mgr->mctx, mgr->sctx, mgr->taskmgr,
435				     mgr->timermgr, ifp, mgr->ncpus,
436				     &ifp->clientmgr);
437	if (result != ISC_R_SUCCESS) {
438		isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
439			      "ns_clientmgr_create() failed: %s",
440			      isc_result_totext(result));
441		goto failure;
442	}
443
444	*ifpret = ifp;
445
446	return (ISC_R_SUCCESS);
447
448failure:
449	isc_mutex_destroy(&ifp->lock);
450
451	ifp->magic = 0;
452	isc_mem_put(mgr->mctx, ifp, sizeof(*ifp));
453
454	return (ISC_R_UNEXPECTED);
455}
456
457static isc_result_t
458ns_interface_listenudp(ns_interface_t *ifp) {
459	isc_result_t result;
460
461	/* Reserve space for an ns_client_t with the netmgr handle */
462	result = isc_nm_listenudp(ifp->mgr->nm, (isc_nmiface_t *)&ifp->addr,
463				  ns__client_request, ifp, sizeof(ns_client_t),
464				  &ifp->udplistensocket);
465	return (result);
466}
467
468static isc_result_t
469ns_interface_listentcp(ns_interface_t *ifp) {
470	isc_result_t result;
471
472	result = isc_nm_listentcpdns(
473		ifp->mgr->nm, (isc_nmiface_t *)&ifp->addr, ns__client_request,
474		ifp, ns__client_tcpconn, ifp, sizeof(ns_client_t),
475		ifp->mgr->backlog, &ifp->mgr->sctx->tcpquota,
476		&ifp->tcplistensocket);
477	if (result != ISC_R_SUCCESS) {
478		isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
479			      "creating TCP socket: %s",
480			      isc_result_totext(result));
481	}
482
483	/*
484	 * We call this now to update the tcp-highwater statistic:
485	 * this is necessary because we are adding to the TCP quota just
486	 * by listening.
487	 */
488	result = ns__client_tcpconn(NULL, ISC_R_SUCCESS, ifp);
489	if (result != ISC_R_SUCCESS) {
490		isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
491			      "connecting TCP socket: %s",
492			      isc_result_totext(result));
493	}
494
495#if 0
496#ifndef ISC_ALLOW_MAPPED
497	isc_socket_ipv6only(ifp->tcpsocket,true);
498#endif /* ifndef ISC_ALLOW_MAPPED */
499
500	if (ifp->dscp != -1) {
501		isc_socket_dscp(ifp->tcpsocket,ifp->dscp);
502	}
503
504	(void)isc_socket_filter(ifp->tcpsocket,"dataready");
505#endif /* if 0 */
506	return (result);
507}
508
509static isc_result_t
510ns_interface_setup(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
511		   const char *name, ns_interface_t **ifpret, bool accept_tcp,
512		   isc_dscp_t dscp, bool *addr_in_use) {
513	isc_result_t result;
514	ns_interface_t *ifp = NULL;
515	REQUIRE(ifpret != NULL && *ifpret == NULL);
516	REQUIRE(addr_in_use == NULL || !*addr_in_use);
517
518	result = ns_interface_create(mgr, addr, name, &ifp);
519	if (result != ISC_R_SUCCESS) {
520		return (result);
521	}
522
523	ifp->dscp = dscp;
524
525	result = ns_interface_listenudp(ifp);
526	if (result != ISC_R_SUCCESS) {
527		if ((result == ISC_R_ADDRINUSE) && (addr_in_use != NULL)) {
528			*addr_in_use = true;
529		}
530		goto cleanup_interface;
531	}
532
533	if (((mgr->sctx->options & NS_SERVER_NOTCP) == 0) && accept_tcp) {
534		result = ns_interface_listentcp(ifp);
535		if (result != ISC_R_SUCCESS) {
536			if ((result == ISC_R_ADDRINUSE) &&
537			    (addr_in_use != NULL)) {
538				*addr_in_use = true;
539			}
540
541			/*
542			 * XXXRTH We don't currently have a way to easily stop
543			 * dispatch service, so we currently return
544			 * ISC_R_SUCCESS (the UDP stuff will work even if TCP
545			 * creation failed).  This will be fixed later.
546			 */
547			result = ISC_R_SUCCESS;
548		}
549	}
550	*ifpret = ifp;
551	return (result);
552
553cleanup_interface:
554	LOCK(&ifp->mgr->lock);
555	ISC_LIST_UNLINK(ifp->mgr->interfaces, ifp, link);
556	UNLOCK(&ifp->mgr->lock);
557	ns_interface_detach(&ifp);
558	return (result);
559}
560
561void
562ns_interface_shutdown(ns_interface_t *ifp) {
563	if (ifp->udplistensocket != NULL) {
564		isc_nm_stoplistening(ifp->udplistensocket);
565		isc_nmsocket_close(&ifp->udplistensocket);
566	}
567	if (ifp->tcplistensocket != NULL) {
568		isc_nm_stoplistening(ifp->tcplistensocket);
569		isc_nmsocket_close(&ifp->tcplistensocket);
570	}
571	if (ifp->clientmgr != NULL) {
572		ns_clientmgr_destroy(&ifp->clientmgr);
573	}
574}
575
576static void
577ns_interface_destroy(ns_interface_t *ifp) {
578	REQUIRE(NS_INTERFACE_VALID(ifp));
579
580	isc_mem_t *mctx = ifp->mgr->mctx;
581
582	ns_interface_shutdown(ifp);
583
584	for (int disp = 0; disp < ifp->nudpdispatch; disp++) {
585		if (ifp->udpdispatch[disp] != NULL) {
586			dns_dispatch_changeattributes(
587				ifp->udpdispatch[disp], 0,
588				DNS_DISPATCHATTR_NOLISTEN);
589			dns_dispatch_detach(&(ifp->udpdispatch[disp]));
590		}
591	}
592
593	if (ifp->tcpsocket != NULL) {
594		isc_socket_detach(&ifp->tcpsocket);
595	}
596
597	isc_mutex_destroy(&ifp->lock);
598
599	ns_interfacemgr_detach(&ifp->mgr);
600
601	isc_refcount_destroy(&ifp->ntcpactive);
602	isc_refcount_destroy(&ifp->ntcpaccepting);
603
604	ifp->magic = 0;
605
606	isc_mem_put(mctx, ifp, sizeof(*ifp));
607}
608
609void
610ns_interface_attach(ns_interface_t *source, ns_interface_t **target) {
611	REQUIRE(NS_INTERFACE_VALID(source));
612	isc_refcount_increment(&source->references);
613	*target = source;
614}
615
616void
617ns_interface_detach(ns_interface_t **targetp) {
618	ns_interface_t *target = *targetp;
619	*targetp = NULL;
620	REQUIRE(target != NULL);
621	REQUIRE(NS_INTERFACE_VALID(target));
622	if (isc_refcount_decrement(&target->references) == 1) {
623		ns_interface_destroy(target);
624	}
625}
626
627/*%
628 * Search the interface list for an interface whose address and port
629 * both match those of 'addr'.  Return a pointer to it, or NULL if not found.
630 */
631static ns_interface_t *
632find_matching_interface(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr) {
633	ns_interface_t *ifp;
634	LOCK(&mgr->lock);
635	for (ifp = ISC_LIST_HEAD(mgr->interfaces); ifp != NULL;
636	     ifp = ISC_LIST_NEXT(ifp, link))
637	{
638		if (isc_sockaddr_equal(&ifp->addr, addr)) {
639			break;
640		}
641	}
642	UNLOCK(&mgr->lock);
643	return (ifp);
644}
645
646/*%
647 * Remove any interfaces whose generation number is not the current one.
648 */
649static void
650purge_old_interfaces(ns_interfacemgr_t *mgr) {
651	ns_interface_t *ifp, *next;
652	LOCK(&mgr->lock);
653	for (ifp = ISC_LIST_HEAD(mgr->interfaces); ifp != NULL; ifp = next) {
654		INSIST(NS_INTERFACE_VALID(ifp));
655		next = ISC_LIST_NEXT(ifp, link);
656		if (ifp->generation != mgr->generation) {
657			char sabuf[256];
658			ISC_LIST_UNLINK(ifp->mgr->interfaces, ifp, link);
659			isc_sockaddr_format(&ifp->addr, sabuf, sizeof(sabuf));
660			isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_INFO,
661				      "no longer listening on %s", sabuf);
662			ns_interface_shutdown(ifp);
663			ns_interface_detach(&ifp);
664		}
665	}
666	UNLOCK(&mgr->lock);
667}
668
669static isc_result_t
670clearacl(isc_mem_t *mctx, dns_acl_t **aclp) {
671	dns_acl_t *newacl = NULL;
672	isc_result_t result;
673	result = dns_acl_create(mctx, 0, &newacl);
674	if (result != ISC_R_SUCCESS) {
675		return (result);
676	}
677	dns_acl_detach(aclp);
678	dns_acl_attach(newacl, aclp);
679	dns_acl_detach(&newacl);
680	return (ISC_R_SUCCESS);
681}
682
683static bool
684listenon_is_ip6_any(ns_listenelt_t *elt) {
685	REQUIRE(elt && elt->acl);
686	return (dns_acl_isany(elt->acl));
687}
688
689static isc_result_t
690setup_locals(ns_interfacemgr_t *mgr, isc_interface_t *interface) {
691	isc_result_t result;
692	unsigned int prefixlen;
693	isc_netaddr_t *netaddr;
694
695	netaddr = &interface->address;
696
697	/* First add localhost address */
698	prefixlen = (netaddr->family == AF_INET) ? 32 : 128;
699	result = dns_iptable_addprefix(mgr->aclenv.localhost->iptable, netaddr,
700				       prefixlen, true);
701	if (result != ISC_R_SUCCESS) {
702		return (result);
703	}
704
705	/* Then add localnets prefix */
706	result = isc_netaddr_masktoprefixlen(&interface->netmask, &prefixlen);
707
708	/* Non contiguous netmasks not allowed by IPv6 arch. */
709	if (result != ISC_R_SUCCESS && netaddr->family == AF_INET6) {
710		return (result);
711	}
712
713	if (result != ISC_R_SUCCESS) {
714		isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING,
715			      "omitting IPv4 interface %s from "
716			      "localnets ACL: %s",
717			      interface->name, isc_result_totext(result));
718		return (ISC_R_SUCCESS);
719	}
720
721	if (prefixlen == 0U) {
722		isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING,
723			      "omitting %s interface %s from localnets ACL: "
724			      "zero prefix length detected",
725			      (netaddr->family == AF_INET) ? "IPv4" : "IPv6",
726			      interface->name);
727		return (ISC_R_SUCCESS);
728	}
729
730	result = dns_iptable_addprefix(mgr->aclenv.localnets->iptable, netaddr,
731				       prefixlen, true);
732	if (result != ISC_R_SUCCESS) {
733		return (result);
734	}
735
736	return (ISC_R_SUCCESS);
737}
738
739static void
740setup_listenon(ns_interfacemgr_t *mgr, isc_interface_t *interface,
741	       in_port_t port) {
742	isc_sockaddr_t *addr;
743	isc_sockaddr_t *old;
744
745	addr = isc_mem_get(mgr->mctx, sizeof(*addr));
746
747	isc_sockaddr_fromnetaddr(addr, &interface->address, port);
748
749	LOCK(&mgr->lock);
750	for (old = ISC_LIST_HEAD(mgr->listenon); old != NULL;
751	     old = ISC_LIST_NEXT(old, link))
752	{
753		if (isc_sockaddr_equal(addr, old)) {
754			break;
755		}
756	}
757
758	if (old != NULL) {
759		isc_mem_put(mgr->mctx, addr, sizeof(*addr));
760	} else {
761		ISC_LIST_APPEND(mgr->listenon, addr, link);
762	}
763	UNLOCK(&mgr->lock);
764}
765
766static void
767clearlistenon(ns_interfacemgr_t *mgr) {
768	isc_sockaddr_t *old;
769
770	LOCK(&mgr->lock);
771	old = ISC_LIST_HEAD(mgr->listenon);
772	while (old != NULL) {
773		ISC_LIST_UNLINK(mgr->listenon, old, link);
774		isc_mem_put(mgr->mctx, old, sizeof(*old));
775		old = ISC_LIST_HEAD(mgr->listenon);
776	}
777	UNLOCK(&mgr->lock);
778}
779
780static isc_result_t
781do_scan(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen, bool verbose) {
782	isc_interfaceiter_t *iter = NULL;
783	bool scan_ipv4 = false;
784	bool scan_ipv6 = false;
785	bool adjusting = false;
786	bool ipv6only = true;
787	bool ipv6pktinfo = true;
788	isc_result_t result;
789	isc_netaddr_t zero_address, zero_address6;
790	ns_listenelt_t *le;
791	isc_sockaddr_t listen_addr;
792	ns_interface_t *ifp;
793	bool log_explicit = false;
794	bool dolistenon;
795	char sabuf[ISC_SOCKADDR_FORMATSIZE];
796	bool tried_listening;
797	bool all_addresses_in_use;
798
799	if (ext_listen != NULL) {
800		adjusting = true;
801	}
802
803	if (isc_net_probeipv6() == ISC_R_SUCCESS) {
804		scan_ipv6 = true;
805	} else if ((mgr->sctx->options & NS_SERVER_DISABLE6) == 0) {
806		isc_log_write(IFMGR_COMMON_LOGARGS,
807			      verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1),
808			      "no IPv6 interfaces found");
809	}
810
811	if (isc_net_probeipv4() == ISC_R_SUCCESS) {
812		scan_ipv4 = true;
813	} else if ((mgr->sctx->options & NS_SERVER_DISABLE4) == 0) {
814		isc_log_write(IFMGR_COMMON_LOGARGS,
815			      verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1),
816			      "no IPv4 interfaces found");
817	}
818
819	/*
820	 * A special, but typical case; listen-on-v6 { any; }.
821	 * When we can make the socket IPv6-only, open a single wildcard
822	 * socket for IPv6 communication.  Otherwise, make separate
823	 * socket for each IPv6 address in order to avoid accepting IPv4
824	 * packets as the form of mapped addresses unintentionally
825	 * unless explicitly allowed.
826	 */
827#ifndef ISC_ALLOW_MAPPED
828	if (scan_ipv6 && isc_net_probe_ipv6only() != ISC_R_SUCCESS) {
829		ipv6only = false;
830		log_explicit = true;
831	}
832#endif /* ifndef ISC_ALLOW_MAPPED */
833	if (scan_ipv6 && isc_net_probe_ipv6pktinfo() != ISC_R_SUCCESS) {
834		ipv6pktinfo = false;
835		log_explicit = true;
836	}
837	if (scan_ipv6 && ipv6only && ipv6pktinfo) {
838		for (le = ISC_LIST_HEAD(mgr->listenon6->elts); le != NULL;
839		     le = ISC_LIST_NEXT(le, link))
840		{
841			struct in6_addr in6a;
842
843			if (!listenon_is_ip6_any(le)) {
844				continue;
845			}
846
847			in6a = in6addr_any;
848			isc_sockaddr_fromin6(&listen_addr, &in6a, le->port);
849
850			ifp = find_matching_interface(mgr, &listen_addr);
851			if (ifp != NULL) {
852				ifp->generation = mgr->generation;
853				if (le->dscp != -1 && ifp->dscp == -1) {
854					ifp->dscp = le->dscp;
855				} else if (le->dscp != ifp->dscp) {
856					isc_sockaddr_format(&listen_addr, sabuf,
857							    sizeof(sabuf));
858					isc_log_write(IFMGR_COMMON_LOGARGS,
859						      ISC_LOG_WARNING,
860						      "%s: conflicting DSCP "
861						      "values, using %d",
862						      sabuf, ifp->dscp);
863				}
864			} else {
865				isc_log_write(IFMGR_COMMON_LOGARGS,
866					      ISC_LOG_INFO,
867					      "listening on IPv6 "
868					      "interfaces, port %u",
869					      le->port);
870				result = ns_interface_setup(mgr, &listen_addr,
871							    "<any>", &ifp, true,
872							    le->dscp, NULL);
873				if (result == ISC_R_SUCCESS) {
874					ifp->flags |= NS_INTERFACEFLAG_ANYADDR;
875				} else {
876					isc_log_write(IFMGR_COMMON_LOGARGS,
877						      ISC_LOG_ERROR,
878						      "listening on all IPv6 "
879						      "interfaces failed");
880				}
881				/* Continue. */
882			}
883		}
884	}
885
886	isc_netaddr_any(&zero_address);
887	isc_netaddr_any6(&zero_address6);
888
889	result = isc_interfaceiter_create(mgr->mctx, &iter);
890	if (result != ISC_R_SUCCESS) {
891		return (result);
892	}
893
894	if (!adjusting) {
895		result = clearacl(mgr->mctx, &mgr->aclenv.localhost);
896		if (result != ISC_R_SUCCESS) {
897			goto cleanup_iter;
898		}
899		result = clearacl(mgr->mctx, &mgr->aclenv.localnets);
900		if (result != ISC_R_SUCCESS) {
901			goto cleanup_iter;
902		}
903		clearlistenon(mgr);
904	}
905
906	tried_listening = false;
907	all_addresses_in_use = true;
908	for (result = isc_interfaceiter_first(iter); result == ISC_R_SUCCESS;
909	     result = isc_interfaceiter_next(iter))
910	{
911		isc_interface_t interface;
912		ns_listenlist_t *ll;
913		unsigned int family;
914
915		result = isc_interfaceiter_current(iter, &interface);
916		if (result != ISC_R_SUCCESS) {
917			break;
918		}
919
920		family = interface.address.family;
921		if (family != AF_INET && family != AF_INET6) {
922			continue;
923		}
924		if (!scan_ipv4 && family == AF_INET) {
925			continue;
926		}
927		if (!scan_ipv6 && family == AF_INET6) {
928			continue;
929		}
930
931		/*
932		 * Test for the address being nonzero rather than testing
933		 * INTERFACE_F_UP, because on some systems the latter
934		 * follows the media state and we could end up ignoring
935		 * the interface for an entire rescan interval due to
936		 * a temporary media glitch at rescan time.
937		 */
938		if (family == AF_INET &&
939		    isc_netaddr_equal(&interface.address, &zero_address)) {
940			continue;
941		}
942		if (family == AF_INET6 &&
943		    isc_netaddr_equal(&interface.address, &zero_address6)) {
944			continue;
945		}
946
947		if (!adjusting) {
948			/*
949			 * If running with -T fixedlocal, then we only
950			 * want 127.0.0.1 and ::1 in the localhost ACL.
951			 */
952			if (((mgr->sctx->options & NS_SERVER_FIXEDLOCAL) !=
953			     0) &&
954			    !isc_netaddr_isloopback(&interface.address))
955			{
956				goto listenon;
957			}
958
959			result = setup_locals(mgr, &interface);
960			if (result != ISC_R_SUCCESS) {
961				goto ignore_interface;
962			}
963		}
964
965	listenon:
966		ll = (family == AF_INET) ? mgr->listenon4 : mgr->listenon6;
967		dolistenon = true;
968		for (le = ISC_LIST_HEAD(ll->elts); le != NULL;
969		     le = ISC_LIST_NEXT(le, link)) {
970			int match;
971			bool ipv6_wildcard = false;
972			isc_netaddr_t listen_netaddr;
973			isc_sockaddr_t listen_sockaddr;
974
975			/*
976			 * Construct a socket address for this IP/port
977			 * combination.
978			 */
979			if (family == AF_INET) {
980				isc_netaddr_fromin(&listen_netaddr,
981						   &interface.address.type.in);
982			} else {
983				isc_netaddr_fromin6(
984					&listen_netaddr,
985					&interface.address.type.in6);
986				isc_netaddr_setzone(&listen_netaddr,
987						    interface.address.zone);
988			}
989			isc_sockaddr_fromnetaddr(&listen_sockaddr,
990						 &listen_netaddr, le->port);
991
992			/*
993			 * See if the address matches the listen-on statement;
994			 * if not, ignore the interface.
995			 */
996			(void)dns_acl_match(&listen_netaddr, NULL, le->acl,
997					    &mgr->aclenv, &match, NULL);
998			if (match <= 0) {
999				continue;
1000			}
1001
1002			if (!adjusting && dolistenon) {
1003				setup_listenon(mgr, &interface, le->port);
1004				dolistenon = false;
1005			}
1006
1007			/*
1008			 * The case of "any" IPv6 address will require
1009			 * special considerations later, so remember it.
1010			 */
1011			if (family == AF_INET6 && ipv6only && ipv6pktinfo &&
1012			    listenon_is_ip6_any(le)) {
1013				ipv6_wildcard = true;
1014			}
1015
1016			/*
1017			 * When adjusting interfaces with extra a listening
1018			 * list, see if the address matches the extra list.
1019			 * If it does, and is also covered by a wildcard
1020			 * interface, we need to listen on the address
1021			 * explicitly.
1022			 */
1023			if (adjusting) {
1024				ns_listenelt_t *ele;
1025
1026				match = 0;
1027				for (ele = ISC_LIST_HEAD(ext_listen->elts);
1028				     ele != NULL;
1029				     ele = ISC_LIST_NEXT(ele, link))
1030				{
1031					(void)dns_acl_match(&listen_netaddr,
1032							    NULL, ele->acl,
1033							    NULL, &match, NULL);
1034					if (match > 0 &&
1035					    (ele->port == le->port ||
1036					     ele->port == 0)) {
1037						break;
1038					} else {
1039						match = 0;
1040					}
1041				}
1042				if (ipv6_wildcard && match == 0) {
1043					continue;
1044				}
1045			}
1046
1047			ifp = find_matching_interface(mgr, &listen_sockaddr);
1048			if (ifp != NULL) {
1049				ifp->generation = mgr->generation;
1050				if (le->dscp != -1 && ifp->dscp == -1) {
1051					ifp->dscp = le->dscp;
1052				} else if (le->dscp != ifp->dscp) {
1053					isc_sockaddr_format(&listen_sockaddr,
1054							    sabuf,
1055							    sizeof(sabuf));
1056					isc_log_write(IFMGR_COMMON_LOGARGS,
1057						      ISC_LOG_WARNING,
1058						      "%s: conflicting DSCP "
1059						      "values, using %d",
1060						      sabuf, ifp->dscp);
1061				}
1062			} else {
1063				bool addr_in_use = false;
1064
1065				if (!adjusting && ipv6_wildcard) {
1066					continue;
1067				}
1068
1069				if (log_explicit && family == AF_INET6 &&
1070				    !adjusting && listenon_is_ip6_any(le)) {
1071					isc_log_write(
1072						IFMGR_COMMON_LOGARGS,
1073						verbose ? ISC_LOG_INFO
1074							: ISC_LOG_DEBUG(1),
1075						"IPv6 socket API is "
1076						"incomplete; explicitly "
1077						"binding to each IPv6 "
1078						"address separately");
1079					log_explicit = false;
1080				}
1081				isc_sockaddr_format(&listen_sockaddr, sabuf,
1082						    sizeof(sabuf));
1083				isc_log_write(
1084					IFMGR_COMMON_LOGARGS, ISC_LOG_INFO,
1085					"%s"
1086					"listening on %s interface "
1087					"%s, %s",
1088					(adjusting) ? "additionally " : "",
1089					(family == AF_INET) ? "IPv4" : "IPv6",
1090					interface.name, sabuf);
1091
1092				result = ns_interface_setup(
1093					mgr, &listen_sockaddr, interface.name,
1094					&ifp, (adjusting) ? false : true,
1095					le->dscp, &addr_in_use);
1096
1097				tried_listening = true;
1098				if (!addr_in_use) {
1099					all_addresses_in_use = false;
1100				}
1101
1102				if (result != ISC_R_SUCCESS) {
1103					isc_log_write(IFMGR_COMMON_LOGARGS,
1104						      ISC_LOG_ERROR,
1105						      "creating %s interface "
1106						      "%s failed; interface "
1107						      "ignored",
1108						      (family == AF_INET) ? "IP"
1109									    "v4"
1110									  : "IP"
1111									    "v"
1112									    "6",
1113						      interface.name);
1114				}
1115				/* Continue. */
1116			}
1117		}
1118		continue;
1119
1120	ignore_interface:
1121		isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
1122			      "ignoring %s interface %s: %s",
1123			      (family == AF_INET) ? "IPv4" : "IPv6",
1124			      interface.name, isc_result_totext(result));
1125		continue;
1126	}
1127	if (result != ISC_R_NOMORE) {
1128		UNEXPECTED_ERROR(__FILE__, __LINE__,
1129				 "interface iteration failed: %s",
1130				 isc_result_totext(result));
1131	} else {
1132		result = ((tried_listening && all_addresses_in_use)
1133				  ? ISC_R_ADDRINUSE
1134				  : ISC_R_SUCCESS);
1135	}
1136cleanup_iter:
1137	isc_interfaceiter_destroy(&iter);
1138	return (result);
1139}
1140
1141static isc_result_t
1142ns_interfacemgr_scan0(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen,
1143		      bool verbose) {
1144	isc_result_t result;
1145	bool purge = true;
1146
1147	REQUIRE(NS_INTERFACEMGR_VALID(mgr));
1148
1149	mgr->generation++; /* Increment the generation count. */
1150
1151	result = do_scan(mgr, ext_listen, verbose);
1152	if ((result != ISC_R_SUCCESS) && (result != ISC_R_ADDRINUSE)) {
1153		purge = false;
1154	}
1155
1156	/*
1157	 * Now go through the interface list and delete anything that
1158	 * does not have the current generation number.  This is
1159	 * how we catch interfaces that go away or change their
1160	 * addresses.
1161	 */
1162	if (purge) {
1163		purge_old_interfaces(mgr);
1164	}
1165
1166	/*
1167	 * Warn if we are not listening on any interface.
1168	 */
1169	if (ext_listen == NULL && ISC_LIST_EMPTY(mgr->interfaces)) {
1170		isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING,
1171			      "not listening on any interfaces");
1172	}
1173
1174	return (result);
1175}
1176
1177bool
1178ns_interfacemgr_islistening(ns_interfacemgr_t *mgr) {
1179	REQUIRE(NS_INTERFACEMGR_VALID(mgr));
1180
1181	return (ISC_LIST_EMPTY(mgr->interfaces) ? false : true);
1182}
1183
1184isc_result_t
1185ns_interfacemgr_scan(ns_interfacemgr_t *mgr, bool verbose) {
1186	isc_result_t result;
1187	bool unlock = false;
1188
1189	/*
1190	 * Check for success because we may already be task-exclusive
1191	 * at this point.  Only if we succeed at obtaining an exclusive
1192	 * lock now will we need to relinquish it later.
1193	 */
1194	result = isc_task_beginexclusive(mgr->excl);
1195	if (result == ISC_R_SUCCESS) {
1196		unlock = true;
1197	}
1198
1199	result = ns_interfacemgr_scan0(mgr, NULL, verbose);
1200
1201	if (unlock) {
1202		isc_task_endexclusive(mgr->excl);
1203	}
1204
1205	return (result);
1206}
1207
1208isc_result_t
1209ns_interfacemgr_adjust(ns_interfacemgr_t *mgr, ns_listenlist_t *list,
1210		       bool verbose) {
1211	return (ns_interfacemgr_scan0(mgr, list, verbose));
1212}
1213
1214void
1215ns_interfacemgr_setlistenon4(ns_interfacemgr_t *mgr, ns_listenlist_t *value) {
1216	REQUIRE(NS_INTERFACEMGR_VALID(mgr));
1217
1218	LOCK(&mgr->lock);
1219	ns_listenlist_detach(&mgr->listenon4);
1220	ns_listenlist_attach(value, &mgr->listenon4);
1221	UNLOCK(&mgr->lock);
1222}
1223
1224void
1225ns_interfacemgr_setlistenon6(ns_interfacemgr_t *mgr, ns_listenlist_t *value) {
1226	REQUIRE(NS_INTERFACEMGR_VALID(mgr));
1227
1228	LOCK(&mgr->lock);
1229	ns_listenlist_detach(&mgr->listenon6);
1230	ns_listenlist_attach(value, &mgr->listenon6);
1231	UNLOCK(&mgr->lock);
1232}
1233
1234void
1235ns_interfacemgr_dumprecursing(FILE *f, ns_interfacemgr_t *mgr) {
1236	ns_interface_t *interface;
1237
1238	REQUIRE(NS_INTERFACEMGR_VALID(mgr));
1239
1240	LOCK(&mgr->lock);
1241	interface = ISC_LIST_HEAD(mgr->interfaces);
1242	while (interface != NULL) {
1243		if (interface->clientmgr != NULL) {
1244			ns_client_dumprecursing(f, interface->clientmgr);
1245		}
1246		interface = ISC_LIST_NEXT(interface, link);
1247	}
1248	UNLOCK(&mgr->lock);
1249}
1250
1251bool
1252ns_interfacemgr_listeningon(ns_interfacemgr_t *mgr,
1253			    const isc_sockaddr_t *addr) {
1254	isc_sockaddr_t *old;
1255	bool result = false;
1256
1257	REQUIRE(NS_INTERFACEMGR_VALID(mgr));
1258	/*
1259	 * If the manager is shutting down it's safer to
1260	 * return true.
1261	 */
1262	if (atomic_load(&mgr->shuttingdown)) {
1263		return (true);
1264	}
1265	LOCK(&mgr->lock);
1266	for (old = ISC_LIST_HEAD(mgr->listenon); old != NULL;
1267	     old = ISC_LIST_NEXT(old, link))
1268	{
1269		if (isc_sockaddr_equal(old, addr)) {
1270			result = true;
1271			break;
1272		}
1273	}
1274	UNLOCK(&mgr->lock);
1275
1276	return (result);
1277}
1278
1279ns_server_t *
1280ns_interfacemgr_getserver(ns_interfacemgr_t *mgr) {
1281	REQUIRE(NS_INTERFACEMGR_VALID(mgr));
1282
1283	return (mgr->sctx);
1284}
1285
1286ns_interface_t *
1287ns__interfacemgr_getif(ns_interfacemgr_t *mgr) {
1288	ns_interface_t *head;
1289	REQUIRE(NS_INTERFACEMGR_VALID(mgr));
1290	LOCK(&mgr->lock);
1291	head = ISC_LIST_HEAD(mgr->interfaces);
1292	UNLOCK(&mgr->lock);
1293	return (head);
1294}
1295
1296ns_interface_t *
1297ns__interfacemgr_nextif(ns_interface_t *ifp) {
1298	ns_interface_t *next;
1299	LOCK(&ifp->lock);
1300	next = ISC_LIST_NEXT(ifp, link);
1301	UNLOCK(&ifp->lock);
1302	return (next);
1303}
1304