DNS resolving and the trailing "."

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view

DNS resolving and the trailing "."

Scott Lystig Fritchie-3
I've been playing around with the DNS resolving functions in R7B-3 and
P8A and have seen some "interesting" behavior when making queries with
a trailing ".".

In my understanding, if a recursive DNS resolver gets a query with a
trailing ".", if the query fails, then the resolver won't bother
re-attempting the query with local domain names appended to the
original query.

As an example, my machine at home has got an /etc/resolv.conf file
that looks this:

     domainname mr.net
     search yyy.mr.net xxx.mr.net

If I try "nslookup blarf.mr.net", up to three separate recursive
queries will be attempted in this order: blarf.mr.net,
blarf.mr.net.yyy.mr.net, and blarf.mr.net.xxx.mr.net.  However, if my
original query has a trailing ".", i.e. "nslookup blarf.mr.net.", the
search path will not be used, and only one query attempt will be made.

Unfortunately, this is not the behavior shown by inet:gethostbyname()
et al.  'inet:gethostbyname("blarf.mr.net.").' will make several
recursive query attempts:

          * 3 queries are attempted with illegal queries: the query
          section of the UDP packet is malformed due to a bug in
          P8A's inet_dns:dn_comp_label().  I haven't figured out why
          the bogus query is sent three times, but it is.  (R7B-* do
          the same thing.)

          * 1 query each for "blarf.mr.net.mr.net",
          "blarf.mr.net.yyy.mr.net", and "blarf.mr.net.xxx.mr.net"

The return value is {error, nxdomain}, which IMO isn't correct.

A (lightly tested) fix for the malformed query bug in
inet_dns:dn_comp_label() is to add a new clause:

        dn_comp_label([$\\, 0 | Name], Ns, Cn, Buf, Offset) ->
            Label = [length(Cn) | reverse([0 | Cn])],
            { Buf ++ Label, Ns};
        dn_comp_label([$. | []], Ns, Cn, Buf, Offset) ->      % new clause
            dn_comp_label([], Ns, Cn, Buf, Offset);           % new clause
        dn_comp_label([$. | Name], Ns, Cn, Buf, Offset) ->
            Label = [length(Cn) | reverse(Cn)],
            dn_comp(Name, Ns, Buf ++ Label, Offset+1);

Unfortunately, this fix alone does not provide the correct behavior.
The caching activities performed by in inet_db don't work correctly
when there's a trailing "." because the RRs (resource records) it
caches do not have any trailing "."  I don't have enough time this
evening to provide a patch for inet_db.erl to do things The Right
Way(tm).  I make my plea to The Release Maintainers to fix this bug.

Why not just remove the trailing "." before attempting DNS resolution?
My understanding is that the trailing "." semantics are provided by
the C library because there are situations where you *know* you don't
want resolv.conf's search path to be used.  If this bug won't be fixed
because The Release Maintainers don't believe it's a bug, then I
humbly suggest that this unusual resolver behavior should be clearly
documented.  :-)