resolve: generate a nice clean error when clients try to resolve a name when the network is down

This commit is contained in:
Lennart Poettering 2016-01-20 21:28:22 +01:00
parent 6955a3ba9d
commit edbcc1fdd9
8 changed files with 38 additions and 1 deletions

View File

@ -80,6 +80,7 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = {
SD_BUS_ERROR_MAP(BUS_ERROR_RR_TYPE_UNSUPPORTED, EOPNOTSUPP),
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_LINK, ENXIO),
SD_BUS_ERROR_MAP(BUS_ERROR_LINK_BUSY, EBUSY),
SD_BUS_ERROR_MAP(BUS_ERROR_NETWORK_DOWN, ENETDOWN),
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_TRANSFER, ENXIO),
SD_BUS_ERROR_MAP(BUS_ERROR_TRANSFER_IN_PROGRESS, EBUSY),

View File

@ -79,6 +79,7 @@
#define BUS_ERROR_RR_TYPE_UNSUPPORTED "org.freedesktop.resolve1.ResourceRecordTypeUnsupported"
#define BUS_ERROR_NO_SUCH_LINK "org.freedesktop.resolve1.NoSuchLink"
#define BUS_ERROR_LINK_BUSY "org.freedesktop.resolve1.LinkBusy"
#define BUS_ERROR_NETWORK_DOWN "org.freedesktop.resolve1.NetworkDown"
#define _BUS_ERROR_DNS "org.freedesktop.resolve1.DnsError."
#define BUS_ERROR_NO_SUCH_TRANSFER "org.freedesktop.import1.NoSuchTransfer"

View File

@ -59,6 +59,9 @@ static int reply_query_state(DnsQuery *q) {
case DNS_TRANSACTION_RR_TYPE_UNSUPPORTED:
return sd_bus_reply_method_errorf(q->request, BUS_ERROR_RR_TYPE_UNSUPPORTED, "Server does not support requested resource record type");
case DNS_TRANSACTION_NETWORK_DOWN:
return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NETWORK_DOWN, "Network is down");
case DNS_TRANSACTION_RCODE_FAILURE: {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;

View File

@ -891,7 +891,8 @@ static int dns_query_synthesize_reply(DnsQuery *q, DnsTransactionState *state) {
DNS_TRANSACTION_RCODE_FAILURE,
DNS_TRANSACTION_NO_SERVERS,
DNS_TRANSACTION_TIMEOUT,
DNS_TRANSACTION_ATTEMPTS_MAX_REACHED))
DNS_TRANSACTION_ATTEMPTS_MAX_REACHED,
DNS_TRANSACTION_NETWORK_DOWN))
return 0;
DNS_QUESTION_FOREACH(key, q->question_utf8) {

View File

@ -1015,3 +1015,22 @@ bool dns_scope_name_needs_search_domain(DnsScope *s, const char *name) {
return dns_name_is_single_label(name);
}
bool dns_scope_network_good(DnsScope *s) {
Iterator i;
Link *l;
/* Checks whether the network is in good state for lookups on this scope. For mDNS/LLMNR/Classic DNS scopes
* bound to links this is easy, as they don't even exist if the link isn't in a suitable state. For the global
* DNS scope we check whether there are any links that are up and have an address. */
if (s->link)
return true;
HASHMAP_FOREACH(l, s->manager->links, i) {
if (link_relevant(l, AF_UNSPEC, false))
return true;
}
return false;
}

View File

@ -107,3 +107,5 @@ void dns_scope_dump(DnsScope *s, FILE *f);
DnsSearchDomain *dns_scope_get_search_domains(DnsScope *s);
bool dns_scope_name_needs_search_domain(DnsScope *s, const char *name);
bool dns_scope_network_good(DnsScope *s);

View File

@ -1094,6 +1094,14 @@ static int dns_transaction_prepare(DnsTransaction *t, usec_t ts) {
dns_transaction_stop_timeout(t);
r = dns_scope_network_good(t->scope);
if (r < 0)
return r;
if (r == 0) {
dns_transaction_complete(t, DNS_TRANSACTION_NETWORK_DOWN);
return 0;
}
if (t->n_attempts >= TRANSACTION_ATTEMPTS_MAX(t->scope->protocol)) {
dns_transaction_complete(t, DNS_TRANSACTION_ATTEMPTS_MAX_REACHED);
return 0;
@ -2969,6 +2977,7 @@ static const char* const dns_transaction_state_table[_DNS_TRANSACTION_STATE_MAX]
[DNS_TRANSACTION_DNSSEC_FAILED] = "dnssec-failed",
[DNS_TRANSACTION_NO_TRUST_ANCHOR] = "no-trust-anchor",
[DNS_TRANSACTION_RR_TYPE_UNSUPPORTED] = "rr-type-unsupported",
[DNS_TRANSACTION_NETWORK_DOWN] = "network-down",
};
DEFINE_STRING_TABLE_LOOKUP(dns_transaction_state, DnsTransactionState);

View File

@ -40,6 +40,7 @@ enum DnsTransactionState {
DNS_TRANSACTION_DNSSEC_FAILED,
DNS_TRANSACTION_NO_TRUST_ANCHOR,
DNS_TRANSACTION_RR_TYPE_UNSUPPORTED,
DNS_TRANSACTION_NETWORK_DOWN,
_DNS_TRANSACTION_STATE_MAX,
_DNS_TRANSACTION_STATE_INVALID = -1
};