dns_ioevent() not called when DNS server is not recursive

Iñaki Baz Castillo ibc at aliax.net
Fri Feb 4 14:31:48 MSK 2011


2011/2/4 Michael Tokarev <mjt at tls.msk.ru>:
>> But after dns_ioevent() I check dns_status() and it returns 0, so no
>> error. I don't understand why. Is it the expected behaviour? if so,
>> how can I realize of the error?
>
> "REFUSED" is not a valid return code for a recursive resolver listed
> in /etc/resolv.conf.  That to say: if the server listed there returns
> "REFUSED" we're screwed, we can't resolve any query.  What to do in
> this very case is not clear.  udns tries to pretend it didn't receive
> that "REFUSED" reply and will retry after a timeout, in a hope the
> next time the query will be answered.

Ok, so it would behave as if a timeout occurs, am I right?

BTW I've repeated the same test I did yesterday, same code and same
non recursive DNS server, and now I get a very different result:


This is the DNS response:

    .... ...1 .... .... = Recursion desired: Do query recursively
  .... .... .... 0101 = Reply code: Refused (5)

And indeed, now the callback routine is called, rr is null (of
course), and dns_status() returns -1:

  DNS_E_TEMPFAIL	= -1,	/* timeout, SERVFAIL or similar */


Not sure what I was getting yesterday in this very same test. I'll try
to reproduce it (by also capturing the UDP response to insect it).



>> Basically this is the important part of my testing code:
>>
>> -------------------------------------------
>>   dns_submit_srv(NULL, domain, service, protocol, 0, dns_cb, NULL)
>>
>>   now = time(NULL);
>>
>>   while (! NULL) {
>>     t = dns_timeouts(0, -1, now);
>>     t = poll(&pfd, 1, 100);
>
> this is not optimal.  dns_timeouts() returned number of seconds
> before next timer will expire (or -1 if no timers are pending).
> So you really want to use this information when calling poll(),
> like this:
>
>      t = poll(&pfd, 1, t < 0 ? -1 : t * 1000);
>
> (the value returned by dns_timeouts() is in seconds, poll()
> expects the timeout to be in milliseconds, hence the multiplier).

Thanks a lot. I'm still learning about this I didn't focus enough on it yet :)


>>     now = time(NULL);
>>     if (t) {
>>       dns_ioevent(NULL, now);
>>       printf("--- dns_status = %i\n", dns_status(NULL));
>>       break;
>>     }
>>   }
>> ------------------------------------------
>
> And there's an error too.  dns_status() is valid only when some
> query is complete - that's either inside the callback routine
> or - in case of syncronous interface like dns_resolve() - right
> after it returned.  I re-read the manpage - indeed, the description
> of this function isn't entirely correct, it tells "return status
> code from last operation" - I mean to say "last completed query"
> not "last operation".

Yes, I understand it. I just wrote "dns_status()" there since no
callback was called *yesterday* when the server replied.



> But it all boils down to one thing, I think.  You misunderstand
> the interface a bit.
>
> DNS isn't like this: submit (send) query, wait for the reply, and
> you'll get answer.  No.  Instead, it's a try and retry and retry
> sort of thing - that is, even when you know you received "something"
> it may be something else, not a reply you're waiting.  The same
> applies to timeouts too.
>
> udns will complete the query when it is ready, not when there's
> "something" received bythe UDP socket.

I know I know, I just was testing it with a single query (no parallel
multiquery and so). I understand that poll() returns true when
something has arrived to the socket, which could be anything. I'm used
to reactor pattenr, don't worry :)

For now I'm just experimenting with udns so I expect no other reply in
the UDP socket other than the response from the DNS server. That's the
reason of my poor code.



Thanks a lot for all your help. I appreciate it a lot.



-- 
Iñaki Baz Castillo
<ibc at aliax.net>


More information about the udns mailing list