From: Martin Schwenke Date: Thu, 28 Jun 2018 10:57:08 +0000 (+1000) Subject: ctdb-common: Move ctdb_sys_send_arp() to ctdb_socket.[ch] X-Git-Tag: tevent-0.9.37~179 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=9c51b278b1700cd5f3e2addc19b7c711cc2ea10b;p=thirdparty%2Fsamba.git ctdb-common: Move ctdb_sys_send_arp() to ctdb_socket.[ch] The system_.c files contain a lot of duplication, making maintenance difficult. These functions are being merged into system_socket.c and system.c. Bring a copy of tcp_checksum6(), renamed to ip6_checksum(). Signed-off-by: Martin Schwenke Reviewed-by: Amitay Isaacs --- diff --git a/ctdb/common/system.h b/ctdb/common/system.h index d63fb91db6b..a0d379210f3 100644 --- a/ctdb/common/system.h +++ b/ctdb/common/system.h @@ -24,7 +24,6 @@ /* From system_.c */ -int ctdb_sys_send_arp(const ctdb_sock_addr *addr, const char *iface); int ctdb_sys_send_tcp(const ctdb_sock_addr *dest, const ctdb_sock_addr *src, uint32_t seq, uint32_t ack, int rst); diff --git a/ctdb/common/system_aix.c b/ctdb/common/system_aix.c index b19e7569929..1856ae299a1 100644 --- a/ctdb/common/system_aix.c +++ b/ctdb/common/system_aix.c @@ -205,22 +205,6 @@ int ctdb_sys_close_capture_socket(void *private_data) return 0; } - - -/* - send gratuitous arp reply after we have taken over an ip address - - saddr is the address we are trying to claim - iface is the interface name we will be using to claim the address - */ -int ctdb_sys_send_arp(const ctdb_sock_addr *addr, const char *iface) -{ - /* FIXME AIX: We don't do gratuitous arp yet */ - return -1; -} - - - /* get ethernet MAC address on AIX */ diff --git a/ctdb/common/system_freebsd.c b/ctdb/common/system_freebsd.c index 9632fb209fa..48e34ed859b 100644 --- a/ctdb/common/system_freebsd.c +++ b/ctdb/common/system_freebsd.c @@ -75,19 +75,6 @@ static uint16_t tcp_checksum6(uint16_t *data, size_t n, struct ip6_hdr *ip6) return sum2; } -/* - send gratuitous arp reply after we have taken over an ip address - - saddr is the address we are trying to claim - iface is the interface name we will be using to claim the address - */ -int ctdb_sys_send_arp(const ctdb_sock_addr *addr, const char *iface) -{ - /* FIXME FreeBSD: We don't do gratuitous arp yet */ - return -1; -} - - /* simple TCP checksum - assumes data is multiple of 2 bytes long */ diff --git a/ctdb/common/system_gnu.c b/ctdb/common/system_gnu.c index c45c6e930d4..43fa66fdc8c 100644 --- a/ctdb/common/system_gnu.c +++ b/ctdb/common/system_gnu.c @@ -74,19 +74,6 @@ static uint16_t tcp_checksum6(uint16_t *data, size_t n, struct ip6_hdr *ip6) return sum2; } -/* - send gratuitous arp reply after we have taken over an ip address - - saddr is the address we are trying to claim - iface is the interface name we will be using to claim the address - */ -int ctdb_sys_send_arp(const ctdb_sock_addr *addr, const char *iface) -{ - /* FIXME GNU/Hurd: We don't do gratuitous arp yet */ - return -1; -} - - /* simple TCP checksum - assumes data is multiple of 2 bytes long */ diff --git a/ctdb/common/system_kfreebsd.c b/ctdb/common/system_kfreebsd.c index 694ae58a37c..8969849aec5 100644 --- a/ctdb/common/system_kfreebsd.c +++ b/ctdb/common/system_kfreebsd.c @@ -74,19 +74,6 @@ static uint16_t tcp_checksum6(uint16_t *data, size_t n, struct ip6_hdr *ip6) return sum2; } -/* - send gratuitous arp reply after we have taken over an ip address - - saddr is the address we are trying to claim - iface is the interface name we will be using to claim the address - */ -int ctdb_sys_send_arp(const ctdb_sock_addr *addr, const char *iface) -{ - /* FIXME kFreeBSD: We don't do gratuitous arp yet */ - return -1; -} - - /* simple TCP checksum - assumes data is multiple of 2 bytes long */ diff --git a/ctdb/common/system_linux.c b/ctdb/common/system_linux.c index a95076dc5f3..991dc531e43 100644 --- a/ctdb/common/system_linux.c +++ b/ctdb/common/system_linux.c @@ -71,230 +71,6 @@ static uint16_t tcp_checksum6(uint16_t *data, size_t n, struct ip6_hdr *ip6) return sum2; } -/* - send gratuitous arp reply after we have taken over an ip address - - saddr is the address we are trying to claim - iface is the interface name we will be using to claim the address - */ -int ctdb_sys_send_arp(const ctdb_sock_addr *addr, const char *iface) -{ - int s, ret; - struct sockaddr_ll sall; - struct ether_header *eh; - struct arphdr *ah; - struct ip6_hdr *ip6; - struct nd_neighbor_advert *nd_na; - struct nd_opt_hdr *nd_oh; - struct ifreq if_hwaddr; - /* Size of IPv6 neighbor advertisement (with option) */ - unsigned char buffer[sizeof(struct ether_header) + - sizeof(struct ip6_hdr) + - sizeof(struct nd_neighbor_advert) + - sizeof(struct nd_opt_hdr) + ETH_ALEN]; - char *ptr; - char bdcast[] = {0xff,0xff,0xff,0xff,0xff,0xff}; - struct ifreq ifr; - - ZERO_STRUCT(sall); - ZERO_STRUCT(ifr); - ZERO_STRUCT(if_hwaddr); - - switch (addr->ip.sin_family) { - case AF_INET: - s = socket(AF_PACKET, SOCK_RAW, 0); - if (s == -1){ - DEBUG(DEBUG_CRIT,(__location__ " failed to open raw socket\n")); - return -1; - } - - DEBUG(DEBUG_DEBUG, (__location__ " Created SOCKET FD:%d for sending arp\n", s)); - strlcpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name)); - if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) { - DEBUG(DEBUG_CRIT,(__location__ " interface '%s' not found\n", iface)); - close(s); - return -1; - } - - /* get the mac address */ - strlcpy(if_hwaddr.ifr_name, iface, sizeof(if_hwaddr.ifr_name)); - ret = ioctl(s, SIOCGIFHWADDR, &if_hwaddr); - if ( ret < 0 ) { - close(s); - DEBUG(DEBUG_CRIT,(__location__ " ioctl failed\n")); - return -1; - } - if (ARPHRD_LOOPBACK == if_hwaddr.ifr_hwaddr.sa_family) { - DEBUG(DEBUG_DEBUG,("Ignoring loopback arp request\n")); - close(s); - return 0; - } - if (if_hwaddr.ifr_hwaddr.sa_family != ARPHRD_ETHER) { - close(s); - errno = EINVAL; - DEBUG(DEBUG_CRIT,(__location__ " not an ethernet address family (0x%x)\n", - if_hwaddr.ifr_hwaddr.sa_family)); - return -1; - } - - - memset(buffer, 0 , 64); - eh = (struct ether_header *)buffer; - memset(eh->ether_dhost, 0xff, ETH_ALEN); - memcpy(eh->ether_shost, if_hwaddr.ifr_hwaddr.sa_data, ETH_ALEN); - eh->ether_type = htons(ETHERTYPE_ARP); - - ah = (struct arphdr *)&buffer[sizeof(struct ether_header)]; - ah->ar_hrd = htons(ARPHRD_ETHER); - ah->ar_pro = htons(ETH_P_IP); - ah->ar_hln = ETH_ALEN; - ah->ar_pln = 4; - - /* send a gratious arp */ - ah->ar_op = htons(ARPOP_REQUEST); - ptr = (char *)&ah[1]; - memcpy(ptr, if_hwaddr.ifr_hwaddr.sa_data, ETH_ALEN); - ptr+=ETH_ALEN; - memcpy(ptr, &addr->ip.sin_addr, 4); - ptr+=4; - memset(ptr, 0, ETH_ALEN); - ptr+=ETH_ALEN; - memcpy(ptr, &addr->ip.sin_addr, 4); - ptr+=4; - - 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")); - return -1; - } - - /* send unsolicited arp reply broadcast */ - ah->ar_op = htons(ARPOP_REPLY); - ptr = (char *)&ah[1]; - memcpy(ptr, if_hwaddr.ifr_hwaddr.sa_data, ETH_ALEN); - ptr+=ETH_ALEN; - memcpy(ptr, &addr->ip.sin_addr, 4); - ptr+=4; - memcpy(ptr, if_hwaddr.ifr_hwaddr.sa_data, ETH_ALEN); - ptr+=ETH_ALEN; - memcpy(ptr, &addr->ip.sin_addr, 4); - ptr+=4; - - ret = sendto(s, buffer, 64, 0, (struct sockaddr *)&sall, sizeof(sall)); - if (ret < 0 ){ - DEBUG(DEBUG_CRIT,(__location__ " failed sendto\n")); - close(s); - return -1; - } - - close(s); - break; - case AF_INET6: - s = socket(AF_PACKET, SOCK_RAW, 0); - if (s == -1){ - DEBUG(DEBUG_CRIT,(__location__ " failed to open raw socket\n")); - return -1; - } - - DEBUG(DEBUG_DEBUG, (__location__ " Created SOCKET FD:%d for sending arp\n", s)); - strlcpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name)); - if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) { - DEBUG(DEBUG_CRIT,(__location__ " interface '%s' not found\n", iface)); - close(s); - return -1; - } - - /* get the mac address */ - strlcpy(if_hwaddr.ifr_name, iface, sizeof(if_hwaddr.ifr_name)); - ret = ioctl(s, SIOCGIFHWADDR, &if_hwaddr); - if ( ret < 0 ) { - close(s); - DEBUG(DEBUG_CRIT,(__location__ " ioctl failed\n")); - return -1; - } - if (ARPHRD_LOOPBACK == if_hwaddr.ifr_hwaddr.sa_family) { - DEBUG(DEBUG_DEBUG,("Ignoring loopback arp request\n")); - close(s); - return 0; - } - if (if_hwaddr.ifr_hwaddr.sa_family != ARPHRD_ETHER) { - close(s); - errno = EINVAL; - DEBUG(DEBUG_CRIT,(__location__ " not an ethernet address family (0x%x)\n", - if_hwaddr.ifr_hwaddr.sa_family)); - return -1; - } - - memset(buffer, 0 , sizeof(buffer)); - eh = (struct ether_header *)buffer; - /* Ethernet multicast: 33:33:00:00:00:01 (see RFC2464, - * section 7) - note zeroes above! */ - eh->ether_dhost[0] = eh->ether_dhost[1] = 0x33; - eh->ether_dhost[5] = 0x01; - memcpy(eh->ether_shost, if_hwaddr.ifr_hwaddr.sa_data, ETH_ALEN); - eh->ether_type = htons(ETHERTYPE_IP6); - - ip6 = (struct ip6_hdr *)(eh+1); - ip6->ip6_vfc = 0x60; - ip6->ip6_plen = htons(sizeof(*nd_na) + - sizeof(struct nd_opt_hdr) + - ETH_ALEN); - ip6->ip6_nxt = IPPROTO_ICMPV6; - ip6->ip6_hlim = 255; - ip6->ip6_src = addr->ip6.sin6_addr; - /* all-nodes multicast */ - - ret = inet_pton(AF_INET6, "ff02::1", &ip6->ip6_dst); - if (ret != 1) { - close(s); - DEBUG(DEBUG_CRIT,(__location__ " failed inet_pton\n")); - return -1; - } - - nd_na = (struct nd_neighbor_advert *)(ip6+1); - nd_na->nd_na_type = ND_NEIGHBOR_ADVERT; - nd_na->nd_na_code = 0; - nd_na->nd_na_flags_reserved = ND_NA_FLAG_OVERRIDE; - nd_na->nd_na_target = addr->ip6.sin6_addr; - /* Option: Target link-layer address */ - nd_oh = (struct nd_opt_hdr *)(nd_na+1); - nd_oh->nd_opt_type = ND_OPT_TARGET_LINKADDR; - nd_oh->nd_opt_len = 1; - memcpy(&(nd_oh+1)[0], if_hwaddr.ifr_hwaddr.sa_data, ETH_ALEN); - - nd_na->nd_na_cksum = tcp_checksum6((uint16_t *)nd_na, - ntohs(ip6->ip6_plen), ip6); - - sall.sll_family = AF_PACKET; - sall.sll_halen = 6; - memcpy(&sall.sll_addr[0], &eh->ether_dhost[0], sall.sll_halen); - sall.sll_protocol = htons(ETH_P_ALL); - sall.sll_ifindex = ifr.ifr_ifindex; - ret = sendto(s, buffer, sizeof(buffer), - 0, (struct sockaddr *)&sall, sizeof(sall)); - if (ret < 0 ){ - close(s); - DEBUG(DEBUG_CRIT,(__location__ " failed sendto\n")); - return -1; - } - - close(s); - break; - default: - DEBUG(DEBUG_CRIT,(__location__ " not an ipv4/ipv6 address (family is %u)\n", addr->ip.sin_family)); - return -1; - } - - return 0; -} - - /* simple TCP checksum - assumes data is multiple of 2 bytes long */ diff --git a/ctdb/common/system_socket.c b/ctdb/common/system_socket.c index 0a9012c1b24..f5c34e2d873 100644 --- a/ctdb/common/system_socket.c +++ b/ctdb/common/system_socket.c @@ -21,6 +21,23 @@ #include "replace.h" #include "system/network.h" +#ifdef HAVE_NETINET_IF_ETHER_H +#include +#endif +#ifdef HAVE_NETINET_IP6_H +#include +#endif +#ifdef HAVE_NETINET_ICMP6_H +#include +#endif +#ifdef HAVE_LINUX_IF_PACKET_H +#include +#endif + +#ifndef ETHERTYPE_IP6 +#define ETHERTYPE_IP6 0x86dd +#endif + #include "lib/util/debug.h" #include "protocol/protocol.h" @@ -45,7 +62,6 @@ uint32_t uint16_checksum(uint16_t *data, size_t n) return sum; } - /* * See if the given IP is currently on an interface */ @@ -215,3 +231,267 @@ bool parse_ip_mask(const char *str, return ret; } + +static uint16_t ip6_checksum(uint16_t *data, size_t n, struct ip6_hdr *ip6) +{ + uint32_t phdr[2]; + uint32_t sum = 0; + uint16_t sum2; + + sum += uint16_checksum((uint16_t *)(void *)&ip6->ip6_src, 16); + sum += uint16_checksum((uint16_t *)(void *)&ip6->ip6_dst, 16); + + phdr[0] = htonl(n); + phdr[1] = htonl(ip6->ip6_nxt); + sum += uint16_checksum((uint16_t *)phdr, 8); + + sum += uint16_checksum(data, n); + + sum = (sum & 0xFFFF) + (sum >> 16); + sum = (sum & 0xFFFF) + (sum >> 16); + sum2 = htons(sum); + sum2 = ~sum2; + if (sum2 == 0) { + return 0xFFFF; + } + return sum2; +} + +/* + * Send gratuitous ARP request/reply or IPv6 neighbor advertisement + */ + +#ifdef HAVE_PACKETSOCKET + +int ctdb_sys_send_arp(const ctdb_sock_addr *addr, const char *iface) +{ + int s, ret; + struct sockaddr_ll sall; + struct ether_header *eh; + struct arphdr *ah; + struct ip6_hdr *ip6; + struct nd_neighbor_advert *nd_na; + struct nd_opt_hdr *nd_oh; + struct ifreq if_hwaddr; + /* Size of IPv6 neighbor advertisement (with option) */ + unsigned char buffer[sizeof(struct ether_header) + + sizeof(struct ip6_hdr) + + sizeof(struct nd_neighbor_advert) + + sizeof(struct nd_opt_hdr) + ETH_ALEN]; + char *ptr; + char bdcast[] = {0xff,0xff,0xff,0xff,0xff,0xff}; + struct ifreq ifr; + + ZERO_STRUCT(sall); + ZERO_STRUCT(ifr); + ZERO_STRUCT(if_hwaddr); + + switch (addr->ip.sin_family) { + case AF_INET: + s = socket(AF_PACKET, SOCK_RAW, 0); + if (s == -1){ + DBG_ERR("Failed to open raw socket\n"); + return -1; + } + + DBG_DEBUG("Created SOCKET FD:%d for sending arp\n", s); + strlcpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name)); + if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) { + DBG_ERR("Interface '%s' not found\n", iface); + close(s); + return -1; + } + + /* get the mac address */ + strlcpy(if_hwaddr.ifr_name, iface, sizeof(if_hwaddr.ifr_name)); + ret = ioctl(s, SIOCGIFHWADDR, &if_hwaddr); + if ( ret < 0 ) { + close(s); + DBG_ERR("ioctl failed\n"); + return -1; + } + if (ARPHRD_LOOPBACK == if_hwaddr.ifr_hwaddr.sa_family) { + D_DEBUG("Ignoring loopback arp request\n"); + close(s); + return 0; + } + if (if_hwaddr.ifr_hwaddr.sa_family != ARPHRD_ETHER) { + close(s); + errno = EINVAL; + DBG_ERR("Not an ethernet address family (0x%x)\n", + if_hwaddr.ifr_hwaddr.sa_family); + return -1; + } + + + memset(buffer, 0 , 64); + eh = (struct ether_header *)buffer; + memset(eh->ether_dhost, 0xff, ETH_ALEN); + memcpy(eh->ether_shost, if_hwaddr.ifr_hwaddr.sa_data, ETH_ALEN); + eh->ether_type = htons(ETHERTYPE_ARP); + + ah = (struct arphdr *)&buffer[sizeof(struct ether_header)]; + ah->ar_hrd = htons(ARPHRD_ETHER); + ah->ar_pro = htons(ETH_P_IP); + ah->ar_hln = ETH_ALEN; + ah->ar_pln = 4; + + /* send a gratious arp */ + ah->ar_op = htons(ARPOP_REQUEST); + ptr = (char *)&ah[1]; + memcpy(ptr, if_hwaddr.ifr_hwaddr.sa_data, ETH_ALEN); + ptr+=ETH_ALEN; + memcpy(ptr, &addr->ip.sin_addr, 4); + ptr+=4; + memset(ptr, 0, ETH_ALEN); + ptr+=ETH_ALEN; + memcpy(ptr, &addr->ip.sin_addr, 4); + ptr+=4; + + 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); + DBG_ERR("Failed sendto\n"); + return -1; + } + + /* send unsolicited arp reply broadcast */ + ah->ar_op = htons(ARPOP_REPLY); + ptr = (char *)&ah[1]; + memcpy(ptr, if_hwaddr.ifr_hwaddr.sa_data, ETH_ALEN); + ptr+=ETH_ALEN; + memcpy(ptr, &addr->ip.sin_addr, 4); + ptr+=4; + memcpy(ptr, if_hwaddr.ifr_hwaddr.sa_data, ETH_ALEN); + ptr+=ETH_ALEN; + memcpy(ptr, &addr->ip.sin_addr, 4); + ptr+=4; + + ret = sendto(s, buffer, 64, 0, + (struct sockaddr *)&sall, sizeof(sall)); + if (ret < 0 ){ + DBG_ERR("Failed sendto\n"); + close(s); + return -1; + } + + close(s); + break; + case AF_INET6: + s = socket(AF_PACKET, SOCK_RAW, 0); + if (s == -1){ + DBG_ERR("Failed to open raw socket\n"); + return -1; + } + + DBG_DEBUG("Created SOCKET FD:%d for sending arp\n", s); + strlcpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name)); + if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) { + DBG_ERR("Interface '%s' not found\n", iface); + close(s); + return -1; + } + + /* get the mac address */ + strlcpy(if_hwaddr.ifr_name, iface, sizeof(if_hwaddr.ifr_name)); + ret = ioctl(s, SIOCGIFHWADDR, &if_hwaddr); + if ( ret < 0 ) { + close(s); + DBG_ERR("ioctl failed\n"); + return -1; + } + if (ARPHRD_LOOPBACK == if_hwaddr.ifr_hwaddr.sa_family) { + DBG_DEBUG("Ignoring loopback arp request\n"); + close(s); + return 0; + } + if (if_hwaddr.ifr_hwaddr.sa_family != ARPHRD_ETHER) { + close(s); + errno = EINVAL; + DBG_ERR("Not an ethernet address family (0x%x)\n", + if_hwaddr.ifr_hwaddr.sa_family); + return -1; + } + + memset(buffer, 0 , sizeof(buffer)); + eh = (struct ether_header *)buffer; + /* + * Ethernet multicast: 33:33:00:00:00:01 (see RFC2464, + * section 7) - note zeroes above! + */ + eh->ether_dhost[0] = eh->ether_dhost[1] = 0x33; + eh->ether_dhost[5] = 0x01; + memcpy(eh->ether_shost, if_hwaddr.ifr_hwaddr.sa_data, ETH_ALEN); + eh->ether_type = htons(ETHERTYPE_IP6); + + ip6 = (struct ip6_hdr *)(eh+1); + ip6->ip6_vfc = 0x60; + ip6->ip6_plen = htons(sizeof(*nd_na) + + sizeof(struct nd_opt_hdr) + + ETH_ALEN); + ip6->ip6_nxt = IPPROTO_ICMPV6; + ip6->ip6_hlim = 255; + ip6->ip6_src = addr->ip6.sin6_addr; + /* all-nodes multicast */ + + ret = inet_pton(AF_INET6, "ff02::1", &ip6->ip6_dst); + if (ret != 1) { + close(s); + DBG_ERR("Failed inet_pton\n"); + return -1; + } + + nd_na = (struct nd_neighbor_advert *)(ip6+1); + nd_na->nd_na_type = ND_NEIGHBOR_ADVERT; + nd_na->nd_na_code = 0; + nd_na->nd_na_flags_reserved = ND_NA_FLAG_OVERRIDE; + nd_na->nd_na_target = addr->ip6.sin6_addr; + /* Option: Target link-layer address */ + nd_oh = (struct nd_opt_hdr *)(nd_na+1); + nd_oh->nd_opt_type = ND_OPT_TARGET_LINKADDR; + nd_oh->nd_opt_len = 1; + memcpy(&(nd_oh+1)[0], if_hwaddr.ifr_hwaddr.sa_data, ETH_ALEN); + + nd_na->nd_na_cksum = ip6_checksum((uint16_t *)nd_na, + ntohs(ip6->ip6_plen), ip6); + + sall.sll_family = AF_PACKET; + sall.sll_halen = 6; + memcpy(&sall.sll_addr[0], &eh->ether_dhost[0], sall.sll_halen); + sall.sll_protocol = htons(ETH_P_ALL); + sall.sll_ifindex = ifr.ifr_ifindex; + ret = sendto(s, buffer, sizeof(buffer), + 0, (struct sockaddr *)&sall, sizeof(sall)); + if (ret < 0 ){ + close(s); + DBG_ERR("Failed sendto\n"); + return -1; + } + + close(s); + break; + default: + DBG_ERR("Not an ipv4/ipv6 address (family is %u)\n", + addr->ip.sin_family); + return -1; + } + + return 0; +} + +#else /* HAVE_PACKETSOCKET */ + +int ctdb_sys_send_arp(const ctdb_sock_addr *addr, const char *iface) +{ + /* Not implemented */ + errno = ENOSYS; + return -1; +} + +#endif /* HAVE_PACKETSOCKET */ diff --git a/ctdb/common/system_socket.h b/ctdb/common/system_socket.h index 50593079148..f405c0c35ba 100644 --- a/ctdb/common/system_socket.h +++ b/ctdb/common/system_socket.h @@ -30,4 +30,6 @@ bool parse_ip_mask(const char *str, ctdb_sock_addr *addr, unsigned *mask); +int ctdb_sys_send_arp(const ctdb_sock_addr *addr, const char *iface); + #endif /* __CTDB_SYSTEM_SOCKET_H__ */