Name/address resolution from the perspective of the OS

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 gethostbyname or 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 http://www.google.com with gethostbyname you will get only the IPv4 address back). The solution involved using the Socket module’s getaddrinfo and 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.

Enter resolve.

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 172.217.22.164
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
$

Note how resolve resolved:

  • 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. .local domain names)

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!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.