Whamcloud - gitweb
LU-17186 utils: replace gethostby*() with get*info() 32/52632/10
authorJian Yu <yujian@whamcloud.com>
Tue, 17 Oct 2023 18:06:39 +0000 (11:06 -0700)
committerOleg Drokin <green@whamcloud.com>
Wed, 3 Jan 2024 03:02:22 +0000 (03:02 +0000)
This patch replaces the deprecated gethostbyname() and
gethostbyaddr() functions with getaddrinfo() and getnameinfo()
functions respectively.

The getaddrinfo() function combines the functionality provided by the
gethostbyname() and getservbyname() functions into a single interface,
but unlike the latter functions, getaddrinfo() is reentrant and allows
programs to eliminate IPv4-versus-IPv6 dependencies.

The getnameinfo() function is the inverse of getaddrinfo(): it
converts a socket address to a corresponding host and service, in a
protocol-independent manner. It combines the functionality of
gethostbyaddr() and getservbyport(), but unlike those functions,
getnameinfo() is reentrant and allows programs to eliminate
IPv4-versus-IPv6 dependencies.

Test-Parameters: kerberos=true testlist=sanity-krb5
Test-Parameters: testgroup=review-dne-selinux-ssk-part-2
Signed-off-by: Jian Yu <yujian@whamcloud.com>
Signed-off-by: Sebastien Buisson <sbuisson@ddn.com>
Change-Id: Iacb5583826cd2f7329455bc6cbb4477f9087f15a
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/52632
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: James Simmons <jsimmons@infradead.org>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
libcfs/autoconf/lustre-libcfs.m4
libcfs/libcfs/util/nidstrings.c
lnet/autoconf/lustre-lnet.m4
lustre/autoconf/lustre-core.m4
lustre/utils/gss/lgss_krb5_utils.c
lustre/utils/gss/lsupport.c
lustre/utils/gss/lsupport.h
lustre/utils/nidlist.c
lustre/utils/portals.c

index ac6db4a..85b4f66 100644 (file)
@@ -2700,8 +2700,6 @@ AC_MSG_NOTICE([LibCFS core checks
 
 # libcfs/libcfs/util/nidstrings.c
 AC_CHECK_HEADERS([netdb.h asm/types.h endian.h])
-AC_CHECK_FUNCS([gethostbyname])
-AC_CHECK_FUNCS([getaddrinfo])
 
 # --------  Check for required packages  --------------
 
index 636fa36..c35d30d 100644 (file)
@@ -119,52 +119,60 @@ libcfs_ip_addr2str_size(const __be32 *addr, size_t asize,
  * sscanf may return immediately if it sees the terminating '0' in a string, so
  * I initialise the %n variable to the expected length.  If sscanf sets it;
  * fine, if it doesn't, then the scan ended at the end of the string, which is
- * fine too :) */
+ * fine too :)
+ */
 static int
 libcfs_ip_str2addr(const char *str, int nob, __u32 *addr)
 {
-       unsigned int    a;
-       unsigned int    b;
-       unsigned int    c;
-       unsigned int    d;
-       int             n = nob; /* XscanfX */
+       unsigned int a, b, c, d;
+       int n = nob;
+       int rc = 0;
 
        /* numeric IP? */
        if (sscanf(str, "%u.%u.%u.%u%n", &a, &b, &c, &d, &n) >= 4 &&
            n == nob &&
            (a & ~0xff) == 0 && (b & ~0xff) == 0 &&
            (c & ~0xff) == 0 && (d & ~0xff) == 0) {
-               *addr = ((a<<24)|(b<<16)|(c<<8)|d);
+               *addr = ((a << 24) | (b << 16) | (c << 8) | d);
                return 1;
        }
 
-#ifdef HAVE_GETHOSTBYNAME
        /* known hostname? */
        if (('a' <= str[0] && str[0] <= 'z') ||
            ('A' <= str[0] && str[0] <= 'Z')) {
-               char *tmp;
-
-               tmp = calloc(1, nob + 1);
-               if (tmp != NULL) {
-                       struct hostent *he;
+               char *tmp = NULL;
+               struct addrinfo hints;
+               struct addrinfo *ai = NULL;
+               struct addrinfo *aip = NULL;
 
-                       memcpy(tmp, str, nob);
-                       tmp[nob] = 0;
+               tmp = (char *)alloca(nob + 1);
+               memcpy(tmp, str, nob);
+               tmp[nob] = 0;
 
-                       he = gethostbyname(tmp);
+               memset(&hints, 0, sizeof(struct addrinfo));
+               hints.ai_family = AF_INET;
 
-                       free(tmp);
+               if (getaddrinfo(tmp, NULL, &hints, &ai) != 0) {
+                       rc = 0;
+                       goto out;
+               }
 
-                       if (he != NULL) {
-                               __u32 ip = *(__u32 *)he->h_addr;
+               for (aip = ai; aip; aip = aip->ai_next) {
+                       if (aip->ai_addr) {
+                               struct sockaddr_in *sin = (void *)ai->ai_addr;
 
+                               __u32 ip = (__u32)sin->sin_addr.s_addr;
                                *addr = ntohl(ip);
-                               return 1;
+
+                               rc = 1;
+                               break;
                        }
                }
+
+               freeaddrinfo(ai);
        }
-#endif
-       return 0;
+out:
+       return rc;
 }
 
 static int
@@ -201,13 +209,17 @@ libcfs_ip_str2addr_size(const char *str, int nob,
                        *alen = 16;
                goto out;
        }
-#ifdef HAVE_GETADDRINFO
+
        /* known hostname? */
        if (('a' <= str[0] && str[0] <= 'z') ||
            ('A' <= str[0] && str[0] <= 'Z')) {
                struct addrinfo *ai = NULL;
+               struct addrinfo hints;
 
-               if (getaddrinfo(tmp, NULL, NULL, &ai) == 0) {
+               memset(&hints, 0, sizeof(struct addrinfo));
+               hints.ai_family = AF_INET;
+
+               if (getaddrinfo(tmp, NULL, &hints, &ai) == 0) {
                        struct addrinfo *a;
                        /* First look for an AF_INET address */
                        for (a = ai; a; a = a->ai_next) {
@@ -236,7 +248,6 @@ libcfs_ip_str2addr_size(const char *str, int nob,
                }
                freeaddrinfo(ai);
        }
-#endif
 out:
        free(tmp);
        return *alen != 0;
index ef49c89..094acf8 100644 (file)
@@ -1309,7 +1309,6 @@ AC_COMPILE_IFELSE([AC_LANG_SOURCE([
 
 # lnet/utils/portals.c
 AC_CHECK_HEADERS([netdb.h])
-AC_CHECK_FUNCS([gethostbyname])
 
 # lnet/utils/wirecheck.c
 AC_CHECK_FUNCS([strnlen])
index 89c09fb..d68ed94 100644 (file)
@@ -4824,7 +4824,6 @@ LC_MDS_MAX_THREADS
 # lustre/utils/create_iam.c
 # lustre/utils/libiam.c
 AC_CHECK_HEADERS([netdb.h endian.h])
-AC_CHECK_FUNCS([gethostbyname])
 
 # lustre/utils/llverfs.c lustre/utils/libmount_utils_ldiskfs.c
 AC_CHECK_HEADERS([ext2fs/ext2fs.h], [], [
index ebe09fb..a8ee720 100644 (file)
@@ -187,10 +187,8 @@ int svc_princ_verify_host(krb5_context ctx,
                          loglevel_t loglevel)
 {
        struct utsname utsbuf;
-       struct hostent *host;
        const int max_namelen = 512;
        char namebuf[max_namelen];
-       char *h_name;
 
        if (krb5_princ_component(ctx, princ, 1) == NULL) {
                logmsg(loglevel, "service principal has no host part\n");
@@ -204,28 +202,27 @@ int svc_princ_verify_host(krb5_context ctx,
                               self_nid);
                        return -1;
                }
-               h_name = namebuf;
        } else {
                if (uname(&utsbuf)) {
                        logmsg(loglevel, "get UTS name: %s\n", strerror(errno));
                        return -1;
                }
 
-               host = gethostbyname(utsbuf.nodename);
-               if (host == NULL) {
-                       logmsg(loglevel, "failed to get local hostname\n");
+               if (getcanonname(utsbuf.nodename, namebuf, max_namelen) != 0) {
+                       logmsg(loglevel,
+                               "failed to get canonical name of %s\n",
+                               utsbuf.nodename);
                        return -1;
                }
-               h_name = host->h_name;
        }
 
        if (lgss_krb5_strcasecmp(krb5_princ_component(ctx, princ, 1),
-                                h_name)) {
+                                namebuf)) {
                logmsg(loglevel, "service principal: hostname %.*s "
                       "doesn't match localhost %s\n",
                       krb5_princ_component(ctx, princ, 1)->length,
                       krb5_princ_component(ctx, princ, 1)->data,
-                      h_name);
+                      namebuf);
                return -1;
        }
 
index 545afa3..6e9b382 100644 (file)
@@ -163,24 +163,118 @@ char gethostname_ex[PATH_MAX] = GSSD_DEFAULT_GETHOSTNAME_EX;
 typedef int lnd_nid2hostname_t(char *lnd, uint32_t net, uint32_t addr,
                                char *buf, int buflen);
 
+int getcanonname(const char *host, char *buf, int buflen)
+{
+       struct addrinfo hints;
+       struct addrinfo *ai = NULL;
+       struct addrinfo *aip = NULL;
+       int err = 0;
+       int rc = 0;
+
+       if (!host || host[0] == '\0') {
+               printerr(LL_ERR,
+                        "network address or hostname was not specified\n");
+               return -1;
+       }
+
+       if (!buf) {
+               printerr(LL_ERR,
+                        "canonical name buffer was not defined\n");
+               return -1;
+       }
+
+       if (buflen <= 0) {
+               printerr(LL_ERR,
+                        "invalid canonical name buffer length: %d\n", buflen);
+               return -1;
+       }
+
+       memset(&hints, 0, sizeof(struct addrinfo));
+       hints.ai_family = AF_INET;
+       hints.ai_flags = AI_CANONNAME;
+
+       err = getaddrinfo(host, NULL, &hints, &ai);
+       if (err != 0) {
+               printerr(LL_ERR,
+                        "failed to get addrinfo for %s: %s\n",
+                        host, gai_strerror(err));
+               return -1;
+       }
+
+       for (aip = ai; aip; aip = aip->ai_next) {
+               if (aip->ai_canonname && aip->ai_canonname[0] != '\0')
+                       break;
+       }
+
+       if (!aip) {
+               printerr(LL_ERR, "failed to get canonical name of %s\n", host);
+               rc = -1;
+               goto out;
+       }
+
+       if (strlen(aip->ai_canonname) >= buflen) {
+               printerr(LL_ERR, "canonical name is too long: %s\n",
+                        aip->ai_canonname);
+               rc = -1;
+               goto out;
+       }
+
+       strncpy(buf, aip->ai_canonname, buflen);
+
+out:
+       if (ai != NULL)
+               freeaddrinfo(ai);
+       return rc;
+}
+
+static int getaddrcanonname(const uint32_t addr, char *buf, int buflen)
+{
+       struct sockaddr_in srcaddr;
+       int err = 0;
+       int rc = -1;
+
+       if (!buf) {
+               printerr(LL_ERR,
+                        "canonical name buffer was not defined\n");
+               goto out;
+       }
+
+       if (buflen <= 0) {
+               printerr(LL_ERR,
+                        "invalid canonical name buffer length: %d\n", buflen);
+               goto out;
+       }
+
+       memset(&srcaddr, 0, sizeof(srcaddr));
+       srcaddr.sin_family = AF_INET;
+       srcaddr.sin_addr.s_addr = (in_addr_t)addr;
+
+       err = getnameinfo((struct sockaddr *)&srcaddr, sizeof(srcaddr),
+                         buf, buflen, NULL, 0, 0);
+       if (err != 0) {
+               printerr(LL_ERR,
+                        "failed to get nameinfo for 0x%x: %s\n",
+                        addr, gai_strerror(err));
+               goto out;
+       }
+       rc = 0;
+
+out:
+       return rc;
+}
+
 /* FIXME what about IPv6? */
 static
 int ipv4_nid2hostname(char *lnd, uint32_t net, uint32_t addr,
                      char *buf, int buflen)
 {
-       struct hostent *ent;
-
        addr = htonl(addr);
-       ent = gethostbyaddr(&addr, sizeof(addr), AF_INET);
-       if (!ent) {
-               printerr(LL_ERR, "%s: can't resolve 0x%x\n", lnd, addr);
-               return -1;
-       }
-       if (strlen(ent->h_name) >= buflen) {
-               printerr(LL_ERR, "%s: name too long: %s\n", lnd, ent->h_name);
+
+       if (getaddrcanonname(addr, buf, buflen) != 0) {
+               printerr(LL_ERR, "%s: failed to get canonical name of 0x%x\n",
+                        lnd, addr);
                return -1;
        }
-       strcpy(buf, ent->h_name);
 
        printerr(LL_INFO, "%s: net 0x%x, addr 0x%x => %s\n",
                 lnd, net, addr, buf);
@@ -192,7 +286,6 @@ int lolnd_nid2hostname(char *lnd, uint32_t net, uint32_t addr,
                       char *buf, int buflen)
 {
        struct utsname uts;
-       struct hostent *ent;
 
        if (addr) {
                printerr(LL_ERR, "%s: addr is 0x%x, we expect 0\n", lnd, addr);
@@ -204,19 +297,12 @@ int lolnd_nid2hostname(char *lnd, uint32_t net, uint32_t addr,
                return -1;
        }
 
-       ent = gethostbyname(uts.nodename);
-       if (!ent) {
-               printerr(LL_ERR, "%s: failed obtain canonical name of %s\n",
+       if (getcanonname(uts.nodename, buf, buflen) != 0) {
+               printerr(LL_ERR, "%s: failed to obtain canonical name of %s\n",
                         lnd, uts.nodename);
                return -1;
        }
 
-       if (strlen(ent->h_name) >= buflen) {
-               printerr(LL_ERR, "%s: name too long: %s\n", lnd, ent->h_name);
-               return -1;
-       }
-       strcpy(buf, ent->h_name);
-
        printerr(LL_DEBUG, "%s: addr 0x%x => %s\n", lnd, addr, buf);
        return 0;
 }
index 36b8d67..6d565f8 100644 (file)
@@ -104,6 +104,7 @@ struct lgssd_upcall_data {
 #define GSSD_DEFAULT_GETHOSTNAME_EX     "/etc/lustre/nid2hostname"
 #define MAPPING_DATABASE_FILE           "/etc/lustre/idmap.conf"
 
+int getcanonname(const char *host, char *buf, int buflen);
 int lnet_nid2hostname(lnet_nid_t nid, char *buf, int buflen);
 void cleanup_mapping(void);
 uid_t parse_uid(char *uidstr);
index 3af3c30..4ca40d1 100644 (file)
@@ -198,6 +198,7 @@ static char *nl_nid_lookup_ipaddr(char *nid)
        struct addrinfo *ai, *aip;
        char name[NI_MAXHOST] = "";
        char *p, *addr, *lnet = NULL, *res = NULL;
+       struct addrinfo hints;
        int len, x;
 
        addr = nl_nid_addr(nid);
@@ -205,7 +206,9 @@ static char *nl_nid_lookup_ipaddr(char *nid)
                p = strchr(nid, '@');
                if (p)
                        lnet = p + 1;
-               if (getaddrinfo(addr, NULL, NULL, &ai) == 0) {
+               memset(&hints, 0, sizeof(struct addrinfo));
+               hints.ai_family = AF_INET;
+               if (getaddrinfo(addr, NULL, &hints, &ai) == 0) {
                        for (aip = ai; aip != NULL; aip = aip->ai_next) {
                                if (getnameinfo(aip->ai_addr, aip->ai_addrlen,
                                    name, sizeof(name), NULL, 0,
index 6be4c15..e9ebf3f 100644 (file)
@@ -32,6 +32,9 @@
 #include <string.h>
 #include <sys/ioctl.h>
 #include <sys/time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
 #include <time.h>
 #include <linux/types.h>
 
@@ -97,31 +100,6 @@ lnet_parse_port(int *port, char *str)
        return -1;
 }
 
-#ifdef HAVE_GETHOSTBYNAME
-static struct hostent *
-ptl_gethostbyname(char *hname)
-{
-       struct hostent *he;
-
-       he = gethostbyname(hname);
-       if (!he) {
-               switch (h_errno) {
-               case HOST_NOT_FOUND:
-               case NO_ADDRESS:
-                       fprintf(stderr, "Unable to resolve hostname: %s\n",
-                               hname);
-                       break;
-               default:
-                       fprintf(stderr, "gethostbyname error for %s: %s\n",
-                               hname, strerror(h_errno));
-                       break;
-               }
-               return NULL;
-       }
-       return he;
-}
-#endif
-
 int
 lnet_parse_ipquad(__u32 *ipaddrp, char *str)
 {
@@ -141,9 +119,11 @@ lnet_parse_ipquad(__u32 *ipaddrp, char *str)
 int
 lnet_parse_ipaddr(__u32 *ipaddrp, char *str)
 {
-#ifdef HAVE_GETHOSTBYNAME
-       struct hostent *he;
-#endif
+       struct addrinfo *ai = NULL;
+       struct addrinfo *aip = NULL;
+       struct addrinfo hints;
+       int err = 0;
+       int rc = -1;
 
        if (!strcmp(str, "_all_")) {
                *ipaddrp = 0;
@@ -153,40 +133,67 @@ lnet_parse_ipaddr(__u32 *ipaddrp, char *str)
        if (lnet_parse_ipquad(ipaddrp, str) == 0)
                return 0;
 
-#ifdef HAVE_GETHOSTBYNAME
-       if ((('a' <= str[0] && str[0] <= 'z') ||
-            ('A' <= str[0] && str[0] <= 'Z')) &&
-             (he = ptl_gethostbyname(str)) != NULL) {
-               __u32 addr = *(__u32 *)he->h_addr;
+       memset(&hints, 0, sizeof(struct addrinfo));
+       hints.ai_family = AF_INET;
 
-               *ipaddrp = ntohl(addr);         /* HOST byte order */
-               return 0;
+       if (('a' <= str[0] && str[0] <= 'z') ||
+           ('A' <= str[0] && str[0] <= 'Z')) {
+               err = getaddrinfo(str, NULL, &hints, &ai);
+               if (err != 0) {
+                       fprintf(stderr,
+                               "failed to get addrinfo for %s: %s\n",
+                               str, gai_strerror(err));
+                       return -1;
+               }
+
+               for (aip = ai; aip; aip = aip->ai_next) {
+                       if (aip->ai_family == AF_INET && aip->ai_addr) {
+                               struct sockaddr_in *sin =
+                                       (void *)ai->ai_addr;
+
+                               __u32 addr = (__u32)sin->sin_addr.s_addr;
+                               *ipaddrp = ntohl(addr);
+                               break;
+                       }
+               }
+               /* FIXME: handle AF_INET6 */
+
+               if (!aip) {
+                       fprintf(stderr, "failed to get IP address for %s\n",
+                               str);
+                       rc = -1;
+                       goto out;
+               }
+
+               rc = 0;
+               goto out;
        }
-#endif
 
-       return -1;
+out:
+       if (ai != NULL)
+               freeaddrinfo(ai);
+       return rc;
 }
 
 char *
 ptl_ipaddr_2_str(__u32 ipaddr, char *str, size_t strsize, int lookup)
 {
-#ifdef HAVE_GETHOSTBYNAME
-       __u32 net_ip;
-       struct hostent *he;
+       struct sockaddr_in srcaddr;
 
        if (lookup) {
-               net_ip = htonl(ipaddr);
-               he = gethostbyaddr(&net_ip, sizeof(net_ip), AF_INET);
-               if (he) {
-                       snprintf(str, strsize, "%s", he->h_name);
-                       return str;
-               }
+               memset(&srcaddr, 0, sizeof(srcaddr));
+               srcaddr.sin_family = AF_INET;
+               srcaddr.sin_addr.s_addr = (in_addr_t)htonl(ipaddr);
+
+               if (getnameinfo((struct sockaddr *)&srcaddr, sizeof(srcaddr),
+                                 str, strsize, NULL, 0, 0) == 0)
+                       goto out;
        }
-#endif
 
-       sprintf(str, "%d.%d.%d.%d",
-               (ipaddr >> 24) & 0xff, (ipaddr >> 16) & 0xff,
-               (ipaddr >> 8) & 0xff, ipaddr & 0xff);
+       snprintf(str, strsize, "%d.%d.%d.%d",
+                (ipaddr >> 24) & 0xff, (ipaddr >> 16) & 0xff,
+                (ipaddr >> 8) & 0xff, ipaddr & 0xff);
+out:
        return str;
 }