convert handling of gratious arps and their controls and helpers to
authorRonnie Sahlberg <ronniesahlberg@gmail.com>
Wed, 4 Jun 2008 05:13:00 +0000 (15:13 +1000)
committerRonnie Sahlberg <ronniesahlberg@gmail.com>
Wed, 4 Jun 2008 05:13:00 +0000 (15:13 +1000)
use the ctdb_sock_addr structure so tehy work for both ipv4 and ipv6

(This used to be ctdb commit 86d6f53512d358ff68b58dac737ffa7576c3cce6)

ctdb/client/ctdb_client.c
ctdb/common/ctdb_util.c
ctdb/common/system_aix.c
ctdb/common/system_linux.c
ctdb/include/ctdb_private.h
ctdb/server/ctdb_takeover.c
ctdb/tools/ctdb.c

index 04befd05cb63f031a4be1485f2a096802c48fe9e..fd9003d107611fbacc1fd4fcff16d25ddb362ae3 100644 (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,
index cb535115b422fbe7fbb4e3aa3cb7eaa0afac09ea..a92a53f1957f7681be211e82114a410770e0349e 100644 (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
  */
index d455ac73dd7bb62577598be3fb649d4f594cbf4f..8742a393c9df8b49ea8991266aaeefb6462cd6cb 100644 (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;
index fb50c6b29b221e7d52859dd501f1228f4ba5f1fd..32db545b09fac144ee7fd05c2ca8ef50de5ca2d3 100644 (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;
+               }
 
-       /* 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;
 }
 
index 2d595ff3a2f4c7d61aee4e8c30bee8a53b80d9f3..8127fd1e06d5ef2ec5d4e6181a29d5b04c83e7fe 100644 (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, 
index 1f1111f1339d262bca1506e3556818d43a45a01f..d9ac49d806e8327de00e916ec0c89b181123f017 100644 (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;
index 6df78130d6e24c815f68c5897209e60735a67ae5..9d6752f13f069925a6387c025c40da75ba668a73 100644 (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;