Hi.

Your diff looks correct. I can't see a reason for the "ar_datalen == -1"
special case here.

According to my tests, gethostbyname() with a bogus nameserver (not
responding, not reachable, ...) now fails with TRY_AGAIN, but still
fails with HOST_NOT_FOUND if "bind" is not set on the lookup
directive, which feels consistent.

I have to review the resolver logic to see if a fix is needed at deeper
level. But still, this diff makes sense on its own, so ok eric@.

Eric.


On Wed, Jun 26, 2019 at 11:57:10AM +0200, Martijn van Duren wrote:
> Found this yesterday while playing with a dnsbl filter for smtpd during 
> network outage and found that gethostbyname returns HOST_NOT_FOUND.
> Glibc, musl, and FreeBSD return TRY_AGAIN.
> 
> This is annoying because for a DNSBL I need to be able to differentiate
> between a resolver not being available and an entry not existing in the
> upstream database.
> 
> The reason is that in gethostnamadr_async.c for case ASR_STATE_NOT_FOUND
> the ar_h_errno is set to HOST_NOT_FOUND if we don't have a subq_h_errno.
> 
> Looking at case ASR_STATE_SUBQUERY we don't copy subq_h_errno from
> ar->ar_h_errno, while res_send_async.c (which is used by gethostnamaddr
> as a backend) always sets ar_h_errno and ar_count in case
> ASR_STATE_HALT.
> 
> I've looked at the code but I can't find any reason why not getting a
> reply gets this special treatment.
> 
> Assuming I haven't missed anything the diff below uses the fact that
> no packet also has ar_count set to 0 (res_send_async.c:268) and always
> copy the ar_h_errno from the subquery.
> 
> This both reduces the LoC and fixes the issue for me.
> 
> OK?
> 
> martijn@
> 
> Index: gethostnamadr_async.c
> ===================================================================
> RCS file: /cvs/src/lib/libc/asr/gethostnamadr_async.c,v
> retrieving revision 1.44
> diff -u -p -r1.44 gethostnamadr_async.c
> --- gethostnamadr_async.c     28 Apr 2018 15:16:49 -0000      1.44
> +++ gethostnamadr_async.c     26 Jun 2019 09:55:02 -0000
> @@ -289,12 +289,10 @@ gethostnamadr_async_run(struct asr_query
>               /* Done. */
>               as->as_subq = NULL;
>  
> -             if (ar->ar_datalen == -1) {
> -                     async_set_state(as, ASR_STATE_NEXT_DB);
> -                     break;
> -             }
> -
> -             /* If we got a packet but no anwser, use the next DB. */
> +             /*
> +              * We either got no packet or a packet without an answer.
> +              * Saveguard the h_errno and use the next DB.
> +              */
>               if (ar->ar_count == 0) {
>                       free(ar->ar_data);
>                       as->as.hostnamadr.subq_h_errno = ar->ar_h_errno;
> 
> 

Reply via email to