gethostbyname(3)
๐ซ gethostbyname(3) โ Library Functions Manual ๐ซ
okay bestie sit DOWN because we're doing a whole legendary one today ๐ this is the gethostbyname family from the Standard C library (libc, -lc) โ the friend group that finds network host entries for you. and yes, half of them are lowkey deprecated and we're gonna be honest about that the whole time, no cap ๐
โจ NAME โจ
so like, the whole squad: gethostbyname, gethostbyaddr, sethostent, gethostent, endhostent, h_errno, herror, hstrerror, gethostbyaddr_r, gethostbyname2, gethostbyname2_r, gethostbyname_r, gethostent_r โ all here to get network host entry ๐ฆ
๐ LIBRARY ๐
Standard C library (that's libc, link it with -lc) ๐
๐ SYNOPSIS ๐
the vibes begin with an include, always:
#include <netdb.h>
void sethostent(int stayopen);
void endhostent(void);
[[deprecated]] extern int h_errno;
[[deprecated]] struct hostent *gethostbyname(const char *name);
[[deprecated]] struct hostent *gethostbyaddr(socklen_t size;
const void addr[size],
socklen_t size, int type);
[[deprecated]] void herror(const char *s);
[[deprecated]] const char *hstrerror(int err);
/* System V/POSIX extension */
struct hostent *gethostent(void);
/* GNU extensions */
[[deprecated]]
struct hostent *gethostbyname2(const char *name, int af);
int gethostent_r(size_t bufsize;
struct hostent *restrict ret,
char buf[restrict bufsize], size_t bufsize,
struct hostent **restrict result,
int *restrict h_errnop);
[[deprecated]]
int gethostbyaddr_r(socklen_t size, size_t bufsize;
const void addr[restrict size], socklen_t size,
int type,
struct hostent *restrict ret,
char buf[restrict bufsize], size_t bufsize,
struct hostent **restrict result,
int *restrict h_errnop);
[[deprecated]]
int gethostbyname_r(size_t bufsize;
const char *restrict name,
struct hostent *restrict ret,
char buf[restrict bufsize], size_t bufsize,
struct hostent **restrict result,
int *restrict h_errnop);
[[deprecated]]
int gethostbyname2_r(size_t bufsize;
const char *restrict name, int af,
struct hostent *restrict ret,
char buf[restrict bufsize], size_t bufsize,
struct hostent **restrict result,
int *restrict h_errnop);
see all those [[deprecated]] tags? yeah. the compiler is literally giving you the side-eye ๐ those functions still work but they are NOT the moment anymore.
๐ธ Feature Test Macro Requirements for glibc ๐ธ
(if you don't know what those are, go read feature_test_macros(7) โ it's giving prerequisite ๐
)
gethostbyname2(), gethostent_r(), gethostbyaddr_r(), gethostbyname_r(),
gethostbyname2_r():
Since glibc 2.19:
_DEFAULT_SOURCE
glibc up to and including 2.19:
_BSD_SOURCE || _SVID_SOURCE
herror(), hstrerror():
Since glibc 2.19:
_DEFAULT_SOURCE
glibc 2.8 to glibc 2.19:
_BSD_SOURCE || _SVID_SOURCE
Before glibc 2.8:
none
h_errno:
Since glibc 2.19
_DEFAULT_SOURCE || _POSIX_C_SOURCE < 200809L
glibc 2.12 to glibc 2.19:
_BSD_SOURCE || _SVID_SOURCE || _POSIX_C_SOURCE < 200809L
Before glibc 2.12:
none
๐ DESCRIPTION ๐
okay first thing, and I need you to hear me on this one:
red alert, bestie ๐จ thegethostbyname*(),gethostbyaddr*(),herror(), andhstrerror()functions are obsolete. like, retro. applications should be usinggetaddrinfo(3),getnameinfo(3), andgai_strerror(3)instead. periodt.
but we're still gonna learn them because you WILL run into them in the wild and you will be the only one in the group chat who knows what's going on ๐
<cyan>sethostent()</cyan> โ if stayopen is true (aka 1), this says "hey, use a connected TCP socket for the name server queries, and keep that connection open across successive queries." otherwise the queries just use UDP datagrams. casual. UDP core ๐ฆ
<cyan>endhostent()</cyan> โ ends the whole TCP-connection-for-name-server-queries thing. wrap it up, we're done here ๐
<cyan>gethostbyname()</cyan> โ returns a hostent structure for the host name you pass in. now here's the tea: name can be either a hostname OR an IPv4 address in standard dot notation (the same kind inet_addr(3) deals with). and if name IS an IPv4 address? no lookup happens at all โ it just copies name straight into the h_name field, and its struct in_addr equivalent straight into the h_addr_list[0] field of the returned hostent. instant. no network call. the way that's so efficient actually?? โจ
a couple more details bestie:
- if
namedoesn't end in a dot AND the environment variableHOSTALIASESis set, the alias file pointed to byHOSTALIASESgets searched fornamefirst (checkhostname(7)for the file format ๐) - the current domain and its parents get searched, unless
nameends in a dot
<cyan>gethostbyaddr()</cyan> โ returns a hostent for the given host address addr, of size size, with address type type. valid address types are AF_INET and AF_INET6 (those live in <sys/socket.h>). the address argument is a pointer to a struct whose type depends on the address type โ for example a struct in_addr * (probs obtained from a call to inet_addr(3)) for address type AF_INET ๐
<cyan>herror()</cyan> โ (obsolete, we been knew) prints the error message associated with the current value of h_errno to stderr. loud and proud ๐ข
<cyan>hstrerror()</cyan> โ (also obsolete) takes an error number (usually h_errno) and hands you back the corresponding message string ๐ซถ
the domain name queries that gethostbyname() and gethostbyaddr() do rely on the Name Service Switch (nsswitch.conf(5)) configured sources, or a local name server (named(8)). the default move is: query the ones configured in nsswitch.conf(5), and if that fails, hit a local name server (named(8)) ๐ง
๐ฐ๏ธ Historical ๐ฐ๏ธ
nsswitch.conf(5) is the modern way of controlling the order of host lookups. iconic. forward-thinking. we love her ๐
in glibc 2.4 and earlier, it was the order keyword that controlled host lookup order, as defined in /etc/host.conf (check host.conf(5)). throwback energy fr fr ๐
the hostent structure is defined in <netdb.h> like this, and I need you to memorize it because it will come up again:
struct hostent {
char *h_name; /* official name of host */
char **h_aliases; /* alias list */
int h_addrtype; /* host address type */
int h_length; /* size of address */
char **h_addr_list; /* list of addresses */
}
#define h_addr h_addr_list[0] /* for backward compatibility */
and now the members, one by one, because every single one matters bestie:
h_nameโ the official name of the host ๐h_aliasesโ an array of alternative names for the host, terminated by a null pointerh_addrtypeโ the type of address; alwaysAF_INETorAF_INET6at presenth_lengthโ the size of the address, in bytes ๐h_addr_listโ an array of pointers to network addresses for the host (in network byte order), terminated by a null pointerh_addrโ the first address inh_addr_list, kept around for backward compatibility ๐
๐ RETURN VALUE ๐
gethostbyname() and gethostbyaddr() hand you back the hostent structure, or a null pointer if something goes wrong. and on error, the h_errno variable is holding an error number, keeping the receipts ๐
heads up tho: when the return value is non-NULL, it may point at static data โ peep the notes below (that's in the next part bestie, don't go anywhere).
๐จ ERRORS ๐จ
the variable h_errno can have these values, and each one is telling you a different story:
HOST_NOT_FOUNDโ the specified host is unknown. they're not in the system, bestie, not even a little ๐NO_DATAโ the requested name is valid but it doesn't have an IP address. a different type of request to the name server for this domain might still get you an answer. oh and btw, the constantNO_ADDRESSis a synonym forNO_DATAโ same vibe, different name ๐ธNO_RECOVERYโ a nonrecoverable name server error happened. no coming back from this one ๐ญTRY_AGAINโ a temporary error occurred on an authoritative name server. just try again later, it's not you, it's them ๐ซถ
๐ FILES ๐
/etc/host.confโ resolver configuration file/etc/hostsโ host database file/etc/nsswitch.confโ name service switch configuration
aand that's part 1 of the gethostbyname(3) saga, keep scrolling bestie there's more ๐โจ
๐ซง ATTRIBUTES ๐ซง
ok so before we go any further, bestie, if you wanna know what all these fancy words even mean, go peek at attributes(7). that's the lore. โจ
here's the whole thread-safety situation, laid out one by one:
gethostbyname()โ Thread safety: MT-Unsaferace:hostbynameenvlocalegethostbyaddr()โ Thread safety: MT-Unsaferace:hostbyaddrenvlocalesethostent(),endhostent(),gethostent_r()โ Thread safety: MT-Unsaferace:hostentenvlocaleherror(),hstrerror()โ Thread safety: MT-Safe ๐gethostent()โ Thread safety: MT-Unsaferace:hostentrace:hostentbufenvlocalegethostbyname2()โ Thread safety: MT-Unsaferace:hostbyname2envlocalegethostbyaddr_r(),gethostbyname_r(),gethostbyname2_r()โ Thread safety: MT-Safeenvlocale๐
and about that hostent word popping up inside race:hostent up there โ lemme translate, bestie: it means that if any of sethostent(), gethostent(), gethostent_r(), or endhostent() get used in parallel across different threads of one program, then data races could occur. like, chaos. ๐ so don't do that.
๐ STANDARDS ๐
sethostent()endhostent()gethostent()
all three of those? POSIX.1-2008. certified, canon, periodt. ๐
gethostent_r()
that one's GNU. house-made. ๐
- Others:
None. nope, not a single one. the rest are out here unstandardized fr fr. ๐ญ
๐ฐ๏ธ HISTORY ๐ฐ๏ธ
sethostent()endhostent()gethostent()
these cuties go all the way back to POSIX.1-2001. vintage. โจ
gethostbyname()gethostbyaddr()h_errno
okay so these three got marked obsolescent back in POSIX.1-2001, and then removed entirely in POSIX.1-2008 โ and the standard was like "use getaddrinfo(3) and getnameinfo(3) instead bestie". so yeah. they're giving retirement era. ๐
๐ NOTES ๐
gethostbyname() and gethostbyaddr() might hand you pointers to static data, and that data can get overwritten by later calls. so if you think "oh I'll just copy the struct hostent" โ nope, that does not suffice, because it's full of pointers. you need a deep copy, okay? a shallow copy is a trap. ๐ชค
in the original BSD implementation, the size argument of gethostbyname() was an int. and then SUSv2 came along and, uh, the standard is buggy โ it declares the size argument of gethostbyaddr() to be of type size_t. which is wrong, because it has to be int, and size_t is not. POSIX.1-2001 makes it socklen_t, which is OK. ๐
see also accept(2).
also: the BSD prototype for gethostbyaddr() uses const char * for the first argument. noted. ๐ซถ
๐ง System V/POSIX extension ๐ง
POSIX requires the gethostent() call, which should return the next entry in the host data base. now โ when you're using DNS/BIND this does not make much sense, but it may be reasonable if the host data base is a file that can be read line by line. on many systems, a routine of this name reads from the file /etc/hosts. it may be available only when the library was built without DNS support. the glibc version will ignore ipv6 entries. and this function is not reentrant, so glibc went ahead and added a reentrant version: gethostent_r(). slay for safety. ๐
๐ GNU extensions ๐
glibc2 also has a gethostbyname2() that works like gethostbyname(), but permits you to specify the address family to which the address must belong. picky in a cute way. ๐
glibc2 also has reentrant versions: gethostent_r(), gethostbyaddr_r(), gethostbyname_r(), and gethostbyname2_r(). here's how they work, bestie: the caller supplies a hostent structure ret which will be filled in on success, and a temporary work buffer buf of size bufsize. after the call, result will point to the result on success. in case of an error or if no entry is found, result will be NULL. the functions return 0 on success and a nonzero error number on failure. and on top of the errors returned by the nonreentrant versions of these functions, if buf is too small, the functions will return ERANGE, and the call should be retried with a larger buffer. ๐ the global variable h_errno is not modified, but the address of a variable in which to store error numbers is passed in h_errnop. so you hand it a place to put the oopsie. ๐
๐ BUGS ๐
gethostbyname() does not recognize components of a dotted IPv4 address string that are expressed in hexadecimal. that's it. that's the bug. sorry hex girlies. ๐
๐ SEE ALSO ๐
getaddrinfo(3), getnameinfo(3), inet(3), inet_ntop(3), inet_pton(3), resolver(3), hosts(5), nsswitch.conf(5), hostname(7), named(8)
okay that's the whole page, bestie, you made it to the end ๐ go forth and resolve those hostnames responsibly (or better yet, use getaddrinfo(3), the standards girlies are literally begging). this was brought to you by Linux man-pages 6.20, dated 2026-02-08, and this page is gethostbyname(3) โ iconic, historic, and slightly obsolescent. mwah. ๐โจ๐ฆ
๐ฆ where this page comes from
- arch rolling: man-pages 6.20-1 ยท BSD-2-Clause AND BSD-3-Clause AND BSD-4.3TAHOE AND BSD-4-Clause-UC AND GPL-1.0-or-later AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-3.0-or-later AND LGPL-3.0-linking-exception AND LGPL-3.0-or-later AND LicenseRef-Public-Domain AND LicenseRef-UltraPermissive AND Linux-man-pages-1-para AND Linux-man-pages-copyleft AND Linux-man-pages-copyleft-2-para AND Linux-man-pages-copyleft-var AND MIT AND Spencer-94
- nixpkgs unstable: man-pages 6.20
- ๐ the page's license: Linux-man-pages-copyleft
- Copyright 1993, David Metcalfe <david@prism.demon.co.uk>
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms