resolved: teach resolved the difference between "routing" and "search" domains

Following the changes to expose the "routing" and "search" domain concepts in networkd, actually make resolved use
them. It will now use routing domains exclusively for making DNS routing decisions, and use search domains additionally
for extending single-label names.
This commit is contained in:
Lennart Poettering 2016-01-25 23:19:49 +01:00
parent d390f8ef2d
commit ad44b56b0f
6 changed files with 93 additions and 46 deletions

View File

@ -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),

View File

@ -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);

View File

@ -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;

View File

@ -44,6 +44,7 @@ struct DnsSearchDomain {
char *name;
bool marked:1;
bool route_only:1;
bool linked:1;
LIST_FIELDS(DnsSearchDomain, domains);

View File

@ -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) {
DnsSearchDomain *d;
r = sd_bus_message_rewind(message, false);
if (r < 0)
return r;
r = dns_search_domain_find(l->search_domains, *i, &d);
for (;;) {
DnsSearchDomain *d;
const char *name;
int route_only;
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),

View File

@ -377,38 +377,60 @@ clear:
return r;
}
static int link_update_search_domains(Link *l) {
_cleanup_strv_free_ char **domains = NULL;
char **i;
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 **sdomains = NULL, **rdomains = NULL;
char **i;
int r, q;
assert(l);
r = sd_network_link_get_search_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);