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