/* 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()`
*/
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,
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);
}
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
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
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));