From: Mark Andrews Date: Sun, 9 Feb 2014 22:46:54 +0000 (+1100) Subject: Add Linux support to: X-Git-Tag: v9.10.0b1~138 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=850b5e80930907e4747347201dc41e4d04e036f8;p=thirdparty%2Fbind9.git Add Linux support to: 3733. [func] Improve interface scanning support. Interface information will be automatically updated if the OS supports routing sockets (MacOS, *BSD, Linux). Use "automatic-interface-scan no;" to disable. Add "rndc scan" to trigger a scan. [RT #23027] --- diff --git a/CHANGES b/CHANGES index 9a243740ff8..e06ed87a438 100644 --- a/CHANGES +++ b/CHANGES @@ -1,7 +1,7 @@ 3733. [func] Improve interface scanning support. Interface information will be automatically updated if the - OS supports routing sockets. Use - "automatic-interface-scan no;" to disable. + OS supports routing sockets (MacOS, *BSD, Linux). + Use "automatic-interface-scan no;" to disable. Add "rndc scan" to trigger a scan. [RT #23027] diff --git a/bin/named/interfacemgr.c b/bin/named/interfacemgr.c index 435200662f7..2dece8e6332 100644 --- a/bin/named/interfacemgr.c +++ b/bin/named/interfacemgr.c @@ -39,6 +39,20 @@ #include #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 +#endif +#endif + +#if defined(HAVE_LINUX_NETLINK_H) && defined(HAVE_LINUX_RTNETLINK_H) +#include +#include +#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 #endif #endif @@ -83,7 +97,7 @@ route_event(isc_task_t *task, isc_event_t *event) { ns_interfacemgr_t *mgr = NULL; isc_region_t r; isc_result_t result; - struct rt_msghdr *rtm; + struct MSGHDR *rtm; UNUSED(task); @@ -102,7 +116,8 @@ route_event(isc_task_t *task, isc_event_t *event) { return; } - rtm = (struct rt_msghdr *)mgr->buf; + rtm = (struct MSGHDR *)mgr->buf; +#ifdef RTM_VERSION if (rtm->rtm_version != RTM_VERSION) { isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, "automatic interface rescanning disabled: " @@ -115,8 +130,9 @@ route_event(isc_task_t *task, isc_event_t *event) { isc_event_free(&event); return; } +#endif - switch (rtm->rtm_type) { + switch (rtm->MSGTYPE) { case RTM_NEWADDR: case RTM_DELADDR: if (ns_g_server->interface_auto) @@ -190,12 +206,13 @@ ns_interfacemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, #ifdef USE_ROUTE_SOCKET mgr->route = NULL; - result = isc_socket_create(mgr->socketmgr, PF_ROUTE, + 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; diff --git a/config.h.in b/config.h.in index 06db5d4af1c..285d9299ae0 100644 --- a/config.h.in +++ b/config.h.in @@ -287,6 +287,12 @@ int sigwait(const unsigned int *set, int *sig); /* Define to 1 if you have the header file. */ #undef HAVE_LINUX_CAPABILITY_H +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_NETLINK_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_RTNETLINK_H + /* Define to 1 if you have the header file. */ #undef HAVE_LINUX_TYPES_H diff --git a/configure b/configure index 5dd7fa6aeb5..4bcde81f8d9 100755 --- a/configure +++ b/configure @@ -12544,7 +12544,7 @@ $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi -for ac_header in fcntl.h regex.h sys/time.h unistd.h sys/mman.h sys/sockio.h sys/select.h sys/param.h sys/sysctl.h net/if6.h sys/socket.h net/route.h +for ac_header in fcntl.h regex.h sys/time.h unistd.h sys/mman.h sys/sockio.h sys/select.h sys/param.h sys/sysctl.h net/if6.h sys/socket.h net/route.h linux/netlink.h linux/rtnetlink.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default diff --git a/configure.in b/configure.in index 18653e4e8e8..bc7826be463 100644 --- a/configure.in +++ b/configure.in @@ -366,7 +366,7 @@ fi AC_HEADER_STDC -AC_CHECK_HEADERS(fcntl.h regex.h sys/time.h unistd.h sys/mman.h sys/sockio.h sys/select.h sys/param.h sys/sysctl.h net/if6.h sys/socket.h net/route.h,,, +AC_CHECK_HEADERS(fcntl.h regex.h sys/time.h unistd.h sys/mman.h sys/sockio.h sys/select.h sys/param.h sys/sysctl.h net/if6.h sys/socket.h net/route.h linux/netlink.h linux/rtnetlink.h,,, [$ac_includes_default #ifdef HAVE_SYS_PARAM_H # include diff --git a/lib/isc/unix/socket.c b/lib/isc/unix/socket.c index 0b39e04156b..b0ef546465c 100644 --- a/lib/isc/unix/socket.c +++ b/lib/isc/unix/socket.c @@ -28,6 +28,11 @@ #include #include +#if defined(HAVE_LINUX_NETLINK_H) && defined(HAVE_LINUX_RTNETLINK_H) +#include +#include +#endif + #include #include #include @@ -2477,10 +2482,41 @@ opensocket(isc__socketmgr_t *manager, isc__socket_t *sock, sock->fd = socket(sock->pf, SOCK_STREAM, 0); break; case isc_sockettype_raw: - sock->fd = socket(sock->pf, SOCK_RAW, 0); -#ifdef PF_ROUTE - if (sock->pf == PF_ROUTE) - sock->bound = 1; + errno = EPFNOSUPPORT; + /* + * PF_ROUTE is a alias for PF_NETLINK on linux. + */ +#if defined(PF_ROUTE) + if (sock->fd == -1 && sock->pf == PF_ROUTE) { +#ifdef NETLINK_ROUTE + sock->fd = socket(sock->pf, SOCK_RAW, + NETLINK_ROUTE); +#else + sock->fd = socket(sock->pf, SOCK_RAW, 0); +#endif + if (sock->fd != -1) { +#ifdef NETLINK_ROUTE + struct sockaddr_nl sa; + int n; + + /* + * Do an implicit bind. + */ + memset(&sa, 0, sizeof(sa)); + sa.nl_family = AF_NETLINK; + sa.nl_groups = RTMGRP_IPV4_IFADDR | + RTMGRP_IPV6_IFADDR; + n = bind(sock->fd, + (struct sockaddr *) &sa, + sizeof(sa)); + if (n < 0) { + close(sock->fd); + sock->fd = -1; + } +#endif + sock->bound = 1; + } + } #endif break; case isc_sockettype_fdwatch: