interfacemgr.c revision 1.4
1/*	$NetBSD: interfacemgr.c,v 1.4 2019/04/28 00:01:15 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#ifdef HAVE_GEOIP
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	atomic_init(&ifp->ntcpaccepting, 0);
431	atomic_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	ifp->magic = 0;
665	isc_mem_put(mctx, ifp, sizeof(*ifp));
666}
667
668void
669ns_interface_attach(ns_interface_t *source, ns_interface_t **target) {
670	REQUIRE(NS_INTERFACE_VALID(source));
671	LOCK(&source->lock);
672	INSIST(source->references > 0);
673	source->references++;
674	UNLOCK(&source->lock);
675	*target = source;
676}
677
678void
679ns_interface_detach(ns_interface_t **targetp) {
680	isc_result_t need_destroy = false;
681	ns_interface_t *target = *targetp;
682	REQUIRE(target != NULL);
683	REQUIRE(NS_INTERFACE_VALID(target));
684	LOCK(&target->lock);
685	REQUIRE(target->references > 0);
686	target->references--;
687	if (target->references == 0)
688		need_destroy = true;
689	UNLOCK(&target->lock);
690	if (need_destroy)
691		ns_interface_destroy(target);
692	*targetp = NULL;
693}
694
695/*%
696 * Search the interface list for an interface whose address and port
697 * both match those of 'addr'.  Return a pointer to it, or NULL if not found.
698 */
699static ns_interface_t *
700find_matching_interface(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr) {
701	ns_interface_t *ifp;
702	for (ifp = ISC_LIST_HEAD(mgr->interfaces); ifp != NULL;
703	     ifp = ISC_LIST_NEXT(ifp, link)) {
704		if (isc_sockaddr_equal(&ifp->addr, addr))
705			break;
706	}
707	return (ifp);
708}
709
710/*%
711 * Remove any interfaces whose generation number is not the current one.
712 */
713static void
714purge_old_interfaces(ns_interfacemgr_t *mgr) {
715	ns_interface_t *ifp, *next;
716	for (ifp = ISC_LIST_HEAD(mgr->interfaces); ifp != NULL; ifp = next) {
717		INSIST(NS_INTERFACE_VALID(ifp));
718		next = ISC_LIST_NEXT(ifp, link);
719		if (ifp->generation != mgr->generation) {
720			char sabuf[256];
721			ISC_LIST_UNLINK(ifp->mgr->interfaces, ifp, link);
722			isc_sockaddr_format(&ifp->addr, sabuf, sizeof(sabuf));
723			isc_log_write(IFMGR_COMMON_LOGARGS,
724				      ISC_LOG_INFO,
725				      "no longer listening on %s", sabuf);
726			ns_interface_shutdown(ifp);
727			ns_interface_detach(&ifp);
728		}
729	}
730}
731
732static isc_result_t
733clearacl(isc_mem_t *mctx, dns_acl_t **aclp) {
734	dns_acl_t *newacl = NULL;
735	isc_result_t result;
736	result = dns_acl_create(mctx, 0, &newacl);
737	if (result != ISC_R_SUCCESS)
738		return (result);
739	dns_acl_detach(aclp);
740	dns_acl_attach(newacl, aclp);
741	dns_acl_detach(&newacl);
742	return (ISC_R_SUCCESS);
743}
744
745static bool
746listenon_is_ip6_any(ns_listenelt_t *elt) {
747	REQUIRE(elt && elt->acl);
748	return dns_acl_isany(elt->acl);
749}
750
751static isc_result_t
752setup_locals(ns_interfacemgr_t *mgr, isc_interface_t *interface) {
753	isc_result_t result;
754	unsigned int prefixlen;
755	isc_netaddr_t *netaddr;
756
757	netaddr = &interface->address;
758
759	/* First add localhost address */
760	prefixlen = (netaddr->family == AF_INET) ? 32 : 128;
761	result = dns_iptable_addprefix(mgr->aclenv.localhost->iptable,
762				       netaddr, prefixlen, true);
763	if (result != ISC_R_SUCCESS)
764		return (result);
765
766	/* Then add localnets prefix */
767	result = isc_netaddr_masktoprefixlen(&interface->netmask,
768					     &prefixlen);
769
770	/* Non contiguous netmasks not allowed by IPv6 arch. */
771	if (result != ISC_R_SUCCESS && netaddr->family == AF_INET6)
772		return (result);
773
774	if (result != ISC_R_SUCCESS) {
775		isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING,
776			      "omitting IPv4 interface %s from "
777			      "localnets ACL: %s", interface->name,
778			      isc_result_totext(result));
779		return (ISC_R_SUCCESS);
780	}
781
782	if (prefixlen == 0U) {
783		isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING,
784			      "omitting %s interface %s from localnets ACL: "
785			      "zero prefix length detected",
786			      (netaddr->family == AF_INET) ? "IPv4" : "IPv6",
787			      interface->name);
788		return (ISC_R_SUCCESS);
789	}
790
791	result = dns_iptable_addprefix(mgr->aclenv.localnets->iptable,
792				       netaddr, prefixlen, true);
793	if (result != ISC_R_SUCCESS)
794		return (result);
795
796	return (ISC_R_SUCCESS);
797}
798
799static void
800setup_listenon(ns_interfacemgr_t *mgr, isc_interface_t *interface,
801	       in_port_t port)
802{
803	isc_sockaddr_t *addr;
804	isc_sockaddr_t *old;
805
806	addr = isc_mem_get(mgr->mctx, sizeof(*addr));
807	if (addr == NULL)
808		return;
809
810	isc_sockaddr_fromnetaddr(addr, &interface->address, port);
811
812	for (old = ISC_LIST_HEAD(mgr->listenon);
813	     old != NULL;
814	     old = ISC_LIST_NEXT(old, link))
815		if (isc_sockaddr_equal(addr, old))
816			break;
817
818	if (old != NULL)
819		isc_mem_put(mgr->mctx, addr, sizeof(*addr));
820	else
821		ISC_LIST_APPEND(mgr->listenon, addr, link);
822}
823
824static void
825clearlistenon(ns_interfacemgr_t *mgr) {
826	isc_sockaddr_t *old;
827
828	old = ISC_LIST_HEAD(mgr->listenon);
829	while (old != NULL) {
830		ISC_LIST_UNLINK(mgr->listenon, old, link);
831		isc_mem_put(mgr->mctx, old, sizeof(*old));
832		old = ISC_LIST_HEAD(mgr->listenon);
833	}
834}
835
836static isc_result_t
837do_scan(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen,
838	bool verbose)
839{
840	isc_interfaceiter_t *iter = NULL;
841	bool scan_ipv4 = false;
842	bool scan_ipv6 = false;
843	bool adjusting = false;
844	bool ipv6only = true;
845	bool ipv6pktinfo = true;
846	isc_result_t result;
847	isc_netaddr_t zero_address, zero_address6;
848	ns_listenelt_t *le;
849	isc_sockaddr_t listen_addr;
850	ns_interface_t *ifp;
851	bool log_explicit = false;
852	bool dolistenon;
853	char sabuf[ISC_SOCKADDR_FORMATSIZE];
854	bool tried_listening;
855	bool all_addresses_in_use;
856
857	if (ext_listen != NULL)
858		adjusting = true;
859
860	if (isc_net_probeipv6() == ISC_R_SUCCESS)
861		scan_ipv6 = true;
862	else if ((mgr->sctx->options & NS_SERVER_DISABLE6) == 0)
863		isc_log_write(IFMGR_COMMON_LOGARGS,
864			      verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1),
865			      "no IPv6 interfaces found");
866
867	if (isc_net_probeipv4() == ISC_R_SUCCESS)
868		scan_ipv4 = true;
869	else if ((mgr->sctx->options & NS_SERVER_DISABLE4) == 0)
870		isc_log_write(IFMGR_COMMON_LOGARGS,
871			      verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1),
872			      "no IPv4 interfaces found");
873
874	/*
875	 * A special, but typical case; listen-on-v6 { any; }.
876	 * When we can make the socket IPv6-only, open a single wildcard
877	 * socket for IPv6 communication.  Otherwise, make separate socket
878	 * for each IPv6 address in order to avoid accepting IPv4 packets
879	 * as the form of mapped addresses unintentionally unless explicitly
880	 * allowed.
881	 */
882#ifndef ISC_ALLOW_MAPPED
883	if (scan_ipv6 == true &&
884	    isc_net_probe_ipv6only() != ISC_R_SUCCESS) {
885		ipv6only = false;
886		log_explicit = true;
887	}
888#endif
889	if (scan_ipv6 == true &&
890	    isc_net_probe_ipv6pktinfo() != ISC_R_SUCCESS) {
891		ipv6pktinfo = false;
892		log_explicit = true;
893	}
894	if (scan_ipv6 == true && ipv6only && ipv6pktinfo) {
895		for (le = ISC_LIST_HEAD(mgr->listenon6->elts);
896		     le != NULL;
897		     le = ISC_LIST_NEXT(le, link)) {
898			struct in6_addr in6a;
899
900			if (!listenon_is_ip6_any(le))
901				continue;
902
903			in6a = in6addr_any;
904			isc_sockaddr_fromin6(&listen_addr, &in6a, le->port);
905
906			ifp = find_matching_interface(mgr, &listen_addr);
907			if (ifp != NULL) {
908				ifp->generation = mgr->generation;
909				if (le->dscp != -1 && ifp->dscp == -1)
910					ifp->dscp = le->dscp;
911				else if (le->dscp != ifp->dscp) {
912					isc_sockaddr_format(&listen_addr,
913							    sabuf,
914							    sizeof(sabuf));
915					isc_log_write(IFMGR_COMMON_LOGARGS,
916						      ISC_LOG_WARNING,
917						      "%s: conflicting DSCP "
918						      "values, using %d",
919						      sabuf, ifp->dscp);
920				}
921			} else {
922				isc_log_write(IFMGR_COMMON_LOGARGS,
923					      ISC_LOG_INFO,
924					      "listening on IPv6 "
925					      "interfaces, port %u",
926					      le->port);
927				result = ns_interface_setup(mgr, &listen_addr,
928							    "<any>", &ifp,
929							    true,
930							    le->dscp,
931							    NULL);
932				if (result == ISC_R_SUCCESS)
933					ifp->flags |= NS_INTERFACEFLAG_ANYADDR;
934				else
935					isc_log_write(IFMGR_COMMON_LOGARGS,
936						      ISC_LOG_ERROR,
937						      "listening on all IPv6 "
938						      "interfaces failed");
939				/* Continue. */
940			}
941		}
942	}
943
944	isc_netaddr_any(&zero_address);
945	isc_netaddr_any6(&zero_address6);
946
947	result = isc_interfaceiter_create(mgr->mctx, &iter);
948	if (result != ISC_R_SUCCESS)
949		return (result);
950
951	if (adjusting == false) {
952		result = clearacl(mgr->mctx, &mgr->aclenv.localhost);
953		if (result != ISC_R_SUCCESS)
954			goto cleanup_iter;
955		result = clearacl(mgr->mctx, &mgr->aclenv.localnets);
956		if (result != ISC_R_SUCCESS)
957			goto cleanup_iter;
958		clearlistenon(mgr);
959	}
960
961	tried_listening = false;
962	all_addresses_in_use = true;
963	for (result = isc_interfaceiter_first(iter);
964	     result == ISC_R_SUCCESS;
965	     result = isc_interfaceiter_next(iter))
966	{
967		isc_interface_t interface;
968		ns_listenlist_t *ll;
969		unsigned int family;
970
971		result = isc_interfaceiter_current(iter, &interface);
972		if (result != ISC_R_SUCCESS)
973			break;
974
975		family = interface.address.family;
976		if (family != AF_INET && family != AF_INET6)
977			continue;
978		if (scan_ipv4 == false && family == AF_INET)
979			continue;
980		if (scan_ipv6 == false && family == AF_INET6)
981			continue;
982
983		/*
984		 * Test for the address being nonzero rather than testing
985		 * INTERFACE_F_UP, because on some systems the latter
986		 * follows the media state and we could end up ignoring
987		 * the interface for an entire rescan interval due to
988		 * a temporary media glitch at rescan time.
989		 */
990		if (family == AF_INET &&
991		    isc_netaddr_equal(&interface.address, &zero_address)) {
992			continue;
993		}
994		if (family == AF_INET6 &&
995		    isc_netaddr_equal(&interface.address, &zero_address6)) {
996			continue;
997		}
998
999		if (adjusting == false) {
1000			/*
1001			 * If running with -T fixedlocal, then we only
1002			 * want 127.0.0.1 and ::1 in the localhost ACL.
1003			 */
1004			if (((mgr->sctx->options &
1005			      NS_SERVER_FIXEDLOCAL) != 0) &&
1006			    !isc_netaddr_isloopback(&interface.address))
1007			{
1008				goto listenon;
1009			}
1010
1011			result = setup_locals(mgr, &interface);
1012			if (result != ISC_R_SUCCESS)
1013				goto ignore_interface;
1014		}
1015
1016 listenon:
1017		ll = (family == AF_INET) ? mgr->listenon4 : mgr->listenon6;
1018		dolistenon = true;
1019		for (le = ISC_LIST_HEAD(ll->elts);
1020		     le != NULL;
1021		     le = ISC_LIST_NEXT(le, link))
1022		{
1023			int match;
1024			bool ipv6_wildcard = false;
1025			isc_netaddr_t listen_netaddr;
1026			isc_sockaddr_t listen_sockaddr;
1027
1028			/*
1029			 * Construct a socket address for this IP/port
1030			 * combination.
1031			 */
1032			if (family == AF_INET) {
1033				isc_netaddr_fromin(&listen_netaddr,
1034						   &interface.address.type.in);
1035			} else {
1036				isc_netaddr_fromin6(&listen_netaddr,
1037						    &interface.address.type.in6);
1038				isc_netaddr_setzone(&listen_netaddr,
1039						    interface.address.zone);
1040			}
1041			isc_sockaddr_fromnetaddr(&listen_sockaddr,
1042						 &listen_netaddr,
1043						 le->port);
1044
1045			/*
1046			 * See if the address matches the listen-on statement;
1047			 * if not, ignore the interface.
1048			 */
1049			(void)dns_acl_match(&listen_netaddr, NULL, le->acl,
1050					    &mgr->aclenv, &match, NULL);
1051			if (match <= 0) {
1052				continue;
1053			}
1054
1055			if (adjusting == false && dolistenon == true) {
1056				setup_listenon(mgr, &interface, le->port);
1057				dolistenon = false;
1058			}
1059
1060			/*
1061			 * The case of "any" IPv6 address will require
1062			 * special considerations later, so remember it.
1063			 */
1064			if (family == AF_INET6 && ipv6only && ipv6pktinfo &&
1065			    listenon_is_ip6_any(le))
1066				ipv6_wildcard = true;
1067
1068			/*
1069			 * When adjusting interfaces with extra a listening
1070			 * list, see if the address matches the extra list.
1071			 * If it does, and is also covered by a wildcard
1072			 * interface, we need to listen on the address
1073			 * explicitly.
1074			 */
1075			if (adjusting == true) {
1076				ns_listenelt_t *ele;
1077
1078				match = 0;
1079				for (ele = ISC_LIST_HEAD(ext_listen->elts);
1080				     ele != NULL;
1081				     ele = ISC_LIST_NEXT(ele, link))
1082				{
1083					(void)dns_acl_match(&listen_netaddr,
1084							    NULL, ele->acl,
1085							    NULL, &match,
1086							    NULL);
1087					if (match > 0 &&
1088					    (ele->port == le->port ||
1089					    ele->port == 0))
1090					{
1091						break;
1092					} else {
1093						match = 0;
1094					}
1095				}
1096				if (ipv6_wildcard == true && match == 0)
1097					continue;
1098			}
1099
1100			ifp = find_matching_interface(mgr, &listen_sockaddr);
1101			if (ifp != NULL) {
1102				ifp->generation = mgr->generation;
1103				if (le->dscp != -1 && ifp->dscp == -1)
1104					ifp->dscp = le->dscp;
1105				else if (le->dscp != ifp->dscp) {
1106					isc_sockaddr_format(&listen_sockaddr,
1107							    sabuf,
1108							    sizeof(sabuf));
1109					isc_log_write(IFMGR_COMMON_LOGARGS,
1110						      ISC_LOG_WARNING,
1111						      "%s: conflicting DSCP "
1112						      "values, using %d",
1113						      sabuf, ifp->dscp);
1114				}
1115			} else {
1116				bool addr_in_use = false;
1117
1118				if (adjusting == false &&
1119				    ipv6_wildcard == true)
1120					continue;
1121
1122				if (log_explicit && family == AF_INET6 &&
1123				    !adjusting && listenon_is_ip6_any(le)) {
1124					isc_log_write(IFMGR_COMMON_LOGARGS,
1125						      verbose ? ISC_LOG_INFO :
1126							      ISC_LOG_DEBUG(1),
1127						      "IPv6 socket API is "
1128						      "incomplete; explicitly "
1129						      "binding to each IPv6 "
1130						      "address separately");
1131					log_explicit = false;
1132				}
1133				isc_sockaddr_format(&listen_sockaddr,
1134						    sabuf, sizeof(sabuf));
1135				isc_log_write(IFMGR_COMMON_LOGARGS,
1136					      ISC_LOG_INFO,
1137					      "%s"
1138					      "listening on %s interface "
1139					      "%s, %s",
1140					      (adjusting == true) ?
1141					      "additionally " : "",
1142					      (family == AF_INET) ?
1143					      "IPv4" : "IPv6",
1144					      interface.name, sabuf);
1145
1146				result = ns_interface_setup(mgr,
1147						    &listen_sockaddr,
1148						    interface.name,
1149						    &ifp,
1150						    (adjusting == true) ?
1151						    false : true,
1152						    le->dscp,
1153						    &addr_in_use);
1154
1155				tried_listening = true;
1156				if (!addr_in_use)
1157					all_addresses_in_use = false;
1158
1159				if (result != ISC_R_SUCCESS) {
1160					isc_log_write(IFMGR_COMMON_LOGARGS,
1161						      ISC_LOG_ERROR,
1162						      "creating %s interface "
1163						      "%s failed; interface "
1164						      "ignored",
1165						      (family == AF_INET) ?
1166						      "IPv4" : "IPv6",
1167						      interface.name);
1168				}
1169				/* Continue. */
1170			}
1171
1172		}
1173		continue;
1174
1175	ignore_interface:
1176		isc_log_write(IFMGR_COMMON_LOGARGS,
1177			      ISC_LOG_ERROR,
1178			      "ignoring %s interface %s: %s",
1179			      (family == AF_INET) ? "IPv4" : "IPv6",
1180			      interface.name, isc_result_totext(result));
1181		continue;
1182	}
1183	if (result != ISC_R_NOMORE)
1184		UNEXPECTED_ERROR(__FILE__, __LINE__,
1185				 "interface iteration failed: %s",
1186				 isc_result_totext(result));
1187	else
1188		result = ((tried_listening && all_addresses_in_use) ?
1189			  ISC_R_ADDRINUSE : ISC_R_SUCCESS);
1190 cleanup_iter:
1191	isc_interfaceiter_destroy(&iter);
1192	return (result);
1193}
1194
1195static isc_result_t
1196ns_interfacemgr_scan0(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen,
1197		      bool verbose)
1198{
1199	isc_result_t result;
1200	bool purge = true;
1201
1202	REQUIRE(NS_INTERFACEMGR_VALID(mgr));
1203
1204	mgr->generation++;	/* Increment the generation count. */
1205
1206	result = do_scan(mgr, ext_listen, verbose);
1207	if ((result != ISC_R_SUCCESS) && (result != ISC_R_ADDRINUSE))
1208		purge = false;
1209
1210	/*
1211	 * Now go through the interface list and delete anything that
1212	 * does not have the current generation number.  This is
1213	 * how we catch interfaces that go away or change their
1214	 * addresses.
1215	 */
1216	if (purge)
1217		purge_old_interfaces(mgr);
1218
1219	/*
1220	 * Warn if we are not listening on any interface.
1221	 */
1222	if (ext_listen == NULL &&
1223	    ISC_LIST_EMPTY(mgr->interfaces))
1224	{
1225		isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING,
1226			      "not listening on any interfaces");
1227	}
1228
1229	return (result);
1230}
1231
1232bool
1233ns_interfacemgr_islistening(ns_interfacemgr_t *mgr) {
1234	REQUIRE(NS_INTERFACEMGR_VALID(mgr));
1235
1236	return (ISC_LIST_EMPTY(mgr->interfaces) ? false : true);
1237}
1238
1239isc_result_t
1240ns_interfacemgr_scan(ns_interfacemgr_t *mgr, bool verbose) {
1241	isc_result_t result;
1242	bool unlock = false;
1243
1244	/*
1245	 * Check for success because we may already be task-exclusive
1246	 * at this point.  Only if we succeed at obtaining an exclusive
1247	 * lock now will we need to relinquish it later.
1248	 */
1249	result = isc_task_beginexclusive(mgr->excl);
1250	if (result == ISC_R_SUCCESS)
1251		unlock = true;
1252
1253	result = ns_interfacemgr_scan0(mgr, NULL, verbose);
1254
1255	if (unlock)
1256		isc_task_endexclusive(mgr->excl);
1257
1258	return (result);
1259}
1260
1261isc_result_t
1262ns_interfacemgr_adjust(ns_interfacemgr_t *mgr, ns_listenlist_t *list,
1263		       bool verbose)
1264{
1265	return (ns_interfacemgr_scan0(mgr, list, verbose));
1266}
1267
1268void
1269ns_interfacemgr_setlistenon4(ns_interfacemgr_t *mgr, ns_listenlist_t *value) {
1270	REQUIRE(NS_INTERFACEMGR_VALID(mgr));
1271
1272	LOCK(&mgr->lock);
1273	ns_listenlist_detach(&mgr->listenon4);
1274	ns_listenlist_attach(value, &mgr->listenon4);
1275	UNLOCK(&mgr->lock);
1276}
1277
1278void
1279ns_interfacemgr_setlistenon6(ns_interfacemgr_t *mgr, ns_listenlist_t *value) {
1280	REQUIRE(NS_INTERFACEMGR_VALID(mgr));
1281
1282	LOCK(&mgr->lock);
1283	ns_listenlist_detach(&mgr->listenon6);
1284	ns_listenlist_attach(value, &mgr->listenon6);
1285	UNLOCK(&mgr->lock);
1286}
1287
1288void
1289ns_interfacemgr_dumprecursing(FILE *f, ns_interfacemgr_t *mgr) {
1290	ns_interface_t *interface;
1291
1292	REQUIRE(NS_INTERFACEMGR_VALID(mgr));
1293
1294	LOCK(&mgr->lock);
1295	interface = ISC_LIST_HEAD(mgr->interfaces);
1296	while (interface != NULL) {
1297		if (interface->clientmgr != NULL)
1298			ns_client_dumprecursing(f, interface->clientmgr);
1299		interface = ISC_LIST_NEXT(interface, link);
1300	}
1301	UNLOCK(&mgr->lock);
1302}
1303
1304bool
1305ns_interfacemgr_listeningon(ns_interfacemgr_t *mgr,
1306			    const isc_sockaddr_t *addr)
1307{
1308	isc_sockaddr_t *old;
1309
1310	REQUIRE(NS_INTERFACEMGR_VALID(mgr));
1311
1312	for (old = ISC_LIST_HEAD(mgr->listenon);
1313	     old != NULL;
1314	     old = ISC_LIST_NEXT(old, link))
1315		if (isc_sockaddr_equal(old, addr))
1316			return (true);
1317	return (false);
1318}
1319
1320ns_interface_t *
1321ns__interfacemgr_getif(ns_interfacemgr_t *mgr) {
1322	REQUIRE(NS_INTERFACEMGR_VALID(mgr));
1323
1324	return (ISC_LIST_HEAD(mgr->interfaces));
1325}
1326
1327ns_interface_t *
1328ns__interfacemgr_nextif(ns_interface_t *ifp) {
1329	return (ISC_LIST_NEXT(ifp, link));
1330}
1331