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.
This commit is contained in:
Lennart Poettering 2016-11-18 17:04:26 +01:00
parent fa105ce6b7
commit 5512a96316
4 changed files with 90 additions and 30 deletions

View File

@ -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) {

View File

@ -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"

View File

@ -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;

View File

@ -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;