Bug 11950 - res_send fails with ETIMEDOUT on successful DNS UPDATE
Summary: res_send fails with ETIMEDOUT on successful DNS UPDATE
Status: RESOLVED INVALID
Alias: None
Product: glibc
Classification: Unclassified
Component: network (show other bugs)
Version: unspecified
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-08-27 05:21 UTC by Dean Scarff
Modified: 2014-06-30 08:10 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:
fweimer: security-


Attachments
accept DNS UPDATE responses without RA set (563 bytes, patch)
2010-08-27 05:22 UTC, Dean Scarff
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Dean Scarff 2010-08-27 05:21:42 UTC
In the glibc resolver (previous versions and current git HEAD), res_send 
interprets some successful DNS UPDATE responses as an indication to retry with 
the next server, because of this test in res_send.c:

        if (anhp->rcode == NOERROR && anhp->ancount == 0
            && anhp->aa == 0 && anhp->ra == 0 && anhp->arcount == 0) {

This test is nonsensical for DNS UPDATE, where the "AA" and "RA" flags are part 
of the much larger Z bitfield, see

  http://tools.ietf.org/html/rfc2136#page-5

for more information.  This issue appears to be limited to UDP queries in 
send_dg().  The end result is that res_send returns failure and sets ETIMEDOUT.

This issue will not occur for all DNS servers; those which allow recursion 
(e.g. BIND9 without recursion disabled) will set the RA bit anyway.

Unfortunately, it's hard to generate a simple test case due to the nature of 
DNS UPDATE (needs crypto, a current timestamp, and a configured server).  I am 
experiencing this issue when using res_send in the context of the dudders DNS 
UPDATE client: http://dudders.sourceforge.net/

Patch attached.
Comment 1 Dean Scarff 2010-08-27 05:22:44 UTC
Created attachment 4951 [details]
accept DNS UPDATE responses without RA set
Comment 2 Dean Scarff 2010-08-27 08:54:28 UTC
Minor correction: testing again I see that res_send sets errno to ECONNREFUSED, 
not ETIMEDOUT.
Comment 3 Florian Weimer 2013-10-18 11:38:40 UTC
I don't think it's reasonable to expect that res_send can be used to send anything that isn't a DNS query.  If you want to send DNS UPDATE messages, you have to implement that on top of the socket API.
Comment 4 Dean Scarff 2013-10-19 23:49:13 UTC
Thanks Florian - I realize it's a little optimistic expecting the resolver library to work for non-QUERY messages.

However, I think there's already some separation in the resolver's high-level routines (res_query and res_search) and res_send; the latter seems intended to be message-agnostic.  I think it's valuable for users of glibc if res_send can preserve its generality - and doing so here is a small change.  Please consider this patch. :)

For portability I ended up implementing my own code for sending DNS messages over sockets (years ago - this is quite an old bug!), just as you suggested.  But it's a shame since it duplicates much of the functionality already present in most implementations of res_send.
Comment 5 Ondrej Bilka 2013-10-21 07:18:12 UTC
A more reasonable approach than adding update functionality to res_send would be adding a high level routine, say res_update. Do you want to work on this?
Comment 6 Florian Weimer 2013-10-21 07:20:34 UTC
(In reply to Ondrej Bilka from comment #5)
> A more reasonable approach than adding update functionality to res_send
> would be adding a high level routine, say res_update. Do you want to work on
> this?

I think upstream already has support for DNS UPDATE, but we have been out of sync for a long, long time.
Comment 7 Ondrej Bilka 2013-10-23 13:10:58 UTC
> I think upstream already has support for DNS UPDATE, 
> but we have been out of sync for a long, long time.

If there is equivalent functionality it should be used instead relying on res_send which may not be portable.