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