Two copies of resolver routines in libc ?

Luigi Rizzo rizzo at
Thu Nov 6 11:33:54 PST 2008

i was recently re-looking at the problem mentioned in

(bogus dns servers on my ISP, telecomitalia, which takes forever
to resolve AAAA queries, coupled with the absence, on the FreeBSD
resolver has no way to disable AAAA queries when IPV6 is compiled
in, which happens with GENERIC kernels).

While looking for a workaround (attached, read later), i noticed
that libc has two versions of the resolver routines: one is in


the other one is embedded into

which includes a slightly modified version of res_nquery, res_ndots,
res_nquerydomain (all parts of the routines documented in resolver(3)).

If we are lucky, this is just replicated code.
But i am not even sure they are the same, e.g. in the handling of
options (in resolv.conf or the environment variable RES_OPTIONS).

This is really annoying, because generally you don't know if an
application uses getaddrinfo() or the traditional gethost*() routines
(which in turn use resolver(3)), so it is hard to tell whether
applications have a consistent behaviour.
If someone has time, it would be worthwhile trying to merge
the two versions of the code into one (and i believe we should
make getaddrinfo use the standard stuff in resolv/

--- As for a fix to my problem: ---

i wanted some trick to disable, in the resolver, the generation of
AAAA queries. resolver(5) mentions some options that can be put
in /etc/resolv.conf or in the RES_OPTIONS environment variable,
to control the behaviour of the resolver.
Some more options are undocumented but implemented, e.g. looking
at /usr/src/lib/libc/resolv/res_init.c you find these additional



The code below (which is completely trivial) add an additional option,
"noaaaa", which disables the generation of AAAA requests. Just do

	setenv RES_OPTIONS noaaaa

and you are done. I don't know of other ways to disable these
requests on normal address resolutions, other than build a kernel
without INET6.

As you see below (and this relates to my original complaint),
i had to make the modification in two places :( because things like
ssh and telnet use getaddrinfo(), whereas e.g. firefox uses res_query().

I have no idea what is used by /usr/bin/host or /usr/bin/dig ,
because they do not seem to use any of the library routines.

Any interest to have this into the system ?


Index: net/getaddrinfo.c
RCS file: /home/ncvs/src/lib/libc/net/getaddrinfo.c,v
retrieving revision
diff -u -r1.69.2.10 getaddrinfo.c
--- net/getaddrinfo.c	28 Sep 2007 06:23:03 -0000
+++ net/getaddrinfo.c	6 Nov 2008 20:35:39 -0000
@@ -85,6 +85,7 @@
 #include <errno.h>
 #include "res_config.h"
+#include "res_private.h"
 #ifdef DEBUG
 #include <syslog.h>
@@ -2257,6 +2258,8 @@
 		oflags = res->_flags;
+		if (res->options & RES_NOAAAA && type == ns_t_aaaa)
+			continue;	/* ignore this request */
 		hp->rcode = NOERROR;	/* default */
Index: resolv/res_init.c
RCS file: /home/ncvs/src/lib/libc/resolv/res_init.c,v
retrieving revision
diff -u -r1.2.2.3 res_init.c
--- resolv/res_init.c	22 Dec 2006 07:33:20 -0000
+++ resolv/res_init.c	6 Nov 2008 20:34:00 -0000
@@ -636,6 +636,8 @@
 			   !strncmp(cp, "no-tld-query",
 				    sizeof("no-tld-query") - 1)) {
 			statp->options |= RES_NOTLDQUERY;
+		} else if (!strncmp(cp, "noaaaa", sizeof("noaaaa") - 1)) {
+			statp->options |= RES_NOAAAA;
 		} else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) {
 			statp->options |= RES_USE_INET6;
 		} else if (!strncmp(cp, "insecure1", sizeof("insecure1") - 1)) {
Index: resolv/res_private.h
RCS file: /home/ncvs/src/lib/libc/resolv/res_private.h,v
retrieving revision
diff -u -r1. res_private.h
--- resolv/res_private.h	17 Jul 2006 10:09:58 -0000
+++ resolv/res_private.h	6 Nov 2008 19:08:29 -0000
@@ -3,6 +3,9 @@
 #ifndef res_private_h
 #define res_private_h
+// additional debug flags to disable AAAA queries
+#define RES_NOAAAA	0x00800000
 struct __res_state_ext {
 	union res_sockaddr_union nsaddrs[MAXNS];
 	struct sort_list {
Index: resolv/res_query.c
RCS file: /home/ncvs/src/lib/libc/resolv/res_query.c,v
retrieving revision
diff -u -r1.3.2.1 res_query.c
--- resolv/res_query.c	17 Jul 2006 10:09:58 -0000
+++ resolv/res_query.c	6 Nov 2008 20:45:23 -0000
@@ -90,6 +90,7 @@
 #include <string.h>
 #include <unistd.h>
 #include "port_after.h"
+#include "res_private.h"
 /* Options.  Leave them on. */
 #define DEBUG
@@ -126,10 +127,12 @@
 	hp->rcode = NOERROR;	/* default */
+	if (statp->options & RES_NOAAAA && type == ns_t_aaaa) {
+		return 0;       /* ignore this request */
+	}
 #ifdef DEBUG
 	if (statp->options & RES_DEBUG)
-		printf(";; res_query(%s, %d, %d)\n", name, class, type);
+		printf(";; res_nquery(%s, %d, %d)\n", name, class, type);
 	n = res_nmkquery(statp, QUERY, name, class, type, NULL, 0, NULL,

More information about the freebsd-net mailing list