From d93c819513217a38f4311ecf3a8a22ef49e77178 Mon Sep 17 00:00:00 2001 From: Quentin Armitage Date: Mon, 9 Nov 2015 17:48:26 +0000 Subject: Ensure the first interface's parameters are set when using libnl3 Patch 60217b63242bee37b1c97a04644be6eb5e18b4c4 sets the interface parameters for each interface, but when using libnl3 there was a conflict with libnl, causing the parameters not to be set for the first interface. This patch makes vrrp_netlink.c use libnl3 if it is available, to avoid the conflict. Signed-off-by: Quentin Armitage (cherry picked from commit 84cf733579bd9a2765b593dc527a45a286828f17) --- keepalived/include/vrrp_netlink.h | 10 +++- keepalived/vrrp/vrrp_if_config.c | 4 +- keepalived/vrrp/vrrp_netlink.c | 120 +++++++++++++++++++++++++------------- 3 files changed, 88 insertions(+), 46 deletions(-) diff --git a/keepalived/include/vrrp_netlink.h b/keepalived/include/vrrp_netlink.h index 2a1d7bf..444bea5 100644 --- a/keepalived/include/vrrp_netlink.h +++ b/keepalived/include/vrrp_netlink.h @@ -32,14 +32,20 @@ #include #include #include +#ifdef _HAVE_LIBNL3_ +#include +#endif /* local includes */ #include "timer.h" /* types definitions */ typedef struct _nl_handle { +#ifdef _HAVE_LIBNL3_ + struct nl_sock* sk; +#endif int fd; - struct sockaddr_nl snl; + uint32_t nl_pid; __u32 seq; thread_t *thread; } nl_handle_t; @@ -58,7 +64,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 *, unsigned long); +extern int netlink_socket(nl_handle_t *, uint32_t, int flags); 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_if_config.c b/keepalived/vrrp/vrrp_if_config.c index 1727700..ce39b30 100644 --- a/keepalived/vrrp/vrrp_if_config.c +++ b/keepalived/vrrp/vrrp_if_config.c @@ -132,7 +132,7 @@ err: rtnl_link_put(new_state); exit: - nl_close ( sk ) ; + nl_socket_free(sk); return res; } @@ -180,7 +180,7 @@ err: rtnl_link_put(new_state); exit: - nl_close(sk); + nl_socket_free(sk); return res; } diff --git a/keepalived/vrrp/vrrp_netlink.c b/keepalived/vrrp/vrrp_netlink.c index 96f885c..6f429c6 100644 --- a/keepalived/vrrp/vrrp_netlink.c +++ b/keepalived/vrrp/vrrp_netlink.c @@ -33,6 +33,9 @@ #include #include #include +#ifdef _HAVE_LIBNL3_ +#include +#endif /* local include */ #include "check_api.h" @@ -42,6 +45,7 @@ #include "memory.h" #include "scheduler.h" #include "utils.h" +#include "bitops.h" /* Global vars */ nl_handle_t nl_kernel; /* Kernel reflection channel */ @@ -49,34 +53,57 @@ nl_handle_t nl_cmd; /* Command channel */ /* Create a socket to netlink interface_t */ int -netlink_socket(nl_handle_t *nl, unsigned long groups) +netlink_socket(nl_handle_t *nl, uint32_t groups, int flags) { - socklen_t addr_len; int ret; memset(nl, 0, sizeof (*nl)); - nl->fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); - if (nl->fd < 0) { - log_message(LOG_INFO, "Netlink: Cannot open netlink socket : (%s)", - strerror(errno)); +#ifdef _HAVE_LIBNL3_ + /* We need to keep libnl3 in step with our netlink socket creation. */ + nl->sk = nl_socket_alloc(); + if ( nl->sk == NULL ) { + log_message(LOG_INFO, "Netlink: Cannot allocate netlink socket" ); return -1; } - ret = fcntl(nl->fd, F_SETFL, O_NONBLOCK); - if (ret < 0) { - log_message(LOG_INFO, - "Netlink: Cannot set netlink socket flags : (%s)", - strerror(errno)); - close(nl->fd); + 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; + } + + 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); + return -1; + } + } + + if ((ret = nl_socket_set_buffer_size(nl->sk, IF_DEFAULT_BUFSIZE, 0))) { + log_message(LOG_INFO, "Netlink: Cannot set netlink buffer size : (%d)", ret); return -1; } - memset(&nl->snl, 0, sizeof (nl->snl)); - nl->snl.nl_family = AF_NETLINK; - nl->snl.nl_groups = groups; + nl->nl_pid = nl_socket_get_local_port(nl->sk); + + nl->fd = nl_socket_get_fd(nl->sk); +#else + socklen_t addr_len; + struct sockaddr_nl snl; + + nl->fd = socket(AF_NETLINK, SOCK_RAW | flags, NETLINK_ROUTE); + if (nl->fd < 0) { + log_message(LOG_INFO, "Netlink: Cannot open netlink socket : (%s)", + strerror(errno)); + return -1; + } + memset(&snl, 0, sizeof (snl)); + snl.nl_family = AF_NETLINK; + snl.nl_groups = groups; - ret = bind(nl->fd, (struct sockaddr *) &nl->snl, sizeof (nl->snl)); + ret = bind(nl->fd, (struct sockaddr *) &snl, sizeof (snl)); if (ret < 0) { log_message(LOG_INFO, "Netlink: Cannot bind netlink socket : (%s)", strerror(errno)); @@ -84,26 +111,31 @@ netlink_socket(nl_handle_t *nl, unsigned long groups) return -1; } - addr_len = sizeof (nl->snl); - ret = getsockname(nl->fd, (struct sockaddr *) &nl->snl, &addr_len); - if (ret < 0 || addr_len != sizeof (nl->snl)) { + addr_len = sizeof (snl); + ret = getsockname(nl->fd, (struct sockaddr *) &snl, &addr_len); + if (ret < 0 || addr_len != sizeof (snl)) { log_message(LOG_INFO, "Netlink: Cannot getsockname : (%s)", strerror(errno)); close(nl->fd); return -1; } - if (nl->snl.nl_family != AF_NETLINK) { + if (snl.nl_family != AF_NETLINK) { log_message(LOG_INFO, "Netlink: Wrong address family %d", - nl->snl.nl_family); + snl.nl_family); close(nl->fd); return -1; } - nl->seq = time(NULL); + /* Save the socket id for checking message source later */ + nl->nl_pid = snl.nl_pid; /* Set default rcvbuf size */ if_setsockopt_rcvbuf(&nl->fd, IF_DEFAULT_BUFSIZE); +#endif + + nl->seq = time(NULL); + if (nl->fd < 0) return -1; @@ -116,7 +148,11 @@ netlink_close(nl_handle_t *nl) { /* First of all release pending thread */ thread_cancel(nl->thread); +#ifdef _HAVE_LIBNL3_ + nl_socket_free(nl->sk); +#else close(nl->fd); +#endif return 0; } @@ -142,12 +178,22 @@ netlink_set_block(nl_handle_t *nl, int *flags) int netlink_set_nonblock(nl_handle_t *nl, int *flags) { +#ifdef _HAVE_LIBNL3_ + int ret; + + if ((ret = nl_socket_set_nonblocking(nl->sk)) < 0 ) { + log_message(LOG_INFO, "Netlink: Cannot set nonblocking : (%s)", + strerror(ret)); + return -1; + } +#else *flags |= O_NONBLOCK; if (fcntl(nl->fd, F_SETFL, *flags) < 0) { log_message(LOG_INFO, "Netlink: Cannot F_SETFL socket : (%s)", strerror(errno)); return -1; } +#endif return 0; } @@ -325,7 +371,7 @@ netlink_parse_info(int (*filter) (struct sockaddr_nl *, struct nlmsghdr *), } /* Skip unsolicited messages from cmd channel */ - if (nl != &nl_cmd && h->nlmsg_pid == nl_cmd.snl.nl_pid) + if (nl != &nl_cmd && h->nlmsg_pid == nl_cmd.nl_pid) continue; error = (*filter) (&snl, h); @@ -578,17 +624,10 @@ netlink_interface_lookup(void) { nl_handle_t nlh; int status = 0; - int ret, flags; - if (netlink_socket(&nlh, 0) < 0) + if (netlink_socket(&nlh, 0, 0) < 0) return -1; - /* Set blocking flag */ - ret = netlink_set_block(&nlh, &flags); - if (ret < 0) - log_message(LOG_INFO, "Netlink: Warning, couldn't set " - "blocking flag to netlink socket..."); - /* Interface lookup */ if (netlink_request(&nlh, AF_PACKET, RTM_GETLINK) < 0) { status = -1; @@ -607,17 +646,10 @@ netlink_address_lookup(void) { nl_handle_t nlh; int status = 0; - int ret, flags; - if (netlink_socket(&nlh, 0) < 0) + if (netlink_socket(&nlh, 0, 0) < 0) return -1; - /* Set blocking flag */ - ret = netlink_set_block(&nlh, &flags); - if (ret < 0) - log_message(LOG_INFO, "Netlink: Warning, couldn't set " - "blocking flag to netlink socket..."); - /* IPv4 Address lookup */ if (netlink_request(&nlh, AF_INET, RTM_GETADDR) < 0) { status = -1; @@ -666,8 +698,12 @@ netlink_reflect_filter(struct sockaddr_nl *snl, struct nlmsghdr *h) /* find the interface_t. Ignore it if we don't know about the interface */ ifp = if_get_by_ifindex(ifi->ifi_index); - if (!ifp) + if (!ifp) { + if (__test_bit(LOG_DETAIL_BIT, &debug)) + log_message(LOG_INFO, "Unknown interface %s %s", (char *)tb[IFLA_IFNAME], + (h->nlmsg_type == RTM_NEWLINK ) ? "added" : "deleted" ); return 0; + } /* * Update flags. @@ -730,7 +766,7 @@ kernel_netlink_init(void) * netlink broadcast messages. */ groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR; - netlink_socket(&nl_kernel, groups); + netlink_socket(&nl_kernel, groups, SOCK_NONBLOCK); if (nl_kernel.fd > 0) { log_message(LOG_INFO, "Registering Kernel netlink reflector"); @@ -740,7 +776,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); + netlink_socket(&nl_cmd, 0, SOCK_NONBLOCK); if (nl_cmd.fd > 0) log_message(LOG_INFO, "Registering Kernel netlink command channel"); else -- 1.7.12.1