]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
resolved: teach resolved the difference between "routing" and "search" domains
authorLennart Poettering <lennart@poettering.net>
Mon, 25 Jan 2016 22:19:49 +0000 (23:19 +0100)
committerLennart Poettering <lennart@poettering.net>
Tue, 26 Jan 2016 13:42:04 +0000 (14:42 +0100)
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.

src/resolve/resolved-bus.c
src/resolve/resolved-dns-query.c
src/resolve/resolved-dns-search-domain.c
src/resolve/resolved-dns-search-domain.h
src/resolve/resolved-link-bus.c
src/resolve/resolved-link.c

index d8e863832746e48cd9593e397978a2a02221cc57..834ae837de3cf6ec17eb0d380619edf1d75e4f75 100644 (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),
index ef977b0948e74f050332a001694faec814019670..a00851658e4661544c263fffe4628c4dfa4ae5b7 100644 (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);
index f9d966abb1ba6308f497567c6d96458a44c51d25..356c05b9a47a2f5ae472f6266f03c162578a0b3a 100644 (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;
index 2e0af31dda7fa8750ad5fc203d788bab83a113f2..c1903b334f04d91cd6671fe961d3a20d4633affb 100644 (file)
@@ -44,6 +44,7 @@ struct DnsSearchDomain {
         char *name;
 
         bool marked:1;
+        bool route_only:1;
 
         bool linked:1;
         LIST_FIELDS(DnsSearchDomain, domains);
index 2ca7ece851bc613b15e3f3cffa5c035eb92c18e3..e6b087f41254bc686e21e6595f7f465080425254 100644 (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) {
+        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),
index 8f0afc185bf9f5dca0709b3f12385308a19bc062..37dd4a6e786f61d8b4ea2b9d6e6f856babdf06e8 100644 (file)
@@ -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_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);