TL;DR: I put together a Perl script that does name/address resolution from the perspective of the OS instead of relying solely on the DNS like the dig or host commands. If this makes sense and sounds useful, just go check out my resolve-pl repository on github. If it doesn’t fully make sense, then read on.
Resolving host names to addresses is a fundamental functionality for the Internet provided by the Domain Name System, but there is more than that. In fact, mappings between host names and network addresses can be also provided by other means, e.g. the multicast DNS, aka zeroconf, Avahi, Bonjour…
Your OS doesn’t necessarily rely on just DNS: what it relies on depends on the OS itself and its configuration. On Linux systems, and more generally on UNIX systems, the name service switch is used. What sources the system should look up and in what order is usually defined in the file
/etc/nsswitch.conf. On my laptop the setting is as follows:
bronto@minardi:~$ grep ^hosts: /etc/nsswitch.conf hosts: files mdns4_minimal [NOTFOUND=return] dns myhostname bronto@minardi:~$
As you can guess, the DNS is not the first source to be looked up: first, files (like
/etc/hosts) are checked, then mDNS, and only if that one fails the DNS is queried.
There is nothing wrong in this set up. Most of the time, we (or I, at least) deal with machines that require DNS look-ups (resolving a name like http://www.google.com to the corresponding addresses) or reverse look-ups (finding out what names is associated to a certain IP address). In these cases, utilities like dig or host are just fine. But if the hosts you are working with are not registered in the DNS, and you are possibly trying to debug a problem that requires resolving their names/addresses, you are in trouble. When such a problem happened to me in the past, I usually put together a Perl one-liner to do the lookup using the system functions
gethostbyaddr. And as it happens for all the things that I find myself doing more than once, I decided I would do it properly to save myself from the annoyance in the future.
So I started coding a small tool. It was supposed to be a very short program, ideally I should have used only the
gethostby* function calls and no external libraries at all.
Reality proved different. In particular,
gethostby* functions work well enough with IPv4, but not as well for IPv6 (e.g.: if you resolve a name, say
gethostbyname you will get only the IPv4 address back). The solution involved using the
getnameinfo, whose interface is more complex than the good old
gethostby* functions. I reworked the script reluctantly, and finally I managed to make it work.
Resolve is a Perl script that does name and address resolution from the perspective of the Operating System. In other words, it will resolve not only global DNS names, but also names propagated through multicast DNS and even names that are registered only in your hosts file. Some examples:
$ resolve www.google.com 127.0.0.1 minardi.local raspberry-b.local 2a00:1450:400f:809::2004 arn11s02-in-x04.1e100.net ip6-localhost ip6-allnodes www.google.com ipv4 18.104.22.168 www.google.com ipv6 2a00:1450:400f:806::2004 127.0.0.1 name localhost minardi.local ipv4 192.168.100.20 raspberry-b.local ipv4 192.168.100.193 2a00:1450:400f:809::2004 name arn11s02-in-x04.1e100.net arn11s02-in-x04.1e100.net ipv6 2a00:1450:400f:809::2004 ip6-localhost alias localhost ip6-localhost ipv6 ::1 ip6-allnodes ipv6 ff02::1 $
- names and addresses (both IPv4 and IPv6) from the DNS (e.g. www.google.com or 2a00:1450:400f:809::2004 )
- names from the hosts file (e.g. localhost, ip6-localhost)
- names from mDNS (e.g.
Reverse lookup of local names may work…
$ resolve 192.168.100.20 192.168.100.20 name minardi $ resolve 192.168.100.1 192.168.100.1 name _gateway $
or not, depending on how the mapping is done and/or if there is a mapping at all:
$ resolve raspberry-b.local raspberry-b.local ipv4 192.168.100.193 $ resolve 192.168.100.193 192.168.100.193 name UNDEFINED $
Your mileage may vary.
Sounds useful? Try it out and… Enjoy!