From: Ronan Pigott Date: Tue, 16 Jan 2024 07:04:41 +0000 (-0700) Subject: network: Serialize DNR servers X-Git-Tag: v257-rc1~171^2~14 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=3fd6708cde0fa4283e2335aca288a40a49406f3c;p=thirdparty%2Fsystemd.git network: Serialize DNR servers 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. --- diff --git a/src/libsystemd-network/sd-dhcp-lease.c b/src/libsystemd-network/sd-dhcp-lease.c index 8c46f8f770b..1c0cd6829b7 100644 --- a/src/libsystemd-network/sd-dhcp-lease.c +++ b/src/libsystemd-network/sd-dhcp-lease.c @@ -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) diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index 4d3f429a300..b1cda06c984 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -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"); diff --git a/src/network/networkd-dns.c b/src/network/networkd-dns.c index 74a371b6d7d..fb2b282bc85 100644 --- a/src/network/networkd-dns.c +++ b/src/network/networkd-dns.c @@ -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, diff --git a/src/network/networkd-dns.h b/src/network/networkd-dns.h index 915cb32fb12..e273d103289 100644 --- a/src/network/networkd-dns.h +++ b/src/network/networkd-dns.h @@ -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_; diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 1a92257059a..fbcc5be9c5d 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -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); diff --git a/src/network/networkd-state-file.c b/src/network/networkd-state-file.c index d8d05c6ffd3..14d4572751a 100644 --- a/src/network/networkd-state-file.c +++ b/src/network/networkd-state-file.c @@ -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,