diff options
Diffstat (limited to 'src/resolve')
-rw-r--r-- | src/resolve/resolved-bus.c | 10 | ||||
-rw-r--r-- | src/resolve/resolved-conf.c | 20 | ||||
-rw-r--r-- | src/resolve/resolved-dns-dnssec.c | 12 | ||||
-rw-r--r-- | src/resolve/resolved-dns-query.c | 13 | ||||
-rw-r--r-- | src/resolve/resolved-dns-search-domain.c | 3 | ||||
-rw-r--r-- | src/resolve/resolved-dns-search-domain.h | 1 | ||||
-rw-r--r-- | src/resolve/resolved-dns-transaction.c | 72 | ||||
-rw-r--r-- | src/resolve/resolved-link-bus.c | 52 | ||||
-rw-r--r-- | src/resolve/resolved-link.c | 56 | ||||
-rw-r--r-- | src/resolve/resolved-manager.c | 6 | ||||
-rw-r--r-- | src/resolve/resolved-manager.h | 1 |
11 files changed, 167 insertions, 79 deletions
diff --git a/src/resolve/resolved-bus.c b/src/resolve/resolved-bus.c index d8e8638327..834ae837de 100644 --- a/src/resolve/resolved-bus.c +++ b/src/resolve/resolved-bus.c @@ -1217,19 +1217,19 @@ static int bus_property_get_search_domains( assert(reply); assert(m); - r = sd_bus_message_open_container(reply, 'a', "(is)"); + r = sd_bus_message_open_container(reply, 'a', "(isb)"); if (r < 0) return r; LIST_FOREACH(domains, d, m->search_domains) { - r = sd_bus_message_append(reply, "(is)", 0, d->name); + r = sd_bus_message_append(reply, "(isb)", 0, d->name, d->route_only); if (r < 0) return r; } HASHMAP_FOREACH(l, m->links, i) { LIST_FOREACH(domains, d, l->search_domains) { - r = sd_bus_message_append(reply, "is", l->ifindex, d->name); + r = sd_bus_message_append(reply, "(isb)", l->ifindex, d->name, d->route_only); if (r < 0) return r; } @@ -1450,7 +1450,7 @@ static const sd_bus_vtable resolve_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("LLMNRHostname", "s", NULL, offsetof(Manager, llmnr_hostname), 0), SD_BUS_PROPERTY("DNS", "a(iiay)", bus_property_get_dns_servers, 0, 0), - SD_BUS_PROPERTY("Domains", "a(is)", bus_property_get_search_domains, 0, 0), + SD_BUS_PROPERTY("SearchDomains", "a(isb)", bus_property_get_search_domains, 0, 0), SD_BUS_PROPERTY("TransactionStatistics", "(tt)", bus_property_get_transaction_statistics, 0, 0), SD_BUS_PROPERTY("CacheStatistics", "(ttt)", bus_property_get_cache_statistics, 0, 0), SD_BUS_PROPERTY("DNSSECStatistics", "(tttt)", bus_property_get_dnssec_statistics, 0, 0), @@ -1463,7 +1463,7 @@ static const sd_bus_vtable resolve_vtable[] = { SD_BUS_METHOD("ResetStatistics", NULL, NULL, bus_method_reset_statistics, 0), SD_BUS_METHOD("GetLink", "i", "o", bus_method_get_link, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SetLinkDNS", "ia(iay)", NULL, bus_method_set_link_dns_servers, 0), - SD_BUS_METHOD("SetLinkDomains", "ias", NULL, bus_method_set_link_search_domains, 0), + SD_BUS_METHOD("SetLinkDomains", "ia(sb)", NULL, bus_method_set_link_search_domains, 0), SD_BUS_METHOD("SetLinkLLMNR", "is", NULL, bus_method_set_link_llmnr, 0), SD_BUS_METHOD("SetLinkMulticastDNS", "is", NULL, bus_method_set_link_mdns, 0), SD_BUS_METHOD("SetLinkDNSSEC", "is", NULL, bus_method_set_link_dnssec, 0), diff --git a/src/resolve/resolved-conf.c b/src/resolve/resolved-conf.c index 88df7534c4..6d8c35164e 100644 --- a/src/resolve/resolved-conf.c +++ b/src/resolve/resolved-conf.c @@ -80,20 +80,34 @@ int manager_parse_dns_server_string_and_warn(Manager *m, DnsServerType type, con int manager_add_search_domain_by_string(Manager *m, const char *domain) { DnsSearchDomain *d; + bool route_only; int r; assert(m); assert(domain); + route_only = *domain == '~'; + if (route_only) + domain++; + + if (dns_name_is_root(domain) || streq(domain, "*")) { + route_only = true; + domain = "."; + } + r = dns_search_domain_find(m->search_domains, domain, &d); if (r < 0) return r; - if (r > 0) { + if (r > 0) dns_search_domain_move_back_and_unmark(d); - return 0; + else { + r = dns_search_domain_new(m, &d, DNS_SEARCH_DOMAIN_SYSTEM, NULL, domain); + if (r < 0) + return r; } - return dns_search_domain_new(m, NULL, DNS_SEARCH_DOMAIN_SYSTEM, NULL, domain); + d->route_only = route_only; + return 0; } int manager_parse_search_domains_and_warn(Manager *m, const char *string) { diff --git a/src/resolve/resolved-dns-dnssec.c b/src/resolve/resolved-dns-dnssec.c index 8e3c78e7bf..76c801cce8 100644 --- a/src/resolve/resolved-dns-dnssec.c +++ b/src/resolve/resolved-dns-dnssec.c @@ -28,18 +28,6 @@ #include "resolved-dns-packet.h" #include "string-table.h" -/* Open question: - * - * How does the DNSSEC canonical form of a hostname with a label - * containing a dot look like, the way DNS-SD does it? - * - * TODO: - * - * - enable by default - * - Allow clients to request DNSSEC even if DNSSEC is off - * - make sure when getting an NXDOMAIN response through CNAME, we still process the first CNAMEs in the packet - * */ - #define VERIFY_RRS_MAX 256 #define MAX_KEY_SIZE (32*1024) diff --git a/src/resolve/resolved-dns-query.c b/src/resolve/resolved-dns-query.c index ef977b0948..a00851658e 100644 --- a/src/resolve/resolved-dns-query.c +++ b/src/resolve/resolved-dns-query.c @@ -93,17 +93,20 @@ static int dns_query_candidate_next_search_domain(DnsQueryCandidate *c) { assert(c); - if (c->search_domain && c->search_domain->linked) { + if (c->search_domain && c->search_domain->linked) next = c->search_domain->domains_next; + else + next = dns_scope_get_search_domains(c->scope); + for (;;) { if (!next) /* We hit the end of the list */ return 0; - } else { - next = dns_scope_get_search_domains(c->scope); + if (!next->route_only) + break; - if (!next) /* OK, there's nothing. */ - return 0; + /* Skip over route-only domains */ + next = next->domains_next; } dns_search_domain_unref(c->search_domain); diff --git a/src/resolve/resolved-dns-search-domain.c b/src/resolve/resolved-dns-search-domain.c index f9d966abb1..356c05b9a4 100644 --- a/src/resolve/resolved-dns-search-domain.c +++ b/src/resolve/resolved-dns-search-domain.c @@ -42,9 +42,6 @@ int dns_search_domain_new( if (r < 0) return r; - if (dns_name_is_root(normalized)) - return -EINVAL; - if (l) { if (l->n_search_domains >= LINK_SEARCH_DOMAINS_MAX) return -E2BIG; diff --git a/src/resolve/resolved-dns-search-domain.h b/src/resolve/resolved-dns-search-domain.h index 2e0af31dda..c1903b334f 100644 --- a/src/resolve/resolved-dns-search-domain.h +++ b/src/resolve/resolved-dns-search-domain.h @@ -44,6 +44,7 @@ struct DnsSearchDomain { char *name; bool marked:1; + bool route_only:1; bool linked:1; LIST_FIELDS(DnsSearchDomain, domains); diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c index 77f9ef0a83..802ad860a4 100644 --- a/src/resolve/resolved-dns-transaction.c +++ b/src/resolve/resolved-dns-transaction.c @@ -732,6 +732,55 @@ fail: dns_transaction_complete(t, DNS_TRANSACTION_ERRNO); } +static int dns_transaction_has_positive_answer(DnsTransaction *t, DnsAnswerFlags *flags) { + int r; + + assert(t); + + /* Checks whether the answer is positive, i.e. either a direct + * answer to the question, or a CNAME/DNAME for it */ + + r = dns_answer_match_key(t->answer, t->key, flags); + if (r != 0) + return r; + + r = dns_answer_find_cname_or_dname(t->answer, t->key, NULL, flags); + if (r != 0) + return r; + + return false; +} + +static int dns_transaction_fix_rcode(DnsTransaction *t) { + int r; + + assert(t); + + /* Fix up the RCODE to SUCCESS if we get at least one matching RR in a response. Note that this contradicts the + * DNS RFCs a bit. Specifically, RFC 6604 Section 3 clarifies that the RCODE shall say something about a + * CNAME/DNAME chain element coming after the last chain element contained in the message, and not the first + * one included. However, it also indicates that not all DNS servers implement this correctly. Moreover, when + * using DNSSEC we usually only can prove the first element of a CNAME/DNAME chain anyway, hence let's settle + * on always processing the RCODE as referring to the immediate look-up we do, i.e. the first element of a + * CNAME/DNAME chain. This way, we uniformly handle CNAME/DNAME chains, regardless if the DNS server + * incorrectly implements RCODE, whether DNSSEC is in use, or whether the DNS server only supplied us with an + * incomplete CNAME/DNAME chain. + * + * Or in other words: if we get at least one positive reply in a message we patch NXDOMAIN to become SUCCESS, + * and then rely on the CNAME chasing logic to figure out that there's actually a CNAME error with a new + * lookup. */ + + if (t->answer_rcode != DNS_RCODE_NXDOMAIN) + return 0; + + r = dns_transaction_has_positive_answer(t, NULL); + if (r <= 0) + return r; + + t->answer_rcode = DNS_RCODE_SUCCESS; + return 0; +} + void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) { usec_t ts; int r; @@ -923,6 +972,10 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) { t->answer_dnssec_result = _DNSSEC_RESULT_INVALID; t->answer_authenticated = false; + r = dns_transaction_fix_rcode(t); + if (r < 0) + goto fail; + /* Block GC while starting requests for additional DNSSEC RRs */ t->block_gc++; r = dns_transaction_request_dnssec_keys(t); @@ -1635,25 +1688,6 @@ static int dns_transaction_request_dnssec_rr(DnsTransaction *t, DnsResourceKey * return 1; } -static int dns_transaction_has_positive_answer(DnsTransaction *t, DnsAnswerFlags *flags) { - int r; - - assert(t); - - /* Checks whether the answer is positive, i.e. either a direct - * answer to the question, or a CNAME/DNAME for it */ - - r = dns_answer_match_key(t->answer, t->key, flags); - if (r != 0) - return r; - - r = dns_answer_find_cname_or_dname(t->answer, t->key, NULL, flags); - if (r != 0) - return r; - - return false; -} - static int dns_transaction_negative_trust_anchor_lookup(DnsTransaction *t, const char *name) { int r; diff --git a/src/resolve/resolved-link-bus.c b/src/resolve/resolved-link-bus.c index 2ca7ece851..e6b087f412 100644 --- a/src/resolve/resolved-link-bus.c +++ b/src/resolve/resolved-link-bus.c @@ -75,12 +75,12 @@ static int property_get_domains( assert(reply); assert(l); - r = sd_bus_message_open_container(reply, 'a', "s"); + r = sd_bus_message_open_container(reply, 'a', "(sb)"); if (r < 0) return r; LIST_FOREACH(domains, d, l->search_domains) { - r = sd_bus_message_append(reply, "s", d->name); + r = sd_bus_message_append(reply, "(sb)", d->name, d->route_only); if (r < 0) return r; } @@ -242,47 +242,71 @@ clear: } int bus_link_method_set_search_domains(sd_bus_message *message, void *userdata, sd_bus_error *error) { - _cleanup_free_ char **domains = NULL; Link *l = userdata; - char **i; int r; assert(message); assert(l); - r = sd_bus_message_read_strv(message, &domains); + r = sd_bus_message_enter_container(message, 'a', "(sb)"); if (r < 0) return r; - STRV_FOREACH(i, domains) { + for (;;) { + const char *name; + int route_only; - r = dns_name_is_valid(*i); + r = sd_bus_message_read(message, "(sb)", &name, &route_only); if (r < 0) return r; if (r == 0) - return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid search domain %s", *i); - if (dns_name_is_root(*i)) + break; + + r = dns_name_is_valid(name); + if (r < 0) + return r; + if (r == 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid search domain %s", name); + if (!route_only && dns_name_is_root(name)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Root domain is not suitable as search domain"); } dns_search_domain_mark_all(l->search_domains); - STRV_FOREACH(i, domains) { + r = sd_bus_message_rewind(message, false); + if (r < 0) + return r; + + for (;;) { DnsSearchDomain *d; + const char *name; + int route_only; - r = dns_search_domain_find(l->search_domains, *i, &d); + r = sd_bus_message_read(message, "(sb)", &name, &route_only); + if (r < 0) + goto clear; + if (r == 0) + break; + + r = dns_search_domain_find(l->search_domains, name, &d); if (r < 0) goto clear; if (r > 0) dns_search_domain_move_back_and_unmark(d); else { - r = dns_search_domain_new(l->manager, NULL, DNS_SEARCH_DOMAIN_LINK, l, *i); + r = dns_search_domain_new(l->manager, &d, DNS_SEARCH_DOMAIN_LINK, l, name); if (r < 0) goto clear; } + + d->route_only = route_only; } + r = sd_bus_message_exit_container(message); + if (r < 0) + goto clear; + dns_search_domain_unlink_marked(l->search_domains); return sd_bus_reply_method_return(message, NULL); @@ -430,7 +454,7 @@ const sd_bus_vtable link_vtable[] = { SD_BUS_PROPERTY("ScopesMask", "t", property_get_scopes_mask, 0, 0), SD_BUS_PROPERTY("DNS", "a(iay)", property_get_dns, 0, 0), - SD_BUS_PROPERTY("Domains", "as", property_get_domains, 0, 0), + SD_BUS_PROPERTY("Domains", "a(sb)", property_get_domains, 0, 0), SD_BUS_PROPERTY("LLMNR", "s", property_get_resolve_support, offsetof(Link, llmnr_support), 0), SD_BUS_PROPERTY("MulticastDNS", "s", property_get_resolve_support, offsetof(Link, mdns_support), 0), SD_BUS_PROPERTY("DNSSEC", "s", property_get_dnssec_mode, offsetof(Link, dnssec_mode), 0), @@ -438,7 +462,7 @@ const sd_bus_vtable link_vtable[] = { SD_BUS_PROPERTY("DNSSECSupport", "b", property_get_dnssec_supported, 0, 0), SD_BUS_METHOD("SetDNS", "a(iay)", NULL, bus_link_method_set_dns_servers, 0), - SD_BUS_METHOD("SetDomains", "as", NULL, bus_link_method_set_search_domains, 0), + SD_BUS_METHOD("SetDomains", "a(sb)", NULL, bus_link_method_set_search_domains, 0), SD_BUS_METHOD("SetLLMNR", "s", NULL, bus_link_method_set_llmnr, 0), SD_BUS_METHOD("SetMulticastDNS", "s", NULL, bus_link_method_set_mdns, 0), SD_BUS_METHOD("SetDNSSEC", "s", NULL, bus_link_method_set_dnssec, 0), diff --git a/src/resolve/resolved-link.c b/src/resolve/resolved-link.c index e2f9c8b400..37dd4a6e78 100644 --- a/src/resolve/resolved-link.c +++ b/src/resolve/resolved-link.c @@ -377,38 +377,60 @@ clear: return r; } +static int link_update_search_domain_one(Link *l, const char *name, bool route_only) { + DnsSearchDomain *d; + int r; + + r = dns_search_domain_find(l->search_domains, name, &d); + if (r < 0) + return r; + if (r > 0) + dns_search_domain_move_back_and_unmark(d); + else { + r = dns_search_domain_new(l->manager, &d, DNS_SEARCH_DOMAIN_LINK, l, name); + if (r < 0) + return r; + } + + d->route_only = route_only; + return 0; +} + static int link_update_search_domains(Link *l) { - _cleanup_strv_free_ char **domains = NULL; + _cleanup_strv_free_ char **sdomains = NULL, **rdomains = NULL; char **i; - int r; + int r, q; assert(l); - r = sd_network_link_get_domains(l->ifindex, &domains); - if (r == -ENODATA) { + r = sd_network_link_get_search_domains(l->ifindex, &sdomains); + if (r < 0 && r != -ENODATA) + goto clear; + + q = sd_network_link_get_route_domains(l->ifindex, &rdomains); + if (q < 0 && q != -ENODATA) { + r = q; + goto clear; + } + + if (r == -ENODATA && q == -ENODATA) { /* networkd knows nothing about this interface, and that's fine. */ r = 0; goto clear; } - if (r < 0) - goto clear; dns_search_domain_mark_all(l->search_domains); - STRV_FOREACH(i, domains) { - DnsSearchDomain *d; - - r = dns_search_domain_find(l->search_domains, *i, &d); + STRV_FOREACH(i, sdomains) { + r = link_update_search_domain_one(l, *i, false); if (r < 0) goto clear; + } - if (r > 0) - dns_search_domain_move_back_and_unmark(d); - else { - r = dns_search_domain_new(l->manager, NULL, DNS_SEARCH_DOMAIN_LINK, l, *i); - if (r < 0) - goto clear; - } + STRV_FOREACH(i, rdomains) { + r = link_update_search_domain_one(l, *i, true); + if (r < 0) + goto clear; } dns_search_domain_unlink_marked(l->search_domains); diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c index 704f012c37..4306403834 100644 --- a/src/resolve/resolved-manager.c +++ b/src/resolve/resolved-manager.c @@ -206,7 +206,7 @@ static int manager_rtnl_listen(Manager *m) { if (r < 0) return r; - r = sd_netlink_attach_event(m->rtnl, m->event, 0); + r = sd_netlink_attach_event(m->rtnl, m->event, SD_EVENT_PRIORITY_IMPORTANT); if (r < 0) return r; @@ -314,6 +314,10 @@ static int manager_network_monitor_listen(Manager *m) { if (r < 0) return r; + r = sd_event_source_set_priority(m->network_event_source, SD_EVENT_PRIORITY_IMPORTANT+5); + if (r < 0) + return r; + (void) sd_event_source_set_description(m->network_event_source, "network-monitor"); return 0; diff --git a/src/resolve/resolved-manager.h b/src/resolve/resolved-manager.h index a4291d57ff..1af49c8fb9 100644 --- a/src/resolve/resolved-manager.h +++ b/src/resolve/resolved-manager.h @@ -74,6 +74,7 @@ struct Manager { LIST_HEAD(DnsSearchDomain, search_domains); unsigned n_search_domains; + bool permit_domain_search; bool need_builtin_fallbacks:1; |