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.
Created attachment 4951 [details] accept DNS UPDATE responses without RA set
Minor correction: testing again I see that res_send sets errno to ECONNREFUSED, not ETIMEDOUT.
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.
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.
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?
(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.
> 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.