summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/basic/strv.c31
-rw-r--r--src/basic/strv.h2
-rw-r--r--src/libsystemd/sd-network/sd-network.c32
-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
-rw-r--r--src/resolve/resolved-link.c2
-rw-r--r--src/resolve/resolved-manager.h1
-rw-r--r--src/systemd/sd-network.h18
12 files changed, 179 insertions, 139 deletions
diff --git a/src/basic/strv.c b/src/basic/strv.c
index 0a3d15706f..dc5bafcf24 100644
--- a/src/basic/strv.c
+++ b/src/basic/strv.c
@@ -871,3 +871,34 @@ rollback:
nl[k] = NULL;
return -ENOMEM;
}
+
+int fputstrv(FILE *f, char **l, const char *separator, bool *space) {
+ bool b = false;
+ char **s;
+ int r;
+
+ /* Like fputs(), but for strv, and with a less stupid argument order */
+
+ if (!f)
+ f = stdout;
+ if (!separator)
+ separator = " ";
+ if (!space)
+ space = &b;
+
+ STRV_FOREACH(s, l) {
+ if (*space) {
+ r = fputs(separator, f);
+ if (r < 0)
+ return r;
+ }
+
+ r = fputs(*s, f);
+ if (r < 0)
+ return r;
+
+ *space = true;
+ }
+
+ return 0;
+}
diff --git a/src/basic/strv.h b/src/basic/strv.h
index bb61db2638..560f90115c 100644
--- a/src/basic/strv.h
+++ b/src/basic/strv.h
@@ -169,3 +169,5 @@ char ***strv_free_free(char ***l);
char **strv_skip(char **l, size_t n);
int strv_extend_n(char ***l, const char *value, size_t n);
+
+int fputstrv(FILE *f, char **l, const char *separator, bool *space);
diff --git a/src/libsystemd/sd-network/sd-network.c b/src/libsystemd/sd-network/sd-network.c
index c1f5867ee4..4b7fad9c81 100644
--- a/src/libsystemd/sd-network/sd-network.c
+++ b/src/libsystemd/sd-network/sd-network.c
@@ -95,10 +95,14 @@ _public_ int sd_network_get_ntp(char ***ret) {
return network_get_strv("NTP", ret);
}
-_public_ int sd_network_get_domains(char ***ret) {
+_public_ int sd_network_get_search_domains(char ***ret) {
return network_get_strv("DOMAINS", ret);
}
+_public_ int sd_network_get_route_domains(char ***ret) {
+ return network_get_strv("ROUTE_DOMAINS", ret);
+}
+
static int network_link_get_string(int ifindex, const char *field, char **ret) {
_cleanup_free_ char *s = NULL, *p = NULL;
int r;
@@ -222,10 +226,14 @@ _public_ int sd_network_link_get_ntp(int ifindex, char ***ret) {
return network_link_get_strv(ifindex, "NTP", ret);
}
-_public_ int sd_network_link_get_domains(int ifindex, char ***ret) {
+_public_ int sd_network_link_get_search_domains(int ifindex, char ***ret) {
return network_link_get_strv(ifindex, "DOMAINS", ret);
}
+_public_ int sd_network_link_get_route_domains(int ifindex, char ***ret) {
+ return network_link_get_strv(ifindex, "ROUTE_DOMAINS", ret);
+}
+
_public_ int sd_network_link_get_carrier_bound_to(int ifindex, char ***ret) {
return network_link_get_strv(ifindex, "CARRIER_BOUND_TO", ret);
}
@@ -234,26 +242,6 @@ _public_ int sd_network_link_get_carrier_bound_by(int ifindex, char ***ret) {
return network_link_get_strv(ifindex, "CARRIER_BOUND_BY", ret);
}
-_public_ int sd_network_link_get_wildcard_domain(int ifindex) {
- _cleanup_free_ char *p = NULL, *s = NULL;
- int r;
-
- assert_return(ifindex > 0, -EINVAL);
-
- if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
- return -ENOMEM;
-
- r = parse_env_file(p, NEWLINE, "WILDCARD_DOMAIN", &s, NULL);
- if (r == -ENOENT)
- return -ENODATA;
- if (r < 0)
- return r;
- if (isempty(s))
- return -ENODATA;
-
- return parse_boolean(s);
-}
-
static inline int MONITOR_TO_FD(sd_network_monitor *m) {
return (int) (unsigned long) m - 1;
}
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;
diff --git a/src/resolve/resolved-link.c b/src/resolve/resolved-link.c
index e2f9c8b400..8f0afc185b 100644
--- a/src/resolve/resolved-link.c
+++ b/src/resolve/resolved-link.c
@@ -384,7 +384,7 @@ static int link_update_search_domains(Link *l) {
assert(l);
- r = sd_network_link_get_domains(l->ifindex, &domains);
+ r = sd_network_link_get_search_domains(l->ifindex, &domains);
if (r == -ENODATA) {
/* networkd knows nothing about this interface, and that's fine. */
r = 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;
diff --git a/src/systemd/sd-network.h b/src/systemd/sd-network.h
index 653c61a162..ff0d2b191e 100644
--- a/src/systemd/sd-network.h
+++ b/src/systemd/sd-network.h
@@ -64,8 +64,11 @@ int sd_network_get_dns(char ***dns);
* representations of IP addresses */
int sd_network_get_ntp(char ***ntp);
-/* Get the search/routing domains for all links. */
-int sd_network_get_domains(char ***domains);
+/* Get the search domains for all links. */
+int sd_network_get_search_domains(char ***domains);
+
+/* Get the search domains for all links. */
+int sd_network_get_route_domains(char ***domains);
/* Get setup state from ifindex.
* Possible states:
@@ -134,8 +137,11 @@ int sd_network_link_get_dnssec_negative_trust_anchors(int ifindex, char ***nta);
int sd_network_link_get_lldp(int ifindex, char **lldp);
-/* Get the DNS domain names for a given link. */
-int sd_network_link_get_domains(int ifindex, char ***domains);
+/* Get the search DNS domain names for a given link. */
+int sd_network_link_get_search_domains(int ifindex, char ***domains);
+
+/* Get the route DNS domain names for a given link. */
+int sd_network_link_get_route_domains(int ifindex, char ***domains);
/* Get the CARRIERS to which current link is bound to. */
int sd_network_link_get_carrier_bound_to(int ifindex, char ***carriers);
@@ -146,10 +152,6 @@ int sd_network_link_get_carrier_bound_by(int ifindex, char ***carriers);
/* Get the timezone that was learnt on a specific link. */
int sd_network_link_get_timezone(int ifindex, char **timezone);
-/* Returns whether or not domains that don't match any link should be resolved
- * on this link. 1 for yes, 0 for no and negative value for error */
-int sd_network_link_get_wildcard_domain(int ifindex);
-
/* Monitor object */
typedef struct sd_network_monitor sd_network_monitor;