1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-02 09:47:23 +03:00

convert handling of gratious arps and their controls and helpers to

use the ctdb_sock_addr structure so tehy work for both ipv4 and ipv6

(This used to be ctdb commit 86d6f53512d358ff68b58dac737ffa7576c3cce6)
This commit is contained in:
Ronnie Sahlberg 2008-06-04 15:13:00 +10:00
parent 1c88f422d5
commit 7d39ac131b
7 changed files with 158 additions and 109 deletions

View File

@ -2385,27 +2385,27 @@ int ctdb_ctrl_killtcp(struct ctdb_context *ctdb,
int ctdb_ctrl_gratious_arp(struct ctdb_context *ctdb,
struct timeval timeout,
uint32_t destnode,
struct sockaddr_in *sin,
ctdb_sock_addr *addr,
const char *ifname)
{
TDB_DATA data;
int32_t res;
int ret, len;
struct ctdb_control_ip_iface *gratious_arp;
struct ctdb_control_gratious_arp *gratious_arp;
TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
len = strlen(ifname)+1;
gratious_arp = talloc_size(tmp_ctx,
offsetof(struct ctdb_control_ip_iface, iface) + len);
offsetof(struct ctdb_control_gratious_arp, iface) + len);
CTDB_NO_MEMORY(ctdb, gratious_arp);
gratious_arp->sin = *sin;
gratious_arp->addr = *addr;
gratious_arp->len = len;
memcpy(&gratious_arp->iface[0], ifname, len);
data.dsize = offsetof(struct ctdb_control_ip_iface, iface) + len;
data.dsize = offsetof(struct ctdb_control_gratious_arp, iface) + len;
data.dptr = (unsigned char *)gratious_arp;
ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_SEND_GRATIOUS_ARP, 0, data, NULL,

View File

@ -370,6 +370,25 @@ bool parse_ip_port(const char *addr, ctdb_sock_addr *saddr)
return ret;
}
/*
parse an ip
*/
bool parse_ip(const char *addr, ctdb_sock_addr *saddr)
{
char *p;
bool ret;
/* now is this a ipv4 or ipv6 address ?*/
p = index(addr, ':');
if (p == NULL) {
ret = parse_ipv4(addr, 0, saddr);
} else {
ret = parse_ipv6(addr, 0, saddr);
}
return ret;
}
/*
parse a ip/mask pair
*/

View File

@ -220,7 +220,7 @@ int ctdb_sys_close_capture_socket(void *private_data)
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 struct sockaddr_in *saddr, const char *iface)
int ctdb_sys_send_arp(const ctdb_sock_addr *addr, const char *iface)
{
/* We dont do grat arp on aix yet */
return 0;

View File

@ -36,7 +36,7 @@
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 struct sockaddr_in *saddr, const char *iface)
int ctdb_sys_send_arp(const ctdb_sock_addr *addr, const char *iface)
{
int s, ret;
struct sockaddr sa;
@ -48,92 +48,94 @@ int ctdb_sys_send_arp(const struct sockaddr_in *saddr, const char *iface)
ZERO_STRUCT(sa);
/* for now, we only handle AF_INET addresses */
if (saddr->sin_family != AF_INET) {
DEBUG(DEBUG_CRIT,(__location__ " not an ipv4 address (family is %u)\n", saddr->sin_family));
return -1;
}
switch (addr->ip.sin_family) {
case AF_INET:
s = socket(AF_INET, SOCK_PACKET, htons(ETHERTYPE_ARP));
if (s == -1){
DEBUG(DEBUG_CRIT,(__location__ " failed to open raw socket\n"));
return -1;
}
s = socket(AF_INET, SOCK_PACKET, htons(ETHERTYPE_ARP));
if (s == -1){
DEBUG(DEBUG_CRIT,(__location__ " failed to open raw socket\n"));
return -1;
}
/* get the mac address */
strcpy(if_hwaddr.ifr_name, iface);
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 != AF_LOCAL) {
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;
strncpy(sa.sa_data, iface, sizeof(sa.sa_data));
ret = sendto(s, buffer, 64, 0, &sa, sizeof(sa));
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;
strncpy(sa.sa_data, iface, sizeof(sa.sa_data));
ret = sendto(s, buffer, 64, 0, &sa, sizeof(sa));
if (ret < 0 ){
DEBUG(DEBUG_CRIT,(__location__ " failed sendto\n"));
return -1;
}
/* get the mac address */
strcpy(if_hwaddr.ifr_name, iface);
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 != AF_LOCAL) {
close(s);
errno = EINVAL;
DEBUG(DEBUG_CRIT,(__location__ " not an ethernet address family (0x%x)\n",
if_hwaddr.ifr_hwaddr.sa_family));
break;
default:
DEBUG(DEBUG_CRIT,(__location__ " not an ipv4 address (family is %u)\n", addr->ip.sin_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, &saddr->sin_addr, 4);
ptr+=4;
memset(ptr, 0, ETH_ALEN);
ptr+=ETH_ALEN;
memcpy(ptr, &saddr->sin_addr, 4);
ptr+=4;
strncpy(sa.sa_data, iface, sizeof(sa.sa_data));
ret = sendto(s, buffer, 64, 0, &sa, sizeof(sa));
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, &saddr->sin_addr, 4);
ptr+=4;
memcpy(ptr, if_hwaddr.ifr_hwaddr.sa_data, ETH_ALEN);
ptr+=ETH_ALEN;
memcpy(ptr, &saddr->sin_addr, 4);
ptr+=4;
strncpy(sa.sa_data, iface, sizeof(sa.sa_data));
ret = sendto(s, buffer, 64, 0, &sa, sizeof(sa));
if (ret < 0 ){
DEBUG(DEBUG_CRIT,(__location__ " failed sendto\n"));
return -1;
}
close(s);
return 0;
}

View File

@ -567,9 +567,8 @@ struct ctdb_control_killtcp {
/*
struct holding a sockaddr_in and an interface name,
used for send_gratious_arp and also add/remove public addresses
used to add/remove public addresses
*/
//struct ctdb_control_gratious_arp {
struct ctdb_control_ip_iface {
struct sockaddr_in sin;
uint32_t mask;
@ -577,6 +576,17 @@ struct ctdb_control_ip_iface {
char iface[1];
};
/*
struct holding a ctdb_sock_addr and an interface name,
used for send_gratious_arp
*/
struct ctdb_control_gratious_arp {
ctdb_sock_addr addr;
uint32_t mask;
uint32_t len;
char iface[1];
};
/*
struct for tcp_add and tcp_remove controls
*/
@ -1166,7 +1176,7 @@ int ctdb_ctrl_get_public_ips(struct ctdb_context *ctdb,
/* from takeover/system.c */
int ctdb_sys_send_arp(const struct sockaddr_in *saddr, const char *iface);
int ctdb_sys_send_arp(const ctdb_sock_addr *addr, const char *iface);
bool ctdb_sys_have_ip(struct sockaddr_in ip);
int ctdb_sys_send_tcp(const ctdb_sock_addr *dest,
const ctdb_sock_addr *src,
@ -1225,6 +1235,7 @@ int ctdb_ctrl_get_all_tunables(struct ctdb_context *ctdb,
void ctdb_start_freeze(struct ctdb_context *ctdb);
bool parse_ip_port(const char *s, ctdb_sock_addr *saddr);
bool parse_ip(const char *s, ctdb_sock_addr *saddr);
int ctdb_sys_open_capture_socket(const char *iface, void **private_data);
int ctdb_sys_close_capture_socket(void *private_data);
@ -1249,7 +1260,7 @@ int ctdb_ctrl_del_public_ip(struct ctdb_context *ctdb,
int ctdb_ctrl_gratious_arp(struct ctdb_context *ctdb,
struct timeval timeout,
uint32_t destnode,
struct sockaddr_in *sin,
ctdb_sock_addr *addr,
const char *ifname);
int ctdb_ctrl_get_tcp_tickles(struct ctdb_context *ctdb,

View File

@ -36,7 +36,7 @@
struct ctdb_takeover_arp {
struct ctdb_context *ctdb;
uint32_t count;
struct sockaddr_in sin;
ctdb_sock_addr addr;
struct ctdb_tcp_array *tcparray;
struct ctdb_vnn *vnn;
};
@ -73,7 +73,7 @@ static void ctdb_control_send_arp(struct event_context *ev, struct timed_event *
struct ctdb_tcp_array *tcparray;
ret = ctdb_sys_send_arp(&arp->sin, arp->vnn->iface);
ret = ctdb_sys_send_arp(&arp->addr, arp->vnn->iface);
if (ret != 0) {
DEBUG(DEBUG_CRIT,(__location__ " sending of arp failed (%s)\n", strerror(errno)));
}
@ -123,10 +123,27 @@ static void takeover_ip_callback(struct ctdb_context *ctdb, int status,
struct takeover_callback_state *state =
talloc_get_type(private_data, struct takeover_callback_state);
struct ctdb_takeover_arp *arp;
char *ip = inet_ntoa(state->sin->sin_addr);
struct ctdb_tcp_array *tcparray;
if (status != 0) {
char ip[128] = "";
switch(state->sin->sin_family){
case AF_INET:
if (inet_ntop(AF_INET, &state->sin->sin_addr, ip, sizeof(ip)) == NULL) {
DEBUG(DEBUG_ERR, (__location__ " inet_ntop() failed\n"));
}
break;
case AF_INET6:
if (inet_ntop(AF_INET6, &state->sin->sin_addr, ip, sizeof(ip)) == NULL) {
DEBUG(DEBUG_ERR, (__location__ " inet_ntop() failed\n"));
}
break;
default:
DEBUG(DEBUG_ERR, (__location__ " cant convert this address family to a string\n"));
break;
}
DEBUG(DEBUG_ERR,(__location__ " Failed to takeover IP %s on interface %s\n",
ip, state->vnn->iface));
ctdb_request_control_reply(ctdb, state->c, NULL, status, NULL);
@ -145,7 +162,9 @@ static void takeover_ip_callback(struct ctdb_context *ctdb, int status,
if (!arp) goto failed;
arp->ctdb = ctdb;
arp->sin = *state->sin;
/* qqq convert state->sin from sockaddr_in to ctdb_sock_addr
no need to cast then*/
arp->addr.ip = *((ctdb_addr_in *)state->sin);
arp->vnn = state->vnn;
tcparray = state->vnn->tcp_array;
@ -1717,7 +1736,7 @@ void ctdb_start_tcp_tickle_update(struct ctdb_context *ctdb)
struct control_gratious_arp {
struct ctdb_context *ctdb;
struct sockaddr_in sin;
ctdb_sock_addr addr;
const char *iface;
int count;
};
@ -1732,7 +1751,7 @@ static void send_gratious_arp(struct event_context *ev, struct timed_event *te,
struct control_gratious_arp *arp = talloc_get_type(private_data,
struct control_gratious_arp);
ret = ctdb_sys_send_arp(&arp->sin, arp->iface);
ret = ctdb_sys_send_arp(&arp->addr, arp->iface);
if (ret != 0) {
DEBUG(DEBUG_ERR,(__location__ " sending of gratious arp failed (%s)\n", strerror(errno)));
}
@ -1755,23 +1774,22 @@ static void send_gratious_arp(struct event_context *ev, struct timed_event *te,
*/
int32_t ctdb_control_send_gratious_arp(struct ctdb_context *ctdb, TDB_DATA indata)
{
struct ctdb_control_ip_iface *gratious_arp = (struct ctdb_control_ip_iface *)indata.dptr;
struct ctdb_control_gratious_arp *gratious_arp = (struct ctdb_control_gratious_arp *)indata.dptr;
struct control_gratious_arp *arp;
/* verify the size of indata */
if (indata.dsize < offsetof(struct ctdb_control_ip_iface, iface)) {
DEBUG(DEBUG_ERR,(__location__ " Too small indata to hold a ctdb_control_ip_iface structure\n"));
if (indata.dsize < offsetof(struct ctdb_control_gratious_arp, iface)) {
DEBUG(DEBUG_ERR,(__location__ " Too small indata to hold a ctdb_control_gratious_arp structure. Got %u require %u bytes\n", indata.dsize, offsetof(struct ctdb_control_gratious_arp, iface)));
return -1;
}
if (indata.dsize !=
( offsetof(struct ctdb_control_ip_iface, iface)
( offsetof(struct ctdb_control_gratious_arp, iface)
+ gratious_arp->len ) ){
DEBUG(DEBUG_ERR,(__location__ " Wrong size of indata. Was %u bytes "
"but should be %u bytes\n",
(unsigned)indata.dsize,
(unsigned)(offsetof(struct ctdb_control_ip_iface, iface)+gratious_arp->len)));
(unsigned)(offsetof(struct ctdb_control_gratious_arp, iface)+gratious_arp->len)));
return -1;
}
@ -1780,7 +1798,7 @@ int32_t ctdb_control_send_gratious_arp(struct ctdb_context *ctdb, TDB_DATA indat
CTDB_NO_MEMORY(ctdb, arp);
arp->ctdb = ctdb;
arp->sin = gratious_arp->sin;
arp->addr = gratious_arp->addr;
arp->iface = talloc_strdup(arp, gratious_arp->iface);
CTDB_NO_MEMORY(ctdb, arp->iface);
arp->count = 0;

View File

@ -837,19 +837,18 @@ static int kill_tcp(struct ctdb_context *ctdb, int argc, const char **argv)
static int control_gratious_arp(struct ctdb_context *ctdb, int argc, const char **argv)
{
int ret;
struct sockaddr_in sin;
ctdb_sock_addr addr;
if (argc < 2) {
usage();
}
sin.sin_family = AF_INET;
if (inet_aton(argv[0], &sin.sin_addr) == 0) {
DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
if (!parse_ip(argv[0], &addr)) {
DEBUG(DEBUG_ERR, ("Bad IP '%s'\n", argv[0]));
return -1;
}
ret = ctdb_ctrl_gratious_arp(ctdb, TIMELIMIT(), options.pnn, &sin, argv[1]);
ret = ctdb_ctrl_gratious_arp(ctdb, TIMELIMIT(), options.pnn, &addr, argv[1]);
if (ret != 0) {
DEBUG(DEBUG_ERR, ("Unable to send gratious_arp from node %u\n", options.pnn));
return ret;