mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-09-01 06:55:30 +00:00
rewrite interfacemgr to use netmgr route sockets
This commit is contained in:
@@ -20,3 +20,4 @@
|
|||||||
|
|
||||||
#define NS_EVENT_CLIENTCONTROL (ISC_EVENTCLASS_NS + 0)
|
#define NS_EVENT_CLIENTCONTROL (ISC_EVENTCLASS_NS + 0)
|
||||||
#define NS_EVENT_HOOKASYNCDONE (ISC_EVENTCLASS_NS + 1)
|
#define NS_EVENT_HOOKASYNCDONE (ISC_EVENTCLASS_NS + 1)
|
||||||
|
#define NS_EVENT_IFSCAN (ISC_EVENTCLASS_NS + 2)
|
||||||
|
@@ -33,10 +33,8 @@
|
|||||||
#ifdef HAVE_NET_ROUTE_H
|
#ifdef HAVE_NET_ROUTE_H
|
||||||
#include <net/route.h>
|
#include <net/route.h>
|
||||||
#if defined(RTM_VERSION) && defined(RTM_NEWADDR) && defined(RTM_DELADDR)
|
#if defined(RTM_VERSION) && defined(RTM_NEWADDR) && defined(RTM_DELADDR)
|
||||||
#define USE_ROUTE_SOCKET 1
|
#define MSGHDR rt_msghdr
|
||||||
#define ROUTE_SOCKET_PROTOCOL PF_ROUTE
|
#define MSGTYPE rtm_type
|
||||||
#define MSGHDR rt_msghdr
|
|
||||||
#define MSGTYPE rtm_type
|
|
||||||
#endif /* if defined(RTM_VERSION) && defined(RTM_NEWADDR) && \
|
#endif /* if defined(RTM_VERSION) && defined(RTM_NEWADDR) && \
|
||||||
* defined(RTM_DELADDR) */
|
* defined(RTM_DELADDR) */
|
||||||
#endif /* ifdef HAVE_NET_ROUTE_H */
|
#endif /* ifdef HAVE_NET_ROUTE_H */
|
||||||
@@ -45,10 +43,8 @@
|
|||||||
#include <linux/netlink.h>
|
#include <linux/netlink.h>
|
||||||
#include <linux/rtnetlink.h>
|
#include <linux/rtnetlink.h>
|
||||||
#if defined(RTM_NEWADDR) && defined(RTM_DELADDR)
|
#if defined(RTM_NEWADDR) && defined(RTM_DELADDR)
|
||||||
#define USE_ROUTE_SOCKET 1
|
#define MSGHDR nlmsghdr
|
||||||
#define ROUTE_SOCKET_PROTOCOL PF_NETLINK
|
#define MSGTYPE nlmsg_type
|
||||||
#define MSGHDR nlmsghdr
|
|
||||||
#define MSGTYPE nlmsg_type
|
|
||||||
#endif /* if defined(RTM_NEWADDR) && defined(RTM_DELADDR) */
|
#endif /* if defined(RTM_NEWADDR) && defined(RTM_DELADDR) */
|
||||||
#endif /* if defined(HAVE_LINUX_NETLINK_H) && defined(HAVE_LINUX_RTNETLINK_H) \
|
#endif /* if defined(HAVE_LINUX_NETLINK_H) && defined(HAVE_LINUX_RTNETLINK_H) \
|
||||||
*/
|
*/
|
||||||
@@ -88,11 +84,7 @@ struct ns_interfacemgr {
|
|||||||
int backlog; /*%< Listen queue size */
|
int backlog; /*%< Listen queue size */
|
||||||
atomic_bool shuttingdown; /*%< Interfacemgr shutting down */
|
atomic_bool shuttingdown; /*%< Interfacemgr shutting down */
|
||||||
ns_clientmgr_t **clientmgrs; /*%< Client managers */
|
ns_clientmgr_t **clientmgrs; /*%< Client managers */
|
||||||
#ifdef USE_ROUTE_SOCKET
|
isc_nmhandle_t *route;
|
||||||
isc_task_t *task;
|
|
||||||
isc_socket_t *route;
|
|
||||||
unsigned char buf[2048];
|
|
||||||
#endif /* ifdef USE_ROUTE_SOCKET */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -101,35 +93,42 @@ purge_old_interfaces(ns_interfacemgr_t *mgr);
|
|||||||
static void
|
static void
|
||||||
clearlistenon(ns_interfacemgr_t *mgr);
|
clearlistenon(ns_interfacemgr_t *mgr);
|
||||||
|
|
||||||
#ifdef USE_ROUTE_SOCKET
|
|
||||||
static void
|
static void
|
||||||
route_event(isc_task_t *task, isc_event_t *event) {
|
scan_event(isc_task_t *task, isc_event_t *event) {
|
||||||
isc_socketevent_t *sevent = NULL;
|
ns_interfacemgr_t *mgr = (ns_interfacemgr_t *)event->ev_arg;
|
||||||
ns_interfacemgr_t *mgr = NULL;
|
|
||||||
isc_region_t r;
|
|
||||||
isc_result_t result;
|
|
||||||
struct MSGHDR *rtm;
|
|
||||||
bool done = true;
|
|
||||||
|
|
||||||
UNUSED(task);
|
UNUSED(task);
|
||||||
|
|
||||||
REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE);
|
ns_interfacemgr_scan(mgr, false);
|
||||||
mgr = event->ev_arg;
|
isc_event_free(&event);
|
||||||
sevent = (isc_socketevent_t *)event;
|
}
|
||||||
|
|
||||||
if (sevent->result != ISC_R_SUCCESS) {
|
static void
|
||||||
if (sevent->result != ISC_R_CANCELED) {
|
route_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
|
||||||
isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
|
void *arg) {
|
||||||
"automatic interface scanning "
|
ns_interfacemgr_t *mgr = (ns_interfacemgr_t *)arg;
|
||||||
"terminated: %s",
|
struct MSGHDR *rtm = NULL;
|
||||||
isc_result_totext(sevent->result));
|
bool done = true;
|
||||||
}
|
|
||||||
ns_interfacemgr_detach(&mgr);
|
isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_DEBUG(3), "route_recv: %s",
|
||||||
isc_event_free(&event);
|
isc_result_totext(eresult));
|
||||||
|
|
||||||
|
if (handle == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
rtm = (struct MSGHDR *)mgr->buf;
|
if (eresult != ISC_R_SUCCESS) {
|
||||||
|
if (eresult != ISC_R_CANCELED) {
|
||||||
|
isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
|
||||||
|
"automatic interface scanning "
|
||||||
|
"terminated: %s",
|
||||||
|
isc_result_totext(eresult));
|
||||||
|
}
|
||||||
|
isc_nmhandle_detach(&mgr->route);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rtm = (struct MSGHDR *)region->base;
|
||||||
#ifdef RTM_VERSION
|
#ifdef RTM_VERSION
|
||||||
if (rtm->rtm_version != RTM_VERSION) {
|
if (rtm->rtm_version != RTM_VERSION) {
|
||||||
isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
|
isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
|
||||||
@@ -137,8 +136,7 @@ route_event(isc_task_t *task, isc_event_t *event) {
|
|||||||
"rtm->rtm_version mismatch (%u != %u) "
|
"rtm->rtm_version mismatch (%u != %u) "
|
||||||
"recompile required",
|
"recompile required",
|
||||||
rtm->rtm_version, RTM_VERSION);
|
rtm->rtm_version, RTM_VERSION);
|
||||||
ns_interfacemgr_detach(&mgr);
|
isc_nmhandle_detach(&mgr->route);
|
||||||
isc_event_free(&event);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif /* ifdef RTM_VERSION */
|
#endif /* ifdef RTM_VERSION */
|
||||||
@@ -147,7 +145,11 @@ route_event(isc_task_t *task, isc_event_t *event) {
|
|||||||
case RTM_NEWADDR:
|
case RTM_NEWADDR:
|
||||||
case RTM_DELADDR:
|
case RTM_DELADDR:
|
||||||
if (mgr->route != NULL && mgr->sctx->interface_auto) {
|
if (mgr->route != NULL && mgr->sctx->interface_auto) {
|
||||||
ns_interfacemgr_scan(mgr, false);
|
isc_event_t *event = NULL;
|
||||||
|
event = isc_event_allocate(mgr->mctx, mgr,
|
||||||
|
NS_EVENT_IFSCAN, scan_event,
|
||||||
|
mgr, sizeof(*event));
|
||||||
|
isc_task_send(mgr->excl, &event);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -156,26 +158,33 @@ route_event(isc_task_t *task, isc_event_t *event) {
|
|||||||
|
|
||||||
LOCK(&mgr->lock);
|
LOCK(&mgr->lock);
|
||||||
if (mgr->route != NULL) {
|
if (mgr->route != NULL) {
|
||||||
/*
|
isc_nm_read(handle, route_recv, mgr);
|
||||||
* Look for next route event.
|
done = false;
|
||||||
*/
|
|
||||||
r.base = mgr->buf;
|
|
||||||
r.length = sizeof(mgr->buf);
|
|
||||||
result = isc_socket_recv(mgr->route, &r, 1, mgr->task,
|
|
||||||
route_event, mgr);
|
|
||||||
if (result == ISC_R_SUCCESS) {
|
|
||||||
done = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
UNLOCK(&mgr->lock);
|
UNLOCK(&mgr->lock);
|
||||||
|
|
||||||
if (done) {
|
if (done) {
|
||||||
ns_interfacemgr_detach(&mgr);
|
isc_nmhandle_detach(&mgr->route);
|
||||||
}
|
}
|
||||||
isc_event_free(&event);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif /* ifdef USE_ROUTE_SOCKET */
|
|
||||||
|
static void
|
||||||
|
route_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) {
|
||||||
|
ns_interfacemgr_t *mgr = (ns_interfacemgr_t *)arg;
|
||||||
|
|
||||||
|
isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_DEBUG(3),
|
||||||
|
"route_connected: %s", isc_result_totext(eresult));
|
||||||
|
|
||||||
|
if (eresult != ISC_R_SUCCESS) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
INSIST(mgr->route == NULL);
|
||||||
|
|
||||||
|
isc_nmhandle_attach(handle, &mgr->route);
|
||||||
|
isc_nm_read(handle, route_recv, mgr);
|
||||||
|
}
|
||||||
|
|
||||||
isc_result_t
|
isc_result_t
|
||||||
ns_interfacemgr_create(isc_mem_t *mctx, ns_server_t *sctx,
|
ns_interfacemgr_create(isc_mem_t *mctx, ns_server_t *sctx,
|
||||||
@@ -185,41 +194,33 @@ ns_interfacemgr_create(isc_mem_t *mctx, ns_server_t *sctx,
|
|||||||
dns_geoip_databases_t *geoip, int ncpus,
|
dns_geoip_databases_t *geoip, int ncpus,
|
||||||
ns_interfacemgr_t **mgrp) {
|
ns_interfacemgr_t **mgrp) {
|
||||||
isc_result_t result;
|
isc_result_t result;
|
||||||
ns_interfacemgr_t *mgr;
|
ns_interfacemgr_t *mgr = NULL;
|
||||||
|
|
||||||
#ifndef USE_ROUTE_SOCKET
|
|
||||||
UNUSED(task);
|
UNUSED(task);
|
||||||
#endif /* ifndef USE_ROUTE_SOCKET */
|
|
||||||
|
|
||||||
REQUIRE(mctx != NULL);
|
REQUIRE(mctx != NULL);
|
||||||
REQUIRE(mgrp != NULL);
|
REQUIRE(mgrp != NULL);
|
||||||
REQUIRE(*mgrp == NULL);
|
REQUIRE(*mgrp == NULL);
|
||||||
|
|
||||||
mgr = isc_mem_get(mctx, sizeof(*mgr));
|
mgr = isc_mem_get(mctx, sizeof(*mgr));
|
||||||
|
*mgr = (ns_interfacemgr_t){ .taskmgr = taskmgr,
|
||||||
|
.timermgr = timermgr,
|
||||||
|
.socketmgr = socketmgr,
|
||||||
|
.nm = nm,
|
||||||
|
.dispatchmgr = dispatchmgr,
|
||||||
|
.generation = 1,
|
||||||
|
.ncpus = ncpus };
|
||||||
|
|
||||||
mgr->mctx = NULL;
|
|
||||||
isc_mem_attach(mctx, &mgr->mctx);
|
isc_mem_attach(mctx, &mgr->mctx);
|
||||||
|
|
||||||
mgr->sctx = NULL;
|
|
||||||
ns_server_attach(sctx, &mgr->sctx);
|
ns_server_attach(sctx, &mgr->sctx);
|
||||||
|
|
||||||
isc_mutex_init(&mgr->lock);
|
isc_mutex_init(&mgr->lock);
|
||||||
|
|
||||||
mgr->excl = NULL;
|
|
||||||
result = isc_taskmgr_excltask(taskmgr, &mgr->excl);
|
result = isc_taskmgr_excltask(taskmgr, &mgr->excl);
|
||||||
if (result != ISC_R_SUCCESS) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
goto cleanup_lock;
|
goto cleanup_lock;
|
||||||
}
|
}
|
||||||
|
|
||||||
mgr->taskmgr = taskmgr;
|
|
||||||
mgr->timermgr = timermgr;
|
|
||||||
mgr->socketmgr = socketmgr;
|
|
||||||
mgr->nm = nm;
|
|
||||||
mgr->dispatchmgr = dispatchmgr;
|
|
||||||
mgr->generation = 1;
|
|
||||||
mgr->listenon4 = NULL;
|
|
||||||
mgr->listenon6 = NULL;
|
|
||||||
mgr->ncpus = ncpus;
|
|
||||||
atomic_init(&mgr->shuttingdown, false);
|
atomic_init(&mgr->shuttingdown, false);
|
||||||
|
|
||||||
ISC_LIST_INIT(mgr->interfaces);
|
ISC_LIST_INIT(mgr->interfaces);
|
||||||
@@ -244,28 +245,14 @@ ns_interfacemgr_create(isc_mem_t *mctx, ns_server_t *sctx,
|
|||||||
UNUSED(geoip);
|
UNUSED(geoip);
|
||||||
#endif /* if defined(HAVE_GEOIP2) */
|
#endif /* if defined(HAVE_GEOIP2) */
|
||||||
|
|
||||||
#ifdef USE_ROUTE_SOCKET
|
result = isc_nm_routeconnect(nm, route_connected, mgr, 0);
|
||||||
mgr->route = NULL;
|
if (result != ISC_R_SUCCESS) {
|
||||||
result = isc_socket_create(mgr->socketmgr, ROUTE_SOCKET_PROTOCOL,
|
isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_INFO,
|
||||||
isc_sockettype_raw, &mgr->route);
|
"unable to open route socket: %s",
|
||||||
switch (result) {
|
isc_result_totext(result));
|
||||||
case ISC_R_NOPERM:
|
|
||||||
case ISC_R_SUCCESS:
|
|
||||||
case ISC_R_NOTIMPLEMENTED:
|
|
||||||
case ISC_R_FAMILYNOSUPPORT:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
goto cleanup_aclenv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mgr->task = NULL;
|
|
||||||
if (mgr->route != NULL) {
|
|
||||||
isc_task_attach(task, &mgr->task);
|
|
||||||
}
|
|
||||||
isc_refcount_init(&mgr->references, (mgr->route != NULL) ? 2 : 1);
|
|
||||||
#else /* ifdef USE_ROUTE_SOCKET */
|
|
||||||
isc_refcount_init(&mgr->references, 1);
|
isc_refcount_init(&mgr->references, 1);
|
||||||
#endif /* ifdef USE_ROUTE_SOCKET */
|
|
||||||
mgr->magic = IFMGR_MAGIC;
|
mgr->magic = IFMGR_MAGIC;
|
||||||
*mgrp = mgr;
|
*mgrp = mgr;
|
||||||
|
|
||||||
@@ -278,25 +265,8 @@ ns_interfacemgr_create(isc_mem_t *mctx, ns_server_t *sctx,
|
|||||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
#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);
|
|
||||||
if (result != ISC_R_SUCCESS) {
|
|
||||||
isc_task_detach(&mgr->task);
|
|
||||||
isc_socket_detach(&mgr->route);
|
|
||||||
ns_interfacemgr_detach(&mgr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* ifdef USE_ROUTE_SOCKET */
|
|
||||||
return (ISC_R_SUCCESS);
|
return (ISC_R_SUCCESS);
|
||||||
|
|
||||||
#ifdef USE_ROUTE_SOCKET
|
|
||||||
cleanup_aclenv:
|
|
||||||
dns_aclenv_detach(&mgr->aclenv);
|
|
||||||
#endif /* ifdef USE_ROUTE_SOCKET */
|
|
||||||
cleanup_listenon:
|
cleanup_listenon:
|
||||||
ns_listenlist_detach(&mgr->listenon4);
|
ns_listenlist_detach(&mgr->listenon4);
|
||||||
ns_listenlist_detach(&mgr->listenon6);
|
ns_listenlist_detach(&mgr->listenon6);
|
||||||
@@ -314,14 +284,9 @@ ns_interfacemgr_destroy(ns_interfacemgr_t *mgr) {
|
|||||||
|
|
||||||
isc_refcount_destroy(&mgr->references);
|
isc_refcount_destroy(&mgr->references);
|
||||||
|
|
||||||
#ifdef USE_ROUTE_SOCKET
|
|
||||||
if (mgr->route != NULL) {
|
if (mgr->route != NULL) {
|
||||||
isc_socket_detach(&mgr->route);
|
isc_nmhandle_detach(&mgr->route);
|
||||||
}
|
}
|
||||||
if (mgr->task != NULL) {
|
|
||||||
isc_task_detach(&mgr->task);
|
|
||||||
}
|
|
||||||
#endif /* ifdef USE_ROUTE_SOCKET */
|
|
||||||
dns_aclenv_detach(&mgr->aclenv);
|
dns_aclenv_detach(&mgr->aclenv);
|
||||||
ns_listenlist_detach(&mgr->listenon4);
|
ns_listenlist_detach(&mgr->listenon4);
|
||||||
ns_listenlist_detach(&mgr->listenon6);
|
ns_listenlist_detach(&mgr->listenon6);
|
||||||
@@ -387,15 +352,13 @@ ns_interfacemgr_shutdown(ns_interfacemgr_t *mgr) {
|
|||||||
*/
|
*/
|
||||||
mgr->generation++;
|
mgr->generation++;
|
||||||
atomic_store(&mgr->shuttingdown, true);
|
atomic_store(&mgr->shuttingdown, true);
|
||||||
#ifdef USE_ROUTE_SOCKET
|
|
||||||
LOCK(&mgr->lock);
|
LOCK(&mgr->lock);
|
||||||
if (mgr->route != NULL) {
|
if (mgr->route != NULL) {
|
||||||
isc_socket_cancel(mgr->route, mgr->task, ISC_SOCKCANCEL_RECV);
|
isc_nmhandle_detach(&mgr->route);
|
||||||
isc_socket_detach(&mgr->route);
|
|
||||||
isc_task_detach(&mgr->task);
|
|
||||||
}
|
}
|
||||||
UNLOCK(&mgr->lock);
|
UNLOCK(&mgr->lock);
|
||||||
#endif /* ifdef USE_ROUTE_SOCKET */
|
|
||||||
purge_old_interfaces(mgr);
|
purge_old_interfaces(mgr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user