From e77bd3fdffe0f5781d48daa5f9f4d12ee81d9cee Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 3 Jul 2020 16:48:29 +0900 Subject: [PATCH] network: support port number and SNI in [Network] DNS= --- src/network/networkd-dhcp-server.c | 4 +- src/network/networkd-link-bus.c | 64 +++++++++++++++++++++--------- src/network/networkd-link.c | 16 ++++---- src/network/networkd-link.h | 2 +- src/network/networkd-manager.c | 22 +++++----- src/network/networkd-network.c | 22 +++++----- src/network/networkd-network.h | 3 +- src/network/networkd-radv.c | 4 +- 8 files changed, 83 insertions(+), 54 deletions(-) diff --git a/src/network/networkd-dhcp-server.c b/src/network/networkd-dhcp-server.c index 265d9dbc79..5129a2e37e 100644 --- a/src/network/networkd-dhcp-server.c +++ b/src/network/networkd-dhcp-server.c @@ -61,10 +61,10 @@ static int link_push_uplink_to_dhcp_server( struct in_addr ia; /* Only look for IPv4 addresses */ - if (link->network->dns[i].family != AF_INET) + if (link->network->dns[i]->family != AF_INET) continue; - ia = link->network->dns[i].address.in; + ia = link->network->dns[i]->address.in; /* Never propagate obviously borked data */ if (in4_addr_is_null(&ia) || in4_addr_is_localhost(&ia)) diff --git a/src/network/networkd-link-bus.c b/src/network/networkd-link-bus.c index 38b005fb63..dec0d9be46 100644 --- a/src/network/networkd-link-bus.c +++ b/src/network/networkd-link-bus.c @@ -14,6 +14,7 @@ #include "networkd-manager.h" #include "parse-util.h" #include "resolve-util.h" +#include "socket-netlink.h" #include "strv.h" #include "user-util.h" @@ -114,7 +115,7 @@ int bus_link_method_set_ntp_servers(sd_bus_message *message, void *userdata, sd_ } int bus_link_method_set_dns_servers(sd_bus_message *message, void *userdata, sd_bus_error *error) { - _cleanup_free_ struct in_addr_data *dns = NULL; + struct in_addr_full **dns = NULL; size_t allocated = 0, n = 0; Link *l = userdata; int r; @@ -131,6 +132,7 @@ int bus_link_method_set_dns_servers(sd_bus_message *message, void *userdata, sd_ return r; for (;;) { + union in_addr_union a; int family; size_t sz; const void *d; @@ -139,50 +141,67 @@ int bus_link_method_set_dns_servers(sd_bus_message *message, void *userdata, sd_ r = sd_bus_message_enter_container(message, 'r', "iay"); if (r < 0) - return r; + goto finalize; if (r == 0) break; r = sd_bus_message_read(message, "i", &family); if (r < 0) - return r; + goto finalize; - if (!IN_SET(family, AF_INET, AF_INET6)) - return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family); + if (!IN_SET(family, AF_INET, AF_INET6)) { + r = sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family); + goto finalize; + } r = sd_bus_message_read_array(message, 'y', &d, &sz); if (r < 0) - return r; - if (sz != FAMILY_ADDRESS_SIZE(family)) - return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid address size"); + goto finalize; + if (sz != FAMILY_ADDRESS_SIZE(family)) { + r = sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid address size"); + goto finalize; + } - if (!dns_server_address_valid(family, d)) - return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid DNS server address"); + if (!dns_server_address_valid(family, d)) { + r = sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid DNS server address"); + goto finalize; + } r = sd_bus_message_exit_container(message); if (r < 0) - return r; + goto finalize; - if (!GREEDY_REALLOC(dns, allocated, n+1)) - return -ENOMEM; + if (!GREEDY_REALLOC(dns, allocated, n+1)) { + r = -ENOMEM; + goto finalize; + } + + memcpy(&a, d, sz); + r = in_addr_full_new(family, &a, 0, 0, NULL, dns + n); + if (r < 0) + goto finalize; - dns[n].family = family; - memcpy(&dns[n].address, d, sz); n++; } r = sd_bus_message_exit_container(message); if (r < 0) - return r; + goto finalize; r = bus_verify_polkit_async(message, CAP_NET_ADMIN, "org.freedesktop.network1.set-dns-servers", NULL, true, UID_INVALID, &l->manager->polkit_registry, error); if (r < 0) - return r; - if (r == 0) - return 1; /* Polkit will call us back */ + goto finalize; + if (r == 0) { + r = 1; /* Polkit will call us back */ + goto finalize; + } + + if (l->n_dns != (unsigned) -1) + for (unsigned i = 0; i < l->n_dns; i++) + in_addr_full_free(l->dns[i]); free_and_replace(l->dns, dns); l->n_dns = n; @@ -190,6 +209,13 @@ int bus_link_method_set_dns_servers(sd_bus_message *message, void *userdata, sd_ (void) link_dirty(l); return sd_bus_reply_method_return(message, NULL); + +finalize: + for (size_t i = 0; i < n; i++) + in_addr_full_free(dns[i]); + free(dns); + + return r; } int bus_link_method_set_domains(sd_bus_message *message, void *userdata, sd_bus_error *error) { diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 24de9a7ac8..7e7713519b 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -666,6 +666,9 @@ void link_ntp_settings_clear(Link *link) { } void link_dns_settings_clear(Link *link) { + if (link->n_dns != (unsigned) -1) + for (unsigned i = 0; i < link->n_dns; i++) + in_addr_full_free(link->dns[i]); link->dns = mfree(link->dns); link->n_dns = (unsigned) -1; @@ -4108,20 +4111,17 @@ static void print_link_hashmap(FILE *f, const char *prefix, Hashmap* h) { fputc('\n', f); } -static void link_save_dns(FILE *f, struct in_addr_data *dns, unsigned n_dns, bool *space) { +static void link_save_dns(FILE *f, struct in_addr_full **dns, unsigned n_dns, bool *space) { for (unsigned j = 0; j < n_dns; j++) { - _cleanup_free_ char *b = NULL; - int r; + const char *str; - r = in_addr_to_string(dns[j].family, &dns[j].address, &b); - if (r < 0) { - log_debug_errno(r, "Failed to format address, ignoring: %m"); + str = in_addr_full_to_string(dns[j]); + if (!str) continue; - } if (*space) fputc(' ', f); - fputs(b, f); + fputs(str, f); *space = true; } } diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index fb12301fe6..e736970503 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -163,7 +163,7 @@ typedef struct Link { bool stats_updated; /* All kinds of DNS configuration the user configured via D-Bus */ - struct in_addr_data *dns; + struct in_addr_full **dns; unsigned n_dns; OrderedSet *search_domains, *route_domains; diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index 4fbb7965be..a87bf25d64 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -1425,33 +1425,33 @@ static int manager_connect_rtnl(Manager *m) { return 0; } -static int ordered_set_put_in_addr_data(OrderedSet *s, const struct in_addr_data *address) { - char *p; +static int ordered_set_put_dns_server(OrderedSet *s, struct in_addr_full *dns) { + const char *p; int r; assert(s); - assert(address); + assert(dns); - r = in_addr_to_string(address->family, &address->address, &p); - if (r < 0) - return r; + p = in_addr_full_to_string(dns); + if (!p) + return 0; - r = ordered_set_consume(s, p); + r = ordered_set_put_strdup(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) { +static int ordered_set_put_dns_servers(OrderedSet *s, struct in_addr_full **dns, unsigned n) { int r, c = 0; unsigned i; assert(s); - assert(addresses || n == 0); + assert(dns || n == 0); for (i = 0; i < n; i++) { - r = ordered_set_put_in_addr_data(s, addresses+i); + r = ordered_set_put_dns_server(s, dns[i]); if (r < 0) return r; @@ -1558,7 +1558,7 @@ static int manager_save(Manager *m) { continue; /* First add the static configured entries */ - r = ordered_set_put_in_addr_datav(dns, link->network->dns, link->network->n_dns); + r = ordered_set_put_dns_servers(dns, link->network->dns, link->network->n_dns); if (r < 0) return r; diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 6a3920adab..94a1a6100f 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -682,6 +682,8 @@ static Network *network_free(Network *network) { sd_ipv4acd_unref(network->dhcp_acd); strv_free(network->ntp); + for (unsigned i = 0; i < network->n_dns; i++) + in_addr_full_free(network->dns[i]); free(network->dns); ordered_set_free_free(network->search_domains); ordered_set_free_free(network->route_domains); @@ -1194,16 +1196,17 @@ int config_parse_dns( assert(rvalue); if (isempty(rvalue)) { + for (unsigned i = 0; i < n->n_dns; i++) + in_addr_full_free(n->dns[i]); n->dns = mfree(n->dns); n->n_dns = 0; return 0; } for (const char *p = rvalue;;) { + _cleanup_(in_addr_full_freep) struct in_addr_full *dns = NULL; _cleanup_free_ char *w = NULL; - union in_addr_union a; - struct in_addr_data *m; - int family; + struct in_addr_full **m; r = extract_first_word(&p, &w, NULL, 0); if (r == -ENOMEM) @@ -1216,22 +1219,21 @@ int config_parse_dns( if (r == 0) return 0; - r = in_addr_from_string_auto(w, &family, &a); + r = in_addr_full_new_from_string(w, &dns); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse dns server address, ignoring: %s", w); continue; } - m = reallocarray(n->dns, n->n_dns + 1, sizeof(struct in_addr_data)); + if (IN_SET(dns->port, 53, 853)) + dns->port = 0; + + m = reallocarray(n->dns, n->n_dns + 1, sizeof(struct in_addr_full*)); if (!m) return log_oom(); - m[n->n_dns++] = (struct in_addr_data) { - .family = family, - .address = a, - }; - + m[n->n_dns++] = TAKE_PTR(dns); n->dns = m; } } diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 424298248f..17109d139c 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -32,6 +32,7 @@ #include "networkd-util.h" #include "ordered-set.h" #include "resolve-util.h" +#include "socket-netlink.h" typedef enum IPv6PrivacyExtensions { /* The values map to the kernel's /proc/sys/net/ipv6/conf/xxx/use_tempaddr values */ @@ -316,7 +317,7 @@ struct Network { OrderedHashmap *sr_iov_by_section; /* All kinds of DNS configuration */ - struct in_addr_data *dns; + struct in_addr_full **dns; unsigned n_dns; OrderedSet *search_domains, *route_domains; diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c index 8b473836db..088cdf11a3 100644 --- a/src/network/networkd-radv.c +++ b/src/network/networkd-radv.c @@ -463,10 +463,10 @@ static int radv_get_ip6dns(Network *network, struct in6_addr **dns, for (i = 0; i < network->n_dns; i++) { union in_addr_union *addr; - if (network->dns[i].family != AF_INET6) + if (network->dns[i]->family != AF_INET6) continue; - addr = &network->dns[i].address; + addr = &network->dns[i]->address; if (in_addr_is_null(AF_INET6, addr) || in_addr_is_link_local(AF_INET6, addr) || -- 2.25.1