From 6da6b7065fa77841fc87a5192f2ef6a31342f82b Mon Sep 17 00:00:00 2001 From: Quentin Armitage Date: Tue, 10 Nov 2015 22:03:25 +0000 Subject: Remove use of deprecated nl_join_groups() The use of nl_join_groups was introduced in commit 84cf733.. in order to resolve quickly a problem introduced in an earlier patch. This patch follows the approach adopted by libnl3, which uses a list of groups, rather than a bitmap which is limited to 32 groups. Signed-off-by: Quentin Armitage (cherry picked from commit 679e5926942400c992c41be5cefe3ecaecfea426) --- keepalived/include/vrrp_netlink.h | 11 +++++++- keepalived/vrrp/vrrp_netlink.c | 58 +++++++++++++++++++++++++++++++-------- 2 files changed, 56 insertions(+), 13 deletions(-) diff --git a/keepalived/include/vrrp_netlink.h b/keepalived/include/vrrp_netlink.h index 444bea5..cc606bf 100644 --- a/keepalived/include/vrrp_netlink.h +++ b/keepalived/include/vrrp_netlink.h @@ -34,6 +34,10 @@ #include #ifdef _HAVE_LIBNL3_ #include +#include +#endif +#ifdef _HAVE_LIBNL1_ +#include #endif /* local includes */ @@ -52,7 +56,12 @@ typedef struct _nl_handle { /* Define types */ #define NETLINK_TIMER (30 * TIMER_HZ) +#ifndef _HAVE_LIBNL3_ +#ifndef _HAVE_LIBNL1_ #define NLMSG_TAIL(nmsg) ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) +#define SOL_NETLINK 270 +#endif +#endif /* Global vars exported */ extern nl_handle_t nl_kernel; /* Kernel reflection channel */ @@ -64,7 +73,7 @@ extern int addattr_l(struct nlmsghdr *, int, int, void *, int); extern int rta_addattr_l(struct rtattr *, int, int, const void *, int); extern char *netlink_scope_n2a(int); extern int netlink_scope_a2n(char *); -extern int netlink_socket(nl_handle_t *, uint32_t, int flags); +extern int netlink_socket(nl_handle_t *, int, int, ...); extern int netlink_close(nl_handle_t *); extern int netlink_talk(nl_handle_t *, struct nlmsghdr *); extern int netlink_interface_lookup(void); diff --git a/keepalived/vrrp/vrrp_netlink.c b/keepalived/vrrp/vrrp_netlink.c index 6f429c6..913f793 100644 --- a/keepalived/vrrp/vrrp_netlink.c +++ b/keepalived/vrrp/vrrp_netlink.c @@ -33,9 +33,7 @@ #include #include #include -#ifdef _HAVE_LIBNL3_ -#include -#endif +#include /* local include */ #include "check_api.h" @@ -53,9 +51,10 @@ nl_handle_t nl_cmd; /* Command channel */ /* Create a socket to netlink interface_t */ int -netlink_socket(nl_handle_t *nl, uint32_t groups, int flags) +netlink_socket(nl_handle_t *nl, int flags, int group, ...) { int ret; + va_list gp; memset(nl, 0, sizeof (*nl)); @@ -67,13 +66,31 @@ netlink_socket(nl_handle_t *nl, uint32_t groups, int flags) return -1; } - nl_join_groups(nl->sk, groups); /* Note: this function is deprecated */ ret = nl_connect(nl->sk, NETLINK_ROUTE); if (ret != 0) { log_message(LOG_INFO, "Netlink: Cannot open netlink socket : (%d)", ret); return -1; } + /* Unfortunately we can't call nl_socket_add_memberships() with variadic arguments + * from a variadic argument list passed to us + */ + va_start(gp, group); + while (group != 0) { + if (group < 0) { + va_end(gp); + return -1; + } + + if ((ret = nl_socket_add_membership(nl->sk, group))) { + log_message(LOG_INFO, "Netlink: Cannot add socket membership 0x%x : (%d)", group, ret); + return -1; + } + + group = va_arg(gp,int); + } + va_end(gp); + if (flags & SOCK_NONBLOCK) { if ((ret = nl_socket_set_nonblocking(nl->sk))) { log_message(LOG_INFO, "Netlink: Cannot set netlink socket non-blocking : (%d)", ret); @@ -99,9 +116,9 @@ netlink_socket(nl_handle_t *nl, uint32_t groups, int flags) strerror(errno)); return -1; } + memset(&snl, 0, sizeof (snl)); snl.nl_family = AF_NETLINK; - snl.nl_groups = groups; ret = bind(nl->fd, (struct sockaddr *) &snl, sizeof (snl)); if (ret < 0) { @@ -111,6 +128,26 @@ netlink_socket(nl_handle_t *nl, uint32_t groups, int flags) return -1; } + /* Join the requested groups */ + va_start(gp, group); + while (group != 0) { + if (group < 0) { + va_end(gp); + return -1; + } + + ret = setsockopt(nl->fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &group, sizeof(group)); + if (ret < 0) { + log_message(LOG_INFO, "Netlink: Cannot add membership on netlink socket : (%s)", + strerror(errno)); + va_end(gp); + return -1; + } + + group = va_arg(gp,int); + } + va_end(gp); + addr_len = sizeof (snl); ret = getsockname(nl->fd, (struct sockaddr *) &snl, &addr_len); if (ret < 0 || addr_len != sizeof (snl)) { @@ -127,7 +164,7 @@ netlink_socket(nl_handle_t *nl, uint32_t groups, int flags) return -1; } - /* Save the socket id for checking message source later */ + /* Save the port id for checking message source later */ nl->nl_pid = snl.nl_pid; /* Set default rcvbuf size */ @@ -755,8 +792,6 @@ kernel_netlink(thread_t * thread) void kernel_netlink_init(void) { - unsigned long groups; - /* Start with a netlink address lookup */ netlink_address_lookup(); @@ -765,8 +800,7 @@ kernel_netlink_init(void) * subscribtion. We subscribe to LINK and ADDR * netlink broadcast messages. */ - groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR; - netlink_socket(&nl_kernel, groups, SOCK_NONBLOCK); + netlink_socket(&nl_kernel, SOCK_NONBLOCK, RTNLGRP_LINK, RTNLGRP_IPV4_IFADDR, RTNLGRP_IPV6_IFADDR, 0); if (nl_kernel.fd > 0) { log_message(LOG_INFO, "Registering Kernel netlink reflector"); @@ -776,7 +810,7 @@ kernel_netlink_init(void) log_message(LOG_INFO, "Error while registering Kernel netlink reflector channel"); /* Prepare netlink command channel. */ - netlink_socket(&nl_cmd, 0, SOCK_NONBLOCK); + netlink_socket(&nl_cmd, SOCK_NONBLOCK, 0); if (nl_cmd.fd > 0) log_message(LOG_INFO, "Registering Kernel netlink command channel"); else -- 1.7.12.1