gethostbyname3() is a deprecated C function that resolves a hostname (like example.com) into one or more IP addresses, returning them in a thread-unsafe static structure. You should use getaddrinfo() instead, because it is thread-safe, supports IPv6, and provides richer control over address selection.
Background: Why gethostbyname3 Exists
The original gethostbyname() appeared in early BSD sockets and became part of POSIX. It returns a pointer to a static struct hostent that contains the host’s official name, aliases, address type, address length, and a list of addresses. The “3” suffix in gethostbyname3() is a GNU extension that adds two extra parameters: the address family (AF_INET or AF_INET6) and flags that control whether to use DNS, NIS, or other name services. It was introduced to give programmers some IPv6 support without requiring a full rewrite, but it never became a standard and is now considered obsolete.
How gethostbyname3 Works
The function signature is:
struct hostent *gethostbyname3(const char *name, int af, int flags);
It performs a lookup using the system’s configured name services (often DNS, but also /etc/hosts or NIS). The af parameter lets you request only IPv4 (AF_INET) or only IPv6 (AF_INET6) results. The flags parameter can include AI_V4MAPPED or AI_ALL, which control whether IPv4 addresses are returned as IPv4-mapped IPv6 addresses. The function returns a pointer to a hostent structure, or NULL on error.
Why It Is Deprecated and Problematic
Several serious issues make gethostbyname3 a bad choice for modern code:
- Thread safety: The returned
hostentis stored in a static buffer. Two threads calling the function concurrently can overwrite each other’s data, causing race conditions. - No IPv6 support in the original: The original
gethostbynameonly returned IPv4 addresses. The “3” variant adds IPv6 but does so inconsistently across platforms. - No control over address selection: You cannot specify whether you want a stream socket or a datagram socket, or whether you need a numeric address. This often leads to connecting to the wrong address when multiple are available.
- No error details: The
h_errnoglobal variable is used for errors, which is not thread-safe and provides less information than thegai_strerror()function used withgetaddrinfo(). - Not portable:
gethostbyname3is a GNU extension and is not available on all Unix-like systems or on Windows.
What to Use Instead: getaddrinfo()
The modern replacement is getaddrinfo(), which is part of the POSIX standard and available on virtually all platforms, including Windows. Its signature is:
int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res);
It returns a linked list of struct addrinfo entries, each containing a socket address structure ready for use with socket() and connect(). The hints parameter lets you filter by address family, socket type, protocol, and flags. For example, to get a TCP stream socket, you set ai_socktype = SOCK_STREAM. To force IPv4 or IPv6, set ai_family = AF_INET or AF_INET6. To get only numeric addresses (no DNS), set AI_NUMERICHOST.
How to Use getaddrinfo() Correctly
Here is a minimal example that resolves a hostname and prints all returned IP addresses:
struct addrinfo hints, *res, *p;
int status;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; // IPv4 or IPv6
hints.ai_socktype = SOCK_STREAM;
status = getaddrinfo("example.com", "http", &hints, &res);
if (status != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
return 1;
}
for (p = res; p != NULL; p = p->ai_next) {
void *addr;
char ipstr[INET6_ADDRSTRLEN];
if (p->ai_family == AF_INET) {
struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr;
addr = &(ipv4->sin_addr);
} else {
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr;
addr = &(ipv6->sin6_addr);
}
inet_ntop(p->ai_family, addr, ipstr, sizeof ipstr);
printf("%s\n", ipstr);
}
freeaddrinfo(res); // always free the linked list
Notice that you must call freeaddrinfo() when done, which is a small price for the safety and flexibility you get.
When You Might Still See gethostbyname3
Legacy codebases, especially those written in the late 1990s or early 2000s, may still use gethostbyname3 because it was a quick fix for IPv6 before getaddrinfo() became widely available. Some older open-source projects have it in their code, and you might encounter it when maintaining such software. However, modern compilers often emit deprecation warnings when they see it, and many distributions have removed it from their headers entirely. If you are writing new code, there is no reason to use it.
Common Mistakes and Misconceptions
- Assuming gethostbyname3 returns all addresses: It does, but they are in a static array that can be overwritten by the next call. If you need to keep them, you must copy them immediately.
- Mixing up the flags: The flags parameter is not the same as the
ai_flagsingetaddrinfo(). The latter has a well-defined set (AI_PASSIVE, AI_CANONNAME, etc.), while the former is less standardized. - Forgetting to check the return value:
getaddrinfo()returns an integer error code, not NULL. Many beginners check for NULL and then wonder why they get a segfault. - Not freeing the result:
freeaddrinfo()is essential to avoid memory leaks. The linked list is dynamically allocated.
Frequently Asked Questions
Is gethostbyname3 still available on Linux?
Yes, glibc still provides it for binary compatibility, but it is not declared in the default feature test macros. You may need to define _GNU_SOURCE to get the declaration. However, it is marked as deprecated and you will get warnings if you enable -Wdeprecated-declarations.
What is the difference between gethostbyname2 and gethostbyname3?
gethostbyname2 takes only two arguments: the hostname and the address family. gethostbyname3 adds a third argument for flags. Both are obsolete; use getaddrinfo().
Can I use getaddrinfo() on Windows?
Yes, getaddrinfo() is available on Windows XP and later. You need to include <ws2tcpip.h> and link against Ws2_32.lib. The API is the same as on POSIX systems.
Does getaddrinfo() support /etc/hosts?
Yes, it uses the system’s name resolution configuration, which typically includes the hosts file. If you want to bypass DNS and only use the hosts file, you can set the AI_NUMERICHOST flag, but that only works for numeric addresses. There is no standard flag to force hosts-file-only lookup; that depends on the system’s nsswitch.conf.
How do I get only IPv6 addresses with getaddrinfo()?
Set hints.ai_family = AF_INET6. The returned list will contain only IPv6 addresses. If you want to allow IPv4-mapped IPv6 addresses, you can set AI_V4MAPPED in hints.ai_flags.
What does the error code EAI_NONAME mean?
It means the hostname or service was not found. This is the equivalent of the old HOST_NOT_FOUND from h_errno. You can use gai_strerror() to get a human-readable message.
Related
Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.
More cards in this drawer
- Best CS 1.6 Server Hosting: Options and How to Choose
- Best Secure Web Browsers for Privacy in 2026
- Nothing Phone 1: Specs, Updates and Buying Advice
- To-Do Lists for Mac: Apps, Features, and How to Choose
- Best Privacy Web Browsers: Which One Should You Use?
- Tower Defense Simulator TDS Codes: What Works Now