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 ๐Ÿšจ the gethostbyname*(), gethostbyaddr*(), herror(), and hstrerror() functions are obsolete. like, retro. applications should be using getaddrinfo(3), getnameinfo(3), and gai_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 name doesn't end in a dot AND the environment variable HOSTALIASES is set, the alias file pointed to by HOSTALIASES gets searched for name first (check hostname(7) for the file format ๐Ÿ“–)
  • the current domain and its parents get searched, unless name ends 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 pointer
  • h_addrtype โ€” the type of address; always AF_INET or AF_INET6 at present
  • h_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 pointer
  • h_addr โ€” the first address in h_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 constant NO_ADDRESS is a synonym for NO_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-Unsafe race:hostbyname env locale
  • gethostbyaddr() โ€” Thread safety: MT-Unsafe race:hostbyaddr env locale
  • sethostent(), endhostent(), gethostent_r() โ€” Thread safety: MT-Unsafe race:hostent env locale
  • herror(), hstrerror() โ€” Thread safety: MT-Safe ๐Ÿ’š
  • gethostent() โ€” Thread safety: MT-Unsafe race:hostent race:hostentbuf env locale
  • gethostbyname2() โ€” Thread safety: MT-Unsafe race:hostbyname2 env locale
  • gethostbyaddr_r(), gethostbyname_r(), gethostbyname2_r() โ€” Thread safety: MT-Safe env locale ๐Ÿ‘‘

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
  • ๐Ÿ’– girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms