From: Pavel Šimerda Date: Wed, 22 Oct 2014 14:37:10 +0000 (+0200) Subject: compat: use AF_INET in legacy gethostbyname as specified by POSIX X-Git-Url: https://www.sourceware.org/git/?a=commitdiff_plain;h=528af2715a2e4f58aeb1216cc5b278ec73ccded1;p=netresolve.git compat: use AF_INET in legacy gethostbyname as specified by POSIX --- diff --git a/compat/libc.c b/compat/libc.c index 78094c3..5ff92d7 100644 --- a/compat/libc.c +++ b/compat/libc.c @@ -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); } diff --git a/tests/test-gethostbyname.c b/tests/test-gethostbyname.c index 4597472..d684cc4 100644 --- a/tests/test-gethostbyname.c +++ b/tests/test-gethostbyname.c @@ -29,7 +29,11 @@ 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));