diff options
Diffstat (limited to 'ctdb')
-rw-r--r-- | ctdb/client/ctdb_client.c | 10 | ||||
-rw-r--r-- | ctdb/common/ctdb_util.c | 19 | ||||
-rw-r--r-- | ctdb/common/system_aix.c | 2 | ||||
-rw-r--r-- | ctdb/common/system_linux.c | 160 | ||||
-rw-r--r-- | ctdb/include/ctdb_private.h | 19 | ||||
-rw-r--r-- | ctdb/server/ctdb_takeover.c | 44 | ||||
-rw-r--r-- | ctdb/tools/ctdb.c | 9 |
7 files changed, 156 insertions, 107 deletions
diff --git a/ctdb/client/ctdb_client.c b/ctdb/client/ctdb_client.c index 04befd05cb6..fd9003d1076 100644 --- a/ctdb/client/ctdb_client.c +++ b/ctdb/client/ctdb_client.c @@ -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, diff --git a/ctdb/common/ctdb_util.c b/ctdb/common/ctdb_util.c index cb535115b42..a92a53f1957 100644 --- a/ctdb/common/ctdb_util.c +++ b/ctdb/common/ctdb_util.c @@ -371,6 +371,25 @@ bool parse_ip_port(const char *addr, ctdb_sock_addr *saddr) } /* + 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 */ bool parse_ip_mask(const char *s, struct sockaddr_in *ip, unsigned *mask) diff --git a/ctdb/common/system_aix.c b/ctdb/common/system_aix.c index d455ac73dd7..8742a393c9d 100644 --- a/ctdb/common/system_aix.c +++ b/ctdb/common/system_aix.c @@ -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; diff --git a/ctdb/common/system_linux.c b/ctdb/common/system_linux.c index fb50c6b29b2..32db545b09f 100644 --- a/ctdb/common/system_linux.c +++ b/ctdb/common/system_linux.c @@ -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; + } - /* 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; + } - 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")); + break; + default: + DEBUG(DEBUG_CRIT,(__location__ " not an ipv4 address (family is %u)\n", addr->ip.sin_family)); return -1; } - close(s); return 0; } diff --git a/ctdb/include/ctdb_private.h b/ctdb/include/ctdb_private.h index 2d595ff3a2f..8127fd1e06d 100644 --- a/ctdb/include/ctdb_private.h +++ b/ctdb/include/ctdb_private.h @@ -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; @@ -578,6 +577,17 @@ struct ctdb_control_ip_iface { }; /* + 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 */ struct ctdb_control_tcp_vnn { @@ -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, diff --git a/ctdb/server/ctdb_takeover.c b/ctdb/server/ctdb_takeover.c index 1f1111f1339..d9ac49d806e 100644 --- a/ctdb/server/ctdb_takeover.c +++ b/ctdb/server/ctdb_takeover.c @@ -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; diff --git a/ctdb/tools/ctdb.c b/ctdb/tools/ctdb.c index 6df78130d6e..9d6752f13f0 100644 --- a/ctdb/tools/ctdb.c +++ b/ctdb/tools/ctdb.c @@ -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; |