Add new command to find which interface is located on
authorRonnie Sahlberg <ronniesahlberg@gmail.com>
Wed, 20 Jun 2012 03:32:02 +0000 (13:32 +1000)
committerMartin Schwenke <martin@meltin.net>
Mon, 6 May 2013 23:36:29 +0000 (09:36 +1000)
(cherry picked from commit f07376309e70f5ccdb7de8453caacc71b451ab48)

Conflicts:
common/system_common.c
include/ctdb_private.h
tools/ctdb.c

common/system_common.c
include/ctdb_private.h
tools/ctdb.c

index f28045f95e5362a864ade4dcfa64df4c0886e83e..6ee615fad0a320f7c1c677f6c8c58b38b82437ee 100644 (file)
@@ -73,3 +73,87 @@ bool ctdb_sys_have_ip(ctdb_sock_addr *_addr)
        close(s);
        return ret == 0;
 }
+
+
+/* find which interface an ip address is currently assigned to */
+char *ctdb_sys_find_ifname(ctdb_sock_addr *addr)
+{
+       int s;
+       int size;
+       struct ifconf ifc;
+       char *ptr;
+
+       s = socket(AF_INET, SOCK_RAW, htons(IPPROTO_RAW));
+       if (s == -1) {
+               DEBUG(DEBUG_CRIT,(__location__ " failed to open raw socket (%s)\n",
+                        strerror(errno)));
+               return NULL;
+       }
+
+
+       size = sizeof(struct ifreq);
+       ifc.ifc_buf = NULL;
+       ifc.ifc_len = size;
+
+       while(ifc.ifc_len > (size - sizeof(struct ifreq))) {
+               size *= 2;
+
+               free(ifc.ifc_buf);      
+               ifc.ifc_len = size;
+               ifc.ifc_buf = malloc(size);
+               memset(ifc.ifc_buf, 0, size);
+               if (ioctl(s, SIOCGIFCONF, (caddr_t)&ifc) < 0) {
+                       DEBUG(DEBUG_CRIT,("Failed to read ifc buffer from socket\n"));
+                       free(ifc.ifc_buf);      
+                       close(s);
+                       return NULL;
+               }
+       }
+
+       for (ptr =(char *)ifc.ifc_buf; ptr < ((char *)ifc.ifc_buf) + ifc.ifc_len; ) {
+               char *ifname;
+               struct ifreq *ifr;
+
+               ifr = (struct ifreq *)ptr;
+
+#ifdef HAVE_SOCKADDR_LEN
+               if (ifr->ifr_addr.sa_len > sizeof(struct sockaddr)) {
+                       ptr += sizeof(ifr->ifr_name) + ifr->ifr_addr.sa_len;
+               } else {
+                       ptr += sizeof(ifr->ifr_name) + sizeof(struct sockaddr);
+               }
+#else
+               ptr += sizeof(struct ifreq);
+#endif
+
+               if (ifr->ifr_addr.sa_family != addr->sa.sa_family) {
+                       continue;
+               }
+
+               switch (addr->sa.sa_family) {
+               case AF_INET:
+
+
+                       if (memcmp(&addr->ip.sin_addr, &((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr, sizeof(addr->ip.sin_addr))) {
+                               continue;
+                       }
+                       break;
+               case AF_INET6:
+                       if (memcmp(&addr->ip6.sin6_addr, &((struct sockaddr_in6 *)&ifr->ifr_addr)->sin6_addr, sizeof(addr->ip6.sin6_addr))) {
+                               continue;
+                       }
+                       break;
+               }
+
+               ifname = strdup(ifr->ifr_name);
+               free(ifc.ifc_buf);      
+               close(s);
+               return ifname;
+       }
+
+
+       free(ifc.ifc_buf);      
+       close(s);
+
+       return NULL;
+}
index 32e8c6880b64e766c8256e2b89ce2fe5493261a7..5ff57b6795be8cc64f046b88bb77a009d40d1c8d 100644 (file)
@@ -1114,6 +1114,7 @@ int ctdb_ctrl_set_iface_link(struct ctdb_context *ctdb,
 uint32_t uint16_checksum(uint16_t *data, size_t n);
 int ctdb_sys_send_arp(const ctdb_sock_addr *addr, const char *iface);
 bool ctdb_sys_have_ip(ctdb_sock_addr *addr);
+char *ctdb_sys_find_ifname(ctdb_sock_addr *addr);
 int ctdb_sys_send_tcp(const ctdb_sock_addr *dest, 
                      const ctdb_sock_addr *src,
                      uint32_t seq, uint32_t ack, int rst);
index d49bc8f813346c8362d935db51ae1b647e96a71f..69dfc701f13a8a86c9017511683300298d79d5dc 100644 (file)
@@ -1772,6 +1772,27 @@ static int control_addip(struct ctdb_context *ctdb, int argc, const char **argv)
        return 0;
 }
 
+/*
+  add a public ip address to a node
+ */
+static int control_ipiface(struct ctdb_context *ctdb, int argc, const char **argv)
+{
+       ctdb_sock_addr addr;
+
+       if (argc != 1) {
+               usage();
+       }
+
+       if (!parse_ip(argv[0], NULL, 0, &addr)) {
+               printf("Badly formed ip : %s\n", argv[0]);
+               return -1;
+       }
+
+       printf("IP on interface %s\n", ctdb_sys_find_ifname(&addr));
+
+       return 0;
+}
+
 static int control_delip(struct ctdb_context *ctdb, int argc, const char **argv);
 
 static int control_delip_all(struct ctdb_context *ctdb, int argc, const char **argv, ctdb_sock_addr *addr)
@@ -5020,6 +5041,7 @@ static const struct {
        { "readkey",         control_readkey,           true,   false,  "read the content off a database key", "<tdb-file> <key>" },
        { "writekey",        control_writekey,          true,   false,  "write to a database key", "<tdb-file> <key> <value>" },
        { "checktcpport",    control_chktcpport,        false,  true,  "check if a service is bound to a specific tcp port or not", "<port>" },
+       { "ipiface",         control_ipiface,           true,   true,  "Find which interface an ip address is hsoted on", "<ip>" },
 };
 
 /*