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