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 {
|
2021-05-22 18:12:11 +02:00
|
|
|
unsigned int magic; /*%< Magic number */
|
2020-02-13 14:44:37 -08:00
|
|
|
isc_refcount_t references;
|
|
|
|
isc_mutex_t lock;
|
2021-05-22 18:12:11 +02:00
|
|
|
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 */
|
|
|
|
int ncpus; /*%< Number of workers */
|
2020-02-12 13:59:18 +01:00
|
|
|
dns_dispatchmgr_t *dispatchmgr;
|
2021-05-22 18:12:11 +02:00
|
|
|
unsigned int generation; /*%< Current generation no */
|
2020-02-13 14:44:37 -08:00
|
|
|
ns_listenlist_t *listenon4;
|
|
|
|
ns_listenlist_t *listenon6;
|
2021-05-22 18:12:11 +02:00
|
|
|
dns_aclenv_t *aclenv; /*%< Localhost/localnets ACLs */
|
|
|
|
ISC_LIST(ns_interface_t) interfaces; /*%< List of interfaces */
|
2005-02-10 05:53:43 +00:00
|
|
|
ISC_LIST(isc_sockaddr_t) listenon;
|
2021-05-22 18:12:11 +02:00
|
|
|
int backlog; /*%< Listen queue size */
|
|
|
|
unsigned int udpdisp; /*%< UDP dispatch count */
|
|
|
|
atomic_bool shuttingdown; /*%< Interfacemgr shutting down */
|
|
|
|
ns_clientmgr_t **clientmgrs; /*%< Client managers */
|
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) {
|
2021-05-22 18:12:11 +02:00
|
|
|
goto cleanup_sctx;
|
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
|
|
|
|
2021-05-22 18:12:11 +02:00
|
|
|
result = dns_aclenv_create(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)
|
2021-05-22 18:12:11 +02: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
|
|
|
|
2021-05-22 18:12:11 +02:00
|
|
|
mgr->clientmgrs = isc_mem_get(mgr->mctx,
|
2021-05-26 10:01:30 +02:00
|
|
|
mgr->ncpus * sizeof(mgr->clientmgrs[0]));
|
2021-05-22 18:12:11 +02:00
|
|
|
for (size_t i = 0; i < (size_t)mgr->ncpus; i++) {
|
|
|
|
result = ns_clientmgr_create(mgr->sctx, mgr->taskmgr,
|
|
|
|
mgr->timermgr, mgr->aclenv, (int)i,
|
|
|
|
&mgr->clientmgrs[i]);
|
|
|
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
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:
|
2021-05-22 18:12:11 +02:00
|
|
|
dns_aclenv_detach(&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);
|
2021-05-22 18:12:11 +02:00
|
|
|
cleanup_sctx:
|
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 */
|
2021-05-22 18:12:11 +02:00
|
|
|
dns_aclenv_detach(&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);
|
2021-05-22 18:12:11 +02:00
|
|
|
for (size_t i = 0; i < (size_t)mgr->ncpus; i++) {
|
|
|
|
ns_clientmgr_destroy(&mgr->clientmgrs[i]);
|
|
|
|
}
|
|
|
|
isc_mem_put(mgr->mctx, mgr->clientmgrs,
|
2021-05-26 10:01:30 +02:00
|
|
|
mgr->ncpus * sizeof(mgr->clientmgrs[0]));
|
2021-05-22 18:12:11 +02:00
|
|
|
|
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));
|
|
|
|
|
2021-05-22 18:12:11 +02:00
|
|
|
return (mgr->aclenv);
|
2000-02-09 22:59:40 +00:00
|
|
|
}
|
|
|
|
|
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
|
|
|
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-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
|
|
|
}
|
|
|
|
|
|
|
|
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 */
|
2021-05-26 08:15:34 +02:00
|
|
|
result = isc_nm_listenudp(ifp->mgr->nm, &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(
|
2021-05-26 08:15:34 +02:00
|
|
|
ifp->mgr->nm, &ifp->addr, ns__client_request, ifp,
|
|
|
|
ns__client_tcpconn, ifp, sizeof(ns_client_t), 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(
|
2021-05-26 08:15:34 +02:00
|
|
|
ifp->mgr->nm, &ifp->addr, ns__client_request, ifp,
|
|
|
|
ns__client_tcpconn, ifp, sizeof(ns_client_t), ifp->mgr->backlog,
|
|
|
|
&ifp->mgr->sctx->tcpquota, sslctx, &ifp->tcplistensocket);
|
2020-10-01 13:18:47 +02:00
|
|
|
|
|
|
|
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,
|
Add (http-)listener-clients option (DoH quota mechanism)
This commit adds support for http-listener-clients global options as
well as ability to override the default in an HTTP server description,
like:
http local-http-server {
...
listener-clients 100;
...
};
This way we have ability to specify per-listener active connections
quota globally and then override it when required. This is exactly
what AT&T requested us: they wanted a functionality to specify quota
globally and then override it for specific IPs. This change
functionality makes such a configuration possible.
It makes sense: for example, one could have different quotas for
internal and external clients. Or, for example, one could use BIND's
internal ability to serve encrypted DoH with some sane quota value for
internal clients, while having un-encrypted DoH listener without quota
to put BIND behind a load balancer doing TLS offloading for external
clients.
Moreover, the code no more shares the quota with TCP, which makes
little sense anyway (see tcp-clients option), because of the nature of
interaction of DoH clients: they tend to keep idle opened connections
for longer periods of time, preventing the TCP and TLS client from
being served. Thus, the need to have a separate, generally larger,
quota for them.
Also, the change makes any option within "http <name> { ... };"
statement optional, making it easier to override only required default
options.
By default, the DoH connections are limited to 300 per listener. I
hope that it is a good initial guesstimate.
2021-05-14 14:18:57 +03:00
|
|
|
size_t neps, isc_quota_t *quota) {
|
2021-04-21 13:52:15 +02:00
|
|
|
#if HAVE_LIBNGHTTP2
|
2020-12-07 14:19:10 +02:00
|
|
|
isc_result_t result;
|
|
|
|
isc_nmsocket_t *sock = NULL;
|
|
|
|
|
2021-05-26 08:15:34 +02:00
|
|
|
result = isc_nm_listenhttp(ifp->mgr->nm, &ifp->addr, ifp->mgr->backlog,
|
Add (http-)listener-clients option (DoH quota mechanism)
This commit adds support for http-listener-clients global options as
well as ability to override the default in an HTTP server description,
like:
http local-http-server {
...
listener-clients 100;
...
};
This way we have ability to specify per-listener active connections
quota globally and then override it when required. This is exactly
what AT&T requested us: they wanted a functionality to specify quota
globally and then override it for specific IPs. This change
functionality makes such a configuration possible.
It makes sense: for example, one could have different quotas for
internal and external clients. Or, for example, one could use BIND's
internal ability to serve encrypted DoH with some sane quota value for
internal clients, while having un-encrypted DoH listener without quota
to put BIND behind a load balancer doing TLS offloading for external
clients.
Moreover, the code no more shares the quota with TCP, which makes
little sense anyway (see tcp-clients option), because of the nature of
interaction of DoH clients: they tend to keep idle opened connections
for longer periods of time, preventing the TCP and TLS client from
being served. Thus, the need to have a separate, generally larger,
quota for them.
Also, the change makes any option within "http <name> { ... };"
statement optional, making it easier to override only required default
options.
By default, the DoH connections are limited to 300 per listener. I
hope that it is a good initial guesstimate.
2021-05-14 14:18:57 +03:00
|
|
|
quota, sslctx, &sock);
|
2020-12-07 14:19:10 +02:00
|
|
|
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
2021-05-26 08:15:34 +02:00
|
|
|
for (size_t i = 0; i < neps; i++) {
|
2021-05-19 18:03:11 +03:00
|
|
|
INSIST(isc_nm_http_path_isvalid(eps[i]));
|
refactor outgoing HTTP connection support
- style, cleanup, and removal of unnecessary code.
- combined isc_nm_http_add_endpoint() and isc_nm_http_add_doh_endpoint()
into one function, renamed isc_http_endpoint().
- moved isc_nm_http_connect_send_request() into doh_test.c as a helper
function; remove it from the public API.
- renamed isc_http2 and isc_nm_http2 types and functions to just isc_http
and isc_nm_http, for consistency with other existing names.
- shortened a number of long names.
- the caller is now responsible for determining the peer address.
in isc_nm_httpconnect(); this eliminates the need to parse the URI
and the dependency on an external resolver.
- the caller is also now responsible for creating the SSL client context,
for consistency with isc_nm_tlsdnsconnect().
- added setter functions for HTTP/2 ALPN. instead of setting up ALPN in
isc_tlsctx_createclient(), we now have a function
isc_tlsctx_enable_http2client_alpn() that can be run from
isc_nm_httpconnect().
- refactored isc_nm_httprequest() into separate read and send functions.
isc_nm_send() or isc_nm_read() is called on an http socket, it will
be stored until a corresponding isc_nm_read() or _send() arrives; when
we have both halves of the pair the HTTP request will be initiated.
- isc_nm_httprequest() is renamed isc__nm_http_request() for use as an
internal helper function by the DoH unit test. (eventually doh_test
should be rewritten to use read and send, and this function should
be removed.)
- added implementations of isc__nm_tls_settimeout() and
isc__nm_http_settimeout().
- increased NGHTTP2 header block length for client connections to 128K.
- use isc_mem_t for internal memory allocations inside nghttp2, to
help track memory leaks.
- send "Cache-Control" header in requests and responses. (note:
currently we try to bypass HTTP caching proxies, but ideally we should
interact with them: https://tools.ietf.org/html/rfc8484#section-5.1)
2021-02-03 16:59:49 -08:00
|
|
|
result = isc_nm_http_endpoint(sock, eps[i],
|
|
|
|
ns__client_request, ifp,
|
|
|
|
sizeof(ns_client_t));
|
2020-12-07 14:19:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
2021-04-21 13:52:15 +02:00
|
|
|
#else
|
|
|
|
UNUSED(ifp);
|
|
|
|
UNUSED(sslctx);
|
|
|
|
UNUSED(eps);
|
|
|
|
UNUSED(neps);
|
|
|
|
return (ISC_R_NOTIMPLEMENTED);
|
|
|
|
#endif
|
2020-12-07 14:19:10 +02:00
|
|
|
}
|
|
|
|
|
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) {
|
Add (http-)listener-clients option (DoH quota mechanism)
This commit adds support for http-listener-clients global options as
well as ability to override the default in an HTTP server description,
like:
http local-http-server {
...
listener-clients 100;
...
};
This way we have ability to specify per-listener active connections
quota globally and then override it when required. This is exactly
what AT&T requested us: they wanted a functionality to specify quota
globally and then override it for specific IPs. This change
functionality makes such a configuration possible.
It makes sense: for example, one could have different quotas for
internal and external clients. Or, for example, one could use BIND's
internal ability to serve encrypted DoH with some sane quota value for
internal clients, while having un-encrypted DoH listener without quota
to put BIND behind a load balancer doing TLS offloading for external
clients.
Moreover, the code no more shares the quota with TCP, which makes
little sense anyway (see tcp-clients option), because of the nature of
interaction of DoH clients: they tend to keep idle opened connections
for longer periods of time, preventing the TCP and TLS client from
being served. Thus, the need to have a separate, generally larger,
quota for them.
Also, the change makes any option within "http <name> { ... };"
statement optional, making it easier to override only required default
options.
By default, the DoH connections are limited to 300 per listener. I
hope that it is a good initial guesstimate.
2021-05-14 14:18:57 +03:00
|
|
|
result = ns_interface_listenhttp(
|
|
|
|
ifp, elt->sslctx, elt->http_endpoints,
|
|
|
|
elt->http_endpoints_number, elt->http_quota);
|
2020-12-07 14:19:10 +02:00
|
|
|
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);
|
|
|
|
}
|
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;
|
2021-05-22 18:12:11 +02:00
|
|
|
result = dns_iptable_addprefix(mgr->aclenv->localhost->iptable, netaddr,
|
2020-02-12 13:59:18 +01:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2021-05-22 18:12:11 +02:00
|
|
|
result = dns_iptable_addprefix(mgr->aclenv->localnets->iptable, netaddr,
|
2020-02-12 13:59:18 +01:00
|
|
|
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) {
|
2021-05-22 18:12:11 +02: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
|
|
|
}
|
2021-05-22 18:12:11 +02: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,
|
2021-05-22 18:12:11 +02:00
|
|
|
mgr->aclenv, &match, NULL);
|
2018-04-26 20:57:41 -07:00
|
|
|
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) {
|
2017-09-08 13:39:09 -07:00
|
|
|
REQUIRE(NS_INTERFACEMGR_VALID(mgr));
|
|
|
|
|
2002-09-10 04:45:54 +00:00
|
|
|
LOCK(&mgr->lock);
|
2021-05-22 18:12:11 +02:00
|
|
|
for (size_t i = 0; i < (size_t)mgr->ncpus; i++) {
|
|
|
|
ns_client_dumprecursing(f, mgr->clientmgrs[i]);
|
2002-09-10 04:45:54 +00:00
|
|
|
}
|
|
|
|
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
|
|
|
}
|
2021-05-22 18:12:11 +02:00
|
|
|
|
|
|
|
ns_clientmgr_t *
|
|
|
|
ns_interfacemgr_getclientmgr(ns_interfacemgr_t *mgr) {
|
|
|
|
int tid = isc_nm_tid();
|
|
|
|
|
|
|
|
REQUIRE(NS_INTERFACEMGR_VALID(mgr));
|
|
|
|
REQUIRE(tid >= 0);
|
|
|
|
REQUIRE(tid < mgr->ncpus);
|
|
|
|
|
|
|
|
return (mgr->clientmgrs[tid]);
|
|
|
|
}
|