]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
rewrite interfacemgr to use netmgr route sockets
authorEvan Hunt <each@isc.org>
Sun, 3 Oct 2021 00:17:54 +0000 (17:17 -0700)
committerEvan Hunt <each@isc.org>
Fri, 15 Oct 2021 08:01:25 +0000 (01:01 -0700)
lib/ns/include/ns/events.h
lib/ns/interfacemgr.c

index b8da178b05e0c75aabb0d9b3c07ca498070b575e..4c5b7bba68ffbb1781704b5b9ef1e726a7983a80 100644 (file)
@@ -20,3 +20,4 @@
 
 #define NS_EVENT_CLIENTCONTROL (ISC_EVENTCLASS_NS + 0)
 #define NS_EVENT_HOOKASYNCDONE (ISC_EVENTCLASS_NS + 1)
+#define NS_EVENT_IFSCAN               (ISC_EVENTCLASS_NS + 2)
index 9673902b61eb629626d596dda0c935d74285f735..8e286e23f79eb05abcde475119acaf90daf07685 100644 (file)
 #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 */
 #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) {
+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;
+       }
+
+       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(sevent->result));
+                                     isc_result_totext(eresult));
                }
-               ns_interfacemgr_detach(&mgr);
-               isc_event_free(&event);
+               isc_nmhandle_detach(&mgr->route);
                return;
        }
 
-       rtm = (struct MSGHDR *)mgr->buf;
+       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);
-       }
-       if (mgr->task != NULL) {
-               isc_task_detach(&mgr->task);
+               isc_nmhandle_detach(&mgr->route);
        }
-#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);
 }