Resolving IP addresses takes a long time (not anymore)

You are here because in one or another way you are resolving an IP address and that takes a long time (5 to 15 or even 30 seconds). Let me guess. You are using Ubuntu and you use gethostbyaddr(), getnameinfo(), or any such function in a programming language like C, C++, Python, Perl, etc. It’s not your fault. To be precise, the problem arises (at least in my case) whenever you are trying to resolve IP 0.0.0.0. This IP, which is also referred to with the code name INADDR_ANY (actually a macro declaration in C) is very helpful when you write a server process and you would like to make it listen to all network interfaces of the machine it resides. For example, it is very common to have two or more external IP addresses for a machine. If you would like your server to accept connections on all such interfaces, then you have to create a socket and afterwards bind it to the IP address 0.0.0.0. A sample program written in C that does exactly this is the following:

#include
#include
#include
#include
#include
#include
#include 
 
int main(void) {
	int sock;
	struct sockaddr_in addr;
	struct hostent *hoste;
	char *host;
 
	printf("Creating socket...");
	// create socket
	sock = socket(AF_INET, SOCK_STREAM, 0);
	if (sock == -1) {
		perror("create socket");
		exit(-1);
	}
	printf("OK\n");
 
	// initialize structure
	memset((void *) &addr, 0, sizeof(struct sockaddr_in));
 
	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = htonl(INADDR_ANY);
 
	printf("Binding...");
	// bind
	if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 		perror("bind"); 		close(sock); 		exit(-1); 	} 	printf("OK\n"); 	// resolving 	printf("Resolving 0.0.0.0 ...\n"); 	hoste = gethostbyaddr(&addr.sin_addr.s_addr, 4, addr.sin_family); 	if (hoste == NULL) { 		fprintf(stderr, "\tWARNING: gethostbyaddr returned NULL\n"); 	} else { 		host = hoste->h_name;
		printf("OK");
		printf("Host: %s\n", host);
	}
 
	printf("Closing socket...\n");
	close(sock);
	printf("Socket closed.\n");
 
	printf("Exit\n");
	return 0;
}

Running the above code in my system (Ubuntu 10.04) takes about 5 seconds.

$ time ./test_gethostbyaddr
Creating socket...OK
Binding...OK
Resolving 0.0.0.0 ...
	WARNING: gethostbyaddr returned NULL
Closing socket...
Socket closed.
Exit
 
real	0m5.005s
user	0m0.010s
sys	0m0.000s

But why does the lookup take so long? Let’s try to resolve 0.0.0.0 manually.

$ time host 0.0.0.0
Host 0.0.0.0.in-addr.arpa. not found: 3(NXDOMAIN)
 
real	0m0.006s
user	0m0.020s
sys	0m0.000s

Nice timing. But what about using nslookup?

$ time nslookup 0.0.0.0
Server:		195.134.100.90
Address:	195.134.100.90#53
 
** server can't find 0.0.0.0.in-addr.arpa.: NXDOMAIN
 
real	0m0.007s
user	0m0.010s
sys	0m0.000s

Nice timing as well. But why my program executes in 5 seconds? Well, the reason is that it does not use these commands to resolve the IP. More correctly, it does not use the underlying services that these two commands use, i.e., named, bind, /etc/hosts, etc., which are also mentioned in the respective man pages.

What service does it use then? It uses avahi. Come on, it can’t use the woolly lemur of Madagaskar. Don’t blame me because the author of avahi baptized it after that animal. Avahi is a daemon service that is included in distributions like Ubuntu, Debian, Fedora, SuSe, etc. and implements the mDNS (multicast DNS) protocol initially proposed by Apple. With mDNS a system can play the role of a DNS server for other computers on the same sub-network. It can also publish services like printing so as other computers find and use them.

Returning back to our problem, for some (configuration-centric) reason that I hadn’t had the time (and probably the mood) to further investigate, when the avahi-daemon is used in Ubuntu, it takes over all resolve lookups coming from such calls as gethostbyaddr() and getnameinfo(). Let’s test it manually:

$ time avahi-resolve --address 0.0.0.0
Failed to resolve address '0.0.0.0': Timeout reached
 
real	0m5.007s
user	0m0.010s
sys	0m0.000s

And this is exactly the amount of time that our program takes to execute. The hard way is to disable avahi-daemon. This can be done by first stopping the daemon

$ sudo service avahi-daemon stop
avahi-daemon stop/waiting

and then removing it from loading during system startup

$ sudo update-rc.d -f avahi-daemon remove
Removing any system startup links for /etc/init.d/avahi-daemon ...
   /etc/rc0.d/K20avahi-daemon
   /etc/rc1.d/K20avahi-daemon
   /etc/rc2.d/S20avahi-daemon
   /etc/rc3.d/S20avahi-daemon
   /etc/rc4.d/S20avahi-daemon
   /etc/rc5.d/S20avahi-daemon
   /etc/rc6.d/K20avahi-daemon

Of course, this has the disadvantage that you lose the useful service of discovery of printers, etc. No big deal for me. But if it counts much for you, then I suggest you read the documentation about how to configure avahi making not responding to lookup requests for INADDR_ANY (0.0.0.0). I bet that it is a configuration issue because running the same program in Fedora 16 it does not incur any time penalty. And if you find yourself searching and finally overcoming it, just drop a line here.

In case that you would like to re-enable it, just type

$ sudo update-rc.d avahi-daemon defaults

Timing, now, our initial program we get the following

$ time ./test_gethostbyaddr
Creating socket...OK
Binding...OK
Resolving 0.0.0.0 ...
	WARNING: gethostbyaddr returned NULL
Closing socket...
Socket closed.
Exit
 
real	0m0.007s
user	0m0.010s
sys	0m0.000s

 

Music Listened: Isn’t She Lovely on Songs in the Key of Life by Stevie Wonder

0 Responses to “Resolving IP addresses takes a long time (not anymore)”


  • No Comments

Leave a Reply




7936 pages viewed, 84 today
4227 visits, 40 today
FireStats icon Powered by FireStats
Terminal illness is Spam proof, with hiddy