When asked to look something up, and all scopes we contact fail we need
to pick a suitable error code for the failure, and given that we look up
things on multiple scopes we might have multiple errors to choose from.
So far we simply picked the error from the last scope in the list, which
hence would be pretty arbitrary.
Let's tweak this a bit, and if we have multiple errors to choose from,
let's prefer "conclusive" failures over "inconclusive" ones. The
"inconclusive" ones in this sense are the ones where we didn't even issue
a request, but couldn't even do that because we had no server, no
network or things like that. The "conclusive" ones are the errors we got
from a server, that hence a "real" in a way.
This addresses the confusion described in #37969. For LLMNR lookups we
generally refuse looking up A addresses via IPv6 and AAAA via IPv4. This
generates a DNS_TRANSACTION_NO_SERVERS error, which we would then return
for one type of lookup but not for the other, because the IPv6 scope is
generally created after the IPv4 one, and hence so far won.
Fixes: #37969
break;
default:
- /* Any kind of failure */
- bad = c;
+ /* Any kind of failure: save the most recent error, as long as we never saved one
+ * before or our current one is "conclusive" in the sense that we definitely did a
+ * lookup, and thus have a real answer (which might be a failure, but is still *some*
+ * answer). */
+
+ if (!bad || !IN_SET(state, DNS_TRANSACTION_NO_SERVERS, DNS_TRANSACTION_NETWORK_DOWN, DNS_TRANSACTION_NO_SOURCE))
+ bad = c;
+ break;
}
}