From d3c9a4ae4efe8c491a6b2d3fa5f30d54bdb23b89 Mon Sep 17 00:00:00 2001 From: Quentin Armitage Date: Sun, 1 Nov 2015 20:10:55 +0000 Subject: Fix socket setup code for IPv4 multicast if_setsockopt_mcast_if was only doing anything for IPv6 interfaces. Make it work also for IPv4 interfaces, and then don't need to call if_setsockopt_bindtodevice for multicast. Is it still necessary to call it for unicast? Signed-off-by: Quentin Armitage (cherry picked from commit 5e611cb5538ca961077b2d868e6dca5a00b4de23) --- keepalived/vrrp/vrrp.c | 16 ++++++++++------ keepalived/vrrp/vrrp_if.c | 15 +++++++++++---- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/keepalived/vrrp/vrrp.c b/keepalived/vrrp/vrrp.c index bb42a44..b9299fe 100644 --- a/keepalived/vrrp/vrrp.c +++ b/keepalived/vrrp/vrrp.c @@ -1446,9 +1446,12 @@ open_vrrp_send_socket(sa_family_t family, int proto, int idx, int unicast) if (family == AF_INET) { /* Set v4 related */ if_setsockopt_hdrincl(&fd); - if_setsockopt_bindtodevice(&fd, ifp); - if (!unicast) + if (unicast) + if_setsockopt_bindtodevice(&fd, ifp); + else { + if_setsockopt_mcast_if(family, &fd, ifp); if_setsockopt_mcast_loop(family, &fd); + } if_setsockopt_priority(&fd); if (fd < 0) return -1; @@ -1496,13 +1499,14 @@ open_vrrp_socket(sa_family_t family, int proto, int idx, if (!unicast) { if_join_vrrp_group(family, &fd, ifp, proto); } + else if (family == AF_INET) { + /* Bind inbound stream */ + if_setsockopt_bindtodevice(&fd, ifp); + } if (fd < 0) return -1; - if (family == AF_INET) { - /* Bind inbound stream */ - if_setsockopt_bindtodevice(&fd, ifp); - } else if (family == AF_INET6) { + if (family == AF_INET6) { /* Let kernel calculate checksum. */ if_setsockopt_ipv6_checksum(&fd); } diff --git a/keepalived/vrrp/vrrp_if.c b/keepalived/vrrp/vrrp_if.c index e186d9a..8374df1 100644 --- a/keepalived/vrrp/vrrp_if.c +++ b/keepalived/vrrp/vrrp_if.c @@ -644,15 +644,22 @@ if_setsockopt_mcast_if(sa_family_t family, int *sd, interface_t *ifp) int ret; unsigned int ifindex; - /* Not applicable for IPv4 */ - if (*sd < 0 || family == AF_INET) + if (*sd < 0) return -1; /* Set interface for sending outbound datagrams */ ifindex = IF_INDEX(ifp); - ret = setsockopt(*sd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex, sizeof(ifindex)); + if ( family == AF_INET) + { + struct ip_mreqn imr ; + imr.imr_ifindex = IF_INDEX(ifp); + ret = setsockopt(*sd, IPPROTO_IP, IP_MULTICAST_IF, &imr, sizeof(imr)); + } + else + ret = setsockopt(*sd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex, sizeof(ifindex)); + if (ret < 0) { - log_message(LOG_INFO, "cant set IPV6_MULTICAST_IF IP option. errno=%d (%m)", errno); + log_message(LOG_INFO, "cant set IP%s_MULTICAST_IF IP option. errno=%d (%m)", (family == AF_INET) ? "" : "V6", errno); close(*sd); *sd = -1; } -- 1.7.12.1