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