2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-31 14:35:26 +00:00

rewrite interfacemgr to use netmgr route sockets

This commit is contained in:
Evan Hunt
2021-10-02 17:17:54 -07:00
parent 075139f60e
commit 68e8b19ddc
2 changed files with 77 additions and 113 deletions

View File

@@ -33,10 +33,8 @@
#ifdef HAVE_NET_ROUTE_H
#include <net/route.h>
#if defined(RTM_VERSION) && defined(RTM_NEWADDR) && defined(RTM_DELADDR)
#define USE_ROUTE_SOCKET 1
#define ROUTE_SOCKET_PROTOCOL PF_ROUTE
#define MSGHDR rt_msghdr
#define MSGTYPE rtm_type
#define MSGHDR rt_msghdr
#define MSGTYPE rtm_type
#endif /* if defined(RTM_VERSION) && defined(RTM_NEWADDR) && \
* defined(RTM_DELADDR) */
#endif /* ifdef HAVE_NET_ROUTE_H */
@@ -45,10 +43,8 @@
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#if defined(RTM_NEWADDR) && defined(RTM_DELADDR)
#define USE_ROUTE_SOCKET 1
#define ROUTE_SOCKET_PROTOCOL PF_NETLINK
#define MSGHDR nlmsghdr
#define MSGTYPE nlmsg_type
#define MSGHDR nlmsghdr
#define MSGTYPE nlmsg_type
#endif /* if defined(RTM_NEWADDR) && defined(RTM_DELADDR) */
#endif /* if defined(HAVE_LINUX_NETLINK_H) && defined(HAVE_LINUX_RTNETLINK_H) \
*/
@@ -88,11 +84,7 @@ struct ns_interfacemgr {
int backlog; /*%< Listen queue size */
atomic_bool shuttingdown; /*%< Interfacemgr shutting down */
ns_clientmgr_t **clientmgrs; /*%< Client managers */
#ifdef USE_ROUTE_SOCKET
isc_task_t *task;
isc_socket_t *route;
unsigned char buf[2048];
#endif /* ifdef USE_ROUTE_SOCKET */
isc_nmhandle_t *route;
};
static void
@@ -101,35 +93,42 @@ purge_old_interfaces(ns_interfacemgr_t *mgr);
static void
clearlistenon(ns_interfacemgr_t *mgr);
#ifdef USE_ROUTE_SOCKET
static void
route_event(isc_task_t *task, isc_event_t *event) {
isc_socketevent_t *sevent = NULL;
ns_interfacemgr_t *mgr = NULL;
isc_region_t r;
isc_result_t result;
struct MSGHDR *rtm;
bool done = true;
scan_event(isc_task_t *task, isc_event_t *event) {
ns_interfacemgr_t *mgr = (ns_interfacemgr_t *)event->ev_arg;
UNUSED(task);
REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE);
mgr = event->ev_arg;
sevent = (isc_socketevent_t *)event;
ns_interfacemgr_scan(mgr, false);
isc_event_free(&event);
}
if (sevent->result != ISC_R_SUCCESS) {
if (sevent->result != ISC_R_CANCELED) {
isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
"automatic interface scanning "
"terminated: %s",
isc_result_totext(sevent->result));
}
ns_interfacemgr_detach(&mgr);
isc_event_free(&event);
static void
route_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
void *arg) {
ns_interfacemgr_t *mgr = (ns_interfacemgr_t *)arg;
struct MSGHDR *rtm = NULL;
bool done = true;
isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_DEBUG(3), "route_recv: %s",
isc_result_totext(eresult));
if (handle == NULL) {
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
if (rtm->rtm_version != RTM_VERSION) {
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) "
"recompile required",
rtm->rtm_version, RTM_VERSION);
ns_interfacemgr_detach(&mgr);
isc_event_free(&event);
isc_nmhandle_detach(&mgr->route);
return;
}
#endif /* ifdef RTM_VERSION */
@@ -147,7 +145,11 @@ route_event(isc_task_t *task, isc_event_t *event) {
case RTM_NEWADDR:
case RTM_DELADDR:
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;
default:
@@ -156,26 +158,33 @@ route_event(isc_task_t *task, isc_event_t *event) {
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);
if (result == ISC_R_SUCCESS) {
done = false;
}
isc_nm_read(handle, route_recv, mgr);
done = false;
}
UNLOCK(&mgr->lock);
if (done) {
ns_interfacemgr_detach(&mgr);
isc_nmhandle_detach(&mgr->route);
}
isc_event_free(&event);
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
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,
ns_interfacemgr_t **mgrp) {
isc_result_t result;
ns_interfacemgr_t *mgr;
ns_interfacemgr_t *mgr = NULL;
#ifndef USE_ROUTE_SOCKET
UNUSED(task);
#endif /* ifndef USE_ROUTE_SOCKET */
REQUIRE(mctx != NULL);
REQUIRE(mgrp != NULL);
REQUIRE(*mgrp == NULL);
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);
mgr->sctx = NULL;
ns_server_attach(sctx, &mgr->sctx);
isc_mutex_init(&mgr->lock);
mgr->excl = NULL;
result = isc_taskmgr_excltask(taskmgr, &mgr->excl);
if (result != ISC_R_SUCCESS) {
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);
ISC_LIST_INIT(mgr->interfaces);
@@ -244,28 +245,14 @@ ns_interfacemgr_create(isc_mem_t *mctx, ns_server_t *sctx,
UNUSED(geoip);
#endif /* if defined(HAVE_GEOIP2) */
#ifdef USE_ROUTE_SOCKET
mgr->route = NULL;
result = isc_socket_create(mgr->socketmgr, ROUTE_SOCKET_PROTOCOL,
isc_sockettype_raw, &mgr->route);
switch (result) {
case ISC_R_NOPERM:
case ISC_R_SUCCESS:
case ISC_R_NOTIMPLEMENTED:
case ISC_R_FAMILYNOSUPPORT:
break;
default:
goto cleanup_aclenv;
result = isc_nm_routeconnect(nm, route_connected, mgr, 0);
if (result != ISC_R_SUCCESS) {
isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_INFO,
"unable to open route socket: %s",
isc_result_totext(result));
}
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);
#endif /* ifdef USE_ROUTE_SOCKET */
mgr->magic = IFMGR_MAGIC;
*mgrp = mgr;
@@ -278,25 +265,8 @@ ns_interfacemgr_create(isc_mem_t *mctx, ns_server_t *sctx,
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);
#ifdef USE_ROUTE_SOCKET
cleanup_aclenv:
dns_aclenv_detach(&mgr->aclenv);
#endif /* ifdef USE_ROUTE_SOCKET */
cleanup_listenon:
ns_listenlist_detach(&mgr->listenon4);
ns_listenlist_detach(&mgr->listenon6);
@@ -314,14 +284,9 @@ ns_interfacemgr_destroy(ns_interfacemgr_t *mgr) {
isc_refcount_destroy(&mgr->references);
#ifdef USE_ROUTE_SOCKET
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);
ns_listenlist_detach(&mgr->listenon4);
ns_listenlist_detach(&mgr->listenon6);
@@ -387,15 +352,13 @@ ns_interfacemgr_shutdown(ns_interfacemgr_t *mgr) {
*/
mgr->generation++;
atomic_store(&mgr->shuttingdown, true);
#ifdef USE_ROUTE_SOCKET
LOCK(&mgr->lock);
if (mgr->route != NULL) {
isc_socket_cancel(mgr->route, mgr->task, ISC_SOCKCANCEL_RECV);
isc_socket_detach(&mgr->route);
isc_task_detach(&mgr->task);
isc_nmhandle_detach(&mgr->route);
}
UNLOCK(&mgr->lock);
#endif /* ifdef USE_ROUTE_SOCKET */
purge_old_interfaces(mgr);
}