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:
parent
1c88f422d5
commit
7d39ac131b
@ -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,
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user