From 9921e1ec214fb21c77e7ab28793682cebb1f5e3c Mon Sep 17 00:00:00 2001 From: Ronnie Sahlberg Date: Thu, 21 May 2009 14:10:45 +1000 Subject: [PATCH] change the socket we use for sending grautious ARPs from AF_INET/SOCK_PACKET to AF_PACKET/SOCK_RAW (This used to be ctdb commit 2c4c20d7803f4449f8d463314c40d4734ec80e2f) --- ctdb/common/system_linux.c | 43 ++++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/ctdb/common/system_linux.c b/ctdb/common/system_linux.c index a771e3ba04f..7a580cc584c 100644 --- a/ctdb/common/system_linux.c +++ b/ctdb/common/system_linux.c @@ -28,7 +28,7 @@ #include #include #include - +#include #ifndef ETHERTYPE_IP6 #define ETHERTYPE_IP6 0x86dd @@ -71,7 +71,7 @@ static uint16_t tcp_checksum6(uint16_t *data, size_t n, struct ip6_hdr *ip6) int ctdb_sys_send_arp(const ctdb_sock_addr *addr, const char *iface) { int s, ret; - struct sockaddr sa; + struct sockaddr_ll sall; struct ether_header *eh; struct arphdr *ah; struct ip6_hdr *ip6; @@ -79,17 +79,25 @@ int ctdb_sys_send_arp(const ctdb_sock_addr *addr, const char *iface) struct ifreq if_hwaddr; unsigned char buffer[78]; /* ipv6 neigh solicitation size */ char *ptr; + char bdcast[] = {0xff,0xff,0xff,0xff,0xff,0xff}; + struct ifreq ifr; - ZERO_STRUCT(sa); + ZERO_STRUCT(sall); switch (addr->ip.sin_family) { case AF_INET: - s = socket(AF_INET, SOCK_PACKET, htons(ETHERTYPE_ARP)); + s = socket(PF_PACKET, SOCK_RAW, htons(ETHERTYPE_ARP)); if (s == -1){ DEBUG(DEBUG_CRIT,(__location__ " failed to open raw socket\n")); return -1; } + strncpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name)); + if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) { + DEBUG(DEBUG_CRIT,(__location__ " interface '%s' not found\n", iface)); + return -1; + } + /* get the mac address */ strcpy(if_hwaddr.ifr_name, iface); ret = ioctl(s, SIOCGIFHWADDR, &if_hwaddr); @@ -136,8 +144,12 @@ int ctdb_sys_send_arp(const ctdb_sock_addr *addr, const char *iface) memcpy(ptr, &addr->ip.sin_addr, 4); ptr+=4; - strncpy(sa.sa_data, iface, sizeof(sa.sa_data)); - ret = sendto(s, buffer, 64, 0, &sa, sizeof(sa)); + sall.sll_family = AF_PACKET; + sall.sll_halen = 6; + memcpy(&sall.sll_addr[0], bdcast, sall.sll_halen); + sall.sll_protocol = htons(ETH_P_ALL); + sall.sll_ifindex = ifr.ifr_ifindex; + ret = sendto(s, buffer, 64, 0, (struct sockaddr *)&sall, sizeof(sall)); if (ret < 0 ){ close(s); DEBUG(DEBUG_CRIT,(__location__ " failed sendto\n")); @@ -156,8 +168,7 @@ int ctdb_sys_send_arp(const ctdb_sock_addr *addr, const char *iface) memcpy(ptr, &addr->ip.sin_addr, 4); ptr+=4; - strncpy(sa.sa_data, iface, sizeof(sa.sa_data)); - ret = sendto(s, buffer, 64, 0, &sa, sizeof(sa)); + ret = sendto(s, buffer, 64, 0, (struct sockaddr *)&sall, sizeof(sall)); if (ret < 0 ){ DEBUG(DEBUG_CRIT,(__location__ " failed sendto\n")); return -1; @@ -166,12 +177,18 @@ int ctdb_sys_send_arp(const ctdb_sock_addr *addr, const char *iface) close(s); break; case AF_INET6: - s = socket(AF_INET, SOCK_PACKET, htons(ETHERTYPE_IP6)); + s = socket(PF_PACKET, SOCK_RAW, htons(ETHERTYPE_ARP)); if (s == -1){ DEBUG(DEBUG_CRIT,(__location__ " failed to open raw socket\n")); return -1; } + strncpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name)); + if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) { + DEBUG(DEBUG_CRIT,(__location__ " interface '%s' not found\n", iface)); + return -1; + } + /* get the mac address */ strcpy(if_hwaddr.ifr_name, iface); ret = ioctl(s, SIOCGIFHWADDR, &if_hwaddr); @@ -213,8 +230,12 @@ int ctdb_sys_send_arp(const ctdb_sock_addr *addr, const char *iface) icmp6->icmp6_cksum = tcp_checksum6((uint16_t *)icmp6, ntohs(ip6->ip6_plen), ip6); - strncpy(sa.sa_data, iface, sizeof(sa.sa_data)); - ret = sendto(s, buffer, 78, 0, &sa, sizeof(sa)); + sall.sll_family = AF_PACKET; + sall.sll_halen = 6; + memcpy(&sall.sll_addr[0], bdcast, sall.sll_halen); + sall.sll_protocol = htons(ETH_P_ALL); + sall.sll_ifindex = ifr.ifr_ifindex; + ret = sendto(s, buffer, 78, 0, (struct sockaddr *)&sall, sizeof(sall)); if (ret < 0 ){ close(s); DEBUG(DEBUG_CRIT,(__location__ " failed sendto\n")); -- 2.34.1