Subject: DNS search list behavior when AAAA returns NODATA

DNS search list behavior when AAAA returns NODATA

From: Paul Marks <pmarks_at_google.com>
Date: Tue, 31 Mar 2015 00:55:48 -0700

I configured the following records on pmarks.net.

# Each of these names has one record:
ipv4-rr.search1 1200 IN A 192.0.2.1
ipv6-rr.search1 1200 IN AAAA 2001:db8::1
text-rr.search1 1200 IN TXT "search1"
# A catch-all wildcard containing three record types:
*.search2 1200 IN A 192.0.2.2
*.search2 1200 IN AAAA 2001:db8::2
*.search2 1200 IN TXT "search2"

With the following search path:

$ grep search /etc/resolv.conf
search search1.pmarks.net search2.pmarks.net

Bind's "host" command follows the search list, but stops on NODATA:

$ host ipv4-rr
ipv4-rr.search1.pmarks.net has address 192.0.2.1
$ host ipv6-rr
ipv6-rr.search1.pmarks.net has IPv6 address 2001:db8::1
$ host text-rr
(no output)
$ host nxdomain-rr
nxdomain-rr.search2.pmarks.net has address 192.0.2.2
nxdomain-rr.search2.pmarks.net has IPv6 address 2001:db8::2

However, c-ares keeps searching past NODATA, until an actual record is found:

$ for x in aaaa a; do ./ahost -t $x ipv4-rr; done
ipv4-rr.search2.pmarks.net 2001:db8::2
ipv4-rr.search1.pmarks.net 192.0.2.1
$ for x in aaaa a; do ./ahost -t $x ipv6-rr; done
ipv6-rr.search1.pmarks.net 2001:db8::1
ipv6-rr.search2.pmarks.net 192.0.2.2
$ for x in aaaa a; do ./ahost -t $x text-rr; done
text-rr.search2.pmarks.net 2001:db8::2
text-rr.search2.pmarks.net 192.0.2.2
$ for x in aaaa a; do ./ahost -t $x nxdomain-rr; done
nxdomain-rr.search2.pmarks.net 2001:db8::2
nxdomain-rr.search2.pmarks.net 192.0.2.2

This behavior is peculiar, for two reasons:

(1) If you're looking up AAAA records on an IPv4-only hostname (or
vice versa), it's wasteful to follow the entire search list, when the
(empty) name was first in line.

(2) It's possible for different record types to match different
"h_name"s, and it's not obvious to callers which name should take
priority if this occurs.

Here's a ham-fisted patch for ares_search.c, which yields Bind-like behavior:

   /* Stop searching unless we got a non-fatal error. */
- if (status != ARES_ENODATA && status != ARES_ESERVFAIL
+ if (/*status != ARES_ENODATA &&*/ status != ARES_ESERVFAIL
       && status != ARES_ENOTFOUND)

$ for x in aaaa a; do ./ahost -t $x ipv4-rr; done
ipv4-rr: DNS server returned answer with no data
ipv4-rr.search1.pmarks.net 192.0.2.1
$ for x in aaaa a; do ./ahost -t $x ipv6-rr; done
ipv6-rr.search1.pmarks.net 2001:db8::1
ipv6-rr: DNS server returned answer with no data
$ for x in aaaa a; do ./ahost -t $x text-rr; done
text-rr: DNS server returned answer with no data
text-rr: DNS server returned answer with no data
$ for x in aaaa a; do ./ahost -t $x nxdomain-rr; done
nxdomain-rr.search2.pmarks.net 2001:db8::2
nxdomain-rr.search2.pmarks.net 192.0.2.2

However, the surrounding code suggests that the current behavior may
be intentional, so I see three possible resolutions:

(1) Declare this behavior a bug, and fix it.
(2) Document this behavior as intentional.
(3) Make it a configuration option.
Received on 2015-03-31