finding authoritative nameservers

Ronald F. Guilmette rfg at
Mon May 19 22:09:27 UTC 2008

In message <ADA073C8-E7F4-4144-ACDA-3CED0669470A at>, 
Chris Buxton <cbuxton at> wrote:

>If I were going to write such code, my algorithm would be as follows:
>- Determine the zone that contains, or should contain, the answer.  
>This can be done by querying any handy resolving name server for the  
>target name, type SOA.

Yes.  As I mentione in my immediately prior post, that's what I finally
settled on... starting out with an SOA query for the thing of interest,
wih the query being sent, just as you said, to any convenient nameserver(s).

>You should get back either a positive or  
>negative answer. The negative answer will usually contain the SOA  
>record of the containing zone;

Yes.  A positive answer _also_ contains a useful SOA record, but in the
ANSWER section.

In the case of a "negative" result, that will most often be a NO_DATA
error.  At least that's what res_query() will give you.

More precisely, res_query() will give you back a -1 with h_error set
to NO_DATA.  And herein lies a bit of a problem...

The packet returned by res_query() when you make the SOA query will
be properly placed into your receiving buffer, *however* res_query()
then proves that it is too smart for its own good.  It looks to see
if the response packet contains at least 1 RR in its ANSWER section,
and if not, then res_query() returns the -1/NO_DATA result.  OK, so
here now is the problem...

In _normal_ circumstances, i.e. when a caller of res_query() only wants
to look at response packets that contain at least one actual ANSWER
section RR, the fact that res_query() returns only -1 when there are
no such RRs is OK and doesn't harm anything.  But in my cases here, I
want and need to unpack and then examine the contents of some response
packets that contain -zero- ANSWER section RRs (but one SOA RR in the
AUTHORUTY section).  The problems is:  How do you properly unpack a
complete DNS response packet if you do not know its precise length?
(The caller of res_query() has no way to know the actual length of the
response packet in this case, because res_query() was ``helpfull' and
return -1 rather than the packet length in this case.  Damn!)

I have written all my own code for unpacking DNS response packets, and
it all works great, _however_ it is is predicated upon the assumption
that among the parameters I can and will pass in to my packet unpacker,
I can and will pass in the true length of the response packet.  (My
unpacket routines use this value all over the place, i.e. to check at
each step of the unpacking process that I have not exceded the end of
the actual packet data, and run off the end so that now I'm unpacking
trailing garbage.)

To be honest, it's been so long now since I wrote my unpacking routines
that I don't even remember now if they really _need_ to have an accurate
pointer to the end of the response packet data or not.  Perhaps they will
still do just fine if I dummy up the end-of-packet pointer in a case like
this so that it points to the first byte past the end of my physical
reception buffer.  I don't know, but I guess I'm going to find out, and
Real Soon.  Sigh.  But I can't help wishing that res_query() could be
just a tiny bit less helpful in these kinds of NO_DATA situations, and
if it would have given me the response packet length, even for packets
containing no ANSWER RRs.

>if it does not, remove a label from the  
>left (up to and including the first dot), and then try again,  
>recursing until a response containing an SOA record is received.

Yes.  I intuited that part also.

>- Query the parent zone to retrieve the target zone's delegation NS  

That would be one approach.  But as I noted in my immediately prior post,
I elected to just force a type `ANY' query (for the original FQDN I was
interested in) to be sent to the primary name server, whose name I grabbed
from the SOA record.  Then I just grab the list of relevant NSes out of
the AUTHORITY section of the response to that ANY query.

This seems to work OK.  Good enough for my purposes anyway.

>... Discard any  results that do not have the AA flag set.

Mmmmmm.  Thank You!  *That* is a subtle point that I need to implment and
integrate into my method also, i.e. when I'm looking at the responses to
my ANY queries.

I wouldn't have caught that if you hadn't mentioned it.  So thanks a bunch.

>- The list of servers that were queried that returned an authoritative  
>response is most likely your final result. However, some special- 
>purpose DNS appliances will return an error or negative answer (not  
>necessarily with AA set) when queried for anything but an A record;  

At this point, I'm not going to worry about what a tiny percentage of
arguably broken nameservers do.  I just need to get the basic algorithim
right first, and then I can worry about adapting to quirks hidden away
in a few dark corners of the global DNS.


More information about the bind-users mailing list