I'm trying to resolve a hostname to an IP address using the /etc/hosts
file only.
That is, if the name cannot be locally resolved, it must fail (ie. no DNS request sent out).
The standard way to resolve a name is with getaddrinfo
, but this will fallback to DNS.
gethostent_r
seems a good candidate since it returns records from the local hosts file, but unfortunately, I do not get IPv6 records, only IPv4.
How can I resolve a name to an IPv4 or IPv6 address based on the local /etc/hosts file only ?
gethostent_r seems a good candidate since it returns records from the local hosts file, but unfortunately, I do not get IPv6 records, only IPv4.
That doesn't sound right to me. It should return both types, assuming they are actually in /etc/hosts – but it will likely return them as two separate entries, as it goes through the file line-by-line.
Other methods:
If you are using glibc, you might be able to call __nss_configure_lookup("hosts", "files")
– an internal glibc function which the getent
tool uses to implement its -s
option (as in {"getent", "-s", "hosts", arg}
).
A slightly better method, also for glibc, is to directly dlopen()
the corresponding libnss "backend" module that is responsible for providing hostname lookup from /etc/hosts; that is, libnss_files.so.2
. The interface between glibc and the libnss modules is a bit messy (especially the several different "hostname" functions), but it is stable.
Either of those might be preferable to writing your own parser, although not due to CPU usage – rather, due to the high chance that your custom parser will be incomplete and won't match the way glibc itself parses /etc/hosts. Make sure to test your parser with multiple address mappings for the same name; multiple names for the same address; mixed IPv4 and IPv6 mappings for the same name; etc. Otherwise users/sysadmins may be very annoyed.
it takes more CPU time for something the system has already done
The system hasn't really "already done" it. On most Linux systems there is no central cache for /etc/hosts; it is parsed independently by each process. (Some systems might have the 'nscd' general-purpose name-lookup cache daemon running but it's uncommon.) So if you do gethostbyname() and let libc read /etc/hosts, that's really the same as parsing it yourself.