compat: use AF_INET in legacy gethostbyname as specified by POSIX
authorPavel Šimerda <psimerda@redhat.com>
Wed, 22 Oct 2014 14:37:10 +0000 (16:37 +0200)
committerPavel Šimerda <psimerda@redhat.com>
Wed, 22 Oct 2014 15:16:07 +0000 (17:16 +0200)
compat/libc.c
tests/test-gethostbyname.c

index 78094c305c46353a4fc72c732b49d5f6c6fa49fc..5ff92d73e3a85bd5c41a3abaf3486dd1ed70c0c3 100644 (file)
@@ -69,8 +69,17 @@ freeaddrinfo(struct addrinfo *result)
 
 /* gethostbyname2:
  *
- * Extended version of `gethostbyname()` with the capability to select address
- * family.
+ * Legacy extended version of `gethostbyname()`o lookup either IPv4 or IPv6 addresses for a
+ * specified family. Result for AF_UNSPEC is not specified.
+ *
+ * Replaced by `getaddrinfo()` as follows:
+ *
+ *  * nodename = node
+ *  * servname = NULL
+ *  * hints.family = family
+ *  * hints.socktype = SOCK_RAW
+ *
+ * See notes for `gethostbyname()`.
  *
  * GNU extention to POSIX.1-2001 `gethostbyname()`
  */
@@ -93,21 +102,37 @@ gethostbyname2(const char *node, int family)
        return he;
 }
 
+/* Legacy functions without a family parameter will only lookup IPv4. */
+#define GETHOSTBYNAME_FAMILY AF_INET
+
 /* gethostbyname:
  *
- * Caller doesn't free the result of this function. Instead, it is kept,
- * referenced by a static pointer, until the next call of `gethostbyname()`,
- * making `gethostbyname()` not reentrant by definition and the answer to the
- * last request is never freed.
+ * Legacy API to lookup IPv4 addresses for a specified hostname. Memory for
+ * the result is allocated in a static buffer. The caller must not free it
+ * and the function is not reentrant.
+ *
+ * Replaced by `getaddrinfo()` as follows:
+ *
+ *  * nodename = node
+ *  * servname = NULL
+ *  * hints.family = AF_INET
+ *  * hints.socktype = SOCK_RAW
+ *
+ * Note: Using SOCK_RAW is not explicitly mandated by POSIX but it is required
+ * by the GNU implementation.
  *
  * Defined in POSIX.1-2001, removed in POSIX.1-2008.
  */
 struct hostent *
 gethostbyname(const char *node)
 {
-       return gethostbyname2(node, AF_UNSPEC);
+       return gethostbyname2(node, GETHOSTBYNAME_FAMILY);
 }
 
+/* gethostbyname2_r:
+ *
+ * Reentrant version of `gethostbyname2()`, see notes for `gethostbyname()`.
+ */
 int
 gethostbyname2_r(const char *name, int family,
                struct hostent *he, char *buffer, size_t buflen,
@@ -170,10 +195,14 @@ gethostbyname2_r(const char *name, int family,
        return 0;
 }
 
+/* gethostbyname2_r:
+ *
+ * Reentrant version of `gethostbyname()`, see notes for `gethostbyname()`.
+ */
 int
 gethostbyname_r(const char *name,
                struct hostent *he, char *buffer, size_t buflen,
                struct hostent **result, int *h_errnop)
 {
-       return gethostbyname2_r(name, AF_UNSPEC, he, buffer, buflen, result, h_errnop);
+       return gethostbyname2_r(name, GETHOSTBYNAME_FAMILY, he, buffer, buflen, result, h_errnop);
 }
index 45974724a67bc2f5cd16d0799804891a2e6af3be..d684cc47ac2a7a13e1daa763188f3118899abad5 100644 (file)
 int
 main(int argc, char **argv)
 {
+#ifdef GETHOSTBYNAME2
        const char *node = "1:2:3:4:5:6:7:8";
+#else
+       const char *node = "1.2.3.4";
+#endif
        struct hostent *result = NULL;
 
 #ifdef REENTRANT
@@ -38,7 +42,7 @@ main(int argc, char **argv)
        char buffer[buflen];
        int my_errno, my_h_errno;
 #ifdef GETHOSTBYNAME2
-       my_errno = gethostbyname2_r(node, AF_UNSPEC, &he, buffer, buflen, &result, &my_h_errno);
+       my_errno = gethostbyname2_r(node, AF_INET6, &he, buffer, buflen, &result, &my_h_errno);
 #else
        my_errno = gethostbyname_r(node, &he, buffer, buflen, &result, &my_h_errno);
 #endif
@@ -46,24 +50,41 @@ main(int argc, char **argv)
        assert(result == &he);
 #else
 #ifdef GETHOSTBYNAME2
-       result = gethostbyname2(node, AF_UNSPEC);
+       result = gethostbyname2(node, AF_INET6);
 #else
        result = gethostbyname(node);
 #endif
 #endif
        assert(result && result->h_addr_list[0]);
 
-       struct { struct hostent he; char *ha[1]; char *al[2]; struct in6_addr ia; } expected = {
+       struct {
+               struct hostent he;
+               char *ha[1];
+               char *al[2];
+#ifdef GETHOSTBYNAME2
+               struct in6_addr ia;
+#else
+               struct in_addr ia;
+#endif
+       } expected = {
                .he = {
                        .h_name = result->h_name,
                        .h_aliases = result->h_aliases,
+#ifdef GETHOSTBYNAME2
                        .h_addrtype = AF_INET6,
+#else
+                       .h_addrtype = AF_INET,
+#endif
                        .h_length = sizeof expected.ia,
                        .h_addr_list = result->h_addr_list,
                },
                .ha = { NULL },
                .al = { *result->h_addr_list, NULL },
+#ifdef GETHOSTBYNAME2
                .ia = { .s6_addr = { 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8} }
+#else
+               .ia = { .s_addr = htonl(0x01020304) }
+#endif
        };
        assert(!memcmp(result, &expected.he, sizeof expected.he));
        assert(result->h_name && !strcmp(result->h_name, node));
This page took 0.047889 seconds and 5 git commands to generate.