From 3df9bec57c3e2d96f7e2a25961585cfa609b61eb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 25 Jan 2016 19:46:00 +0100 Subject: 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. --- src/network/networkctl.c | 45 ++++++------- src/network/networkd-link.c | 49 +++----------- src/network/networkd-manager.c | 21 ++++-- src/network/networkd-network-gperf.gperf | 2 +- src/network/networkd-network.c | 112 +++++++++++++++++++++---------- src/network/networkd-network.h | 3 +- 6 files changed, 124 insertions(+), 108 deletions(-) (limited to 'src/network') 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; -- cgit v1.2.3-54-g00ecf From dce8364918220bde8f2b520f17931451da72ffcf Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 25 Jan 2016 20:14:58 +0100 Subject: networkctl: move strv_isempty() check into dump_list() Previously, each invocation of dump_list() was prefixed with a call to strv_isempty() to suppress invocation of the function when the list is empty anyway. Move the check into the function itself, so that we can reduce the code a bit in size. (Also, prefix a couple of invocations we knowingly ignore return errors with a (void) cast). --- src/network/networkctl.c | 62 ++++++++++++++++++++---------------------------- 1 file changed, 26 insertions(+), 36 deletions(-) (limited to 'src/network') diff --git a/src/network/networkctl.c b/src/network/networkctl.c index c710ecda61..253692aa64 100644 --- a/src/network/networkctl.c +++ b/src/network/networkctl.c @@ -490,6 +490,9 @@ static int dump_addresses( static void dump_list(const char *prefix, char **l) { char **i; + if (strv_isempty(l)) + return; + STRV_FOREACH(i, l) { printf("%*s%s\n", (int) strlen(prefix), @@ -552,7 +555,6 @@ static int link_status_one( return rtnl_log_parse_error(r); have_mac = sd_netlink_message_read_ether_addr(reply, IFLA_ADDRESS, &e) >= 0; - if (have_mac) { const uint8_t *p; bool all_zeroes = true; @@ -567,34 +569,35 @@ static int link_status_one( have_mac = false; } - sd_netlink_message_read_u32(reply, IFLA_MTU, &mtu); + (void) sd_netlink_message_read_u32(reply, IFLA_MTU, &mtu); - sd_network_link_get_operational_state(ifindex, &operational_state); + (void) sd_network_link_get_operational_state(ifindex, &operational_state); operational_state_to_color(operational_state, &on_color_operational, &off_color_operational); - sd_network_link_get_setup_state(ifindex, &setup_state); + (void) sd_network_link_get_setup_state(ifindex, &setup_state); setup_state_to_color(setup_state, &on_color_setup, &off_color_setup); - sd_network_link_get_dns(ifindex, &dns); - sd_network_link_get_search_domains(ifindex, &search_domains); - sd_network_link_get_route_domains(ifindex, &route_domains); + (void) sd_network_link_get_dns(ifindex, &dns); + (void) sd_network_link_get_search_domains(ifindex, &search_domains); + (void) sd_network_link_get_route_domains(ifindex, &route_domains); + (void) sd_network_link_get_ntp(ifindex, &ntp); sprintf(devid, "n%i", ifindex); - (void)sd_device_new_from_device_id(&d, devid); + (void) sd_device_new_from_device_id(&d, devid); if (d) { - (void)sd_device_get_property_value(d, "ID_NET_LINK_FILE", &link); - (void)sd_device_get_property_value(d, "ID_NET_DRIVER", &driver); - (void)sd_device_get_property_value(d, "ID_PATH", &path); + (void) sd_device_get_property_value(d, "ID_NET_LINK_FILE", &link); + (void) sd_device_get_property_value(d, "ID_NET_DRIVER", &driver); + (void) sd_device_get_property_value(d, "ID_PATH", &path); r = sd_device_get_property_value(d, "ID_VENDOR_FROM_DATABASE", &vendor); if (r < 0) - (void)sd_device_get_property_value(d, "ID_VENDOR", &vendor); + (void) sd_device_get_property_value(d, "ID_VENDOR", &vendor); r = sd_device_get_property_value(d, "ID_MODEL_FROM_DATABASE", &model); if (r < 0) - (void)sd_device_get_property_value(d, "ID_MODEL", &model); + (void) sd_device_get_property_value(d, "ID_MODEL", &model); } link_get_type_string(iftype, d, &t); @@ -643,22 +646,14 @@ static int link_status_one( dump_addresses(rtnl, " Address: ", ifindex); dump_gateways(rtnl, hwdb, " Gateway: ", ifindex); - if (!strv_isempty(dns)) - dump_list(" DNS: ", dns); - if (!strv_isempty(search_domains)) - dump_list(" Search Domains: ", search_domains); - if (!strv_isempty(route_domains)) - dump_list(" Route Domains: ", route_domains); + dump_list(" DNS: ", dns); + dump_list(" Search Domains: ", search_domains); + dump_list(" Route Domains: ", route_domains); - (void) sd_network_link_get_ntp(ifindex, &ntp); - if (!strv_isempty(ntp)) - dump_list(" NTP: ", ntp); - - if (!strv_isempty(carrier_bound_to)) - dump_list("Carrier Bound To: ", carrier_bound_to); + dump_list(" NTP: ", ntp); - if (!strv_isempty(carrier_bound_by)) - dump_list("Carrier Bound By: ", carrier_bound_by); + dump_list("Carrier Bound To: ", carrier_bound_to); + dump_list("Carrier Bound By: ", carrier_bound_by); (void) sd_network_link_get_timezone(ifindex, &tz); if (tz) @@ -697,21 +692,16 @@ static int link_status(int argc, char *argv[], void *userdata) { 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); + dump_list("Search Domains: ", search_domains); sd_network_get_route_domains(&route_domains); - if (!strv_isempty(route_domains)) - dump_list(" Route Domains: ", route_domains); - + dump_list(" Route Domains: ", route_domains); sd_network_get_ntp(&ntp); - if (!strv_isempty(ntp)) - dump_list(" NTP: ", ntp); + dump_list(" NTP: ", ntp); return 0; } -- cgit v1.2.3-54-g00ecf From 0061695507e889069c0c974cf85cd570f7ec9a88 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 25 Jan 2016 20:31:11 +0100 Subject: networkd: use an OrderedSet instead of Set to collect link domains For the search domain logic the order is highly relevant, hence make sure when collecting the various search domains to add them to an ordered set, so that the order between search domains of a specific link is retained. --- Makefile.am | 1 + src/basic/ordered-set.c | 64 ++++++++++++++++++++++++++++++++++++++++++ src/basic/ordered-set.h | 6 ++++ src/network/networkd-manager.c | 39 ++++++++++++------------- 4 files changed, 91 insertions(+), 19 deletions(-) create mode 100644 src/basic/ordered-set.c (limited to 'src/network') diff --git a/Makefile.am b/Makefile.am index 1f204b826c..f933b5228e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -840,6 +840,7 @@ libbasic_la_SOURCES = \ src/basic/siphash24.h \ src/basic/set.h \ src/basic/ordered-set.h \ + src/basic/ordered-set.c \ src/basic/bitmap.c \ src/basic/bitmap.h \ src/basic/fdset.c \ diff --git a/src/basic/ordered-set.c b/src/basic/ordered-set.c new file mode 100644 index 0000000000..2e0bdf6488 --- /dev/null +++ b/src/basic/ordered-set.c @@ -0,0 +1,64 @@ +/*** + This file is part of systemd. + + Copyright 2016 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include "ordered-set.h" +#include "strv.h" + +int ordered_set_consume(OrderedSet *s, void *p) { + int r; + + r = ordered_set_put(s, p); + if (r <= 0) + free(p); + + return r; +} + +int ordered_set_put_strdup(OrderedSet *s, const char *p) { + char *c; + int r; + + assert(s); + assert(p); + + c = strdup(p); + if (!c) + return -ENOMEM; + + r = ordered_set_consume(s, c); + if (r == -EEXIST) + return 0; + + return r; +} + +int ordered_set_put_strdupv(OrderedSet *s, char **l) { + int n = 0, r; + char **i; + + STRV_FOREACH(i, l) { + r = ordered_set_put_strdup(s, *i); + if (r < 0) + return r; + + n += r; + } + + return n; +} diff --git a/src/basic/ordered-set.h b/src/basic/ordered-set.h index da10e90ff2..ab185c11aa 100644 --- a/src/basic/ordered-set.h +++ b/src/basic/ordered-set.h @@ -62,9 +62,15 @@ static inline bool ordered_set_iterate(OrderedSet *s, Iterator *i, void **value) return ordered_hashmap_iterate((OrderedHashmap*) s, i, value, NULL); } +int ordered_set_consume(OrderedSet *s, void *p); +int ordered_set_put_strdup(OrderedSet *s, const char *p); +int ordered_set_put_strdupv(OrderedSet *s, char **l); + #define ORDERED_SET_FOREACH(e, s, i) \ for ((i) = ITERATOR_FIRST; ordered_set_iterate((s), &(i), (void**)&(e)); ) DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedSet*, ordered_set_free); +DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedSet*, ordered_set_free_free); #define _cleanup_ordered_set_free_ _cleanup_(ordered_set_freep) +#define _cleanup_ordered_set_free_free_ _cleanup_(ordered_set_free_freep) diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index 7392f4758d..7b801ae6c9 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -35,6 +35,7 @@ #include "local-addresses.h" #include "netlink-util.h" #include "networkd.h" +#include "ordered-set.h" #include "path-util.h" #include "set.h" #include "udev-util.h" @@ -776,7 +777,7 @@ static int manager_connect_rtnl(Manager *m) { return 0; } -static int set_put_in_addr(Set *s, const struct in_addr *address) { +static int ordered_set_put_in_addr(OrderedSet *s, const struct in_addr *address) { char *p; int r; @@ -786,21 +787,21 @@ static int set_put_in_addr(Set *s, const struct in_addr *address) { if (r < 0) return r; - r = set_consume(s, p); + r = ordered_set_consume(s, p); if (r == -EEXIST) return 0; return r; } -static int set_put_in_addrv(Set *s, const struct in_addr *addresses, int n) { +static int ordered_set_put_in_addrv(OrderedSet *s, const struct in_addr *addresses, int n) { int r, i, c = 0; assert(s); assert(n <= 0 || addresses); for (i = 0; i < n; i++) { - r = set_put_in_addr(s, addresses+i); + r = ordered_set_put_in_addr(s, addresses+i); if (r < 0) return r; @@ -810,17 +811,17 @@ static int set_put_in_addrv(Set *s, const struct in_addr *addresses, int n) { return c; } -static void print_string_set(FILE *f, const char *field, Set *s) { +static void print_string_set(FILE *f, const char *field, OrderedSet *s) { bool space = false; Iterator i; char *p; - if (set_isempty(s)) + if (ordered_set_isempty(s)) return; fputs(field, f); - SET_FOREACH(p, s, i) { + ORDERED_SET_FOREACH(p, s, i) { if (space) fputc(' ', f); fputs(p, f); @@ -830,7 +831,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, *search_domains = NULL, *route_domains = NULL; + _cleanup_ordered_set_free_free_ OrderedSet *dns = NULL, *ntp = NULL, *search_domains = NULL, *route_domains = NULL; Link *link; Iterator i; _cleanup_free_ char *temp_path = NULL; @@ -843,19 +844,19 @@ static int manager_save(Manager *m) { assert(m->state_file); /* We add all NTP and DNS server to a set, to filter out duplicates */ - dns = set_new(&string_hash_ops); + dns = ordered_set_new(&string_hash_ops); if (!dns) return -ENOMEM; - ntp = set_new(&string_hash_ops); + ntp = ordered_set_new(&string_hash_ops); if (!ntp) return -ENOMEM; - search_domains = set_new(&string_hash_ops); + search_domains = ordered_set_new(&string_hash_ops); if (!search_domains) return -ENOMEM; - route_domains = set_new(&string_hash_ops); + route_domains = ordered_set_new(&string_hash_ops); if (!route_domains) return -ENOMEM; @@ -870,19 +871,19 @@ static int manager_save(Manager *m) { continue; /* First add the static configured entries */ - r = set_put_strdupv(dns, link->network->dns); + r = ordered_set_put_strdupv(dns, link->network->dns); if (r < 0) return r; - r = set_put_strdupv(ntp, link->network->ntp); + r = ordered_set_put_strdupv(ntp, link->network->ntp); if (r < 0) return r; - r = set_put_strdupv(search_domains, link->network->search_domains); + r = ordered_set_put_strdupv(search_domains, link->network->search_domains); if (r < 0) return r; - r = set_put_strdupv(route_domains, link->network->route_domains); + r = ordered_set_put_strdupv(route_domains, link->network->route_domains); if (r < 0) return r; @@ -895,7 +896,7 @@ static int manager_save(Manager *m) { r = sd_dhcp_lease_get_dns(link->dhcp_lease, &addresses); if (r > 0) { - r = set_put_in_addrv(dns, addresses, r); + r = ordered_set_put_in_addrv(dns, addresses, r); if (r < 0) return r; } else if (r < 0 && r != -ENODATA) @@ -907,7 +908,7 @@ static int manager_save(Manager *m) { r = sd_dhcp_lease_get_ntp(link->dhcp_lease, &addresses); if (r > 0) { - r = set_put_in_addrv(ntp, addresses, r); + r = ordered_set_put_in_addrv(ntp, addresses, r); if (r < 0) return r; } else if (r < 0 && r != -ENODATA) @@ -919,7 +920,7 @@ static int manager_save(Manager *m) { r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname); if (r >= 0) { - r = set_put_strdup(search_domains, domainname); + r = ordered_set_put_strdup(search_domains, domainname); if (r < 0) return r; } else if (r != -ENODATA) -- cgit v1.2.3-54-g00ecf From 482d1aeb671e813535f0ff9fadf4e1827ee32e20 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 25 Jan 2016 20:33:47 +0100 Subject: networkd: when filtering out duplicate domain names use DNS comparison When we collect the domain names of the various links and other sources in one ordered set, make sure to use proper DNS name comparison to filter out duplicates. --- src/network/networkd-manager.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/network') diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index 7b801ae6c9..e8d4b042d4 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -29,6 +29,7 @@ #include "bus-util.h" #include "conf-parser.h" #include "def.h" +#include "dns-domain.h" #include "fd-util.h" #include "fileio.h" #include "libudev-private.h" @@ -852,11 +853,11 @@ static int manager_save(Manager *m) { if (!ntp) return -ENOMEM; - search_domains = ordered_set_new(&string_hash_ops); + search_domains = ordered_set_new(&dns_name_hash_ops); if (!search_domains) return -ENOMEM; - route_domains = ordered_set_new(&string_hash_ops); + route_domains = ordered_set_new(&dns_name_hash_ops); if (!route_domains) return -ENOMEM; -- cgit v1.2.3-54-g00ecf From 27cb34f57458758ee8615d72c6a60a39d4b92226 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 25 Jan 2016 21:47:02 +0100 Subject: networkd: rename a few Network object properties to be more like the configuration settings All booleans called dhcp_xyz are now called ".dhcp_use_xyz", to match their respective configuration file settings. This should clarify things a bit, in particular as there is a DHCP hostname that was previously called just ".hostname" because ".dhcp_hostname" was already existing as a bool. Since this confusion is removed now because the bool is called ".dhcp_use_hostname", the string field is now renamed to ".dhcp_hostname". --- src/network/networkd-dhcp4.c | 32 ++++++++++++++++---------------- src/network/networkd-link.c | 16 ++++++++-------- src/network/networkd-manager.c | 6 +++--- src/network/networkd-network-gperf.gperf | 28 ++++++++++++++-------------- src/network/networkd-network.c | 12 ++++++------ src/network/networkd-network.h | 18 +++++++++--------- 6 files changed, 56 insertions(+), 56 deletions(-) (limited to 'src/network') diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index c7d22876bc..59eccb392f 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -158,7 +158,7 @@ static int dhcp_lease_lost(Link *link) { log_link_warning(link, "DHCP lease lost"); - if (link->network->dhcp_routes) { + if (link->network->dhcp_use_routes) { _cleanup_free_ sd_dhcp_route **routes = NULL; int n, i; @@ -223,7 +223,7 @@ static int dhcp_lease_lost(Link *link) { } } - if (link->network->dhcp_mtu) { + if (link->network->dhcp_use_mtu) { uint16_t mtu; r = sd_dhcp_lease_get_mtu(link->dhcp_lease, &mtu); @@ -238,11 +238,11 @@ static int dhcp_lease_lost(Link *link) { } } - if (link->network->dhcp_hostname) { + if (link->network->dhcp_use_hostname) { const char *hostname = NULL; - if (link->network->hostname) - hostname = link->network->hostname; + if (link->network->dhcp_hostname) + hostname = link->network->dhcp_hostname; else (void) sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname); @@ -412,7 +412,7 @@ static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) { link->dhcp_lease = sd_dhcp_lease_ref(lease); link_dirty(link); - if (link->network->dhcp_mtu) { + if (link->network->dhcp_use_mtu) { uint16_t mtu; r = sd_dhcp_lease_get_mtu(lease, &mtu); @@ -423,11 +423,11 @@ static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) { } } - if (link->network->dhcp_hostname) { + if (link->network->dhcp_use_hostname) { const char *hostname = NULL; - if (link->network->hostname) - hostname = link->network->hostname; + if (link->network->dhcp_hostname) + hostname = link->network->dhcp_hostname; else (void) sd_dhcp_lease_get_hostname(lease, &hostname); @@ -438,7 +438,7 @@ static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) { } } - if (link->network->dhcp_timezone) { + if (link->network->dhcp_use_timezone) { const char *tz = NULL; (void) sd_dhcp_lease_get_timezone(link->dhcp_lease, &tz); @@ -571,14 +571,14 @@ int dhcp4_configure(Link *link) { return r; } - if (link->network->dhcp_mtu) { + if (link->network->dhcp_use_mtu) { r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_INTERFACE_MTU); if (r < 0) return r; } - if (link->network->dhcp_routes) { + if (link->network->dhcp_use_routes) { r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_STATIC_ROUTE); if (r < 0) @@ -589,7 +589,7 @@ int dhcp4_configure(Link *link) { return r; } - /* Always acquire the timezone and NTP*/ + /* Always acquire the timezone and NTP */ r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_NTP_SERVER); if (r < 0) return r; @@ -598,18 +598,18 @@ int dhcp4_configure(Link *link) { if (r < 0) return r; - if (link->network->dhcp_sendhost) { + if (link->network->dhcp_send_hostname) { _cleanup_free_ char *hostname = NULL; const char *hn = NULL; - if (!link->network->hostname) { + if (!link->network->dhcp_hostname) { hostname = gethostname_malloc(); if (!hostname) return -ENOMEM; hn = hostname; } else - hn = link->network->hostname; + hn = link->network->dhcp_hostname; if (!is_localhost(hn)) { r = sd_dhcp_client_set_hostname(link->dhcp_client, hn); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index c152ec3cf6..b0e0c4f9e7 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -767,7 +767,7 @@ static int link_push_dns_to_dhcp_server(Link *link, sd_dhcp_server *s) { addresses[n_addresses++] = ia; } - if (link->network->dhcp_dns && + if (link->network->dhcp_use_dns && link->dhcp_lease) { const struct in_addr *da = NULL; int n; @@ -812,7 +812,7 @@ static int link_push_ntp_to_dhcp_server(Link *link, sd_dhcp_server *s) { addresses[n_addresses++] = ia; } - if (link->network->dhcp_ntp && + if (link->network->dhcp_use_ntp && link->dhcp_lease) { const struct in_addr *da = NULL; int n; @@ -2744,7 +2744,7 @@ int link_save(Link *link) { space = false; fputstrv(f, link->network->dns, NULL, &space); - if (link->network->dhcp_dns && + if (link->network->dhcp_use_dns && link->dhcp_lease) { const struct in_addr *addresses; @@ -2757,7 +2757,7 @@ int link_save(Link *link) { } } - if (link->network->dhcp_dns && dhcp6_lease) { + if (link->network->dhcp_use_dns && dhcp6_lease) { struct in6_addr *in6_addrs; r = sd_dhcp6_lease_get_dns(dhcp6_lease, &in6_addrs); @@ -2774,7 +2774,7 @@ int link_save(Link *link) { space = false; fputstrv(f, link->network->ntp, NULL, &space); - if (link->network->dhcp_ntp && + if (link->network->dhcp_use_ntp && link->dhcp_lease) { const struct in_addr *addresses; @@ -2787,7 +2787,7 @@ int link_save(Link *link) { } } - if (link->network->dhcp_ntp && dhcp6_lease) { + if (link->network->dhcp_use_ntp && dhcp6_lease) { struct in6_addr *in6_addrs; char **hosts; @@ -2810,7 +2810,7 @@ int link_save(Link *link) { fputs("DOMAINS=", f); fputstrv(f, link->network->search_domains, NULL, &space); - if (link->network->dhcp_domains && + if (link->network->dhcp_use_domains && link->dhcp_lease) { const char *domainname; @@ -2823,7 +2823,7 @@ int link_save(Link *link) { } } - if (link->network->dhcp_domains && dhcp6_lease) { + if (link->network->dhcp_use_domains && dhcp6_lease) { char **domains; r = sd_dhcp6_lease_get_domains(dhcp6_lease, &domains); diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index e8d4b042d4..0701dd02dd 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -892,7 +892,7 @@ static int manager_save(Manager *m) { continue; /* Secondly, add the entries acquired via DHCP */ - if (link->network->dhcp_dns) { + if (link->network->dhcp_use_dns) { const struct in_addr *addresses; r = sd_dhcp_lease_get_dns(link->dhcp_lease, &addresses); @@ -904,7 +904,7 @@ static int manager_save(Manager *m) { return r; } - if (link->network->dhcp_ntp) { + if (link->network->dhcp_use_ntp) { const struct in_addr *addresses; r = sd_dhcp_lease_get_ntp(link->dhcp_lease, &addresses); @@ -916,7 +916,7 @@ static int manager_save(Manager *m) { return r; } - if (link->network->dhcp_domains) { + if (link->network->dhcp_use_domains) { const char *domainname; r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname); diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 325aac7a61..89b28196dc 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -68,19 +68,19 @@ Route.Metric, config_parse_route_priority, Route.Scope, config_parse_route_scope, 0, 0 Route.PreferredSource, config_parse_preferred_src, 0, 0 DHCP.ClientIdentifier, config_parse_dhcp_client_identifier, 0, offsetof(Network, dhcp_client_identifier) -DHCP.UseDNS, config_parse_bool, 0, offsetof(Network, dhcp_dns) -DHCP.UseNTP, config_parse_bool, 0, offsetof(Network, dhcp_ntp) -DHCP.UseMTU, config_parse_bool, 0, offsetof(Network, dhcp_mtu) -DHCP.UseHostname, config_parse_bool, 0, offsetof(Network, dhcp_hostname) -DHCP.UseDomains, config_parse_bool, 0, offsetof(Network, dhcp_domains) -DHCP.UseRoutes, config_parse_bool, 0, offsetof(Network, dhcp_routes) -DHCP.SendHostname, config_parse_bool, 0, offsetof(Network, dhcp_sendhost) -DHCP.Hostname, config_parse_hostname, 0, offsetof(Network, hostname) +DHCP.UseDNS, config_parse_bool, 0, offsetof(Network, dhcp_use_dns) +DHCP.UseNTP, config_parse_bool, 0, offsetof(Network, dhcp_use_ntp) +DHCP.UseMTU, config_parse_bool, 0, offsetof(Network, dhcp_use_mtu) +DHCP.UseHostname, config_parse_bool, 0, offsetof(Network, dhcp_use_hostname) +DHCP.UseDomains, config_parse_bool, 0, offsetof(Network, dhcp_use_domains) +DHCP.UseRoutes, config_parse_bool, 0, offsetof(Network, dhcp_use_routes) +DHCP.SendHostname, config_parse_bool, 0, offsetof(Network, dhcp_send_hostname) +DHCP.Hostname, config_parse_hostname, 0, offsetof(Network, dhcp_hostname) DHCP.RequestBroadcast, config_parse_bool, 0, offsetof(Network, dhcp_broadcast) DHCP.CriticalConnection, config_parse_bool, 0, offsetof(Network, dhcp_critical) DHCP.VendorClassIdentifier, config_parse_string, 0, offsetof(Network, dhcp_vendor_class_identifier) DHCP.RouteMetric, config_parse_unsigned, 0, offsetof(Network, dhcp_route_metric) -DHCP.UseTimezone, config_parse_bool, 0, offsetof(Network, dhcp_timezone) +DHCP.UseTimezone, config_parse_bool, 0, offsetof(Network, dhcp_use_timezone) DHCPServer.MaxLeaseTimeSec, config_parse_sec, 0, offsetof(Network, dhcp_server_max_lease_time_usec) DHCPServer.DefaultLeaseTimeSec, config_parse_sec, 0, offsetof(Network, dhcp_server_default_lease_time_usec) DHCPServer.EmitDNS, config_parse_bool, 0, offsetof(Network, dhcp_server_emit_dns) @@ -101,9 +101,9 @@ BridgeFDB.MACAddress, config_parse_fdb_hwaddr, BridgeFDB.VLANId, config_parse_fdb_vlan_id, 0, 0 /* backwards compatibility: do not add new entries to this section */ Network.IPv4LL, config_parse_ipv4ll, 0, offsetof(Network, link_local) -DHCPv4.UseDNS, config_parse_bool, 0, offsetof(Network, dhcp_dns) -DHCPv4.UseMTU, config_parse_bool, 0, offsetof(Network, dhcp_mtu) -DHCPv4.UseHostname, config_parse_bool, 0, offsetof(Network, dhcp_hostname) -DHCP.UseDomainName, config_parse_bool, 0, offsetof(Network, dhcp_domains) -DHCPv4.UseDomainName, config_parse_bool, 0, offsetof(Network, dhcp_domains) +DHCPv4.UseDNS, config_parse_bool, 0, offsetof(Network, dhcp_use_dns) +DHCPv4.UseMTU, config_parse_bool, 0, offsetof(Network, dhcp_use_mtu) +DHCPv4.UseHostname, config_parse_bool, 0, offsetof(Network, dhcp_use_hostname) +DHCP.UseDomainName, config_parse_bool, 0, offsetof(Network, dhcp_use_domains) +DHCPv4.UseDomainName, config_parse_bool, 0, offsetof(Network, dhcp_use_domains) DHCPv4.CriticalConnection, config_parse_bool, 0, offsetof(Network, dhcp_critical) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 1e520062f4..2a28ff2f47 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -105,11 +105,11 @@ static int network_load_one(Manager *manager, const char *filename) { *d = '\0'; network->dhcp = ADDRESS_FAMILY_NO; - network->dhcp_ntp = true; - network->dhcp_dns = true; - network->dhcp_hostname = true; - network->dhcp_routes = true; - network->dhcp_sendhost = true; + network->dhcp_use_ntp = true; + network->dhcp_use_dns = true; + network->dhcp_use_hostname = true; + network->dhcp_use_routes = true; + network->dhcp_send_hostname = true; network->dhcp_route_metric = DHCP_ROUTE_METRIC; network->dhcp_client_identifier = DHCP_CLIENT_ID_DUID; @@ -227,7 +227,7 @@ void network_free(Network *network) { free(network->description); free(network->dhcp_vendor_class_identifier); - free(network->hostname); + free(network->dhcp_hostname); free(network->mac); diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index d17093d384..c8e705f237 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -79,17 +79,17 @@ struct Network { AddressFamilyBoolean dhcp; DCHPClientIdentifier dhcp_client_identifier; char *dhcp_vendor_class_identifier; - char *hostname; - bool dhcp_dns; - bool dhcp_ntp; - bool dhcp_mtu; - bool dhcp_hostname; - bool dhcp_domains; - bool dhcp_sendhost; + char *dhcp_hostname; + bool dhcp_use_dns; + bool dhcp_use_ntp; + bool dhcp_use_mtu; + bool dhcp_use_hostname; + bool dhcp_use_domains; + bool dhcp_send_hostname; bool dhcp_broadcast; bool dhcp_critical; - bool dhcp_routes; - bool dhcp_timezone; + bool dhcp_use_routes; + bool dhcp_use_timezone; unsigned dhcp_route_metric; /* DHCP Server Support */ -- cgit v1.2.3-54-g00ecf From b2a81c0b524fee0a1713720462b6db5c302c3933 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 25 Jan 2016 22:27:01 +0100 Subject: networkd: optinally use DHCP lease domain info for routing only This changes the UseDomains= setting of .network files to take an optional third value "route", in addition to the boolean values. If set, the passed domain information is used for routing rules only, but not for the search path logic. --- man/systemd.network.xml | 23 +++++++++------- src/network/networkd-link.c | 46 +++++++++++++++++++------------- src/network/networkd-manager.c | 9 +++++-- src/network/networkd-network-gperf.gperf | 6 ++--- src/network/networkd-network.c | 10 +++++++ src/network/networkd-network.h | 14 +++++++++- 6 files changed, 75 insertions(+), 33 deletions(-) (limited to 'src/network') diff --git a/man/systemd.network.xml b/man/systemd.network.xml index be88d66072..f88751b672 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -717,15 +717,20 @@ UseDomains= - When true (not the default), the domain name - received from the DHCP server will be used for DNS - resolution over this link. When a name cannot be resolved - as specified, the domain name will be used a suffix and - name resolution of that will be attempted. - - This corresponds to the - option in resolv.conf5 - and should not be enabled on untrusted networks. + Takes a boolean argument, or a the special value route. When true, the domain name + received from the DHCP server will be used as DNS search domain over this link, similar to the effect of + the setting. If set to route, the domain name received from + the DHCP server will be used for routing DNS queries only, but not for searching, similar to the effect of + the setting when the argument is prefixed with ~. Defaults to + false. + + It is recommended to enable this option only on trusted networks, as setting this affects resolution + of all host names, in particular to single-label names. It is generally safer to use the supplied domain + only as routing domain, rather than as search domain, in order to not have it affect local resolution of + single-label names. + + When set to true, this setting corresponds to the option in resolv.conf5. diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index b0e0c4f9e7..bf13544dbc 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -2731,6 +2731,8 @@ int link_save(Link *link) { if (link->network) { bool space; sd_dhcp6_lease *dhcp6_lease = NULL; + const char *dhcp_domainname = NULL; + char **dhcp6_domains = NULL; if (link->dhcp6_client) { r = sd_dhcp6_client_get_lease(link->dhcp6_client, &dhcp6_lease); @@ -2807,34 +2809,42 @@ int link_save(Link *link) { fputc('\n', f); - fputs("DOMAINS=", f); - fputstrv(f, link->network->search_domains, NULL, &space); - - if (link->network->dhcp_use_domains && - link->dhcp_lease) { - const char *domainname; + if (link->network->dhcp_use_domains != DHCP_USE_DOMAINS_NO) { + if (link->dhcp_lease) + (void) sd_dhcp_lease_get_domainname(link->dhcp_lease, &dhcp_domainname); - r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname); - if (r >= 0) { - if (space) - fputc(' ', f); - fputs(domainname, f); - space = true; - } + if (dhcp6_lease) + (void) sd_dhcp6_lease_get_domains(dhcp6_lease, &dhcp6_domains); } - if (link->network->dhcp_use_domains && dhcp6_lease) { - char **domains; + fputs("DOMAINS=", f); + fputstrv(f, link->network->search_domains, NULL, &space); - r = sd_dhcp6_lease_get_domains(dhcp6_lease, &domains); - if (r >= 0) - fputstrv(f, domains, NULL, &space); + if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_YES && dhcp_domainname) { + if (space) + fputc(' ', f); + fputs(dhcp_domainname, f); + space = true; } + if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_YES && dhcp6_domains) + fputstrv(f, dhcp6_domains, NULL, &space); + fputc('\n', f); fputs("ROUTE_DOMAINS=", f); fputstrv(f, link->network->route_domains, NULL, NULL); + + if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_ROUTE && dhcp_domainname) { + if (space) + fputc(' ', f); + fputs(dhcp_domainname, f); + space = true; + } + + if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_ROUTE && dhcp6_domains) + fputstrv(f, dhcp6_domains, NULL, &space); + fputc('\n', f); fprintf(f, "LLMNR=%s\n", diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index 0701dd02dd..723a92b5b8 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -916,12 +916,17 @@ static int manager_save(Manager *m) { return r; } - if (link->network->dhcp_use_domains) { + if (link->network->dhcp_use_domains != DHCP_USE_DOMAINS_NO) { const char *domainname; r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname); if (r >= 0) { - r = ordered_set_put_strdup(search_domains, domainname); + + if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_YES) + r = ordered_set_put_strdup(search_domains, domainname); + else + r = ordered_set_put_strdup(route_domains, domainname); + if (r < 0) return r; } else if (r != -ENODATA) diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 89b28196dc..409df1709f 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -72,7 +72,7 @@ DHCP.UseDNS, config_parse_bool, DHCP.UseNTP, config_parse_bool, 0, offsetof(Network, dhcp_use_ntp) DHCP.UseMTU, config_parse_bool, 0, offsetof(Network, dhcp_use_mtu) DHCP.UseHostname, config_parse_bool, 0, offsetof(Network, dhcp_use_hostname) -DHCP.UseDomains, config_parse_bool, 0, offsetof(Network, dhcp_use_domains) +DHCP.UseDomains, config_parse_dhcp_use_domains, 0, offsetof(Network, dhcp_use_domains) DHCP.UseRoutes, config_parse_bool, 0, offsetof(Network, dhcp_use_routes) DHCP.SendHostname, config_parse_bool, 0, offsetof(Network, dhcp_send_hostname) DHCP.Hostname, config_parse_hostname, 0, offsetof(Network, dhcp_hostname) @@ -104,6 +104,6 @@ Network.IPv4LL, config_parse_ipv4ll, DHCPv4.UseDNS, config_parse_bool, 0, offsetof(Network, dhcp_use_dns) DHCPv4.UseMTU, config_parse_bool, 0, offsetof(Network, dhcp_use_mtu) DHCPv4.UseHostname, config_parse_bool, 0, offsetof(Network, dhcp_use_hostname) -DHCP.UseDomainName, config_parse_bool, 0, offsetof(Network, dhcp_use_domains) -DHCPv4.UseDomainName, config_parse_bool, 0, offsetof(Network, dhcp_use_domains) +DHCP.UseDomainName, config_parse_dhcp_use_domains, 0, offsetof(Network, dhcp_use_domains) +DHCPv4.UseDomainName, config_parse_dhcp_use_domains, 0, offsetof(Network, dhcp_use_domains) DHCPv4.CriticalConnection, config_parse_bool, 0, offsetof(Network, dhcp_critical) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 2a28ff2f47..e1a811129d 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -1005,3 +1005,13 @@ int config_parse_dnssec_negative_trust_anchors( return 0; } + +DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains, dhcp_use_domains, DHCPUseDomains, "Failed to parse DHCP use domains setting"); + +static const char* const dhcp_use_domains_table[_DHCP_USE_DOMAINS_MAX] = { + [DHCP_USE_DOMAINS_NO] = "no", + [DHCP_USE_DOMAINS_ROUTE] = "route", + [DHCP_USE_DOMAINS_YES] = "yes", +}; + +DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dhcp_use_domains, DHCPUseDomains, DHCP_USE_DOMAINS_YES); diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index c8e705f237..626dfbd40a 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -52,6 +52,14 @@ typedef enum IPv6PrivacyExtensions { _IPV6_PRIVACY_EXTENSIONS_INVALID = -1, } IPv6PrivacyExtensions; +typedef enum DHCPUseDomains { + DHCP_USE_DOMAINS_NO, + DHCP_USE_DOMAINS_YES, + DHCP_USE_DOMAINS_ROUTE, + _DHCP_USE_DOMAINS_MAX, + _DHCP_USE_DOMAINS_INVALID = -1, +} DHCPUseDomains; + struct Network { Manager *manager; @@ -84,7 +92,7 @@ struct Network { bool dhcp_use_ntp; bool dhcp_use_mtu; bool dhcp_use_hostname; - bool dhcp_use_domains; + DHCPUseDomains dhcp_use_domains; bool dhcp_send_hostname; bool dhcp_broadcast; bool dhcp_critical; @@ -174,6 +182,7 @@ int config_parse_timezone(const char *unit, const char *filename, unsigned line, int config_parse_dhcp_server_dns(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); int config_parse_dhcp_server_ntp(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); int config_parse_dnssec_negative_trust_anchors(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); +int config_parse_dhcp_use_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); /* Legacy IPv4LL support */ int config_parse_ipv4ll(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); @@ -187,3 +196,6 @@ int network_object_find(sd_bus *bus, const char *path, const char *interface, vo const char* ipv6_privacy_extensions_to_string(IPv6PrivacyExtensions i) _const_; IPv6PrivacyExtensions ipv6_privacy_extensions_from_string(const char *s) _pure_; + +const char* dhcp_use_domains_to_string(DHCPUseDomains p) _const_; +DHCPUseDomains dhcp_use_domains_from_string(const char *s) _pure_; -- cgit v1.2.3-54-g00ecf From d390f8ef2dc0cd041914d3c2fd3e1081605cbfc8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 25 Jan 2016 22:42:36 +0100 Subject: util: introduce fputs_with_space() and make use of it at various places The call combines outputing a string with prefixing it with a space, optionally. This is useful to shorten the logic for outputing lists of strings, that are space separated. --- src/basic/fileio.c | 29 +++++++++++++++++++++++++++++ src/basic/fileio.h | 2 ++ src/basic/strv.c | 15 ++------------- src/network/networkd-link.c | 40 ++++++++++------------------------------ src/network/networkd-manager.c | 9 +++------ 5 files changed, 46 insertions(+), 49 deletions(-) (limited to 'src/network') diff --git a/src/basic/fileio.c b/src/basic/fileio.c index 5ed5460904..3ff70310e1 100644 --- a/src/basic/fileio.c +++ b/src/basic/fileio.c @@ -1251,3 +1251,32 @@ int read_timestamp_file(const char *fn, usec_t *ret) { *ret = (usec_t) t; return 0; } + +int fputs_with_space(FILE *f, const char *s, const char *separator, bool *space) { + int r; + + assert(s); + + /* Outputs the specified string with fputs(), but optionally prefixes it with a separator. The *space parameter + * when specified shall initially point to a boolean variable initialized to false. It is set to true after the + * first invocation. This call is supposed to be use in loops, where a separator shall be inserted between each + * element, but not before the first one. */ + + if (!f) + f = stdout; + + if (space) { + if (!separator) + separator = " "; + + if (*space) { + r = fputs(separator, f); + if (r < 0) + return r; + } + + *space = true; + } + + return fputs(s, f); +} diff --git a/src/basic/fileio.h b/src/basic/fileio.h index 95e8698941..9e09574133 100644 --- a/src/basic/fileio.h +++ b/src/basic/fileio.h @@ -82,3 +82,5 @@ int tempfn_random_child(const char *p, const char *extra, char **ret); int write_timestamp_file_atomic(const char *fn, usec_t n); int read_timestamp_file(const char *fn, usec_t *ret); + +int fputs_with_space(FILE *f, const char *s, const char *separator, bool *space); diff --git a/src/basic/strv.c b/src/basic/strv.c index dc5bafcf24..5532c53ad1 100644 --- a/src/basic/strv.c +++ b/src/basic/strv.c @@ -29,6 +29,7 @@ #include "alloc-util.h" #include "escape.h" #include "extract-word.h" +#include "fileio.h" #include "string-util.h" #include "strv.h" #include "util.h" @@ -879,25 +880,13 @@ int fputstrv(FILE *f, char **l, const char *separator, bool *space) { /* 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); + r = fputs_with_space(f, *s, separator, space); if (r < 0) return r; - - *space = true; } return 0; diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index bf13544dbc..a2f0eceb6d 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -2820,12 +2820,8 @@ int link_save(Link *link) { fputs("DOMAINS=", f); fputstrv(f, link->network->search_domains, NULL, &space); - if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_YES && dhcp_domainname) { - if (space) - fputc(' ', f); - fputs(dhcp_domainname, f); - space = true; - } + if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_YES && dhcp_domainname) + fputs_with_space(f, dhcp_domainname, NULL, &space); if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_YES && dhcp6_domains) fputstrv(f, dhcp6_domains, NULL, &space); @@ -2835,12 +2831,8 @@ int link_save(Link *link) { fputs("ROUTE_DOMAINS=", f); fputstrv(f, link->network->route_domains, NULL, NULL); - if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_ROUTE && dhcp_domainname) { - if (space) - fputc(' ', f); - fputs(dhcp_domainname, f); - space = true; - } + if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_ROUTE && dhcp_domainname) + fputs_with_space(f, dhcp_domainname, NULL, &space); if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_ROUTE && dhcp6_domains) fputstrv(f, dhcp6_domains, NULL, &space); @@ -2861,12 +2853,8 @@ int link_save(Link *link) { fputs("DNSSEC_NTA=", f); space = false; - SET_FOREACH(n, link->network->dnssec_negative_trust_anchors, i) { - if (space) - fputc(' ', f); - fputs(n, f); - space = true; - } + SET_FOREACH(n, link->network->dnssec_negative_trust_anchors, i) + fputs_with_space(f, n, NULL, &space); fputc('\n', f); } @@ -2906,12 +2894,8 @@ int link_save(Link *link) { bool space = false; fputs("CARRIER_BOUND_TO=", f); - HASHMAP_FOREACH(carrier, link->bound_to_links, i) { - if (space) - fputc(' ', f); - fputs(carrier->ifname, f); - space = true; - } + HASHMAP_FOREACH(carrier, link->bound_to_links, i) + fputs_with_space(f, carrier->ifname, NULL, &space); fputc('\n', f); } @@ -2921,12 +2905,8 @@ int link_save(Link *link) { bool space = false; fputs("CARRIER_BOUND_BY=", f); - HASHMAP_FOREACH(carrier, link->bound_by_links, i) { - if (space) - fputc(' ', f); - fputs(carrier->ifname, f); - space = true; - } + HASHMAP_FOREACH(carrier, link->bound_by_links, i) + fputs_with_space(f, carrier->ifname, NULL, &space); fputc('\n', f); } diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index 723a92b5b8..c10635d202 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -822,12 +822,9 @@ static void print_string_set(FILE *f, const char *field, OrderedSet *s) { fputs(field, f); - ORDERED_SET_FOREACH(p, s, i) { - if (space) - fputc(' ', f); - fputs(p, f); - space = true; - } + ORDERED_SET_FOREACH(p, s, i) + fputs_with_space(f, p, NULL, &space); + fputc('\n', f); } -- cgit v1.2.3-54-g00ecf