diff options
Diffstat (limited to 'libglusterfs/src')
| -rw-r--r-- | libglusterfs/src/common-utils.c | 232 | ||||
| -rw-r--r-- | libglusterfs/src/common-utils.h | 2 | 
2 files changed, 234 insertions, 0 deletions
diff --git a/libglusterfs/src/common-utils.c b/libglusterfs/src/common-utils.c index ab3674eadec..034e3da25ea 100644 --- a/libglusterfs/src/common-utils.c +++ b/libglusterfs/src/common-utils.c @@ -45,6 +45,7 @@  #include "globals.h"  #include "lkowner.h"  #include "syscall.h" +#include <ifaddrs.h>  #ifndef AI_ADDRCONFIG  #define AI_ADDRCONFIG 0 @@ -2565,3 +2566,234 @@ gf_get_hostname_from_ip (char *client_ip, char **hostname)          return ret;  } + +gf_boolean_t +gf_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; +} + +char * +get_ip_from_addrinfo (struct addrinfo *addr, char **ip) +{ +        char buf[64]; +        void *in_addr = NULL; +        struct sockaddr_in *s4 = NULL; +        struct sockaddr_in6 *s6 = NULL; + +        switch (addr->ai_family) +        { +                case AF_INET: +                        s4 = (struct sockaddr_in *)addr->ai_addr; +                        in_addr = &s4->sin_addr; +                        break; + +                case AF_INET6: +                        s6 = (struct sockaddr_in6 *)addr->ai_addr; +                        in_addr = &s6->sin6_addr; +                        break; + +                default: +                        gf_log ("glusterd", GF_LOG_ERROR, "Invalid family"); +                        return NULL; +        } + +        if (!inet_ntop(addr->ai_family, in_addr, buf, sizeof(buf))) { +                gf_log ("glusterd", GF_LOG_ERROR, "String conversion failed"); +                return NULL; +        } + +        *ip = strdup (buf); +        return *ip; +} + +gf_boolean_t +gf_is_loopback_localhost (const struct sockaddr *sa, char *hostname) +{ +        GF_ASSERT (sa); + +        gf_boolean_t is_local = _gf_false; +        const struct in_addr *addr4 = NULL; +        const struct in6_addr *addr6 = NULL; +        uint8_t      *ap   = NULL; +        struct in6_addr loopbackaddr6 = IN6ADDR_LOOPBACK_INIT; + +        switch (sa->sa_family) { +                case AF_INET: +                        addr4 = &(((struct sockaddr_in *)sa)->sin_addr); +                        ap = (uint8_t*)&addr4->s_addr; +                        if (ap[0] == 127) +                                is_local = _gf_true; +                        break; + +                case AF_INET6: +                        addr6 = &(((struct sockaddr_in6 *)sa)->sin6_addr); +                        if (memcmp (addr6, &loopbackaddr6, +                                    sizeof (loopbackaddr6)) == 0) +                                is_local = _gf_true; +                        break; + +                default: +                        if (hostname) +                                gf_log ("glusterd", GF_LOG_ERROR, +                                        "unknown address family %d for %s", +                                        sa->sa_family, hostname); +                        break; +        } + +        return is_local; +} + +gf_boolean_t +gf_is_local_addr (char *hostname) +{ +        int32_t         ret = -1; +        struct          addrinfo *result = NULL; +        struct          addrinfo *res = NULL; +        gf_boolean_t    found = _gf_false; +        char            *ip = NULL; +        xlator_t        *this = NULL; + +        this = THIS; +        ret = getaddrinfo (hostname, NULL, NULL, &result); + +        if (ret != 0) { +                gf_log (this->name, GF_LOG_ERROR, "error in getaddrinfo: %s\n", +                        gai_strerror(ret)); +                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)); + +                found = gf_is_loopback_localhost (res->ai_addr, hostname) +                        || gf_interface_search (ip); +                if (found) +                        goto out; +        } + +out: +        if (result) +                freeaddrinfo (result); + +        if (!found) +                gf_log (this->name, GF_LOG_DEBUG, "%s is not local", hostname); + +        return found; +} + +gf_boolean_t +gf_is_same_address (char *name1, char *name2) +{ +        struct addrinfo         *addr1 = NULL; +        struct addrinfo         *addr2 = NULL; +        struct addrinfo         *p = NULL; +        struct addrinfo         *q = NULL; +        gf_boolean_t            ret = _gf_false; +        int                     gai_err = 0; + +        gai_err = getaddrinfo(name1,NULL,NULL,&addr1); +        if (gai_err != 0) { +                gf_log (name1, GF_LOG_WARNING, +                        "error in getaddrinfo: %s\n", gai_strerror(gai_err)); +                goto out; +        } + +        gai_err = getaddrinfo(name2,NULL,NULL,&addr2); +        if (gai_err != 0) { +                gf_log (name2, GF_LOG_WARNING, +                        "error in getaddrinfo: %s\n", gai_strerror(gai_err)); +                goto out; +        } + +        for (p = addr1; p; p = p->ai_next) { +                for (q = addr2; q; q = q->ai_next) { +                        if (p->ai_addrlen != q->ai_addrlen) { +                                continue; +                        } +                        if (memcmp(p->ai_addr,q->ai_addr,p->ai_addrlen)) { +                                continue; +                        } +                        ret = _gf_true; +                        goto out; +                } +        } + +out: +        if (addr1) { +                freeaddrinfo(addr1); +        } +        if (addr2) { +                freeaddrinfo(addr2); +        } +        return ret; + +} + diff --git a/libglusterfs/src/common-utils.h b/libglusterfs/src/common-utils.h index 1fb36d658f7..b0d9c18b31d 100644 --- a/libglusterfs/src/common-utils.h +++ b/libglusterfs/src/common-utils.h @@ -582,5 +582,7 @@ char *gf_get_reserved_ports();  int gf_process_reserved_ports (gf_boolean_t ports[]);  gf_boolean_t gf_ports_reserved (char *blocked_port, gf_boolean_t *ports);  int gf_get_hostname_from_ip (char *client_ip, char **hostname); +gf_boolean_t gf_is_local_addr (char *hostname); +gf_boolean_t gf_is_same_address (char *host1, char *host2);  #endif /* _COMMON_UTILS_H */  | 
