]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: support port number and SNI in [Network] DNS=
authorYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 3 Jul 2020 07:48:29 +0000 (16:48 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 20 Jul 2020 19:08:22 +0000 (04:08 +0900)
src/network/networkd-dhcp-server.c
src/network/networkd-link-bus.c
src/network/networkd-link.c
src/network/networkd-link.h
src/network/networkd-manager.c
src/network/networkd-network.c
src/network/networkd-network.h
src/network/networkd-radv.c

index 265d9dbc79c40720de25567c711005e0130accbb..5129a2e37e2dbce77868bcf1ba184f2c3cc4e9dc 100644 (file)
@@ -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))
index 38b005fb63c9a9f80ba912bd75fa0f8fd3b02aec..dec0d9be46165abe8982ba15f612959e1021713c 100644 (file)
@@ -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) {
index 24de9a7ac892e6d9be9a6bc42828fb5aa87635e9..7e7713519b3305452fa1138e3c4d32836a284c7a 100644 (file)
@@ -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;
         }
 }
index fb12301fe6e5b2d2294174b61712adde1b3740df..e73697050307f26fb018ad40de59690bc7665698 100644 (file)
@@ -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;
 
index 4fbb7965be022ff376e641feeae355ac36662083..a87bf25d649d3b0df051e72c91b2e3923d0b21cb 100644 (file)
@@ -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;
 
index 6a3920adabd9bd70c402637caa70739669409077..94a1a6100fed6cd2b1736d3127cf5316d1c49b69 100644 (file)
@@ -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;
         }
 }
index 424298248f963b877b52b1f94635d8bd6674f171..17109d139cfac7ff034272d34da5d61a33175715 100644 (file)
@@ -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;
 
index 8b473836dbf7e1b610633dca8938caf77a63ebd3..088cdf11a3660b581b47687e8e605ef45c783286 100644 (file)
@@ -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) ||