From f5a511b72689557db75353eb5bd6c1ea5724f799 Mon Sep 17 00:00:00 2001 From: Ronnie Sahlberg Date: Wed, 20 Jun 2012 13:32:02 +1000 Subject: [PATCH] Add new command to find which interface is located on (cherry picked from commit f07376309e70f5ccdb7de8453caacc71b451ab48) Conflicts: common/system_common.c include/ctdb_private.h tools/ctdb.c --- common/system_common.c | 84 ++++++++++++++++++++++++++++++++++++++++++ include/ctdb_private.h | 1 + tools/ctdb.c | 22 +++++++++++ 3 files changed, 107 insertions(+) diff --git a/common/system_common.c b/common/system_common.c index f28045f9..6ee615fa 100644 --- a/common/system_common.c +++ b/common/system_common.c @@ -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; +} diff --git a/include/ctdb_private.h b/include/ctdb_private.h index 32e8c688..5ff57b67 100644 --- a/include/ctdb_private.h +++ b/include/ctdb_private.h @@ -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); diff --git a/tools/ctdb.c b/tools/ctdb.c index d49bc8f8..69dfc701 100644 --- a/tools/ctdb.c +++ b/tools/ctdb.c @@ -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", " " }, { "writekey", control_writekey, true, false, "write to a database key", " " }, { "checktcpport", control_chktcpport, false, true, "check if a service is bound to a specific tcp port or not", "" }, + { "ipiface", control_ipiface, true, true, "Find which interface an ip address is hsoted on", "" }, }; /* -- 2.34.1