]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: Add serialization for DoT resolvers
authorRonan Pigott <ronan@rjp.ie>
Sat, 24 Feb 2024 00:24:40 +0000 (17:24 -0700)
committerRonan Pigott <ronan@rjp.ie>
Mon, 21 Oct 2024 16:10:19 +0000 (09:10 -0700)
For now only DoT is supported, so DoT resolvers are represented using
the existing configuration format.

src/libsystemd-network/network-internal.c
src/libsystemd-network/network-internal.h
src/network/networkd-state-file.c

index c8aa021ee064d6ea090871cea1afa9d570da0751..9a1d1fda161671e828aa008122d37990e61a25ae 100644 (file)
@@ -14,6 +14,7 @@
 #include "log.h"
 #include "network-internal.h"
 #include "parse-util.h"
+#include "strv.h"
 
 size_t serialize_in_addrs(FILE *f,
                           const struct in_addr *addresses,
@@ -131,6 +132,99 @@ int deserialize_in6_addrs(struct in6_addr **ret, const char *string) {
         return size;
 }
 
+int serialize_dnr(FILE *f, const sd_dns_resolver *dnr, size_t n_dnr, bool *with_leading_space) {
+        int r;
+
+        bool _space = false;
+        if (!with_leading_space)
+                with_leading_space = &_space;
+
+        int n = 0;
+        _cleanup_strv_free_ char **names = NULL;
+        r = dns_resolvers_to_dot_strv(dnr, n_dnr, &names);
+        if (r < 0)
+                return r;
+        if (r > 0)
+                fputstrv(f, names, NULL, with_leading_space);
+        n += r;
+        return n;
+}
+
+static int coalesce_dnr(sd_dns_resolver *dnr, size_t n_dnr, int family, const char *auth_name,
+                union in_addr_union *addr) {
+        assert(dnr || n_dnr == 0);
+        assert(auth_name);
+        assert(addr);
+
+        /* Look through list of DNR for matching resolvers to add our addr to. Since DoT is assumed, no need
+         * to compare transports/dohpath/etc. */
+        FOREACH_ARRAY(res, dnr, n_dnr) {
+                if (family == res->family && streq(auth_name, res->auth_name)) {
+                        if (!GREEDY_REALLOC(res->addrs, res->n_addrs + 1))
+                                return -ENOMEM;
+                        res->addrs[res->n_addrs++] = *addr;
+                        return true;
+                }
+        }
+
+        return false;
+}
+
+/* Deserialized resolvers are assumed to offer DoT service. */
+int deserialize_dnr(sd_dns_resolver **ret, const char *string) {
+        int r;
+
+        assert(ret);
+        assert(string);
+
+        sd_dns_resolver *dnr = NULL;
+        size_t n = 0;
+        CLEANUP_ARRAY(dnr, n, dns_resolver_done_many);
+        int priority = 0;
+
+        for (;;) {
+                _cleanup_free_ char *word = NULL;
+
+                r = extract_first_word(&string, &word, NULL, 0);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        break;
+
+                uint16_t port;
+                int family;
+                _cleanup_free_ union in_addr_union *addr = new(union in_addr_union, 1);
+                _cleanup_free_ char *auth_name = NULL;
+
+                r = in_addr_port_ifindex_name_from_string_auto(word, &family, addr, &port, NULL, &auth_name);
+                if (r < 0)
+                        return r;
+
+                r = coalesce_dnr(dnr, n, family, auth_name, addr);
+                if (r < 0)
+                        return r;
+                if (r > 0)
+                        continue;
+
+                if (!GREEDY_REALLOC(dnr, n+1))
+                        return -ENOMEM;
+
+                priority = n+1;
+                dnr[n++] = (sd_dns_resolver) {
+                        .priority = priority, /* not serialized, but this will preserve the order */
+                        .auth_name = TAKE_PTR(auth_name),
+                        .family = family,
+                        .addrs = TAKE_PTR(addr),
+                        .n_addrs = 1,
+                        .transports = SD_DNS_ALPN_DOT,
+                        .port = port,
+                };
+        }
+
+        *ret = TAKE_PTR(dnr);
+        return n;
+}
+
 void serialize_dhcp_routes(FILE *f, const char *key, sd_dhcp_route **routes, size_t size) {
         assert(f);
         assert(key);
index 5aa225e977a9668361528c9ecba9023402b39f11..6a102e92c47e1ad16aaa7e6a7e656cbf998d7c0c 100644 (file)
@@ -17,6 +17,9 @@ void serialize_in6_addrs(FILE *f, const struct in6_addr *addresses,
                          bool *with_leading_space);
 int deserialize_in6_addrs(struct in6_addr **addresses, const char *string);
 
+int serialize_dnr(FILE *f, const sd_dns_resolver *dnr, size_t n_dnr, bool *with_leading_space);
+int deserialize_dnr(sd_dns_resolver **ret, const char *string);
+
 /* don't include "dhcp-lease-internal.h" as it causes conflicts between netinet/ip.h and linux/ip.h */
 struct sd_dhcp_route;
 struct sd_dhcp_lease;
index 481e2d930b7388997ea2c1a5da16fdbfcbd9c156..d8d05c6ffd33ca367a7cf1ad5daae2f6b2413ead 100644 (file)
@@ -5,6 +5,7 @@
 
 #include "alloc-util.h"
 #include "dns-domain.h"
+#include "dns-resolver-internal.h"
 #include "escape.h"
 #include "fd-util.h"
 #include "fileio.h"