diff options
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-utils.c | 97 |
1 files changed, 78 insertions, 19 deletions
diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c index f778ec76318..e3e77eb0a4c 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.c +++ b/xlators/mgmt/glusterd/src/glusterd-utils.c @@ -48,6 +48,7 @@ #include <unistd.h> #include <fnmatch.h> #include <sys/statvfs.h> +#include <ifaddrs.h> #ifdef GF_LINUX_HOST_OS #include <mntent.h> @@ -192,13 +193,85 @@ get_ip_from_addrinfo (struct addrinfo *addr, char **ip) } gf_boolean_t +glusterd_interface_search (char *ip) +{ + int32_t ret = -1; + gf_boolean_t found = _gf_false; + struct ifaddrs *ifaddr, *ifa; + int family; + char host[NI_MAXHOST]; + xlator_t *this = NULL; + char *pct = NULL; + + this = THIS; + + ret = getifaddrs (&ifaddr); + + if (ret != 0) { + gf_log (this->name, GF_LOG_ERROR, "getifaddrs() failed: %s\n", + gai_strerror(ret)); + goto out; + } + + for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { + if (!ifa->ifa_addr) { + /* + * This seemingly happens if an interface hasn't + * been bound to a particular protocol (seen with + * TUN devices). + */ + continue; + } + family = ifa->ifa_addr->sa_family; + + if (family != AF_INET && family != AF_INET6) + continue; + + ret = getnameinfo (ifa->ifa_addr, + (family == AF_INET) ? sizeof(struct sockaddr_in) : + sizeof(struct sockaddr_in6), + host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); + + if (ret != 0) { + gf_log (this->name, GF_LOG_ERROR, + "getnameinfo() failed: %s\n", + gai_strerror(ret)); + goto out; + } + + /* + * Sometimes the address comes back as addr%eth0 or + * similar. Since % is an invalid character, we can + * strip it out with confidence that doing so won't + * harm anything. + */ + pct = index(host,'%'); + if (pct) { + *pct = '\0'; + } + + if (strncmp (ip, host, NI_MAXHOST) == 0) { + gf_log (this->name, GF_LOG_DEBUG, + "%s is local address at interface %s", + ip, ifa->ifa_name); + found = _gf_true; + goto out; + } + } +out: + if(ifaddr) + freeifaddrs (ifaddr); + return found; +} + + +gf_boolean_t glusterd_is_local_addr (char *hostname) { int32_t ret = -1; struct addrinfo *result = NULL; struct addrinfo *res = NULL; gf_boolean_t found = _gf_false; - int sd = -1; char *ip = NULL; xlator_t *this = NULL; @@ -212,27 +285,13 @@ glusterd_is_local_addr (char *hostname) } for (res = result; res != NULL; res = res->ai_next) { - found = glusterd_is_loopback_localhost (res->ai_addr, hostname); - if (found) - goto out; - } - - for (res = result; res != NULL; res = res->ai_next) { gf_log (this->name, GF_LOG_DEBUG, "%s ", get_ip_from_addrinfo (res, &ip)); - sd = socket (res->ai_family, SOCK_DGRAM, 0); - if (sd == -1) + + found = glusterd_is_loopback_localhost (res->ai_addr, hostname) + || glusterd_interface_search (ip); + if (found) goto out; - /*If bind succeeds then its a local address*/ - ret = bind (sd, res->ai_addr, res->ai_addrlen); - if (ret == 0) { - found = _gf_true; - gf_log (this->name, GF_LOG_DEBUG, "%s is local", - get_ip_from_addrinfo (res, &ip)); - close (sd); - break; - } - close (sd); } out: |