1999-05-20 12:37:35 +00:00
|
|
|
/*
|
2018-02-23 09:53:12 +01:00
|
|
|
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
2000-08-01 01:33:37 +00:00
|
|
|
*
|
2016-06-27 14:56:38 +10:00
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
2020-09-14 16:20:40 -07:00
|
|
|
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
2018-02-23 09:53:12 +01:00
|
|
|
*
|
|
|
|
* See the COPYRIGHT file distributed with this work for additional
|
|
|
|
* information regarding copyright ownership.
|
1999-05-20 12:37:35 +00:00
|
|
|
*/
|
|
|
|
|
2005-04-27 04:57:32 +00:00
|
|
|
/*! \file */
|
2000-06-22 22:00:42 +00:00
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
#include <stdbool.h>
|
|
|
|
|
2000-04-28 03:53:48 +00:00
|
|
|
#include <isc/interfaceiter.h>
|
2019-11-05 15:34:35 -08:00
|
|
|
#include <isc/netmgr.h>
|
2011-07-28 04:04:37 +00:00
|
|
|
#include <isc/os.h>
|
2017-09-28 10:09:22 -07:00
|
|
|
#include <isc/random.h>
|
2000-05-08 14:38:29 +00:00
|
|
|
#include <isc/string.h>
|
2000-04-28 03:53:48 +00:00
|
|
|
#include <isc/task.h>
|
2000-01-11 21:18:22 +00:00
|
|
|
#include <isc/util.h>
|
1999-05-20 12:37:35 +00:00
|
|
|
|
2000-01-25 21:21:05 +00:00
|
|
|
#include <dns/acl.h>
|
1999-07-24 01:17:28 +00:00
|
|
|
#include <dns/dispatch.h>
|
|
|
|
|
2017-09-08 13:39:09 -07:00
|
|
|
#include <ns/client.h>
|
|
|
|
#include <ns/interfacemgr.h>
|
2020-02-12 13:59:18 +01:00
|
|
|
#include <ns/log.h>
|
2017-09-08 13:39:09 -07:00
|
|
|
#include <ns/server.h>
|
2019-11-22 18:34:50 -03:00
|
|
|
#include <ns/stats.h>
|
2014-02-07 17:16:37 +11:00
|
|
|
|
|
|
|
#ifdef HAVE_NET_ROUTE_H
|
|
|
|
#include <net/route.h>
|
|
|
|
#if defined(RTM_VERSION) && defined(RTM_NEWADDR) && defined(RTM_DELADDR)
|
2020-02-13 14:44:37 -08:00
|
|
|
#define USE_ROUTE_SOCKET 1
|
2014-02-10 09:46:54 +11:00
|
|
|
#define ROUTE_SOCKET_PROTOCOL PF_ROUTE
|
2020-02-13 14:44:37 -08:00
|
|
|
#define MSGHDR rt_msghdr
|
|
|
|
#define MSGTYPE rtm_type
|
2020-02-13 21:48:23 +01:00
|
|
|
#endif /* if defined(RTM_VERSION) && defined(RTM_NEWADDR) && \
|
|
|
|
* defined(RTM_DELADDR) */
|
|
|
|
#endif /* ifdef HAVE_NET_ROUTE_H */
|
2014-02-10 09:46:54 +11:00
|
|
|
|
|
|
|
#if defined(HAVE_LINUX_NETLINK_H) && defined(HAVE_LINUX_RTNETLINK_H)
|
|
|
|
#include <linux/netlink.h>
|
|
|
|
#include <linux/rtnetlink.h>
|
|
|
|
#if defined(RTM_NEWADDR) && defined(RTM_DELADDR)
|
2020-02-13 14:44:37 -08:00
|
|
|
#define USE_ROUTE_SOCKET 1
|
2014-02-10 09:46:54 +11:00
|
|
|
#define ROUTE_SOCKET_PROTOCOL PF_NETLINK
|
2020-02-13 14:44:37 -08:00
|
|
|
#define MSGHDR nlmsghdr
|
|
|
|
#define MSGTYPE nlmsg_type
|
2020-02-13 21:48:23 +01:00
|
|
|
#endif /* if defined(RTM_NEWADDR) && defined(RTM_DELADDR) */
|
|
|
|
#endif /* if defined(HAVE_LINUX_NETLINK_H) && defined(HAVE_LINUX_RTNETLINK_H) \
|
|
|
|
*/
|
1999-05-20 12:37:35 +00:00
|
|
|
|
2014-02-18 22:36:14 -08:00
|
|
|
#ifdef TUNE_LARGE
|
2014-02-19 23:46:31 +00:00
|
|
|
#define UDPBUFFERS 32768
|
2020-02-13 21:48:23 +01:00
|
|
|
#else /* ifdef TUNE_LARGE */
|
2014-02-18 22:36:14 -08:00
|
|
|
#define UDPBUFFERS 1000
|
|
|
|
#endif /* TUNE_LARGE */
|
|
|
|
|
2020-02-13 14:44:37 -08:00
|
|
|
#define IFMGR_MAGIC ISC_MAGIC('I', 'F', 'M', 'G')
|
2020-02-12 13:59:18 +01:00
|
|
|
#define NS_INTERFACEMGR_VALID(t) ISC_MAGIC_VALID(t, IFMGR_MAGIC)
|
1999-05-20 12:37:35 +00:00
|
|
|
|
2000-01-18 22:57:24 +00:00
|
|
|
#define IFMGR_COMMON_LOGARGS \
|
2017-09-08 13:39:09 -07:00
|
|
|
ns_lctx, NS_LOGCATEGORY_NETWORK, NS_LOGMODULE_INTERFACEMGR
|
2000-01-18 22:57:24 +00:00
|
|
|
|
2005-04-27 04:57:32 +00:00
|
|
|
/*% nameserver interface manager structure */
|
1999-05-20 12:37:35 +00:00
|
|
|
struct ns_interfacemgr {
|
2020-02-13 14:44:37 -08:00
|
|
|
unsigned int magic; /*%< Magic number. */
|
|
|
|
isc_refcount_t references;
|
|
|
|
isc_mutex_t lock;
|
|
|
|
isc_mem_t *mctx; /*%< Memory context. */
|
|
|
|
ns_server_t *sctx; /*%< Server context. */
|
|
|
|
isc_taskmgr_t *taskmgr; /*%< Task manager. */
|
|
|
|
isc_task_t *excl; /*%< Exclusive task. */
|
|
|
|
isc_timermgr_t *timermgr; /*%< Timer manager. */
|
|
|
|
isc_socketmgr_t *socketmgr; /*%< Socket manager. */
|
|
|
|
isc_nm_t *nm; /*%< Net manager. */
|
2020-01-28 11:05:07 +01:00
|
|
|
int ncpus; /*%< Number of workers . */
|
2020-02-12 13:59:18 +01:00
|
|
|
dns_dispatchmgr_t *dispatchmgr;
|
2020-02-13 14:44:37 -08:00
|
|
|
unsigned int generation; /*%< Current generation no. */
|
|
|
|
ns_listenlist_t *listenon4;
|
|
|
|
ns_listenlist_t *listenon6;
|
|
|
|
dns_aclenv_t aclenv; /*%< Localhost/localnets ACLs */
|
2020-02-12 13:59:18 +01:00
|
|
|
ISC_LIST(ns_interface_t) interfaces; /*%< List of interfaces. */
|
2005-02-10 05:53:43 +00:00
|
|
|
ISC_LIST(isc_sockaddr_t) listenon;
|
2020-02-13 14:44:37 -08:00
|
|
|
int backlog; /*%< Listen queue size */
|
|
|
|
unsigned int udpdisp; /*%< UDP dispatch count */
|
|
|
|
atomic_bool shuttingdown; /*%< Interfacemgr is shutting
|
|
|
|
* down */
|
2014-02-07 17:16:37 +11:00
|
|
|
#ifdef USE_ROUTE_SOCKET
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_task_t *task;
|
2020-02-12 13:59:18 +01:00
|
|
|
isc_socket_t *route;
|
|
|
|
unsigned char buf[2048];
|
2020-02-13 21:48:23 +01:00
|
|
|
#endif /* ifdef USE_ROUTE_SOCKET */
|
1999-05-20 12:37:35 +00:00
|
|
|
};
|
|
|
|
|
2020-02-14 08:14:03 +01:00
|
|
|
static void
|
|
|
|
purge_old_interfaces(ns_interfacemgr_t *mgr);
|
1999-05-20 12:37:35 +00:00
|
|
|
|
2020-02-14 08:14:03 +01:00
|
|
|
static void
|
|
|
|
clearlistenon(ns_interfacemgr_t *mgr);
|
2005-02-10 05:53:43 +00:00
|
|
|
|
2014-02-07 17:16:37 +11:00
|
|
|
#ifdef USE_ROUTE_SOCKET
|
|
|
|
static void
|
2020-02-13 14:44:37 -08:00
|
|
|
route_event(isc_task_t *task, isc_event_t *event) {
|
2014-02-07 17:16:37 +11:00
|
|
|
isc_socketevent_t *sevent = NULL;
|
|
|
|
ns_interfacemgr_t *mgr = NULL;
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_region_t r;
|
|
|
|
isc_result_t result;
|
|
|
|
struct MSGHDR *rtm;
|
|
|
|
bool done = true;
|
2014-02-07 17:16:37 +11:00
|
|
|
|
|
|
|
UNUSED(task);
|
|
|
|
|
|
|
|
REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE);
|
|
|
|
mgr = event->ev_arg;
|
|
|
|
sevent = (isc_socketevent_t *)event;
|
|
|
|
|
|
|
|
if (sevent->result != ISC_R_SUCCESS) {
|
2020-02-13 21:48:23 +01:00
|
|
|
if (sevent->result != ISC_R_CANCELED) {
|
2014-02-07 17:16:37 +11:00
|
|
|
isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
|
|
|
|
"automatic interface scanning "
|
|
|
|
"terminated: %s",
|
|
|
|
isc_result_totext(sevent->result));
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2014-02-07 17:16:37 +11:00
|
|
|
ns_interfacemgr_detach(&mgr);
|
|
|
|
isc_event_free(&event);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-02-10 09:46:54 +11:00
|
|
|
rtm = (struct MSGHDR *)mgr->buf;
|
|
|
|
#ifdef RTM_VERSION
|
2014-02-07 17:16:37 +11:00
|
|
|
if (rtm->rtm_version != RTM_VERSION) {
|
|
|
|
isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
|
|
|
|
"automatic interface rescanning disabled: "
|
|
|
|
"rtm->rtm_version mismatch (%u != %u) "
|
2020-02-12 13:59:18 +01:00
|
|
|
"recompile required",
|
|
|
|
rtm->rtm_version, RTM_VERSION);
|
2014-02-07 17:16:37 +11:00
|
|
|
ns_interfacemgr_detach(&mgr);
|
|
|
|
isc_event_free(&event);
|
|
|
|
return;
|
|
|
|
}
|
2020-02-13 21:48:23 +01:00
|
|
|
#endif /* ifdef RTM_VERSION */
|
2014-02-07 17:16:37 +11:00
|
|
|
|
2014-02-10 09:46:54 +11:00
|
|
|
switch (rtm->MSGTYPE) {
|
2014-02-07 17:16:37 +11:00
|
|
|
case RTM_NEWADDR:
|
|
|
|
case RTM_DELADDR:
|
2020-02-13 21:48:23 +01:00
|
|
|
if (mgr->route != NULL && mgr->sctx->interface_auto) {
|
2018-04-17 08:29:14 -07:00
|
|
|
ns_interfacemgr_scan(mgr, false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2014-02-07 17:16:37 +11:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2014-04-03 19:48:29 -07:00
|
|
|
LOCK(&mgr->lock);
|
|
|
|
if (mgr->route != NULL) {
|
|
|
|
/*
|
|
|
|
* Look for next route event.
|
|
|
|
*/
|
|
|
|
r.base = mgr->buf;
|
|
|
|
r.length = sizeof(mgr->buf);
|
|
|
|
result = isc_socket_recv(mgr->route, &r, 1, mgr->task,
|
|
|
|
route_event, mgr);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
2018-04-17 08:29:14 -07:00
|
|
|
done = false;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2014-04-03 19:48:29 -07:00
|
|
|
}
|
|
|
|
UNLOCK(&mgr->lock);
|
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (done) {
|
2014-02-07 17:16:37 +11:00
|
|
|
ns_interfacemgr_detach(&mgr);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2014-02-07 17:16:37 +11:00
|
|
|
isc_event_free(&event);
|
2014-04-03 19:48:29 -07:00
|
|
|
return;
|
2014-02-07 17:16:37 +11:00
|
|
|
}
|
2020-02-13 21:48:23 +01:00
|
|
|
#endif /* ifdef USE_ROUTE_SOCKET */
|
2014-02-07 17:16:37 +11:00
|
|
|
|
1999-07-24 01:17:28 +00:00
|
|
|
isc_result_t
|
2020-02-12 13:59:18 +01:00
|
|
|
ns_interfacemgr_create(isc_mem_t *mctx, ns_server_t *sctx,
|
|
|
|
isc_taskmgr_t *taskmgr, isc_timermgr_t *timermgr,
|
|
|
|
isc_socketmgr_t *socketmgr, isc_nm_t *nm,
|
|
|
|
dns_dispatchmgr_t *dispatchmgr, isc_task_t *task,
|
|
|
|
unsigned int udpdisp, dns_geoip_databases_t *geoip,
|
2020-01-28 11:05:07 +01:00
|
|
|
int ncpus, ns_interfacemgr_t **mgrp) {
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_result_t result;
|
1999-05-20 12:37:35 +00:00
|
|
|
ns_interfacemgr_t *mgr;
|
2000-01-11 21:18:22 +00:00
|
|
|
|
2014-08-30 15:47:25 +10:00
|
|
|
#ifndef USE_ROUTE_SOCKET
|
|
|
|
UNUSED(task);
|
2020-02-13 21:48:23 +01:00
|
|
|
#endif /* ifndef USE_ROUTE_SOCKET */
|
2014-08-30 15:47:25 +10:00
|
|
|
|
1999-05-20 12:37:35 +00:00
|
|
|
REQUIRE(mctx != NULL);
|
|
|
|
REQUIRE(mgrp != NULL);
|
|
|
|
REQUIRE(*mgrp == NULL);
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-05-20 12:37:35 +00:00
|
|
|
mgr = isc_mem_get(mctx, sizeof(*mgr));
|
|
|
|
|
2013-03-08 14:38:03 +11:00
|
|
|
mgr->mctx = NULL;
|
|
|
|
isc_mem_attach(mctx, &mgr->mctx);
|
|
|
|
|
2017-09-08 13:39:09 -07:00
|
|
|
mgr->sctx = NULL;
|
|
|
|
ns_server_attach(sctx, &mgr->sctx);
|
|
|
|
|
2018-11-16 15:33:22 +01:00
|
|
|
isc_mutex_init(&mgr->lock);
|
2017-09-08 13:39:09 -07:00
|
|
|
|
|
|
|
mgr->excl = NULL;
|
|
|
|
result = isc_taskmgr_excltask(taskmgr, &mgr->excl);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
goto cleanup_lock;
|
|
|
|
}
|
2000-01-11 21:18:22 +00:00
|
|
|
|
1999-05-20 12:37:35 +00:00
|
|
|
mgr->taskmgr = taskmgr;
|
2017-09-08 13:39:09 -07:00
|
|
|
mgr->timermgr = timermgr;
|
1999-05-20 12:37:35 +00:00
|
|
|
mgr->socketmgr = socketmgr;
|
2019-11-05 15:34:35 -08:00
|
|
|
mgr->nm = nm;
|
2000-05-10 21:34:50 +00:00
|
|
|
mgr->dispatchmgr = dispatchmgr;
|
1999-05-20 12:37:35 +00:00
|
|
|
mgr->generation = 1;
|
2000-06-05 19:10:13 +00:00
|
|
|
mgr->listenon4 = NULL;
|
2000-08-01 01:33:37 +00:00
|
|
|
mgr->listenon6 = NULL;
|
2017-09-08 13:39:09 -07:00
|
|
|
mgr->udpdisp = udpdisp;
|
2020-01-28 11:05:07 +01:00
|
|
|
mgr->ncpus = ncpus;
|
2019-12-07 23:44:16 +01:00
|
|
|
atomic_init(&mgr->shuttingdown, false);
|
2008-07-22 23:47:04 +00:00
|
|
|
|
1999-05-20 12:37:35 +00:00
|
|
|
ISC_LIST_INIT(mgr->interfaces);
|
2005-02-10 05:53:43 +00:00
|
|
|
ISC_LIST_INIT(mgr->listenon);
|
1999-05-20 12:37:35 +00:00
|
|
|
|
2000-06-05 19:10:13 +00:00
|
|
|
/*
|
|
|
|
* The listen-on lists are initially empty.
|
|
|
|
*/
|
|
|
|
result = ns_listenlist_create(mctx, &mgr->listenon4);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2017-09-08 13:39:09 -07:00
|
|
|
goto cleanup_ctx;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-06-05 19:10:13 +00:00
|
|
|
ns_listenlist_attach(mgr->listenon4, &mgr->listenon6);
|
2000-02-09 22:59:40 +00:00
|
|
|
|
|
|
|
result = dns_aclenv_init(mctx, &mgr->aclenv);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2000-02-09 22:59:40 +00:00
|
|
|
goto cleanup_listenon;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2019-06-27 21:08:20 -07:00
|
|
|
#if defined(HAVE_GEOIP2)
|
2017-09-08 13:39:09 -07:00
|
|
|
mgr->aclenv.geoip = geoip;
|
2020-02-13 21:48:23 +01:00
|
|
|
#else /* if defined(HAVE_GEOIP2) */
|
2017-09-08 13:39:09 -07:00
|
|
|
UNUSED(geoip);
|
2020-02-13 21:48:23 +01:00
|
|
|
#endif /* if defined(HAVE_GEOIP2) */
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2014-02-07 17:16:37 +11:00
|
|
|
#ifdef USE_ROUTE_SOCKET
|
|
|
|
mgr->route = NULL;
|
2014-02-10 09:46:54 +11:00
|
|
|
result = isc_socket_create(mgr->socketmgr, ROUTE_SOCKET_PROTOCOL,
|
2014-02-07 17:16:37 +11:00
|
|
|
isc_sockettype_raw, &mgr->route);
|
|
|
|
switch (result) {
|
|
|
|
case ISC_R_NOPERM:
|
|
|
|
case ISC_R_SUCCESS:
|
|
|
|
case ISC_R_NOTIMPLEMENTED:
|
2014-02-10 09:46:54 +11:00
|
|
|
case ISC_R_FAMILYNOSUPPORT:
|
2020-02-12 13:59:18 +01:00
|
|
|
break;
|
2014-02-07 17:16:37 +11:00
|
|
|
default:
|
|
|
|
goto cleanup_aclenv;
|
|
|
|
}
|
|
|
|
|
|
|
|
mgr->task = NULL;
|
2019-11-05 15:34:35 -08:00
|
|
|
if (mgr->route != NULL) {
|
2014-08-18 13:16:28 +10:00
|
|
|
isc_task_attach(task, &mgr->task);
|
2019-11-05 15:34:35 -08:00
|
|
|
}
|
2019-05-16 18:43:06 +02:00
|
|
|
isc_refcount_init(&mgr->references, (mgr->route != NULL) ? 2 : 1);
|
2020-02-13 21:48:23 +01:00
|
|
|
#else /* ifdef USE_ROUTE_SOCKET */
|
2019-05-16 18:43:06 +02:00
|
|
|
isc_refcount_init(&mgr->references, 1);
|
2020-02-13 21:48:23 +01:00
|
|
|
#endif /* ifdef USE_ROUTE_SOCKET */
|
1999-05-20 12:37:35 +00:00
|
|
|
mgr->magic = IFMGR_MAGIC;
|
|
|
|
*mgrp = mgr;
|
2014-02-07 17:16:37 +11:00
|
|
|
|
|
|
|
#ifdef USE_ROUTE_SOCKET
|
|
|
|
if (mgr->route != NULL) {
|
|
|
|
isc_region_t r = { mgr->buf, sizeof(mgr->buf) };
|
|
|
|
|
|
|
|
result = isc_socket_recv(mgr->route, &r, 1, mgr->task,
|
|
|
|
route_event, mgr);
|
2014-04-03 19:48:29 -07:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
isc_task_detach(&mgr->task);
|
|
|
|
isc_socket_detach(&mgr->route);
|
2014-02-07 17:16:37 +11:00
|
|
|
ns_interfacemgr_detach(&mgr);
|
2014-04-03 19:48:29 -07:00
|
|
|
}
|
2014-02-07 17:16:37 +11:00
|
|
|
}
|
2020-02-13 21:48:23 +01:00
|
|
|
#endif /* ifdef USE_ROUTE_SOCKET */
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
2000-01-13 23:32:41 +00:00
|
|
|
|
2014-02-07 17:16:37 +11:00
|
|
|
#ifdef USE_ROUTE_SOCKET
|
2020-02-12 13:59:18 +01:00
|
|
|
cleanup_aclenv:
|
2014-02-07 17:16:37 +11:00
|
|
|
dns_aclenv_destroy(&mgr->aclenv);
|
2020-02-13 21:48:23 +01:00
|
|
|
#endif /* ifdef USE_ROUTE_SOCKET */
|
2020-02-12 13:59:18 +01:00
|
|
|
cleanup_listenon:
|
2000-06-05 19:10:13 +00:00
|
|
|
ns_listenlist_detach(&mgr->listenon4);
|
|
|
|
ns_listenlist_detach(&mgr->listenon6);
|
2020-02-12 13:59:18 +01:00
|
|
|
cleanup_lock:
|
2017-09-08 13:39:09 -07:00
|
|
|
isc_mutex_destroy(&mgr->lock);
|
2020-02-12 13:59:18 +01:00
|
|
|
cleanup_ctx:
|
2017-09-08 13:39:09 -07:00
|
|
|
ns_server_detach(&mgr->sctx);
|
2013-03-08 14:38:03 +11:00
|
|
|
isc_mem_putanddetach(&mgr->mctx, mgr, sizeof(*mgr));
|
2000-01-13 23:32:41 +00:00
|
|
|
return (result);
|
1999-05-20 12:37:35 +00:00
|
|
|
}
|
|
|
|
|
2000-01-11 21:18:22 +00:00
|
|
|
static void
|
2020-02-13 14:44:37 -08:00
|
|
|
ns_interfacemgr_destroy(ns_interfacemgr_t *mgr) {
|
2000-01-11 21:18:22 +00:00
|
|
|
REQUIRE(NS_INTERFACEMGR_VALID(mgr));
|
2014-02-07 17:16:37 +11:00
|
|
|
|
2019-07-23 08:27:30 -04:00
|
|
|
isc_refcount_destroy(&mgr->references);
|
|
|
|
|
2014-02-07 17:16:37 +11:00
|
|
|
#ifdef USE_ROUTE_SOCKET
|
2020-02-13 21:48:23 +01:00
|
|
|
if (mgr->route != NULL) {
|
2014-02-07 17:16:37 +11:00
|
|
|
isc_socket_detach(&mgr->route);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
|
|
|
if (mgr->task != NULL) {
|
2014-02-07 17:16:37 +11:00
|
|
|
isc_task_detach(&mgr->task);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
|
|
|
#endif /* ifdef USE_ROUTE_SOCKET */
|
2000-02-09 22:59:40 +00:00
|
|
|
dns_aclenv_destroy(&mgr->aclenv);
|
2000-06-05 19:10:13 +00:00
|
|
|
ns_listenlist_detach(&mgr->listenon4);
|
|
|
|
ns_listenlist_detach(&mgr->listenon6);
|
2005-02-10 05:53:43 +00:00
|
|
|
clearlistenon(mgr);
|
2018-11-19 10:31:09 +00:00
|
|
|
isc_mutex_destroy(&mgr->lock);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (mgr->sctx != NULL) {
|
2017-09-08 13:39:09 -07:00
|
|
|
ns_server_detach(&mgr->sctx);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
|
|
|
if (mgr->excl != NULL) {
|
2017-09-08 13:39:09 -07:00
|
|
|
isc_task_detach(&mgr->excl);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-01-11 21:18:22 +00:00
|
|
|
mgr->magic = 0;
|
2013-03-08 14:38:03 +11:00
|
|
|
isc_mem_putanddetach(&mgr->mctx, mgr, sizeof(*mgr));
|
2000-01-11 21:18:22 +00:00
|
|
|
}
|
|
|
|
|
2017-09-08 13:39:09 -07:00
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
ns_interfacemgr_setbacklog(ns_interfacemgr_t *mgr, int backlog) {
|
2017-09-08 13:39:09 -07:00
|
|
|
REQUIRE(NS_INTERFACEMGR_VALID(mgr));
|
|
|
|
LOCK(&mgr->lock);
|
|
|
|
mgr->backlog = backlog;
|
|
|
|
UNLOCK(&mgr->lock);
|
|
|
|
}
|
|
|
|
|
2000-02-09 22:59:40 +00:00
|
|
|
dns_aclenv_t *
|
2020-02-13 14:44:37 -08:00
|
|
|
ns_interfacemgr_getaclenv(ns_interfacemgr_t *mgr) {
|
2017-09-08 13:39:09 -07:00
|
|
|
REQUIRE(NS_INTERFACEMGR_VALID(mgr));
|
|
|
|
|
2000-02-09 22:59:40 +00:00
|
|
|
return (&mgr->aclenv);
|
|
|
|
}
|
|
|
|
|
2000-01-11 21:18:22 +00:00
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
ns_interfacemgr_attach(ns_interfacemgr_t *source, ns_interfacemgr_t **target) {
|
2000-01-11 21:18:22 +00:00
|
|
|
REQUIRE(NS_INTERFACEMGR_VALID(source));
|
2019-07-15 11:19:03 +02:00
|
|
|
isc_refcount_increment(&source->references);
|
2000-01-11 21:18:22 +00:00
|
|
|
*target = source;
|
|
|
|
}
|
|
|
|
|
2000-08-01 01:33:37 +00:00
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
ns_interfacemgr_detach(ns_interfacemgr_t **targetp) {
|
2000-01-11 21:18:22 +00:00
|
|
|
ns_interfacemgr_t *target = *targetp;
|
2020-02-08 04:37:54 -08:00
|
|
|
*targetp = NULL;
|
2000-01-11 21:18:22 +00:00
|
|
|
REQUIRE(target != NULL);
|
|
|
|
REQUIRE(NS_INTERFACEMGR_VALID(target));
|
2019-05-16 18:43:06 +02:00
|
|
|
if (isc_refcount_decrement(&target->references) == 1) {
|
2000-01-11 21:18:22 +00:00
|
|
|
ns_interfacemgr_destroy(target);
|
2019-05-16 18:43:06 +02:00
|
|
|
}
|
2000-01-11 21:18:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
ns_interfacemgr_shutdown(ns_interfacemgr_t *mgr) {
|
2000-01-11 21:18:22 +00:00
|
|
|
REQUIRE(NS_INTERFACEMGR_VALID(mgr));
|
|
|
|
|
2005-04-27 04:57:32 +00:00
|
|
|
/*%
|
2000-01-11 21:18:22 +00:00
|
|
|
* Shut down and detach all interfaces.
|
|
|
|
* By incrementing the generation count, we make purge_old_interfaces()
|
|
|
|
* consider all interfaces "old".
|
|
|
|
*/
|
|
|
|
mgr->generation++;
|
2019-12-07 23:44:16 +01:00
|
|
|
atomic_store(&mgr->shuttingdown, true);
|
2014-02-07 17:16:37 +11:00
|
|
|
#ifdef USE_ROUTE_SOCKET
|
2014-04-03 19:48:29 -07:00
|
|
|
LOCK(&mgr->lock);
|
|
|
|
if (mgr->route != NULL) {
|
2014-02-07 17:16:37 +11:00
|
|
|
isc_socket_cancel(mgr->route, mgr->task, ISC_SOCKCANCEL_RECV);
|
2014-04-03 19:48:29 -07:00
|
|
|
isc_socket_detach(&mgr->route);
|
|
|
|
isc_task_detach(&mgr->task);
|
|
|
|
}
|
|
|
|
UNLOCK(&mgr->lock);
|
2020-02-13 21:48:23 +01:00
|
|
|
#endif /* ifdef USE_ROUTE_SOCKET */
|
2000-01-11 21:18:22 +00:00
|
|
|
purge_old_interfaces(mgr);
|
|
|
|
}
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
static isc_result_t
|
1999-05-20 12:37:35 +00:00
|
|
|
ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
|
2020-02-13 14:44:37 -08:00
|
|
|
const char *name, ns_interface_t **ifpret) {
|
2000-12-11 19:24:30 +00:00
|
|
|
ns_interface_t *ifp;
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_result_t result;
|
|
|
|
int disp;
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2000-01-11 21:18:22 +00:00
|
|
|
REQUIRE(NS_INTERFACEMGR_VALID(mgr));
|
2011-07-28 11:16:04 +00:00
|
|
|
|
1999-05-20 12:37:35 +00:00
|
|
|
ifp = isc_mem_get(mgr->mctx, sizeof(*ifp));
|
2020-02-12 13:59:18 +01:00
|
|
|
*ifp = (ns_interface_t){ .generation = mgr->generation,
|
|
|
|
.addr = *addr,
|
|
|
|
.dscp = -1 };
|
2011-07-28 11:16:04 +00:00
|
|
|
|
2017-09-14 18:11:56 +10:00
|
|
|
strlcpy(ifp->name, name, sizeof(ifp->name));
|
1999-05-20 12:37:35 +00:00
|
|
|
|
2018-11-16 15:33:22 +01:00
|
|
|
isc_mutex_init(&ifp->lock);
|
2000-01-11 21:18:22 +00:00
|
|
|
|
2019-11-05 15:34:35 -08:00
|
|
|
for (disp = 0; disp < MAX_UDP_DISPATCH; disp++) {
|
2011-07-28 04:04:37 +00:00
|
|
|
ifp->udpdispatch[disp] = NULL;
|
2019-11-05 15:34:35 -08:00
|
|
|
}
|
2011-07-28 11:16:04 +00:00
|
|
|
|
2000-01-17 23:48:15 +00:00
|
|
|
/*
|
|
|
|
* Create a single TCP client object. It will replace itself
|
|
|
|
* with a new one as soon as it gets a connection, so the actual
|
|
|
|
* connections will be handled in parallel even though there is
|
|
|
|
* only one client initially.
|
|
|
|
*/
|
2019-04-17 15:22:27 +02:00
|
|
|
isc_refcount_init(&ifp->ntcpaccepting, 0);
|
|
|
|
isc_refcount_init(&ifp->ntcpactive, 0);
|
2019-02-06 11:27:11 -08:00
|
|
|
|
2000-09-22 00:13:08 +00:00
|
|
|
ISC_LINK_INIT(ifp, link);
|
|
|
|
|
2000-08-01 01:33:37 +00:00
|
|
|
ns_interfacemgr_attach(mgr, &ifp->mgr);
|
2019-07-04 15:45:06 +02:00
|
|
|
LOCK(&mgr->lock);
|
2000-01-11 21:18:22 +00:00
|
|
|
ISC_LIST_APPEND(mgr->interfaces, ifp, link);
|
2019-07-04 15:45:06 +02:00
|
|
|
UNLOCK(&mgr->lock);
|
2000-01-11 21:18:22 +00:00
|
|
|
|
2019-05-16 18:43:06 +02:00
|
|
|
isc_refcount_init(&ifp->references, 1);
|
2000-01-11 21:18:22 +00:00
|
|
|
ifp->magic = IFACE_MAGIC;
|
2019-11-05 15:34:35 -08:00
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
result = ns_clientmgr_create(mgr->mctx, mgr->sctx, mgr->taskmgr,
|
2020-01-28 11:05:07 +01:00
|
|
|
mgr->timermgr, ifp, mgr->ncpus,
|
|
|
|
&ifp->clientmgr);
|
2019-11-05 15:34:35 -08:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
|
|
|
|
"ns_clientmgr_create() failed: %s",
|
|
|
|
isc_result_totext(result));
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
2020-12-07 14:19:10 +02:00
|
|
|
ifp->tcplistensocket = NULL;
|
|
|
|
ifp->http_listensocket = NULL;
|
|
|
|
ifp->http_secure_listensocket = NULL;
|
|
|
|
|
2000-01-11 21:18:22 +00:00
|
|
|
*ifpret = ifp;
|
|
|
|
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
2000-01-11 21:18:22 +00:00
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
failure:
|
2018-11-19 10:31:09 +00:00
|
|
|
isc_mutex_destroy(&ifp->lock);
|
2011-07-28 11:16:04 +00:00
|
|
|
|
2000-01-11 21:18:22 +00:00
|
|
|
ifp->magic = 0;
|
|
|
|
isc_mem_put(mgr->mctx, ifp, sizeof(*ifp));
|
|
|
|
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_UNEXPECTED);
|
2000-01-11 21:18:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
ns_interface_listenudp(ns_interface_t *ifp) {
|
2000-01-11 21:18:22 +00:00
|
|
|
isc_result_t result;
|
2011-07-28 04:04:37 +00:00
|
|
|
|
2019-11-05 15:34:35 -08:00
|
|
|
/* Reserve space for an ns_client_t with the netmgr handle */
|
2020-02-12 13:59:18 +01:00
|
|
|
result = isc_nm_listenudp(ifp->mgr->nm, (isc_nmiface_t *)&ifp->addr,
|
|
|
|
ns__client_request, ifp, sizeof(ns_client_t),
|
2019-11-05 15:34:35 -08:00
|
|
|
&ifp->udplistensocket);
|
2000-01-11 21:18:22 +00:00
|
|
|
return (result);
|
|
|
|
}
|
1999-07-24 01:17:28 +00:00
|
|
|
|
2000-01-11 21:18:22 +00:00
|
|
|
static isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
ns_interface_listentcp(ns_interface_t *ifp) {
|
2000-01-11 21:18:22 +00:00
|
|
|
isc_result_t result;
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
result = isc_nm_listentcpdns(
|
|
|
|
ifp->mgr->nm, (isc_nmiface_t *)&ifp->addr, ns__client_request,
|
2020-06-17 12:09:10 -07:00
|
|
|
ifp, ns__client_tcpconn, ifp, sizeof(ns_client_t),
|
2020-02-12 13:59:18 +01:00
|
|
|
ifp->mgr->backlog, &ifp->mgr->sctx->tcpquota,
|
|
|
|
&ifp->tcplistensocket);
|
2000-01-11 21:18:22 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2000-01-18 22:57:24 +00:00
|
|
|
isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
|
2020-02-12 13:59:18 +01:00
|
|
|
"creating TCP socket: %s",
|
|
|
|
isc_result_totext(result));
|
2000-01-11 21:18:22 +00:00
|
|
|
}
|
2019-11-05 15:34:35 -08:00
|
|
|
|
2019-11-22 18:34:50 -03:00
|
|
|
/*
|
2019-11-25 18:36:14 -03:00
|
|
|
* We call this now to update the tcp-highwater statistic:
|
|
|
|
* this is necessary because we are adding to the TCP quota just
|
|
|
|
* by listening.
|
2019-11-22 18:34:50 -03:00
|
|
|
*/
|
2020-06-17 12:09:10 -07:00
|
|
|
result = ns__client_tcpconn(NULL, ISC_R_SUCCESS, ifp);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
|
|
|
|
"connecting TCP socket: %s",
|
|
|
|
isc_result_totext(result));
|
|
|
|
}
|
2019-11-22 18:34:50 -03:00
|
|
|
|
2019-11-05 15:34:35 -08:00
|
|
|
#if 0
|
2001-11-29 13:14:33 +00:00
|
|
|
#ifndef ISC_ALLOW_MAPPED
|
2020-02-13 21:48:23 +01:00
|
|
|
isc_socket_ipv6only(ifp->tcpsocket,true);
|
|
|
|
#endif /* ifndef ISC_ALLOW_MAPPED */
|
2013-03-22 12:27:54 -07:00
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (ifp->dscp != -1) {
|
|
|
|
isc_socket_dscp(ifp->tcpsocket,ifp->dscp);
|
|
|
|
}
|
2013-03-22 12:27:54 -07:00
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
(void)isc_socket_filter(ifp->tcpsocket,"dataready");
|
|
|
|
#endif /* if 0 */
|
2014-12-18 11:58:50 +05:30
|
|
|
return (result);
|
1999-05-20 12:37:35 +00:00
|
|
|
}
|
|
|
|
|
2020-10-01 13:18:47 +02:00
|
|
|
/*
|
|
|
|
* XXXWPK we should probably pass a complete object with key, cert, and other
|
|
|
|
* TLS related options.
|
|
|
|
*/
|
|
|
|
static isc_result_t
|
2020-12-17 11:40:29 +01:00
|
|
|
ns_interface_listentls(ns_interface_t *ifp, isc_tlsctx_t *sslctx) {
|
2020-10-01 13:18:47 +02:00
|
|
|
isc_result_t result;
|
|
|
|
|
|
|
|
result = isc_nm_listentlsdns(
|
|
|
|
ifp->mgr->nm, (isc_nmiface_t *)&ifp->addr, ns__client_request,
|
|
|
|
ifp, ns__client_tcpconn, ifp, sizeof(ns_client_t),
|
|
|
|
ifp->mgr->backlog, &ifp->mgr->sctx->tcpquota, sslctx,
|
|
|
|
&ifp->tcplistensocket);
|
|
|
|
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
|
|
|
|
"creating TLS socket: %s",
|
|
|
|
isc_result_totext(result));
|
2020-12-17 11:40:29 +01:00
|
|
|
isc_tlsctx_free(&sslctx);
|
2020-10-01 13:18:47 +02:00
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We call this now to update the tcp-highwater statistic:
|
|
|
|
* this is necessary because we are adding to the TCP quota just
|
|
|
|
* by listening.
|
|
|
|
*/
|
|
|
|
result = ns__client_tcpconn(NULL, ISC_R_SUCCESS, ifp);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
|
|
|
|
"updating TCP stats: %s",
|
|
|
|
isc_result_totext(result));
|
|
|
|
}
|
|
|
|
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2020-12-07 14:19:10 +02:00
|
|
|
static isc_result_t
|
|
|
|
ns_interface_listenhttp(ns_interface_t *ifp, isc_tlsctx_t *sslctx, char **eps,
|
|
|
|
size_t neps) {
|
|
|
|
isc_result_t result;
|
|
|
|
isc_nmsocket_t *sock = NULL;
|
|
|
|
size_t i = 0;
|
|
|
|
|
|
|
|
result = isc_nm_listenhttp(ifp->mgr->nm, (isc_nmiface_t *)&ifp->addr,
|
|
|
|
ifp->mgr->backlog, &ifp->mgr->sctx->tcpquota,
|
|
|
|
sslctx, &sock);
|
|
|
|
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
for (i = 0; i < neps; i++) {
|
|
|
|
result = isc_nm_http_add_doh_endpoint(
|
|
|
|
sock, eps[i], ns__client_request, ifp,
|
|
|
|
sizeof(ns_client_t));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
|
|
|
|
"creating %s socket: %s",
|
|
|
|
sslctx ? "HTTPS" : "HTTP",
|
|
|
|
isc_result_totext(result));
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sslctx) {
|
|
|
|
ifp->http_secure_listensocket = sock;
|
|
|
|
} else {
|
|
|
|
ifp->http_listensocket = sock;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We call this now to update the tcp-highwater statistic:
|
|
|
|
* this is necessary because we are adding to the TCP quota just
|
|
|
|
* by listening.
|
|
|
|
*/
|
|
|
|
result = ns__client_tcpconn(NULL, ISC_R_SUCCESS, ifp);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
|
|
|
|
"updating TCP stats: %s",
|
|
|
|
isc_result_totext(result));
|
|
|
|
}
|
|
|
|
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
static isc_result_t
|
2000-01-11 21:18:22 +00:00
|
|
|
ns_interface_setup(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
|
2020-02-12 13:59:18 +01:00
|
|
|
const char *name, ns_interface_t **ifpret, bool accept_tcp,
|
2020-10-01 13:18:47 +02:00
|
|
|
ns_listenelt_t *elt, bool *addr_in_use) {
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_result_t result;
|
2000-01-11 21:18:22 +00:00
|
|
|
ns_interface_t *ifp = NULL;
|
|
|
|
REQUIRE(ifpret != NULL && *ifpret == NULL);
|
2020-03-30 13:49:55 -07:00
|
|
|
REQUIRE(addr_in_use == NULL || !*addr_in_use);
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2000-02-16 19:57:06 +00:00
|
|
|
result = ns_interface_create(mgr, addr, name, &ifp);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2000-01-11 21:18:22 +00:00
|
|
|
return (result);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-05-20 12:37:35 +00:00
|
|
|
|
2020-10-01 13:18:47 +02:00
|
|
|
ifp->dscp = elt->dscp;
|
|
|
|
|
2020-12-07 14:19:10 +02:00
|
|
|
if (elt->is_http) {
|
|
|
|
result = ns_interface_listenhttp(ifp, elt->sslctx,
|
|
|
|
elt->http_endpoints,
|
|
|
|
elt->http_endpoints_number);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
goto cleanup_interface;
|
|
|
|
}
|
|
|
|
*ifpret = ifp;
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2020-10-01 13:18:47 +02:00
|
|
|
if (elt->sslctx != NULL) {
|
|
|
|
result = ns_interface_listentls(ifp, elt->sslctx);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
goto cleanup_interface;
|
|
|
|
}
|
|
|
|
*ifpret = ifp;
|
|
|
|
return (result);
|
|
|
|
}
|
2013-03-22 12:27:54 -07:00
|
|
|
|
2000-01-11 21:18:22 +00:00
|
|
|
result = ns_interface_listenudp(ifp);
|
2014-12-20 00:31:54 -08:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2020-02-13 21:48:23 +01:00
|
|
|
if ((result == ISC_R_ADDRINUSE) && (addr_in_use != NULL)) {
|
2018-04-17 08:29:14 -07:00
|
|
|
*addr_in_use = true;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-01-11 21:18:22 +00:00
|
|
|
goto cleanup_interface;
|
2014-12-20 00:31:54 -08:00
|
|
|
}
|
1999-07-24 01:17:28 +00:00
|
|
|
|
2020-03-30 13:47:58 -07:00
|
|
|
if (((mgr->sctx->options & NS_SERVER_NOTCP) == 0) && accept_tcp) {
|
2019-11-05 15:34:35 -08:00
|
|
|
result = ns_interface_listentcp(ifp);
|
2002-08-30 02:05:30 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2014-12-18 11:58:50 +05:30
|
|
|
if ((result == ISC_R_ADDRINUSE) &&
|
2020-02-13 21:48:23 +01:00
|
|
|
(addr_in_use != NULL)) {
|
2018-04-17 08:29:14 -07:00
|
|
|
*addr_in_use = true;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2014-12-18 11:58:50 +05:30
|
|
|
|
2002-08-30 02:05:30 +00:00
|
|
|
/*
|
|
|
|
* XXXRTH We don't currently have a way to easily stop
|
2004-08-10 04:55:39 +00:00
|
|
|
* dispatch service, so we currently return
|
2002-08-30 02:05:30 +00:00
|
|
|
* ISC_R_SUCCESS (the UDP stuff will work even if TCP
|
|
|
|
* creation failed). This will be fixed later.
|
|
|
|
*/
|
|
|
|
result = ISC_R_SUCCESS;
|
|
|
|
}
|
2000-01-11 21:18:22 +00:00
|
|
|
}
|
|
|
|
*ifpret = ifp;
|
2011-03-11 06:11:27 +00:00
|
|
|
return (result);
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
cleanup_interface:
|
2019-07-04 15:45:06 +02:00
|
|
|
LOCK(&ifp->mgr->lock);
|
2000-08-01 01:33:37 +00:00
|
|
|
ISC_LIST_UNLINK(ifp->mgr->interfaces, ifp, link);
|
2019-07-04 15:45:06 +02:00
|
|
|
UNLOCK(&ifp->mgr->lock);
|
2020-10-09 22:06:41 +02:00
|
|
|
ns_interface_shutdown(ifp);
|
2000-01-11 21:18:22 +00:00
|
|
|
ns_interface_detach(&ifp);
|
|
|
|
return (result);
|
|
|
|
}
|
1999-05-20 12:37:35 +00:00
|
|
|
|
2000-09-22 00:13:08 +00:00
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
ns_interface_shutdown(ns_interface_t *ifp) {
|
2019-11-05 15:34:35 -08:00
|
|
|
if (ifp->udplistensocket != NULL) {
|
2020-03-20 11:55:10 +01:00
|
|
|
isc_nm_stoplistening(ifp->udplistensocket);
|
2020-06-04 14:54:36 -07:00
|
|
|
isc_nmsocket_close(&ifp->udplistensocket);
|
2019-11-05 15:34:35 -08:00
|
|
|
}
|
|
|
|
if (ifp->tcplistensocket != NULL) {
|
2020-03-20 11:55:10 +01:00
|
|
|
isc_nm_stoplistening(ifp->tcplistensocket);
|
2020-06-04 14:54:36 -07:00
|
|
|
isc_nmsocket_close(&ifp->tcplistensocket);
|
2019-11-05 15:34:35 -08:00
|
|
|
}
|
2020-12-07 14:19:10 +02:00
|
|
|
if (ifp->http_listensocket != NULL) {
|
|
|
|
isc_nm_stoplistening(ifp->http_listensocket);
|
|
|
|
isc_nmsocket_close(&ifp->http_listensocket);
|
|
|
|
}
|
|
|
|
if (ifp->http_secure_listensocket != NULL) {
|
|
|
|
isc_nm_stoplistening(ifp->http_secure_listensocket);
|
|
|
|
isc_nmsocket_close(&ifp->http_secure_listensocket);
|
|
|
|
}
|
2019-11-05 15:34:35 -08:00
|
|
|
if (ifp->clientmgr != NULL) {
|
2000-09-22 00:13:08 +00:00
|
|
|
ns_clientmgr_destroy(&ifp->clientmgr);
|
2019-11-05 15:34:35 -08:00
|
|
|
}
|
2000-09-22 00:13:08 +00:00
|
|
|
}
|
|
|
|
|
2000-01-11 21:18:22 +00:00
|
|
|
static void
|
2020-02-13 14:44:37 -08:00
|
|
|
ns_interface_destroy(ns_interface_t *ifp) {
|
2011-07-28 11:16:04 +00:00
|
|
|
REQUIRE(NS_INTERFACE_VALID(ifp));
|
|
|
|
|
2019-07-04 15:45:06 +02:00
|
|
|
isc_mem_t *mctx = ifp->mgr->mctx;
|
2019-09-27 12:11:16 +02:00
|
|
|
|
2000-09-22 00:13:08 +00:00
|
|
|
ns_interface_shutdown(ifp);
|
|
|
|
|
2019-07-04 15:45:06 +02:00
|
|
|
for (int disp = 0; disp < ifp->nudpdispatch; disp++) {
|
2011-07-28 04:04:37 +00:00
|
|
|
if (ifp->udpdispatch[disp] != NULL) {
|
2020-02-12 13:59:18 +01:00
|
|
|
dns_dispatch_changeattributes(
|
|
|
|
ifp->udpdispatch[disp], 0,
|
|
|
|
DNS_DISPATCHATTR_NOLISTEN);
|
2011-07-28 04:04:37 +00:00
|
|
|
dns_dispatch_detach(&(ifp->udpdispatch[disp]));
|
|
|
|
}
|
2019-07-04 15:45:06 +02:00
|
|
|
}
|
2011-07-28 11:16:04 +00:00
|
|
|
|
2019-07-04 15:45:06 +02:00
|
|
|
if (ifp->tcpsocket != NULL) {
|
1999-08-18 00:36:24 +00:00
|
|
|
isc_socket_detach(&ifp->tcpsocket);
|
2019-07-04 15:45:06 +02:00
|
|
|
}
|
1999-05-20 12:37:35 +00:00
|
|
|
|
2018-11-19 10:31:09 +00:00
|
|
|
isc_mutex_destroy(&ifp->lock);
|
2000-01-11 21:18:22 +00:00
|
|
|
|
|
|
|
ns_interfacemgr_detach(&ifp->mgr);
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2019-04-17 15:22:27 +02:00
|
|
|
isc_refcount_destroy(&ifp->ntcpactive);
|
|
|
|
isc_refcount_destroy(&ifp->ntcpaccepting);
|
|
|
|
|
1999-05-23 08:26:43 +00:00
|
|
|
ifp->magic = 0;
|
2019-07-04 15:45:06 +02:00
|
|
|
|
2000-01-11 21:18:22 +00:00
|
|
|
isc_mem_put(mctx, ifp, sizeof(*ifp));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
ns_interface_attach(ns_interface_t *source, ns_interface_t **target) {
|
2000-01-11 21:18:22 +00:00
|
|
|
REQUIRE(NS_INTERFACE_VALID(source));
|
2019-05-16 18:43:06 +02:00
|
|
|
isc_refcount_increment(&source->references);
|
2000-01-11 21:18:22 +00:00
|
|
|
*target = source;
|
|
|
|
}
|
|
|
|
|
2000-08-01 01:33:37 +00:00
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
ns_interface_detach(ns_interface_t **targetp) {
|
2000-01-11 21:18:22 +00:00
|
|
|
ns_interface_t *target = *targetp;
|
2020-02-08 04:37:54 -08:00
|
|
|
*targetp = NULL;
|
2000-01-11 21:18:22 +00:00
|
|
|
REQUIRE(target != NULL);
|
|
|
|
REQUIRE(NS_INTERFACE_VALID(target));
|
2019-05-16 18:43:06 +02:00
|
|
|
if (isc_refcount_decrement(&target->references) == 1) {
|
2000-01-11 21:18:22 +00:00
|
|
|
ns_interface_destroy(target);
|
2019-05-16 18:43:06 +02:00
|
|
|
}
|
1999-05-20 12:37:35 +00:00
|
|
|
}
|
|
|
|
|
2005-04-27 04:57:32 +00:00
|
|
|
/*%
|
1999-05-20 12:37:35 +00:00
|
|
|
* Search the interface list for an interface whose address and port
|
|
|
|
* both match those of 'addr'. Return a pointer to it, or NULL if not found.
|
|
|
|
*/
|
|
|
|
static ns_interface_t *
|
2020-02-13 14:44:37 -08:00
|
|
|
find_matching_interface(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr) {
|
2000-12-11 19:24:30 +00:00
|
|
|
ns_interface_t *ifp;
|
2019-07-04 15:45:06 +02:00
|
|
|
LOCK(&mgr->lock);
|
2000-12-11 19:24:30 +00:00
|
|
|
for (ifp = ISC_LIST_HEAD(mgr->interfaces); ifp != NULL;
|
2020-02-13 14:44:37 -08:00
|
|
|
ifp = ISC_LIST_NEXT(ifp, link))
|
|
|
|
{
|
2019-07-04 15:45:06 +02:00
|
|
|
if (isc_sockaddr_equal(&ifp->addr, addr)) {
|
1999-05-20 12:37:35 +00:00
|
|
|
break;
|
2019-07-04 15:45:06 +02:00
|
|
|
}
|
1999-05-20 12:37:35 +00:00
|
|
|
}
|
2019-07-04 15:45:06 +02:00
|
|
|
UNLOCK(&mgr->lock);
|
2000-12-11 19:24:30 +00:00
|
|
|
return (ifp);
|
1999-05-20 12:37:35 +00:00
|
|
|
}
|
|
|
|
|
2005-04-27 04:57:32 +00:00
|
|
|
/*%
|
1999-05-20 12:37:35 +00:00
|
|
|
* Remove any interfaces whose generation number is not the current one.
|
|
|
|
*/
|
|
|
|
static void
|
2020-02-13 14:44:37 -08:00
|
|
|
purge_old_interfaces(ns_interfacemgr_t *mgr) {
|
2000-12-11 19:24:30 +00:00
|
|
|
ns_interface_t *ifp, *next;
|
2019-07-04 15:45:06 +02:00
|
|
|
LOCK(&mgr->lock);
|
2000-12-11 19:24:30 +00:00
|
|
|
for (ifp = ISC_LIST_HEAD(mgr->interfaces); ifp != NULL; ifp = next) {
|
2000-01-11 21:18:22 +00:00
|
|
|
INSIST(NS_INTERFACE_VALID(ifp));
|
1999-05-20 12:37:35 +00:00
|
|
|
next = ISC_LIST_NEXT(ifp, link);
|
2000-01-11 21:18:22 +00:00
|
|
|
if (ifp->generation != mgr->generation) {
|
2000-02-16 19:57:06 +00:00
|
|
|
char sabuf[256];
|
2000-01-11 21:18:22 +00:00
|
|
|
ISC_LIST_UNLINK(ifp->mgr->interfaces, ifp, link);
|
2000-05-14 20:52:35 +00:00
|
|
|
isc_sockaddr_format(&ifp->addr, sabuf, sizeof(sabuf));
|
2020-02-12 13:59:18 +01:00
|
|
|
isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_INFO,
|
2000-02-16 19:57:06 +00:00
|
|
|
"no longer listening on %s", sabuf);
|
2000-09-22 00:13:08 +00:00
|
|
|
ns_interface_shutdown(ifp);
|
2000-01-11 21:18:22 +00:00
|
|
|
ns_interface_detach(&ifp);
|
1999-05-20 12:37:35 +00:00
|
|
|
}
|
|
|
|
}
|
2019-07-04 15:45:06 +02:00
|
|
|
UNLOCK(&mgr->lock);
|
1999-05-20 12:37:35 +00:00
|
|
|
}
|
|
|
|
|
2000-02-09 22:59:40 +00:00
|
|
|
static isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
clearacl(isc_mem_t *mctx, dns_acl_t **aclp) {
|
|
|
|
dns_acl_t *newacl = NULL;
|
2000-02-09 22:59:40 +00:00
|
|
|
isc_result_t result;
|
2007-09-12 01:09:08 +00:00
|
|
|
result = dns_acl_create(mctx, 0, &newacl);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2000-02-09 22:59:40 +00:00
|
|
|
return (result);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-02-09 22:59:40 +00:00
|
|
|
dns_acl_detach(aclp);
|
|
|
|
dns_acl_attach(newacl, aclp);
|
|
|
|
dns_acl_detach(&newacl);
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
static bool
|
2020-02-13 14:44:37 -08:00
|
|
|
listenon_is_ip6_any(ns_listenelt_t *elt) {
|
2008-07-22 23:47:04 +00:00
|
|
|
REQUIRE(elt && elt->acl);
|
2020-02-13 21:48:23 +01:00
|
|
|
return (dns_acl_isany(elt->acl));
|
2002-08-16 23:46:11 +00:00
|
|
|
}
|
|
|
|
|
2001-10-22 03:31:24 +00:00
|
|
|
static isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
setup_locals(ns_interfacemgr_t *mgr, isc_interface_t *interface) {
|
|
|
|
isc_result_t result;
|
|
|
|
unsigned int prefixlen;
|
2008-07-22 23:47:04 +00:00
|
|
|
isc_netaddr_t *netaddr;
|
|
|
|
|
|
|
|
netaddr = &interface->address;
|
2002-08-30 02:05:30 +00:00
|
|
|
|
2008-07-22 23:47:04 +00:00
|
|
|
/* First add localhost address */
|
2007-09-12 01:09:08 +00:00
|
|
|
prefixlen = (netaddr->family == AF_INET) ? 32 : 128;
|
2020-02-12 13:59:18 +01:00
|
|
|
result = dns_iptable_addprefix(mgr->aclenv.localhost->iptable, netaddr,
|
|
|
|
prefixlen, true);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2002-08-30 02:05:30 +00:00
|
|
|
return (result);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2002-08-30 02:05:30 +00:00
|
|
|
|
2008-07-22 23:47:04 +00:00
|
|
|
/* Then add localnets prefix */
|
2020-02-12 13:59:18 +01:00
|
|
|
result = isc_netaddr_masktoprefixlen(&interface->netmask, &prefixlen);
|
2002-08-30 02:05:30 +00:00
|
|
|
|
2009-01-17 11:04:25 +00:00
|
|
|
/* Non contiguous netmasks not allowed by IPv6 arch. */
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result != ISC_R_SUCCESS && netaddr->family == AF_INET6) {
|
2002-08-30 02:05:30 +00:00
|
|
|
return (result);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2002-08-30 02:05:30 +00:00
|
|
|
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2013-09-26 07:40:34 +10:00
|
|
|
isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING,
|
2002-08-30 02:05:30 +00:00
|
|
|
"omitting IPv4 interface %s from "
|
2020-02-12 13:59:18 +01:00
|
|
|
"localnets ACL: %s",
|
|
|
|
interface->name, isc_result_totext(result));
|
2008-07-22 23:47:04 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
2002-08-30 02:05:30 +00:00
|
|
|
}
|
|
|
|
|
2013-09-26 07:40:34 +10:00
|
|
|
if (prefixlen == 0U) {
|
|
|
|
isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING,
|
|
|
|
"omitting %s interface %s from localnets ACL: "
|
|
|
|
"zero prefix length detected",
|
|
|
|
(netaddr->family == AF_INET) ? "IPv4" : "IPv6",
|
|
|
|
interface->name);
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
result = dns_iptable_addprefix(mgr->aclenv.localnets->iptable, netaddr,
|
|
|
|
prefixlen, true);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2007-09-12 01:09:08 +00:00
|
|
|
return (result);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2007-09-12 01:09:08 +00:00
|
|
|
|
2002-08-30 02:05:30 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2005-02-10 05:53:43 +00:00
|
|
|
static void
|
|
|
|
setup_listenon(ns_interfacemgr_t *mgr, isc_interface_t *interface,
|
2020-02-13 14:44:37 -08:00
|
|
|
in_port_t port) {
|
2005-02-10 05:53:43 +00:00
|
|
|
isc_sockaddr_t *addr;
|
|
|
|
isc_sockaddr_t *old;
|
|
|
|
|
|
|
|
addr = isc_mem_get(mgr->mctx, sizeof(*addr));
|
|
|
|
|
|
|
|
isc_sockaddr_fromnetaddr(addr, &interface->address, port);
|
|
|
|
|
2019-07-04 15:45:06 +02:00
|
|
|
LOCK(&mgr->lock);
|
2020-02-12 13:59:18 +01:00
|
|
|
for (old = ISC_LIST_HEAD(mgr->listenon); old != NULL;
|
2020-02-13 14:44:37 -08:00
|
|
|
old = ISC_LIST_NEXT(old, link))
|
|
|
|
{
|
2019-07-04 15:45:06 +02:00
|
|
|
if (isc_sockaddr_equal(addr, old)) {
|
2008-07-22 23:47:04 +00:00
|
|
|
break;
|
2019-07-04 15:45:06 +02:00
|
|
|
}
|
|
|
|
}
|
2005-02-10 05:53:43 +00:00
|
|
|
|
2019-07-04 15:45:06 +02:00
|
|
|
if (old != NULL) {
|
2005-02-10 05:53:43 +00:00
|
|
|
isc_mem_put(mgr->mctx, addr, sizeof(*addr));
|
2019-07-04 15:45:06 +02:00
|
|
|
} else {
|
2005-02-10 05:53:43 +00:00
|
|
|
ISC_LIST_APPEND(mgr->listenon, addr, link);
|
2019-07-04 15:45:06 +02:00
|
|
|
}
|
|
|
|
UNLOCK(&mgr->lock);
|
2005-02-10 05:53:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2020-02-13 14:44:37 -08:00
|
|
|
clearlistenon(ns_interfacemgr_t *mgr) {
|
2005-02-10 05:53:43 +00:00
|
|
|
isc_sockaddr_t *old;
|
|
|
|
|
2019-07-04 15:45:06 +02:00
|
|
|
LOCK(&mgr->lock);
|
2005-02-10 05:53:43 +00:00
|
|
|
old = ISC_LIST_HEAD(mgr->listenon);
|
|
|
|
while (old != NULL) {
|
|
|
|
ISC_LIST_UNLINK(mgr->listenon, old, link);
|
|
|
|
isc_mem_put(mgr->mctx, old, sizeof(*old));
|
|
|
|
old = ISC_LIST_HEAD(mgr->listenon);
|
|
|
|
}
|
2019-07-04 15:45:06 +02:00
|
|
|
UNLOCK(&mgr->lock);
|
2005-02-10 05:53:43 +00:00
|
|
|
}
|
|
|
|
|
2002-08-30 02:05:30 +00:00
|
|
|
static isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
do_scan(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen, bool verbose) {
|
1999-05-20 12:37:35 +00:00
|
|
|
isc_interfaceiter_t *iter = NULL;
|
2020-02-13 14:44:37 -08:00
|
|
|
bool scan_ipv4 = false;
|
|
|
|
bool scan_ipv6 = false;
|
|
|
|
bool adjusting = false;
|
|
|
|
bool ipv6only = true;
|
|
|
|
bool ipv6pktinfo = true;
|
|
|
|
isc_result_t result;
|
|
|
|
isc_netaddr_t zero_address, zero_address6;
|
|
|
|
ns_listenelt_t *le;
|
|
|
|
isc_sockaddr_t listen_addr;
|
|
|
|
ns_interface_t *ifp;
|
|
|
|
bool log_explicit = false;
|
|
|
|
bool dolistenon;
|
|
|
|
char sabuf[ISC_SOCKADDR_FORMATSIZE];
|
|
|
|
bool tried_listening;
|
|
|
|
bool all_addresses_in_use;
|
2002-08-16 23:46:11 +00:00
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (ext_listen != NULL) {
|
2018-04-17 08:29:14 -07:00
|
|
|
adjusting = true;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2002-08-30 02:05:30 +00:00
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (isc_net_probeipv6() == ISC_R_SUCCESS) {
|
2018-04-17 08:29:14 -07:00
|
|
|
scan_ipv6 = true;
|
2020-02-13 21:48:23 +01:00
|
|
|
} else if ((mgr->sctx->options & NS_SERVER_DISABLE6) == 0) {
|
2002-08-16 23:46:11 +00:00
|
|
|
isc_log_write(IFMGR_COMMON_LOGARGS,
|
|
|
|
verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1),
|
|
|
|
"no IPv6 interfaces found");
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2002-08-16 23:46:11 +00:00
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (isc_net_probeipv4() == ISC_R_SUCCESS) {
|
2018-04-17 08:29:14 -07:00
|
|
|
scan_ipv4 = true;
|
2020-02-13 21:48:23 +01:00
|
|
|
} else if ((mgr->sctx->options & NS_SERVER_DISABLE4) == 0) {
|
2002-08-16 23:46:11 +00:00
|
|
|
isc_log_write(IFMGR_COMMON_LOGARGS,
|
|
|
|
verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1),
|
|
|
|
"no IPv4 interfaces found");
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2002-08-16 23:46:11 +00:00
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
/*
|
|
|
|
* A special, but typical case; listen-on-v6 { any; }.
|
|
|
|
* When we can make the socket IPv6-only, open a single wildcard
|
|
|
|
* socket for IPv6 communication. Otherwise, make separate
|
|
|
|
* socket for each IPv6 address in order to avoid accepting IPv4
|
|
|
|
* packets as the form of mapped addresses unintentionally
|
|
|
|
* unless explicitly allowed.
|
|
|
|
*/
|
2002-10-29 04:40:26 +00:00
|
|
|
#ifndef ISC_ALLOW_MAPPED
|
2020-03-30 13:47:58 -07:00
|
|
|
if (scan_ipv6 && isc_net_probe_ipv6only() != ISC_R_SUCCESS) {
|
2018-04-17 08:29:14 -07:00
|
|
|
ipv6only = false;
|
|
|
|
log_explicit = true;
|
2002-10-29 04:40:26 +00:00
|
|
|
}
|
2020-02-13 21:48:23 +01:00
|
|
|
#endif /* ifndef ISC_ALLOW_MAPPED */
|
2020-03-30 13:47:58 -07:00
|
|
|
if (scan_ipv6 && isc_net_probe_ipv6pktinfo() != ISC_R_SUCCESS) {
|
2018-04-17 08:29:14 -07:00
|
|
|
ipv6pktinfo = false;
|
|
|
|
log_explicit = true;
|
2004-04-29 01:37:14 +00:00
|
|
|
}
|
2020-03-30 13:47:58 -07:00
|
|
|
if (scan_ipv6 && ipv6only && ipv6pktinfo) {
|
2020-02-12 13:59:18 +01:00
|
|
|
for (le = ISC_LIST_HEAD(mgr->listenon6->elts); le != NULL;
|
2020-02-13 14:44:37 -08:00
|
|
|
le = ISC_LIST_NEXT(le, link))
|
|
|
|
{
|
2002-08-17 03:00:49 +00:00
|
|
|
struct in6_addr in6a;
|
2002-08-16 23:46:11 +00:00
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (!listenon_is_ip6_any(le)) {
|
2002-08-17 03:00:49 +00:00
|
|
|
continue;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2002-08-16 23:46:11 +00:00
|
|
|
|
2002-08-17 03:00:49 +00:00
|
|
|
in6a = in6addr_any;
|
|
|
|
isc_sockaddr_fromin6(&listen_addr, &in6a, le->port);
|
|
|
|
|
|
|
|
ifp = find_matching_interface(mgr, &listen_addr);
|
|
|
|
if (ifp != NULL) {
|
|
|
|
ifp->generation = mgr->generation;
|
2020-02-13 21:48:23 +01:00
|
|
|
if (le->dscp != -1 && ifp->dscp == -1) {
|
2013-03-22 12:27:54 -07:00
|
|
|
ifp->dscp = le->dscp;
|
2020-02-13 21:48:23 +01:00
|
|
|
} else if (le->dscp != ifp->dscp) {
|
2020-02-12 13:59:18 +01:00
|
|
|
isc_sockaddr_format(&listen_addr, sabuf,
|
2013-03-22 12:27:54 -07:00
|
|
|
sizeof(sabuf));
|
|
|
|
isc_log_write(IFMGR_COMMON_LOGARGS,
|
|
|
|
ISC_LOG_WARNING,
|
|
|
|
"%s: conflicting DSCP "
|
|
|
|
"values, using %d",
|
|
|
|
sabuf, ifp->dscp);
|
|
|
|
}
|
2002-08-17 03:00:49 +00:00
|
|
|
} else {
|
2002-08-16 23:46:11 +00:00
|
|
|
isc_log_write(IFMGR_COMMON_LOGARGS,
|
2002-08-17 03:00:49 +00:00
|
|
|
ISC_LOG_INFO,
|
|
|
|
"listening on IPv6 "
|
|
|
|
"interfaces, port %u",
|
|
|
|
le->port);
|
|
|
|
result = ns_interface_setup(mgr, &listen_addr,
|
2020-02-12 13:59:18 +01:00
|
|
|
"<any>", &ifp, true,
|
2020-10-01 13:18:47 +02:00
|
|
|
le, NULL);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
2004-04-29 01:37:14 +00:00
|
|
|
ifp->flags |= NS_INTERFACEFLAG_ANYADDR;
|
2020-02-13 21:48:23 +01:00
|
|
|
} else {
|
2002-08-17 03:00:49 +00:00
|
|
|
isc_log_write(IFMGR_COMMON_LOGARGS,
|
|
|
|
ISC_LOG_ERROR,
|
|
|
|
"listening on all IPv6 "
|
|
|
|
"interfaces failed");
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2002-08-17 03:00:49 +00:00
|
|
|
/* Continue. */
|
|
|
|
}
|
2002-08-16 23:46:11 +00:00
|
|
|
}
|
|
|
|
}
|
2001-09-10 23:03:09 +00:00
|
|
|
|
|
|
|
isc_netaddr_any(&zero_address);
|
2002-08-16 23:46:11 +00:00
|
|
|
isc_netaddr_any6(&zero_address6);
|
1999-05-20 12:37:35 +00:00
|
|
|
|
1999-07-24 01:17:28 +00:00
|
|
|
result = isc_interfaceiter_create(mgr->mctx, &iter);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2001-10-22 03:31:24 +00:00
|
|
|
return (result);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-01-20 00:00:00 +00:00
|
|
|
|
2020-03-30 13:49:55 -07:00
|
|
|
if (!adjusting) {
|
2002-08-30 02:05:30 +00:00
|
|
|
result = clearacl(mgr->mctx, &mgr->aclenv.localhost);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2002-08-30 02:05:30 +00:00
|
|
|
goto cleanup_iter;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2002-08-30 02:05:30 +00:00
|
|
|
result = clearacl(mgr->mctx, &mgr->aclenv.localnets);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2002-08-30 02:05:30 +00:00
|
|
|
goto cleanup_iter;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2005-02-10 05:53:43 +00:00
|
|
|
clearlistenon(mgr);
|
2002-08-30 02:05:30 +00:00
|
|
|
}
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
tried_listening = false;
|
|
|
|
all_addresses_in_use = true;
|
2020-02-12 13:59:18 +01:00
|
|
|
for (result = isc_interfaceiter_first(iter); result == ISC_R_SUCCESS;
|
2020-02-13 14:44:37 -08:00
|
|
|
result = isc_interfaceiter_next(iter))
|
|
|
|
{
|
|
|
|
isc_interface_t interface;
|
2002-08-16 23:46:11 +00:00
|
|
|
ns_listenlist_t *ll;
|
2020-02-13 14:44:37 -08:00
|
|
|
unsigned int family;
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-07-24 01:17:28 +00:00
|
|
|
result = isc_interfaceiter_current(iter, &interface);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
1999-07-24 01:17:28 +00:00
|
|
|
break;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-01-13 23:32:41 +00:00
|
|
|
|
2002-08-16 23:46:11 +00:00
|
|
|
family = interface.address.family;
|
2020-02-13 21:48:23 +01:00
|
|
|
if (family != AF_INET && family != AF_INET6) {
|
2002-08-16 23:46:11 +00:00
|
|
|
continue;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2020-03-30 13:49:55 -07:00
|
|
|
if (!scan_ipv4 && family == AF_INET) {
|
2002-08-16 23:46:11 +00:00
|
|
|
continue;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2020-03-30 13:49:55 -07:00
|
|
|
if (!scan_ipv6 && family == AF_INET6) {
|
2000-01-20 00:00:00 +00:00
|
|
|
continue;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-01-20 00:00:00 +00:00
|
|
|
|
2001-09-10 23:03:09 +00:00
|
|
|
/*
|
|
|
|
* Test for the address being nonzero rather than testing
|
|
|
|
* INTERFACE_F_UP, because on some systems the latter
|
|
|
|
* follows the media state and we could end up ignoring
|
|
|
|
* the interface for an entire rescan interval due to
|
|
|
|
* a temporary media glitch at rescan time.
|
|
|
|
*/
|
2002-08-16 23:46:11 +00:00
|
|
|
if (family == AF_INET &&
|
|
|
|
isc_netaddr_equal(&interface.address, &zero_address)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (family == AF_INET6 &&
|
|
|
|
isc_netaddr_equal(&interface.address, &zero_address6)) {
|
2000-02-07 18:47:43 +00:00
|
|
|
continue;
|
2002-08-16 23:46:11 +00:00
|
|
|
}
|
2000-02-07 18:47:43 +00:00
|
|
|
|
2020-03-30 13:49:55 -07:00
|
|
|
if (!adjusting) {
|
2017-10-06 15:13:27 -07:00
|
|
|
/*
|
|
|
|
* If running with -T fixedlocal, then we only
|
|
|
|
* want 127.0.0.1 and ::1 in the localhost ACL.
|
|
|
|
*/
|
2020-02-12 13:59:18 +01:00
|
|
|
if (((mgr->sctx->options & NS_SERVER_FIXEDLOCAL) !=
|
|
|
|
0) &&
|
2020-02-13 14:44:37 -08:00
|
|
|
!isc_netaddr_isloopback(&interface.address))
|
|
|
|
{
|
2017-10-06 15:13:27 -07:00
|
|
|
goto listenon;
|
|
|
|
}
|
|
|
|
|
2002-08-30 02:05:30 +00:00
|
|
|
result = setup_locals(mgr, &interface);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2001-10-12 23:05:58 +00:00
|
|
|
goto ignore_interface;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-10-12 23:05:58 +00:00
|
|
|
}
|
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
listenon:
|
2002-08-16 23:46:11 +00:00
|
|
|
ll = (family == AF_INET) ? mgr->listenon4 : mgr->listenon6;
|
2018-04-17 08:29:14 -07:00
|
|
|
dolistenon = true;
|
2020-02-12 13:59:18 +01:00
|
|
|
for (le = ISC_LIST_HEAD(ll->elts); le != NULL;
|
|
|
|
le = ISC_LIST_NEXT(le, link)) {
|
2020-02-13 14:44:37 -08:00
|
|
|
int match;
|
|
|
|
bool ipv6_wildcard = false;
|
|
|
|
isc_netaddr_t listen_netaddr;
|
2000-02-15 19:53:05 +00:00
|
|
|
isc_sockaddr_t listen_sockaddr;
|
1999-07-24 01:17:28 +00:00
|
|
|
|
2000-01-13 23:32:41 +00:00
|
|
|
/*
|
|
|
|
* Construct a socket address for this IP/port
|
|
|
|
* combination.
|
|
|
|
*/
|
2002-08-16 23:46:11 +00:00
|
|
|
if (family == AF_INET) {
|
|
|
|
isc_netaddr_fromin(&listen_netaddr,
|
|
|
|
&interface.address.type.in);
|
|
|
|
} else {
|
2020-02-12 13:59:18 +01:00
|
|
|
isc_netaddr_fromin6(
|
|
|
|
&listen_netaddr,
|
|
|
|
&interface.address.type.in6);
|
2002-10-24 03:52:35 +00:00
|
|
|
isc_netaddr_setzone(&listen_netaddr,
|
|
|
|
interface.address.zone);
|
2002-08-16 23:46:11 +00:00
|
|
|
}
|
2000-02-15 19:53:05 +00:00
|
|
|
isc_sockaddr_fromnetaddr(&listen_sockaddr,
|
2020-02-12 13:59:18 +01:00
|
|
|
&listen_netaddr, le->port);
|
2000-01-13 23:32:41 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* See if the address matches the listen-on statement;
|
|
|
|
* if not, ignore the interface.
|
|
|
|
*/
|
2018-04-26 20:57:41 -07:00
|
|
|
(void)dns_acl_match(&listen_netaddr, NULL, le->acl,
|
|
|
|
&mgr->aclenv, &match, NULL);
|
|
|
|
if (match <= 0) {
|
2000-01-13 23:32:41 +00:00
|
|
|
continue;
|
2018-04-26 20:57:41 -07:00
|
|
|
}
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2020-03-30 13:49:55 -07:00
|
|
|
if (!adjusting && dolistenon) {
|
2005-02-10 05:53:43 +00:00
|
|
|
setup_listenon(mgr, &interface, le->port);
|
2018-04-17 08:29:14 -07:00
|
|
|
dolistenon = false;
|
2005-02-10 05:53:43 +00:00
|
|
|
}
|
|
|
|
|
2002-08-30 02:05:30 +00:00
|
|
|
/*
|
|
|
|
* The case of "any" IPv6 address will require
|
|
|
|
* special considerations later, so remember it.
|
|
|
|
*/
|
2004-04-29 01:37:14 +00:00
|
|
|
if (family == AF_INET6 && ipv6only && ipv6pktinfo &&
|
2020-02-13 21:48:23 +01:00
|
|
|
listenon_is_ip6_any(le)) {
|
2018-04-17 08:29:14 -07:00
|
|
|
ipv6_wildcard = true;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2002-08-30 02:05:30 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* When adjusting interfaces with extra a listening
|
|
|
|
* list, see if the address matches the extra list.
|
|
|
|
* If it does, and is also covered by a wildcard
|
|
|
|
* interface, we need to listen on the address
|
|
|
|
* explicitly.
|
|
|
|
*/
|
2020-03-30 13:47:58 -07:00
|
|
|
if (adjusting) {
|
2002-08-30 02:05:30 +00:00
|
|
|
ns_listenelt_t *ele;
|
|
|
|
|
|
|
|
match = 0;
|
|
|
|
for (ele = ISC_LIST_HEAD(ext_listen->elts);
|
|
|
|
ele != NULL;
|
2020-02-13 14:44:37 -08:00
|
|
|
ele = ISC_LIST_NEXT(ele, link))
|
|
|
|
{
|
2005-11-30 03:33:49 +00:00
|
|
|
(void)dns_acl_match(&listen_netaddr,
|
|
|
|
NULL, ele->acl,
|
2020-02-12 13:59:18 +01:00
|
|
|
NULL, &match, NULL);
|
2007-02-02 02:18:06 +00:00
|
|
|
if (match > 0 &&
|
|
|
|
(ele->port == le->port ||
|
2020-02-12 13:59:18 +01:00
|
|
|
ele->port == 0)) {
|
2002-08-30 02:05:30 +00:00
|
|
|
break;
|
2018-04-26 20:57:41 -07:00
|
|
|
} else {
|
2002-08-30 02:05:30 +00:00
|
|
|
match = 0;
|
2018-04-26 20:57:41 -07:00
|
|
|
}
|
2002-08-30 02:05:30 +00:00
|
|
|
}
|
2020-03-30 13:47:58 -07:00
|
|
|
if (ipv6_wildcard && match == 0) {
|
2002-08-30 02:05:30 +00:00
|
|
|
continue;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2002-08-30 02:05:30 +00:00
|
|
|
}
|
|
|
|
|
2000-02-15 19:53:05 +00:00
|
|
|
ifp = find_matching_interface(mgr, &listen_sockaddr);
|
2000-01-13 23:32:41 +00:00
|
|
|
if (ifp != NULL) {
|
|
|
|
ifp->generation = mgr->generation;
|
2020-02-13 21:48:23 +01:00
|
|
|
if (le->dscp != -1 && ifp->dscp == -1) {
|
2013-03-22 12:27:54 -07:00
|
|
|
ifp->dscp = le->dscp;
|
2020-02-13 21:48:23 +01:00
|
|
|
} else if (le->dscp != ifp->dscp) {
|
2015-02-10 14:01:38 -08:00
|
|
|
isc_sockaddr_format(&listen_sockaddr,
|
2013-03-22 12:27:54 -07:00
|
|
|
sabuf,
|
|
|
|
sizeof(sabuf));
|
|
|
|
isc_log_write(IFMGR_COMMON_LOGARGS,
|
|
|
|
ISC_LOG_WARNING,
|
|
|
|
"%s: conflicting DSCP "
|
|
|
|
"values, using %d",
|
|
|
|
sabuf, ifp->dscp);
|
|
|
|
}
|
2000-01-13 23:32:41 +00:00
|
|
|
} else {
|
2018-04-17 08:29:14 -07:00
|
|
|
bool addr_in_use = false;
|
2014-12-18 11:58:50 +05:30
|
|
|
|
2020-03-30 13:49:55 -07:00
|
|
|
if (!adjusting && ipv6_wildcard) {
|
2002-08-30 02:05:30 +00:00
|
|
|
continue;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2002-08-30 02:05:30 +00:00
|
|
|
|
2002-10-31 04:08:22 +00:00
|
|
|
if (log_explicit && family == AF_INET6 &&
|
2004-04-29 01:37:14 +00:00
|
|
|
!adjusting && listenon_is_ip6_any(le)) {
|
2020-02-12 13:59:18 +01:00
|
|
|
isc_log_write(
|
|
|
|
IFMGR_COMMON_LOGARGS,
|
|
|
|
verbose ? ISC_LOG_INFO
|
|
|
|
: ISC_LOG_DEBUG(1),
|
|
|
|
"IPv6 socket API is "
|
|
|
|
"incomplete; explicitly "
|
|
|
|
"binding to each IPv6 "
|
|
|
|
"address separately");
|
2018-04-17 08:29:14 -07:00
|
|
|
log_explicit = false;
|
2002-10-31 04:08:22 +00:00
|
|
|
}
|
2020-02-12 13:59:18 +01:00
|
|
|
isc_sockaddr_format(&listen_sockaddr, sabuf,
|
|
|
|
sizeof(sabuf));
|
|
|
|
isc_log_write(
|
|
|
|
IFMGR_COMMON_LOGARGS, ISC_LOG_INFO,
|
|
|
|
"%s"
|
|
|
|
"listening on %s interface "
|
|
|
|
"%s, %s",
|
2020-03-30 13:47:58 -07:00
|
|
|
(adjusting) ? "additionally " : "",
|
2020-02-12 13:59:18 +01:00
|
|
|
(family == AF_INET) ? "IPv4" : "IPv6",
|
|
|
|
interface.name, sabuf);
|
|
|
|
|
|
|
|
result = ns_interface_setup(
|
|
|
|
mgr, &listen_sockaddr, interface.name,
|
2020-10-01 13:18:47 +02:00
|
|
|
&ifp, (adjusting) ? false : true, le,
|
|
|
|
&addr_in_use);
|
2014-12-18 11:58:50 +05:30
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
tried_listening = true;
|
2020-02-13 21:48:23 +01:00
|
|
|
if (!addr_in_use) {
|
2018-04-17 08:29:14 -07:00
|
|
|
all_addresses_in_use = false;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2002-08-30 02:05:30 +00:00
|
|
|
|
2000-04-06 22:03:35 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2000-01-18 22:57:24 +00:00
|
|
|
isc_log_write(IFMGR_COMMON_LOGARGS,
|
2002-08-16 23:46:11 +00:00
|
|
|
ISC_LOG_ERROR,
|
|
|
|
"creating %s interface "
|
|
|
|
"%s failed; interface "
|
|
|
|
"ignored",
|
2020-02-12 13:59:18 +01:00
|
|
|
(family == AF_INET) ? "IP"
|
|
|
|
"v4"
|
|
|
|
: "IP"
|
|
|
|
"v"
|
|
|
|
"6",
|
2002-08-16 23:46:11 +00:00
|
|
|
interface.name);
|
2000-01-13 23:32:41 +00:00
|
|
|
}
|
2000-01-11 21:18:22 +00:00
|
|
|
/* Continue. */
|
1999-05-20 12:37:35 +00:00
|
|
|
}
|
|
|
|
}
|
2000-02-09 22:59:40 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
ignore_interface:
|
2020-02-12 13:59:18 +01:00
|
|
|
isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
|
2002-08-16 23:46:11 +00:00
|
|
|
"ignoring %s interface %s: %s",
|
|
|
|
(family == AF_INET) ? "IPv4" : "IPv6",
|
2000-02-09 22:59:40 +00:00
|
|
|
interface.name, isc_result_totext(result));
|
|
|
|
continue;
|
1999-05-20 12:37:35 +00:00
|
|
|
}
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result != ISC_R_NOMORE) {
|
1999-07-24 01:17:28 +00:00
|
|
|
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
2002-08-16 23:46:11 +00:00
|
|
|
"interface iteration failed: %s",
|
1999-07-24 01:17:28 +00:00
|
|
|
isc_result_totext(result));
|
2020-02-13 21:48:23 +01:00
|
|
|
} else {
|
2020-02-12 13:59:18 +01:00
|
|
|
result = ((tried_listening && all_addresses_in_use)
|
|
|
|
? ISC_R_ADDRINUSE
|
|
|
|
: ISC_R_SUCCESS);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2020-02-12 13:59:18 +01:00
|
|
|
cleanup_iter:
|
1999-05-20 12:37:35 +00:00
|
|
|
isc_interfaceiter_destroy(&iter);
|
2001-10-22 03:31:24 +00:00
|
|
|
return (result);
|
1999-07-24 01:17:28 +00:00
|
|
|
}
|
|
|
|
|
2014-12-18 11:58:50 +05:30
|
|
|
static isc_result_t
|
2002-08-30 02:05:30 +00:00
|
|
|
ns_interfacemgr_scan0(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen,
|
2020-02-13 14:44:37 -08:00
|
|
|
bool verbose) {
|
2014-12-18 11:58:50 +05:30
|
|
|
isc_result_t result;
|
2020-02-13 14:44:37 -08:00
|
|
|
bool purge = true;
|
1999-08-18 00:36:24 +00:00
|
|
|
|
2000-01-11 21:18:22 +00:00
|
|
|
REQUIRE(NS_INTERFACEMGR_VALID(mgr));
|
1999-07-24 01:17:28 +00:00
|
|
|
|
2020-02-12 13:59:18 +01:00
|
|
|
mgr->generation++; /* Increment the generation count. */
|
1999-07-24 01:17:28 +00:00
|
|
|
|
2014-12-18 11:58:50 +05:30
|
|
|
result = do_scan(mgr, ext_listen, verbose);
|
2020-02-13 21:48:23 +01:00
|
|
|
if ((result != ISC_R_SUCCESS) && (result != ISC_R_ADDRINUSE)) {
|
2018-04-17 08:29:14 -07:00
|
|
|
purge = false;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-05-20 12:37:35 +00:00
|
|
|
|
2000-12-11 19:24:30 +00:00
|
|
|
/*
|
|
|
|
* Now go through the interface list and delete anything that
|
|
|
|
* does not have the current generation number. This is
|
|
|
|
* how we catch interfaces that go away or change their
|
|
|
|
* addresses.
|
1999-05-20 12:37:35 +00:00
|
|
|
*/
|
2020-02-13 21:48:23 +01:00
|
|
|
if (purge) {
|
2001-10-22 03:31:24 +00:00
|
|
|
purge_old_interfaces(mgr);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-05-20 12:37:35 +00:00
|
|
|
|
2001-06-15 23:18:04 +00:00
|
|
|
/*
|
2017-09-08 13:39:09 -07:00
|
|
|
* Warn if we are not listening on any interface.
|
2001-06-15 23:18:04 +00:00
|
|
|
*/
|
2020-02-12 13:59:18 +01:00
|
|
|
if (ext_listen == NULL && ISC_LIST_EMPTY(mgr->interfaces)) {
|
2000-01-18 22:57:24 +00:00
|
|
|
isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING,
|
1999-10-23 00:02:23 +00:00
|
|
|
"not listening on any interfaces");
|
2002-08-30 02:05:30 +00:00
|
|
|
}
|
2014-12-18 11:58:50 +05:30
|
|
|
|
|
|
|
return (result);
|
2002-08-30 02:05:30 +00:00
|
|
|
}
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
bool
|
2020-02-13 14:44:37 -08:00
|
|
|
ns_interfacemgr_islistening(ns_interfacemgr_t *mgr) {
|
2014-12-18 11:58:50 +05:30
|
|
|
REQUIRE(NS_INTERFACEMGR_VALID(mgr));
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
return (ISC_LIST_EMPTY(mgr->interfaces) ? false : true);
|
2014-12-18 11:58:50 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
2020-02-13 14:44:37 -08:00
|
|
|
ns_interfacemgr_scan(ns_interfacemgr_t *mgr, bool verbose) {
|
2017-09-08 13:39:09 -07:00
|
|
|
isc_result_t result;
|
2020-02-13 14:44:37 -08:00
|
|
|
bool unlock = false;
|
2017-09-08 13:39:09 -07:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Check for success because we may already be task-exclusive
|
|
|
|
* at this point. Only if we succeed at obtaining an exclusive
|
|
|
|
* lock now will we need to relinquish it later.
|
|
|
|
*/
|
|
|
|
result = isc_task_beginexclusive(mgr->excl);
|
2020-02-13 21:48:23 +01:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
2018-04-17 08:29:14 -07:00
|
|
|
unlock = true;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2017-09-08 13:39:09 -07:00
|
|
|
|
|
|
|
result = ns_interfacemgr_scan0(mgr, NULL, verbose);
|
|
|
|
|
2020-02-13 21:48:23 +01:00
|
|
|
if (unlock) {
|
2017-09-08 13:39:09 -07:00
|
|
|
isc_task_endexclusive(mgr->excl);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2017-09-08 13:39:09 -07:00
|
|
|
|
|
|
|
return (result);
|
2002-08-30 02:05:30 +00:00
|
|
|
}
|
|
|
|
|
2014-12-18 11:58:50 +05:30
|
|
|
isc_result_t
|
2002-08-30 02:05:30 +00:00
|
|
|
ns_interfacemgr_adjust(ns_interfacemgr_t *mgr, ns_listenlist_t *list,
|
2020-02-13 14:44:37 -08:00
|
|
|
bool verbose) {
|
2014-12-18 11:58:50 +05:30
|
|
|
return (ns_interfacemgr_scan0(mgr, list, verbose));
|
1999-05-20 12:37:35 +00:00
|
|
|
}
|
2000-01-13 23:32:41 +00:00
|
|
|
|
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
ns_interfacemgr_setlistenon4(ns_interfacemgr_t *mgr, ns_listenlist_t *value) {
|
2017-09-08 13:39:09 -07:00
|
|
|
REQUIRE(NS_INTERFACEMGR_VALID(mgr));
|
|
|
|
|
2000-06-05 19:10:13 +00:00
|
|
|
LOCK(&mgr->lock);
|
|
|
|
ns_listenlist_detach(&mgr->listenon4);
|
|
|
|
ns_listenlist_attach(value, &mgr->listenon4);
|
|
|
|
UNLOCK(&mgr->lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
ns_interfacemgr_setlistenon6(ns_interfacemgr_t *mgr, ns_listenlist_t *value) {
|
2017-09-08 13:39:09 -07:00
|
|
|
REQUIRE(NS_INTERFACEMGR_VALID(mgr));
|
|
|
|
|
2000-01-13 23:32:41 +00:00
|
|
|
LOCK(&mgr->lock);
|
2000-06-05 19:10:13 +00:00
|
|
|
ns_listenlist_detach(&mgr->listenon6);
|
|
|
|
ns_listenlist_attach(value, &mgr->listenon6);
|
2000-01-13 23:32:41 +00:00
|
|
|
UNLOCK(&mgr->lock);
|
|
|
|
}
|
2002-09-10 04:45:54 +00:00
|
|
|
|
|
|
|
void
|
2020-02-13 14:44:37 -08:00
|
|
|
ns_interfacemgr_dumprecursing(FILE *f, ns_interfacemgr_t *mgr) {
|
2002-09-10 04:45:54 +00:00
|
|
|
ns_interface_t *interface;
|
|
|
|
|
2017-09-08 13:39:09 -07:00
|
|
|
REQUIRE(NS_INTERFACEMGR_VALID(mgr));
|
|
|
|
|
2002-09-10 04:45:54 +00:00
|
|
|
LOCK(&mgr->lock);
|
|
|
|
interface = ISC_LIST_HEAD(mgr->interfaces);
|
|
|
|
while (interface != NULL) {
|
2020-02-13 21:48:23 +01:00
|
|
|
if (interface->clientmgr != NULL) {
|
2002-09-10 04:45:54 +00:00
|
|
|
ns_client_dumprecursing(f, interface->clientmgr);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2002-09-10 04:45:54 +00:00
|
|
|
interface = ISC_LIST_NEXT(interface, link);
|
|
|
|
}
|
|
|
|
UNLOCK(&mgr->lock);
|
|
|
|
}
|
2005-02-10 05:53:43 +00:00
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
bool
|
2020-02-13 14:44:37 -08:00
|
|
|
ns_interfacemgr_listeningon(ns_interfacemgr_t *mgr,
|
|
|
|
const isc_sockaddr_t *addr) {
|
2005-02-10 05:53:43 +00:00
|
|
|
isc_sockaddr_t *old;
|
2020-02-13 14:44:37 -08:00
|
|
|
bool result = false;
|
2005-02-10 05:53:43 +00:00
|
|
|
|
2017-09-08 13:39:09 -07:00
|
|
|
REQUIRE(NS_INTERFACEMGR_VALID(mgr));
|
2019-12-07 23:44:16 +01:00
|
|
|
/*
|
|
|
|
* If the manager is shutting down it's safer to
|
|
|
|
* return true.
|
|
|
|
*/
|
|
|
|
if (atomic_load(&mgr->shuttingdown)) {
|
|
|
|
return (true);
|
|
|
|
}
|
2019-07-04 15:45:06 +02:00
|
|
|
LOCK(&mgr->lock);
|
2020-02-12 13:59:18 +01:00
|
|
|
for (old = ISC_LIST_HEAD(mgr->listenon); old != NULL;
|
2020-02-13 14:44:37 -08:00
|
|
|
old = ISC_LIST_NEXT(old, link))
|
|
|
|
{
|
2019-07-04 15:45:06 +02:00
|
|
|
if (isc_sockaddr_equal(old, addr)) {
|
|
|
|
result = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
UNLOCK(&mgr->lock);
|
|
|
|
|
|
|
|
return (result);
|
2005-02-10 05:53:43 +00:00
|
|
|
}
|
2017-09-08 13:39:09 -07:00
|
|
|
|
2020-06-17 12:09:10 -07:00
|
|
|
ns_server_t *
|
|
|
|
ns_interfacemgr_getserver(ns_interfacemgr_t *mgr) {
|
|
|
|
REQUIRE(NS_INTERFACEMGR_VALID(mgr));
|
|
|
|
|
|
|
|
return (mgr->sctx);
|
|
|
|
}
|
|
|
|
|
2017-09-08 13:39:09 -07:00
|
|
|
ns_interface_t *
|
2020-02-13 14:44:37 -08:00
|
|
|
ns__interfacemgr_getif(ns_interfacemgr_t *mgr) {
|
2019-07-04 15:45:06 +02:00
|
|
|
ns_interface_t *head;
|
2017-09-08 13:39:09 -07:00
|
|
|
REQUIRE(NS_INTERFACEMGR_VALID(mgr));
|
2019-07-04 15:45:06 +02:00
|
|
|
LOCK(&mgr->lock);
|
|
|
|
head = ISC_LIST_HEAD(mgr->interfaces);
|
|
|
|
UNLOCK(&mgr->lock);
|
|
|
|
return (head);
|
2017-09-08 13:39:09 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
ns_interface_t *
|
2020-02-13 14:44:37 -08:00
|
|
|
ns__interfacemgr_nextif(ns_interface_t *ifp) {
|
2019-07-04 15:45:06 +02:00
|
|
|
ns_interface_t *next;
|
|
|
|
LOCK(&ifp->lock);
|
|
|
|
next = ISC_LIST_NEXT(ifp, link);
|
|
|
|
UNLOCK(&ifp->lock);
|
|
|
|
return (next);
|
2017-09-08 13:39:09 -07:00
|
|
|
}
|