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)
committerMichael Adam <obnox@samba.org>
Fri, 6 Jun 2014 13:00:34 +0000 (15:00 +0200)
(cherry picked from commit f07376309e70f5ccdb7de8453caacc71b451ab48)

Conflicts:

tools/ctdb.c

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

index 9a0600b15f02214013f3aeb268f7afd7ea81f646..78eeb820bbea827e43e9c2e91112122341af418e 100644 (file)
@@ -72,3 +72,85 @@ bool ctdb_sys_have_ip(ctdb_sock_addr *_addr)
 }
 
 
+/* 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 ec2111127f8f18e8d56deef9c3b916e6e23ad17a..b52066015d53afe5ed285b9a3ce9657ea71a5aac 100644 (file)
@@ -1417,6 +1417,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);
 bool ctdb_sys_check_iface_exists(const char *iface);
 int ctdb_sys_send_tcp(const ctdb_sock_addr *dest, 
                      const ctdb_sock_addr *src,
index cb4e240647df5c1985dfdc860717c28f1da8156f..72f1b074efe642097acbd1ca12b89a658c92470b 100644 (file)
@@ -1371,6 +1371,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)
@@ -4481,6 +4502,7 @@ static const struct {
        { "getdbprio",        control_getdbprio,        false,  false, "Get DB priority", "<dbid>"},
        { "msglisten",        control_msglisten,        false,  false, "Listen on a srvid port for messages", "<msg srvid>"},
        { "msgsend",          control_msgsend,  false,  false, "Send a message to srvid", "<srvid> <message>"},
+       { "ipiface",         control_ipiface,           true,   true,  "Find which interface an ip address is hsoted on", "<ip>" },
 };
 
 /*