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]
#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
+#endif
+#endif
+
+#if defined(HAVE_LINUX_NETLINK_H) && defined(HAVE_LINUX_RTNETLINK_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
#endif
#endif
ns_interfacemgr_t *mgr = NULL;
isc_region_t r;
isc_result_t result;
- struct rt_msghdr *rtm;
+ struct MSGHDR *rtm;
UNUSED(task);
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: "
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)
#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;
/* Define to 1 if you have the <linux/capability.h> header file. */
#undef HAVE_LINUX_CAPABILITY_H
+/* Define to 1 if you have the <linux/netlink.h> header file. */
+#undef HAVE_LINUX_NETLINK_H
+
+/* Define to 1 if you have the <linux/rtnetlink.h> header file. */
+#undef HAVE_LINUX_RTNETLINK_H
+
/* Define to 1 if you have the <linux/types.h> header file. */
#undef HAVE_LINUX_TYPES_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
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 <sys/param.h>
#include <sys/time.h>
#include <sys/uio.h>
+#if defined(HAVE_LINUX_NETLINK_H) && defined(HAVE_LINUX_RTNETLINK_H)
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#endif
+
#include <errno.h>
#include <fcntl.h>
#include <stddef.h>
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: