summaryrefslogtreecommitdiff
path: root/src/network
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2016-01-25 19:46:00 +0100
committerLennart Poettering <lennart@poettering.net>2016-01-26 14:42:03 +0100
commit3df9bec57c3e2d96f7e2a25961585cfa609b61eb (patch)
tree41dc9aafc458479cc827fe32a75eacbd9afdb3b0 /src/network
parent1d35b2d6e25ba100c903f02c92c67389e67bb913 (diff)
networkd: rework Domains= setting
Previously, .network files only knew a vaguely defined "Domains=" concept, for which the documentation declared it was the "DNS domain" for the network connection, without specifying what that means. With this the Domains setting is reworked, so that there are now "routing" domains and "search" domains. The former are to be used by resolved to route DNS request to specific network interfaces, the latter is to be used for searching single-label hostnames with (in addition to being used for routing). Both settings are configured in the "Domains=" setting. Normal domain names listed in it are now considered search domains (for compatibility with existing setups), while those prefixed with "~" are considered routing domains only. To route all lookups to a specific interface the routing domain "." may be used, referring to the root domain. An alternative syntax for this is the "*", as was already implemented before using the "wildcard" domain concept. This commit adds proper parsers for this new logic, and exposes this via the sd-network API. This information is not used by resolved yet, this will be added in a later commit.
Diffstat (limited to 'src/network')
-rw-r--r--src/network/networkctl.c45
-rw-r--r--src/network/networkd-link.c49
-rw-r--r--src/network/networkd-manager.c21
-rw-r--r--src/network/networkd-network-gperf.gperf2
-rw-r--r--src/network/networkd-network.c112
-rw-r--r--src/network/networkd-network.h3
6 files changed, 124 insertions, 108 deletions
diff --git a/src/network/networkctl.c b/src/network/networkctl.c
index 4a8fa4d8f3..c710ecda61 100644
--- a/src/network/networkctl.c
+++ b/src/network/networkctl.c
@@ -502,7 +502,7 @@ static int link_status_one(
sd_netlink *rtnl,
sd_hwdb *hwdb,
const char *name) {
- _cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **domains = NULL;
+ _cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **search_domains = NULL, **route_domains = NULL;
_cleanup_free_ char *setup_state = NULL, *operational_state = NULL, *tz = NULL;
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
_cleanup_(sd_device_unrefp) sd_device *d = NULL;
@@ -576,18 +576,8 @@ static int link_status_one(
setup_state_to_color(setup_state, &on_color_setup, &off_color_setup);
sd_network_link_get_dns(ifindex, &dns);
- sd_network_link_get_domains(ifindex, &domains);
- r = sd_network_link_get_wildcard_domain(ifindex);
- if (r > 0) {
- char *wildcard;
-
- wildcard = strdup("*");
- if (!wildcard)
- return log_oom();
-
- if (strv_consume(&domains, wildcard) < 0)
- return log_oom();
- }
+ sd_network_link_get_search_domains(ifindex, &search_domains);
+ sd_network_link_get_route_domains(ifindex, &route_domains);
sprintf(devid, "n%i", ifindex);
@@ -655,8 +645,10 @@ static int link_status_one(
if (!strv_isempty(dns))
dump_list(" DNS: ", dns);
- if (!strv_isempty(domains))
- dump_list(" Domain: ", domains);
+ if (!strv_isempty(search_domains))
+ dump_list(" Search Domains: ", search_domains);
+ if (!strv_isempty(route_domains))
+ dump_list(" Route Domains: ", route_domains);
(void) sd_network_link_get_ntp(ifindex, &ntp);
if (!strv_isempty(ntp))
@@ -691,30 +683,35 @@ static int link_status(int argc, char *argv[], void *userdata) {
if (argc <= 1 && !arg_all) {
_cleanup_free_ char *operational_state = NULL;
- _cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **domains = NULL;
+ _cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **search_domains = NULL, **route_domains;
const char *on_color_operational, *off_color_operational;
sd_network_get_operational_state(&operational_state);
operational_state_to_color(operational_state, &on_color_operational, &off_color_operational);
- printf("%s%s%s State: %s%s%s\n",
+ printf("%s%s%s State: %s%s%s\n",
on_color_operational, draw_special_char(DRAW_BLACK_CIRCLE), off_color_operational,
on_color_operational, strna(operational_state), off_color_operational);
- dump_addresses(rtnl, " Address: ", 0);
- dump_gateways(rtnl, hwdb, " Gateway: ", 0);
+ dump_addresses(rtnl, " Address: ", 0);
+ dump_gateways(rtnl, hwdb, " Gateway: ", 0);
sd_network_get_dns(&dns);
if (!strv_isempty(dns))
- dump_list(" DNS: ", dns);
+ dump_list(" DNS: ", dns);
+
+ sd_network_get_search_domains(&search_domains);
+ if (!strv_isempty(search_domains))
+ dump_list("Search Domains: ", search_domains);
+
+ sd_network_get_route_domains(&route_domains);
+ if (!strv_isempty(route_domains))
+ dump_list(" Route Domains: ", route_domains);
- sd_network_get_domains(&domains);
- if (!strv_isempty(domains))
- dump_list(" Domain: ", domains);
sd_network_get_ntp(&ntp);
if (!strv_isempty(ntp))
- dump_list(" NTP: ", ntp);
+ dump_list(" NTP: ", ntp);
return 0;
}
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index bbda691c08..c152ec3cf6 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -2729,7 +2729,6 @@ int link_save(Link *link) {
admin_state, oper_state);
if (link->network) {
- char **address, **domain;
bool space;
sd_dhcp6_lease *dhcp6_lease = NULL;
@@ -2743,12 +2742,7 @@ int link_save(Link *link) {
fputs("DNS=", f);
space = false;
- STRV_FOREACH(address, link->network->dns) {
- if (space)
- fputc(' ', f);
- fputs(*address, f);
- space = true;
- }
+ fputstrv(f, link->network->dns, NULL, &space);
if (link->network->dhcp_dns &&
link->dhcp_lease) {
@@ -2778,12 +2772,7 @@ int link_save(Link *link) {
fputs("NTP=", f);
space = false;
- STRV_FOREACH(address, link->network->ntp) {
- if (space)
- fputc(' ', f);
- fputs(*address, f);
- space = true;
- }
+ fputstrv(f, link->network->ntp, NULL, &space);
if (link->network->dhcp_ntp &&
link->dhcp_lease) {
@@ -2801,7 +2790,6 @@ int link_save(Link *link) {
if (link->network->dhcp_ntp && dhcp6_lease) {
struct in6_addr *in6_addrs;
char **hosts;
- char **hostname;
r = sd_dhcp6_lease_get_ntp_addrs(dhcp6_lease,
&in6_addrs);
@@ -2813,26 +2801,14 @@ int link_save(Link *link) {
}
r = sd_dhcp6_lease_get_ntp_fqdn(dhcp6_lease, &hosts);
- if (r > 0) {
- STRV_FOREACH(hostname, hosts) {
- if (space)
- fputc(' ', f);
- fputs(*hostname, f);
- space = true;
- }
- }
+ if (r > 0)
+ fputstrv(f, hosts, NULL, &space);
}
fputc('\n', f);
fputs("DOMAINS=", f);
- space = false;
- STRV_FOREACH(domain, link->network->domains) {
- if (space)
- fputc(' ', f);
- fputs(*domain, f);
- space = true;
- }
+ fputstrv(f, link->network->search_domains, NULL, &space);
if (link->network->dhcp_domains &&
link->dhcp_lease) {
@@ -2851,20 +2827,15 @@ int link_save(Link *link) {
char **domains;
r = sd_dhcp6_lease_get_domains(dhcp6_lease, &domains);
- if (r >= 0) {
- STRV_FOREACH(domain, domains) {
- if (space)
- fputc(' ', f);
- fputs(*domain, f);
- space = true;
- }
- }
+ if (r >= 0)
+ fputstrv(f, domains, NULL, &space);
}
fputc('\n', f);
- fprintf(f, "WILDCARD_DOMAIN=%s\n",
- yes_no(link->network->wildcard_domain));
+ fputs("ROUTE_DOMAINS=", f);
+ fputstrv(f, link->network->route_domains, NULL, NULL);
+ fputc('\n', f);
fprintf(f, "LLMNR=%s\n",
resolve_support_to_string(link->network->llmnr));
diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c
index 24f5304cb0..7392f4758d 100644
--- a/src/network/networkd-manager.c
+++ b/src/network/networkd-manager.c
@@ -830,7 +830,7 @@ static void print_string_set(FILE *f, const char *field, Set *s) {
}
static int manager_save(Manager *m) {
- _cleanup_set_free_free_ Set *dns = NULL, *ntp = NULL, *domains = NULL;
+ _cleanup_set_free_free_ Set *dns = NULL, *ntp = NULL, *search_domains = NULL, *route_domains = NULL;
Link *link;
Iterator i;
_cleanup_free_ char *temp_path = NULL;
@@ -851,8 +851,12 @@ static int manager_save(Manager *m) {
if (!ntp)
return -ENOMEM;
- domains = set_new(&string_hash_ops);
- if (!domains)
+ search_domains = set_new(&string_hash_ops);
+ if (!search_domains)
+ return -ENOMEM;
+
+ route_domains = set_new(&string_hash_ops);
+ if (!route_domains)
return -ENOMEM;
HASHMAP_FOREACH(link, m->links, i) {
@@ -874,7 +878,11 @@ static int manager_save(Manager *m) {
if (r < 0)
return r;
- r = set_put_strdupv(domains, link->network->domains);
+ r = set_put_strdupv(search_domains, link->network->search_domains);
+ if (r < 0)
+ return r;
+
+ r = set_put_strdupv(route_domains, link->network->route_domains);
if (r < 0)
return r;
@@ -911,7 +919,7 @@ static int manager_save(Manager *m) {
r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname);
if (r >= 0) {
- r = set_put_strdup(domains, domainname);
+ r = set_put_strdup(search_domains, domainname);
if (r < 0)
return r;
} else if (r != -ENODATA)
@@ -934,7 +942,8 @@ static int manager_save(Manager *m) {
print_string_set(f, "DNS=", dns);
print_string_set(f, "NTP=", ntp);
- print_string_set(f, "DOMAINS=", domains);
+ print_string_set(f, "DOMAINS=", search_domains);
+ print_string_set(f, "ROUTE_DOMAINS=", route_domains);
r = fflush_and_check(f);
if (r < 0)
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index 2f2a36ccca..325aac7a61 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -43,7 +43,7 @@ Network.IPv6Token, config_parse_ipv6token,
Network.LLDP, config_parse_bool, 0, offsetof(Network, lldp)
Network.Address, config_parse_address, 0, 0
Network.Gateway, config_parse_gateway, 0, 0
-Network.Domains, config_parse_domains, 0, offsetof(Network, domains)
+Network.Domains, config_parse_domains, 0, 0
Network.DNS, config_parse_strv, 0, offsetof(Network, dns)
Network.LLMNR, config_parse_resolve_support, 0, offsetof(Network, llmnr)
Network.MulticastDNS, config_parse_resolve_support, 0, offsetof(Network, mdns)
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index c11cb3dcb3..1e520062f4 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -233,7 +233,8 @@ void network_free(Network *network) {
strv_free(network->ntp);
strv_free(network->dns);
- strv_free(network->domains);
+ strv_free(network->search_domains);
+ strv_free(network->route_domains);
strv_free(network->bind_carrier);
netdev_unref(network->bridge);
@@ -384,7 +385,10 @@ int network_apply(Manager *manager, Network *network, Link *link) {
route->protocol = RTPROT_STATIC;
}
- if (network->dns || network->ntp || network->domains) {
+ if (!strv_isempty(network->dns) ||
+ !strv_isempty(network->ntp) ||
+ !strv_isempty(network->search_domains) ||
+ !strv_isempty(network->route_domains)) {
manager_dirty(manager);
link_dirty(link);
}
@@ -469,49 +473,85 @@ int config_parse_netdev(const char *unit,
return 0;
}
-int config_parse_domains(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
- Network *network = userdata;
- char ***domains = data;
- char **domain;
+int config_parse_domains(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ const char *p;
+ Network *n = data;
int r;
- r = config_parse_strv(unit, filename, line, section, section_line,
- lvalue, ltype, rvalue, domains, userdata);
- if (r < 0)
- return r;
+ assert(n);
+ assert(lvalue);
+ assert(rvalue);
- strv_uniq(*domains);
- network->wildcard_domain = !!strv_find(*domains, "*");
+ if (isempty(rvalue)) {
+ n->search_domains = strv_free(n->search_domains);
+ n->route_domains = strv_free(n->route_domains);
+ return 0;
+ }
- STRV_FOREACH(domain, *domains) {
- if (is_localhost(*domain))
- log_syntax(unit, LOG_ERR, filename, line, 0, "'localhost' domain names may not be configured, ignoring assignment: %s", *domain);
- else {
- r = dns_name_is_valid(*domain);
- if (r <= 0 && !streq(*domain, "*")) {
- if (r < 0)
- log_error_errno(r, "Failed to validate domain name: %s: %m", *domain);
- if (r == 0)
- log_warning("Domain name is not valid, ignoring assignment: %s", *domain);
- } else
+ p = rvalue;
+ for (;;) {
+ _cleanup_free_ char *w = NULL, *normalized = NULL;
+ const char *domain;
+ bool is_route;
+
+ r = extract_first_word(&p, &w, NULL, 0);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract search or route domain, ignoring: %s", rvalue);
+ break;
+ }
+ if (r == 0)
+ break;
+
+ is_route = w[0] == '~';
+ domain = is_route ? w + 1 : w;
+
+ if (dns_name_is_root(domain) || streq(domain, "*")) {
+ /* If the root domain appears as is, or the special token "*" is found, we'll consider this as
+ * routing domain, unconditionally. */
+ is_route = true;
+ domain = "."; /* make sure we don't allow empty strings, thus write the root domain as "." */
+
+ } else {
+ r = dns_name_normalize(domain, &normalized);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "'%s' is not a valid domain name, ignoring.", domain);
+ continue;
+ }
+
+ domain = normalized;
+
+ if (is_localhost(domain)) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "'localhost' domain names may not be configure as search or route domains, ignoring assignment: %s", domain);
continue;
+ }
}
- strv_remove(*domains, *domain);
+ if (is_route) {
+ r = strv_extend(&n->route_domains, domain);
+ if (r < 0)
+ return log_oom();
- /* We removed one entry, make sure we don't skip the next one */
- domain--;
+ } else {
+ r = strv_extend(&n->search_domains, domain);
+ if (r < 0)
+ return log_oom();
+ }
}
+ strv_uniq(n->route_domains);
+ strv_uniq(n->search_domains);
+
return 0;
}
@@ -930,7 +970,7 @@ int config_parse_dnssec_negative_trust_anchors(
Network *n = data;
int r;
- assert(filename);
+ assert(n);
assert(lvalue);
assert(rvalue);
diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h
index b07fa41abc..d17093d384 100644
--- a/src/network/networkd-network.h
+++ b/src/network/networkd-network.h
@@ -141,8 +141,7 @@ struct Network {
Hashmap *routes_by_section;
Hashmap *fdb_entries_by_section;
- bool wildcard_domain;
- char **domains, **dns, **ntp, **bind_carrier;
+ char **search_domains, **route_domains, **dns, **ntp, **bind_carrier;
ResolveSupport llmnr;
ResolveSupport mdns;