]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: Serialize DNR servers
authorRonan Pigott <ronan@rjp.ie>
Tue, 16 Jan 2024 07:04:41 +0000 (00:04 -0700)
committerRonan Pigott <ronan@rjp.ie>
Mon, 21 Oct 2024 16:10:19 +0000 (09:10 -0700)
Implement serialization/deserialization for DNR servers. This re-uses
the string format in place for user configuration of DoT servers, and as
a consequence non-DoT servers are discarded when recording the link
configuration, for correctness.

This also enables sd-resolved to use these servers as it would other DNS
servers.

src/libsystemd-network/sd-dhcp-lease.c
src/network/networkd-dhcp4.c
src/network/networkd-dns.c
src/network/networkd-dns.h
src/network/networkd-network.h
src/network/networkd-state-file.c

index 8c46f8f770bdad2a5184deb8cb0e4a0896ab0e02..1c0cd6829b79427afc10fc623c3b7db0ff1a10de 100644 (file)
@@ -1290,6 +1290,14 @@ int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
                 fputc('\n', f);
         }
 
+        sd_dns_resolver *resolvers;
+        r = sd_dhcp_lease_get_dnr(lease, &resolvers);
+        if (r > 0) {
+                fputs("DNR=", f);
+                serialize_dnr(f, resolvers, r, NULL);
+                fputc('\n', f);
+        }
+
         r = sd_dhcp_lease_get_ntp(lease, &addresses);
         if (r > 0) {
                 fputs("NTP=", f);
@@ -1398,6 +1406,7 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
                 *next_server = NULL,
                 *broadcast = NULL,
                 *dns = NULL,
+                *dnr = NULL,
                 *ntp = NULL,
                 *sip = NULL,
                 *pop3 = NULL,
@@ -1435,6 +1444,7 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
                            "NEXT_SERVER", &next_server,
                            "BROADCAST", &broadcast,
                            "DNS", &dns,
+                           "DNR", &dnr,
                            "NTP", &ntp,
                            "SIP", &sip,
                            "POP3", &pop3,
@@ -1537,6 +1547,13 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
                         lease->servers[SD_DHCP_LEASE_DNS].size = r;
         }
 
+        if (dnr) {
+                r = deserialize_dnr(&lease->dnr, dnr);
+                if (r < 0)
+                        log_debug_errno(r, "Failed to deserialize DNR servers %s, ignoring: %m", dnr);
+                lease->n_dnr = r;
+        }
+
         if (ntp) {
                 r = deserialize_in_addrs(&lease->servers[SD_DHCP_LEASE_NTP].addr, ntp);
                 if (r < 0)
index 4d3f429a3007b3846dbaf2e53ebf021a54d1090f..b1cda06c984ebbda1df1be31cea3bc69c210de79 100644 (file)
@@ -1558,7 +1558,7 @@ static int dhcp4_configure(Link *link) {
                                 return log_link_debug_errno(link, r, "DHCPv4 CLIENT: Failed to set request flag for SIP server: %m");
                 }
 
-                if (network_dhcp_use_dnr(link->network)) {
+                if (link_get_use_dnr(link, NETWORK_CONFIG_SOURCE_DHCP4)) {
                         r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_V4_DNR);
                         if (r < 0)
                                 return log_link_debug_errno(link, r, "DHCPv4 CLIENT: Failed to set request flag for DNR: %m");
index 74a371b6d7decb899bc1c05b96ee1c11af053d64..fb2b282bc85695e3254b03ed9af1f69554097c80 100644 (file)
@@ -94,6 +94,31 @@ bool link_get_use_dns(Link *link, NetworkConfigSource proto) {
         return true;
 }
 
+bool link_get_use_dnr(Link *link, NetworkConfigSource proto) {
+        int n;
+
+        assert(link);
+
+        if (!link->network)
+                return false;
+
+        switch (proto) {
+        case NETWORK_CONFIG_SOURCE_DHCP4:
+                n = link->network->dhcp_use_dnr;
+                break;
+        default:
+                assert_not_reached();
+        }
+
+        /* If set explicitly, use that */
+        if (n >= 0)
+                return n;
+
+        /* Otherwise, default to the same as the UseDNS setting. After all,
+         * this is just another way for the server to tell us about DNS configuration. */
+        return link_get_use_dns(link, proto);
+}
+
 int config_parse_domains(
                 const char *unit,
                 const char *filename,
index 915cb32fb12bb72137d2b6e66873f5a61c363534..e273d10328967b181727d56b134b1ab00d16714c 100644 (file)
@@ -17,6 +17,7 @@ typedef enum UseDomains {
 
 UseDomains link_get_use_domains(Link *link, NetworkConfigSource proto);
 bool link_get_use_dns(Link *link, NetworkConfigSource proto);
+bool link_get_use_dnr(Link *link, NetworkConfigSource proto);
 
 const char* use_domains_to_string(UseDomains p) _const_;
 UseDomains use_domains_from_string(const char *s) _pure_;
index 1a92257059a459fe0dd8471459d1729c2bb04200..fbcc5be9c5d103e62842ed7d0e21fb56ccc348e2 100644 (file)
@@ -421,10 +421,6 @@ int network_load(Manager *manager, OrderedHashmap **networks);
 int network_reload(Manager *manager);
 int network_load_one(Manager *manager, OrderedHashmap **networks, const char *filename);
 int network_verify(Network *network);
-static inline int network_dhcp_use_dnr(Network *network) {
-        assert(network);
-        return network->dhcp_use_dnr < 0 ? network->dhcp_use_dns : network->dhcp_use_dnr;
-}
 
 int manager_build_dhcp_pd_subnet_ids(Manager *manager);
 
index d8d05c6ffd33ca367a7cf1ad5daae2f6b2413ead..14d4572751a09e0e65e9f0f37c4355cf4baef9fd 100644 (file)
@@ -114,6 +114,24 @@ static int link_put_dns(Link *link, OrderedSet **s) {
                 }
         }
 
+        if (link->dhcp_lease && link_get_use_dnr(link, NETWORK_CONFIG_SOURCE_DHCP4)) {
+                sd_dns_resolver *resolvers;
+
+                r = sd_dhcp_lease_get_dnr(link->dhcp_lease, &resolvers);
+                if (r >= 0) {
+                        struct in_addr_full **dot_servers;
+                        size_t n = 0;
+                        CLEANUP_ARRAY(dot_servers, n, in_addr_full_array_free);
+
+                        r = dns_resolvers_to_dot_addrs(resolvers, r, &dot_servers, &n);
+                        if (r < 0)
+                                return r;
+                        r = ordered_set_put_dns_servers(s, link->ifindex, dot_servers, n);
+                        if (r < 0)
+                                return r;
+                }
+        }
+
         if (link->dhcp6_lease && link_get_use_dns(link, NETWORK_CONFIG_SOURCE_DHCP6)) {
                 const struct in6_addr *addresses;
 
@@ -523,6 +541,42 @@ static void serialize_addresses(
                 fputc('\n', f);
 }
 
+static void serialize_resolvers(
+                FILE *f,
+                const char *lvalue,
+                bool *space,
+                sd_dhcp_lease *lease,
+                bool conditional) {
+
+        bool _space = false;
+        if (!space)
+                space = &_space;
+
+        if (lvalue)
+                fprintf(f, "%s=", lvalue);
+
+        if (lease && conditional) {
+                sd_dns_resolver *resolvers;
+                _cleanup_strv_free_ char **names = NULL;
+                int r;
+
+                r = sd_dhcp_lease_get_dnr(lease, &resolvers);
+                if (r < 0)
+                        return (void) log_warning_errno(r, "Failed to get DNR from DHCP lease, ignoring.");
+
+                r = dns_resolvers_to_dot_strv(resolvers, r, &names);
+                if (r < 0)
+                        return (void) log_warning_errno(r, "Failed to get DoT servers from DHCP DNR, ignoring.");
+                if (r > 0)
+                        fputstrv(f, names, NULL, space);
+        }
+
+        if (lvalue)
+                fputc('\n', f);
+
+        return;
+}
+
 static void link_save_domains(Link *link, FILE *f, OrderedSet *static_domains, UseDomains use_domains) {
         bool space = false;
         const char *p;
@@ -666,6 +720,13 @@ static int link_save(Link *link) {
                         space = false;
                         link_save_dns(link, f, link->network->dns, link->network->n_dns, &space);
 
+                        /* DNR resolvers are not required to provide Do53 service, however resolved doesn't
+                         * know how to handle such a server so for now Do53 service is required, and
+                         * assumed. */
+                        serialize_resolvers(f, NULL, &space,
+                                            link->dhcp_lease,
+                                            link_get_use_dnr(link, NETWORK_CONFIG_SOURCE_DHCP4));
+
                         serialize_addresses(f, NULL, &space,
                                             NULL,
                                             link->dhcp_lease,