static void vrrp_vmac_handler(vector_t *strvec) { vrrp_t *vrrp = LIST_TAIL_DATA(vrrp_data->vrrp); vrrp->vmac |= 1; if (!vrrp->saddr) vrrp->saddr = IF_ADDR(vrrp->ifp); if (vector_size(strvec) == 2) { strncpy(vrrp->vmac_ifname, vector_slot(strvec, 1), IFNAMSIZ - 1); } else if (vrrp->vrid) { snprintf(vrrp->vmac_ifname, IFNAMSIZ, "vrrp.%d", vrrp->vrid); } if (strlen(vrrp->vmac_ifname)) { log_message(LOG_INFO, "vmac_ifname=%s for vrrp_instace %s" , vrrp->vmac_ifname , vrrp->iname); } if (vrrp->ifp && !(vrrp->vmac & 2)) { unsigned int base_ifindex = vrrp->ifp->base_ifindex; netlink_link_add_vmac(vrrp); /* restore base ifindex (deleted when adding VMAC) */ vrrp->ifp->base_ifindex = base_ifindex; } /* flag interface as a VMAC interface */ vrrp->ifp->vmac = 1; }
int if_join_vrrp_group(sa_family_t family, int *sd, interface_t *ifp, int proto) { struct ip_mreqn imr; struct ipv6_mreq imr6; int ret = 0; if (*sd < 0) return -1; /* -> outbound processing option * join the multicast group. * binding the socket to the interface for outbound multicast * traffic. */ if (family == AF_INET) { memset(&imr, 0, sizeof(imr)); imr.imr_multiaddr.s_addr = htonl(INADDR_VRRP_GROUP); imr.imr_address.s_addr = IF_ADDR(ifp); imr.imr_ifindex = IF_INDEX(ifp); /* -> Need to handle multicast convergance after takeover. * We retry until multicast is available on the interface. */ ret = setsockopt(*sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &imr, sizeof(struct ip_mreqn)); } else { memset(&imr6, 0, sizeof(imr6)); imr6.ipv6mr_multiaddr.s6_addr16[0] = htons(0xff02); imr6.ipv6mr_multiaddr.s6_addr16[7] = htons(0x12); imr6.ipv6mr_interface = IF_INDEX(ifp); ret = setsockopt(*sd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char *) &imr6, sizeof(struct ipv6_mreq)); } if (ret < 0) { log_message(LOG_INFO, "cant do IP%s_ADD_MEMBERSHIP errno=%s (%d)", (family == AF_INET) ? "" : "V6", strerror(errno), errno); close(*sd); *sd = -1; } return *sd; }
static void vrrp_vmac_handler(vector_t *strvec) { vrrp_t *vrrp = LIST_TAIL_DATA(vrrp_data->vrrp); vrrp->vmac_flags |= VRRP_VMAC_FL_SET; if (!vrrp->saddr.ss_family && vrrp->family == AF_INET) inet_ip4tosockaddr(IF_ADDR(vrrp->ifp), &vrrp->saddr); if (vector_size(strvec) == 2) { strncpy(vrrp->vmac_ifname, vector_slot(strvec, 1), IFNAMSIZ - 1); } else if (vrrp->vrid) { snprintf(vrrp->vmac_ifname, IFNAMSIZ, "vrrp.%d", vrrp->vrid); } else { return; } netlink_link_add_vmac(vrrp); }
static void vrrp_vmac_handler(vector strvec) { vrrp_rt *vrrp = LIST_TAIL_DATA(vrrp_data->vrrp); vrrp->vmac = 1; if (!(vrrp->mcast_saddr)) vrrp->mcast_saddr = IF_ADDR(vrrp->ifp); if (strvec && (strvec->allocated == 2)) strncpy(vrrp->vmac_ifname, VECTOR_SLOT(strvec, 1), IFNAMSIZ - 1); else snprintf(vrrp->vmac_ifname, IFNAMSIZ, "vrrp.%d", vrrp->vrid); log_message(LOG_INFO, "vrrp_vmac_handler: vmac ifname is %s", vrrp->vmac_ifname); if (vrrp->ifp && !(vrrp->vmac & 2)) netlink_link_add_vmac(vrrp); }
int if_leave_vrrp_group(sa_family_t family, int sd, interface_t *ifp) { struct ip_mreqn imr; struct ipv6_mreq imr6; int ret = 0; /* If fd is -1 then we add a membership trouble */ if (sd < 0 || !ifp) return -1; /* Leaving the VRRP multicast group */ if (family == AF_INET) { memset(&imr, 0, sizeof(imr)); /* FIXME: change this to use struct ip_mreq */ imr.imr_multiaddr.s_addr = htonl(INADDR_VRRP_GROUP); imr.imr_address.s_addr = IF_ADDR(ifp); imr.imr_ifindex = IF_INDEX(ifp); ret = setsockopt(sd, IPPROTO_IP, IP_DROP_MEMBERSHIP, (char *) &imr, sizeof (struct ip_mreqn)); } else { memset(&imr6, 0, sizeof(imr6)); /* rfc5798.5.1.2.2 : destination IPv6 mcast group is * ff02:0:0:0:0:0:0:12. */ imr6.ipv6mr_multiaddr.s6_addr16[0] = htons(0xff02); imr6.ipv6mr_multiaddr.s6_addr16[7] = htons(0x12); imr6.ipv6mr_interface = IF_INDEX(ifp); ret = setsockopt(sd, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, (char *) &imr6, sizeof(struct ipv6_mreq)); } if (ret < 0) { log_message(LOG_INFO, "cant do IP%s_DROP_MEMBERSHIP errno=%s (%d)", (family == AF_INET) ? "" : "V6", strerror(errno), errno); close(sd); return -1; } /* Finally close the desc */ close(sd); return 0; }