#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) \
*/
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
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,
"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 */
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:
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,
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);
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;
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);
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);
*/
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);
}