From 5512a96316ef54b398a746428d4ded28bda2cccc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 18 Nov 2016 17:04:26 +0100 Subject: networkd: store DNS servers configured per-network as parsed addresses DNS servers must be specified as IP addresses, hence let's store them as that internally, so that they are guaranteed to be fully normalized always, and invalid data cannot be stored. --- src/network/networkd-link.c | 35 +++++++++++++++++--------- src/network/networkd-manager.c | 56 +++++++++++++++++++++++++++++++++++------- src/network/networkd-network.c | 24 +++++++++++------- src/network/networkd-network.h | 5 +++- 4 files changed, 90 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 0b634572a9..b7743557ec 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -854,28 +854,26 @@ static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userda static int link_push_dns_to_dhcp_server(Link *link, sd_dhcp_server *s) { _cleanup_free_ struct in_addr *addresses = NULL; size_t n_addresses = 0, n_allocated = 0; - char **a; + unsigned i; log_debug("Copying DNS server information from %s", link->ifname); if (!link->network) return 0; - STRV_FOREACH(a, link->network->dns) { - struct in_addr ia; + for (i = 0; i < link->network->n_dns; i++) { /* Only look for IPv4 addresses */ - if (inet_pton(AF_INET, *a, &ia) <= 0) + if (link->network->dns[i].family != AF_INET) continue; if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1)) return log_oom(); - addresses[n_addresses++] = ia; + addresses[n_addresses++] = link->network->dns[i].address.in; } - if (link->network->dhcp_use_dns && - link->dhcp_lease) { + if (link->network->dhcp_use_dns && link->dhcp_lease) { const struct in_addr *da = NULL; int n; @@ -919,8 +917,7 @@ static int link_push_ntp_to_dhcp_server(Link *link, sd_dhcp_server *s) { addresses[n_addresses++] = ia; } - if (link->network->dhcp_use_ntp && - link->dhcp_lease) { + if (link->network->dhcp_use_ntp && link->dhcp_lease) { const struct in_addr *da = NULL; int n; @@ -3235,7 +3232,7 @@ int link_save(Link *link) { if (r < 0) goto fail; - fchmod(fileno(f), 0644); + (void) fchmod(fileno(f), 0644); fprintf(f, "# This is private data. Do not parse.\n" @@ -3248,6 +3245,7 @@ int link_save(Link *link) { sd_dhcp6_lease *dhcp6_lease = NULL; const char *dhcp_domainname = NULL; char **dhcp6_domains = NULL; + unsigned j; if (link->dhcp6_client) { r = sd_dhcp6_client_get_lease(link->dhcp6_client, &dhcp6_lease); @@ -3259,7 +3257,22 @@ int link_save(Link *link) { fputs("DNS=", f); space = false; - fputstrv(f, link->network->dns, NULL, &space); + + for (j = 0; j < link->network->n_dns; j++) { + _cleanup_free_ char *b = NULL; + + r = in_addr_to_string(link->network->dns[j].family, + &link->network->dns[j].address, &b); + if (r < 0) { + log_debug_errno(r, "Failed to format address, ignoring: %m"); + continue; + } + + if (space) + fputc(' ', f); + fputs(b, f); + space = true; + } if (link->network->dhcp_use_dns && link->dhcp_lease) { diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index a1252c9b51..c3d3f48a3f 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -774,11 +774,48 @@ static int manager_connect_rtnl(Manager *m) { return 0; } -static int ordered_set_put_in_addr(OrderedSet *s, const struct in_addr *address) { +static int ordered_set_put_in_addr_data(OrderedSet *s, const struct in_addr_data *address) { char *p; int r; assert(s); + assert(address); + + r = in_addr_to_string(address->family, &address->address, &p); + if (r < 0) + return r; + + r = ordered_set_consume(s, p); + if (r == -EEXIST) + return 0; + + return r; +} + +static int ordered_set_put_in_addr_datav(OrderedSet *s, const struct in_addr_data *addresses, unsigned n) { + int r, c = 0; + unsigned i; + + assert(s); + assert(addresses || n == 0); + + for (i = 0; i < n; i++) { + r = ordered_set_put_in_addr_data(s, addresses+i); + if (r < 0) + return r; + + c += r; + } + + return c; +} + +static int ordered_set_put_in4_addr(OrderedSet *s, const struct in_addr *address) { + char *p; + int r; + + assert(s); + assert(address); r = in_addr_to_string(AF_INET, (const union in_addr_union*) address, &p); if (r < 0) @@ -791,14 +828,15 @@ static int ordered_set_put_in_addr(OrderedSet *s, const struct in_addr *address) return r; } -static int ordered_set_put_in_addrv(OrderedSet *s, const struct in_addr *addresses, int n) { - int r, i, c = 0; +static int ordered_set_put_in4_addrv(OrderedSet *s, const struct in_addr *addresses, unsigned n) { + int r, c = 0; + unsigned i; assert(s); - assert(n <= 0 || addresses); + assert(n == 0 || addresses); for (i = 0; i < n; i++) { - r = ordered_set_put_in_addr(s, addresses+i); + r = ordered_set_put_in4_addr(s, addresses+i); if (r < 0) return r; @@ -865,7 +903,7 @@ static int manager_save(Manager *m) { continue; /* First add the static configured entries */ - r = ordered_set_put_strdupv(dns, link->network->dns); + r = ordered_set_put_in_addr_datav(dns, link->network->dns, link->network->n_dns); if (r < 0) return r; @@ -890,7 +928,7 @@ static int manager_save(Manager *m) { r = sd_dhcp_lease_get_dns(link->dhcp_lease, &addresses); if (r > 0) { - r = ordered_set_put_in_addrv(dns, addresses, r); + r = ordered_set_put_in4_addrv(dns, addresses, r); if (r < 0) return r; } else if (r < 0 && r != -ENODATA) @@ -902,7 +940,7 @@ static int manager_save(Manager *m) { r = sd_dhcp_lease_get_ntp(link->dhcp_lease, &addresses); if (r > 0) { - r = ordered_set_put_in_addrv(ntp, addresses, r); + r = ordered_set_put_in4_addrv(ntp, addresses, r); if (r < 0) return r; } else if (r < 0 && r != -ENODATA) @@ -934,7 +972,7 @@ static int manager_save(Manager *m) { if (r < 0) return r; - fchmod(fileno(f), 0644); + (void) fchmod(fileno(f), 0644); fprintf(f, "# This is private data. Do not parse.\n" diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index e3a77c2152..bc4dc95ff9 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -244,7 +244,7 @@ void network_free(Network *network) { free(network->mac); strv_free(network->ntp); - strv_free(network->dns); + free(network->dns); strv_free(network->search_domains); strv_free(network->route_domains); strv_free(network->bind_carrier); @@ -396,7 +396,7 @@ int network_apply(Network *network, Link *link) { route->protocol = RTPROT_STATIC; } - if (!strv_isempty(network->dns) || + if (network->n_dns > 0 || !strv_isempty(network->ntp) || !strv_isempty(network->search_domains) || !strv_isempty(network->route_domains)) @@ -1004,29 +1004,35 @@ int config_parse_dns( for (;;) { _cleanup_free_ char *w = NULL; union in_addr_union a; + struct in_addr_data *m; int family; - r = extract_first_word(&rvalue, &w, NULL, EXTRACT_QUOTES|EXTRACT_RETAIN_ESCAPE); - if (r == 0) - break; + r = extract_first_word(&rvalue, &w, NULL, 0); if (r == -ENOMEM) return log_oom(); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Invalid syntax, ignoring: %s", rvalue); break; } + if (r == 0) + break; r = in_addr_from_string_auto(w, &family, &a); if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse dns server address, ignoring: %s", w); + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse dns server address, ignoring: %s", w); continue; } - r = strv_consume(&n->dns, w); - if (r < 0) + m = realloc(n->dns, (n->n_dns + 1) * sizeof(struct in_addr_data)); + if (!m) return log_oom(); - w = NULL; + m[n->n_dns++] = (struct in_addr_data) { + .family = family, + .address = a, + }; + + n->dns = m; } return 0; diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 735d7f7a77..17cff956da 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -194,7 +194,10 @@ struct Network { Hashmap *routes_by_section; Hashmap *fdb_entries_by_section; - char **search_domains, **route_domains, **dns, **ntp, **bind_carrier; + struct in_addr_data *dns; + unsigned n_dns; + + char **search_domains, **route_domains, **ntp, **bind_carrier; ResolveSupport llmnr; ResolveSupport mdns; -- cgit v1.2.3-54-g00ecf