From 1a98cf1669de8c3c243ea3321fe71e997d08f6b0 Mon Sep 17 00:00:00 2001 From: Robin Ebert Date: Sun, 3 Oct 2021 14:00:01 +0200 Subject: [PATCH] core: add support for connection.dns-over-tls --- man/NetworkManager.conf.xml | 4 + src/core/devices/nm-device.c | 30 ++++++- src/core/dns/nm-dns-systemd-resolved.c | 42 +++++++--- src/core/nm-ip4-config.c | 104 ++++++++++++++++--------- src/core/nm-ip4-config.h | 15 ++-- src/core/vpn/nm-vpn-connection.c | 1 + 6 files changed, 145 insertions(+), 51 deletions(-) diff --git a/man/NetworkManager.conf.xml b/man/NetworkManager.conf.xml index 7eaa4cb2a1..617b94bdf7 100644 --- a/man/NetworkManager.conf.xml +++ b/man/NetworkManager.conf.xml @@ -800,6 +800,10 @@ ipv6.ip6-privacy=0 connection.mdns If unspecified, the ultimate default values depends on the DNS plugin. With systemd-resolved the default currently is "no" (0) and for all other plugins also "no" (0). + + connection.dns-over-tls + If unspecified, the ultimate default values depends on the DNS plugin. With systemd-resolved the default currently is global setting and for all other plugins "no" (0). + connection.stable-id diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c index 9197124d9a..3c20aa5051 100644 --- a/src/core/devices/nm-device.c +++ b/src/core/devices/nm-device.c @@ -1198,6 +1198,29 @@ _prop_get_connection_llmnr(NMDevice *self) NM_SETTING_CONNECTION_LLMNR_DEFAULT); } +static NMSettingConnectionDnsOverTls +_prop_get_connection_dns_over_tls(NMDevice *self) +{ + NMConnection * connection; + NMSettingConnectionDnsOverTls dns_over_tls = NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT; + + g_return_val_if_fail(NM_IS_DEVICE(self), NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT); + + connection = nm_device_get_applied_connection(self); + if (connection) + dns_over_tls = nm_setting_connection_get_dns_over_tls( + nm_connection_get_setting_connection(connection)); + if (dns_over_tls != NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT) + return dns_over_tls; + + return nm_config_data_get_connection_default_int64(NM_CONFIG_GET_DATA, + NM_CON_DEFAULT("connection.dns-over-tls"), + self, + NM_SETTING_CONNECTION_DNS_OVER_TLS_NO, + NM_SETTING_CONNECTION_DNS_OVER_TLS_YES, + NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT); +} + static guint32 _prop_get_ipvx_route_table(NMDevice *self, int addr_family) { @@ -8996,6 +9019,7 @@ ensure_con_ip_config(NMDevice *self, int addr_family) nm_connection_get_setting_ip4_config(connection), _prop_get_connection_mdns(self), _prop_get_connection_llmnr(self), + _prop_get_connection_dns_over_tls(self), nm_device_get_route_table(self, addr_family), nm_device_get_route_metric(self, addr_family)); } else { @@ -9500,6 +9524,7 @@ dhcp4_notify(NMDhcpClient *client, const NMDhcpClientNotifyData *notify_data, NM nm_connection_get_setting_ip4_config(connection), NM_SETTING_CONNECTION_MDNS_DEFAULT, NM_SETTING_CONNECTION_LLMNR_DEFAULT, + NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT, nm_device_get_route_table(self, AF_INET), nm_device_get_route_metric(self, AF_INET)); @@ -11314,6 +11339,7 @@ act_stage3_ip_config_start(NMDevice * self, nm_connection_get_setting_ip4_config(connection), NM_SETTING_CONNECTION_MDNS_DEFAULT, NM_SETTING_CONNECTION_LLMNR_DEFAULT, + NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT, nm_device_get_route_table(self, AF_INET), nm_device_get_route_metric(self, AF_INET)); configs = g_new0(NMIP4Config *, 2); @@ -12500,6 +12526,7 @@ nm_device_reactivate_ip_config(NMDevice * self, s_ip_new, _prop_get_connection_mdns(self), _prop_get_connection_llmnr(self), + _prop_get_connection_dns_over_tls(self), nm_device_get_route_table(self, AF_INET), nm_device_get_route_metric(self, AF_INET)); } else { @@ -12633,7 +12660,8 @@ can_reapply_change(NMDevice * self, NM_SETTING_CONNECTION_METERED, NM_SETTING_CONNECTION_LLDP, NM_SETTING_CONNECTION_MDNS, - NM_SETTING_CONNECTION_LLMNR); + NM_SETTING_CONNECTION_LLMNR, + NM_SETTING_CONNECTION_DNS_OVER_TLS); } if (NM_IN_STRSET(setting_name, diff --git a/src/core/dns/nm-dns-systemd-resolved.c b/src/core/dns/nm-dns-systemd-resolved.c index 938b7dc0f2..a55746b6c9 100644 --- a/src/core/dns/nm-dns-systemd-resolved.c +++ b/src/core/dns/nm-dns-systemd-resolved.c @@ -286,14 +286,15 @@ free_pending_updates(NMDnsSystemdResolved *self) static gboolean prepare_one_interface(NMDnsSystemdResolved *self, InterfaceConfig *ic) { - GVariantBuilder dns; - GVariantBuilder domains; - NMCListElem * elem; - NMSettingConnectionMdns mdns = NM_SETTING_CONNECTION_MDNS_DEFAULT; - NMSettingConnectionLlmnr llmnr = NM_SETTING_CONNECTION_LLMNR_DEFAULT; - const char * mdns_arg = NULL, *llmnr_arg = NULL; - gboolean has_config = FALSE; - gboolean has_default_route = FALSE; + GVariantBuilder dns; + GVariantBuilder domains; + NMCListElem * elem; + NMSettingConnectionMdns mdns = NM_SETTING_CONNECTION_MDNS_DEFAULT; + NMSettingConnectionLlmnr llmnr = NM_SETTING_CONNECTION_LLMNR_DEFAULT; + NMSettingConnectionDnsOverTls dns_over_tls = NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT; + const char * mdns_arg = NULL, *llmnr_arg = NULL, *dns_over_tls_arg = NULL; + gboolean has_config = FALSE; + gboolean has_default_route = FALSE; g_variant_builder_init(&dns, G_VARIANT_TYPE("(ia(iay))")); g_variant_builder_add(&dns, "i", ic->ifindex); @@ -315,6 +316,8 @@ prepare_one_interface(NMDnsSystemdResolved *self, InterfaceConfig *ic) if (NM_IS_IP4_CONFIG(ip_config)) { mdns = NM_MAX(mdns, nm_ip4_config_mdns_get(NM_IP4_CONFIG(ip_config))); llmnr = NM_MAX(llmnr, nm_ip4_config_llmnr_get(NM_IP4_CONFIG(ip_config))); + dns_over_tls = + NM_MAX(dns_over_tls, nm_ip4_config_dns_over_tls_get(NM_IP4_CONFIG(ip_config))); } } @@ -353,7 +356,24 @@ prepare_one_interface(NMDnsSystemdResolved *self, InterfaceConfig *ic) } nm_assert(llmnr_arg); - if (!nm_str_is_empty(mdns_arg) || !nm_str_is_empty(llmnr_arg)) + switch (dns_over_tls) { + case NM_SETTING_CONNECTION_DNS_OVER_TLS_NO: + dns_over_tls_arg = "no"; + break; + case NM_SETTING_CONNECTION_DNS_OVER_TLS_OPPORTUNISTIC: + dns_over_tls_arg = "opportunistic"; + break; + case NM_SETTING_CONNECTION_DNS_OVER_TLS_YES: + dns_over_tls_arg = "yes"; + break; + case NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT: + dns_over_tls_arg = ""; + break; + } + nm_assert(dns_over_tls_arg); + + if (!nm_str_is_empty(mdns_arg) || !nm_str_is_empty(llmnr_arg) + || !nm_str_is_empty(dns_over_tls_arg)) has_config = TRUE; _request_item_append(self, "SetLinkDomains", ic->ifindex, g_variant_builder_end(&domains)); @@ -370,6 +390,10 @@ prepare_one_interface(NMDnsSystemdResolved *self, InterfaceConfig *ic) ic->ifindex, g_variant_new("(is)", ic->ifindex, llmnr_arg ?: "")); _request_item_append(self, "SetLinkDNS", ic->ifindex, g_variant_builder_end(&dns)); + _request_item_append(self, + "SetLinkDNSOverTLS", + ic->ifindex, + g_variant_new("(is)", ic->ifindex, dns_over_tls_arg ?: "")); return has_config; } diff --git a/src/core/nm-ip4-config.c b/src/core/nm-ip4-config.c index a622b05379..90398dcc07 100644 --- a/src/core/nm-ip4-config.c +++ b/src/core/nm-ip4-config.c @@ -287,27 +287,28 @@ NM_GOBJECT_PROPERTIES_DEFINE(NMIP4Config, PROP_DNS_PRIORITY, ); typedef struct { - bool metered : 1; - bool never_default : 1; - guint32 mtu; - int ifindex; - NMIPConfigSource mtu_source; - int dns_priority; - NMSettingConnectionMdns mdns; - NMSettingConnectionLlmnr llmnr; - GArray * nameservers; - GPtrArray * domains; - GPtrArray * searches; - GPtrArray * dns_options; - GArray * nis; - char * nis_domain; - GArray * wins; - GVariant * address_data_variant; - GVariant * addresses_variant; - GVariant * route_data_variant; - GVariant * routes_variant; - NMDedupMultiIndex * multi_idx; - const NMPObject * best_default_route; + bool metered : 1; + bool never_default : 1; + guint32 mtu; + int ifindex; + NMIPConfigSource mtu_source; + int dns_priority; + NMSettingConnectionMdns mdns; + NMSettingConnectionLlmnr llmnr; + NMSettingConnectionDnsOverTls dns_over_tls; + GArray * nameservers; + GPtrArray * domains; + GPtrArray * searches; + GPtrArray * dns_options; + GArray * nis; + char * nis_domain; + GArray * wins; + GVariant * address_data_variant; + GVariant * addresses_variant; + GVariant * route_data_variant; + GVariant * routes_variant; + NMDedupMultiIndex * multi_idx; + const NMPObject * best_default_route; union { NMIPConfigDedupMultiIdxType idx_ip4_addresses_; NMDedupMultiIdxType idx_ip4_addresses; @@ -747,12 +748,13 @@ nm_ip4_config_commit(const NMIP4Config * self, } void -nm_ip4_config_merge_setting(NMIP4Config * self, - NMSettingIPConfig * setting, - NMSettingConnectionMdns mdns, - NMSettingConnectionLlmnr llmnr, - guint32 route_table, - guint32 route_metric) +nm_ip4_config_merge_setting(NMIP4Config * self, + NMSettingIPConfig * setting, + NMSettingConnectionMdns mdns, + NMSettingConnectionLlmnr llmnr, + NMSettingConnectionDnsOverTls dns_over_tls, + guint32 route_table, + guint32 route_metric) { guint naddresses, nroutes, nnameservers, nsearches; int i, priority; @@ -868,6 +870,7 @@ nm_ip4_config_merge_setting(NMIP4Config * self, nm_ip4_config_mdns_set(self, mdns); nm_ip4_config_llmnr_set(self, llmnr); + nm_ip4_config_dns_over_tls_set(self, dns_over_tls); nm_ip4_config_set_never_default(self, nm_setting_ip_config_get_never_default(setting)); @@ -1112,6 +1115,10 @@ nm_ip4_config_merge(NMIP4Config * dst, /* LLMNR */ nm_ip4_config_llmnr_set(dst, NM_MAX(nm_ip4_config_llmnr_get(src), nm_ip4_config_llmnr_get(dst))); + /* dns_over_tls */ + nm_ip4_config_dns_over_tls_set( + dst, + NM_MAX(nm_ip4_config_dns_over_tls_get(src), nm_ip4_config_dns_over_tls_get(dst))); g_object_thaw_notify(G_OBJECT(dst)); } @@ -1357,6 +1364,10 @@ nm_ip4_config_subtract(NMIP4Config * dst, if (nm_ip4_config_llmnr_get(src) == nm_ip4_config_llmnr_get(dst)) nm_ip4_config_llmnr_set(dst, NM_SETTING_CONNECTION_LLMNR_DEFAULT); + /* dns_over_tls */ + if (nm_ip4_config_dns_over_tls_get(src) == nm_ip4_config_dns_over_tls_get(dst)) + nm_ip4_config_dns_over_tls_set(dst, NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT); + g_object_thaw_notify(G_OBJECT(dst)); } @@ -1466,6 +1477,7 @@ skip_routes: /* ignore WINS */ /* ignore mdns */ /* ignore LLMNR */ + /* ignore dns_over_tls */ if (update_dst) g_object_thaw_notify(G_OBJECT(dst)); @@ -1777,6 +1789,11 @@ nm_ip4_config_replace(NMIP4Config *dst, const NMIP4Config *src, gboolean *releva has_relevant_changes = TRUE; } + if (src_priv->dns_over_tls != dst_priv->dns_over_tls) { + dst_priv->dns_over_tls = src_priv->dns_over_tls; + has_relevant_changes = TRUE; + } + /* DNS priority */ if (src_priv->dns_priority != dst_priv->dns_priority) { nm_ip4_config_set_dns_priority(dst, src_priv->dns_priority); @@ -2521,6 +2538,18 @@ nm_ip4_config_llmnr_set(NMIP4Config *self, NMSettingConnectionLlmnr llmnr) NM_IP4_CONFIG_GET_PRIVATE(self)->llmnr = llmnr; } +NMSettingConnectionDnsOverTls +nm_ip4_config_dns_over_tls_get(const NMIP4Config *self) +{ + return NM_IP4_CONFIG_GET_PRIVATE(self)->dns_over_tls; +} + +void +nm_ip4_config_dns_over_tls_set(NMIP4Config *self, NMSettingConnectionDnsOverTls dns_over_tls) +{ + NM_IP4_CONFIG_GET_PRIVATE(self)->dns_over_tls = dns_over_tls; +} + /*****************************************************************************/ NMIPConfigFlags @@ -2901,6 +2930,10 @@ nm_ip4_config_hash(const NMIP4Config *self, GChecksum *sum, gboolean dns_only) if (val != NM_SETTING_CONNECTION_LLMNR_DEFAULT) g_checksum_update(sum, (const guint8 *) &val, sizeof(val)); + val = nm_ip4_config_dns_over_tls_get(self); + if (val != NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT) + g_checksum_update(sum, (const guint8 *) &val, sizeof(val)); + /* FIXME(ip-config-checksum): the DNS priority should be considered relevant * and added into the checksum as well, but this can't be done right now * because in the DNS manager we rely on the fact that an empty @@ -3095,14 +3128,15 @@ nm_ip4_config_init(NMIP4Config *self) nm_ip_config_dedup_multi_idx_type_init((NMIPConfigDedupMultiIdxType *) &priv->idx_ip4_routes, NMP_OBJECT_TYPE_IP4_ROUTE); - priv->mdns = NM_SETTING_CONNECTION_MDNS_DEFAULT; - priv->llmnr = NM_SETTING_CONNECTION_LLMNR_DEFAULT; - priv->nameservers = g_array_new(FALSE, FALSE, sizeof(guint32)); - priv->domains = g_ptr_array_new_with_free_func(g_free); - priv->searches = g_ptr_array_new_with_free_func(g_free); - priv->dns_options = g_ptr_array_new_with_free_func(g_free); - priv->nis = g_array_new(FALSE, TRUE, sizeof(guint32)); - priv->wins = g_array_new(FALSE, TRUE, sizeof(guint32)); + priv->mdns = NM_SETTING_CONNECTION_MDNS_DEFAULT; + priv->llmnr = NM_SETTING_CONNECTION_LLMNR_DEFAULT; + priv->dns_over_tls = NM_SETTING_CONNECTION_DNS_OVER_TLS_DEFAULT; + priv->nameservers = g_array_new(FALSE, FALSE, sizeof(guint32)); + priv->domains = g_ptr_array_new_with_free_func(g_free); + priv->searches = g_ptr_array_new_with_free_func(g_free); + priv->dns_options = g_ptr_array_new_with_free_func(g_free); + priv->nis = g_array_new(FALSE, TRUE, sizeof(guint32)); + priv->wins = g_array_new(FALSE, TRUE, sizeof(guint32)); } NMIP4Config * diff --git a/src/core/nm-ip4-config.h b/src/core/nm-ip4-config.h index 326b884def..2eb193b2be 100644 --- a/src/core/nm-ip4-config.h +++ b/src/core/nm-ip4-config.h @@ -124,12 +124,13 @@ gboolean nm_ip4_config_commit(const NMIP4Config * self, NMPlatform * platform, NMIPRouteTableSyncMode route_table_sync); -void nm_ip4_config_merge_setting(NMIP4Config * self, - NMSettingIPConfig * setting, - NMSettingConnectionMdns mdns, - NMSettingConnectionLlmnr llmnr, - guint32 route_table, - guint32 route_metric); +void nm_ip4_config_merge_setting(NMIP4Config * self, + NMSettingIPConfig * setting, + NMSettingConnectionMdns mdns, + NMSettingConnectionLlmnr llmnr, + NMSettingConnectionDnsOverTls dns_over_tls, + guint32 route_table, + guint32 route_metric); NMSetting *nm_ip4_config_create_setting(const NMIP4Config *self); void nm_ip4_config_merge(NMIP4Config * dst, @@ -161,6 +162,8 @@ NMSettingConnectionMdns nm_ip4_config_mdns_get(const NMIP4Config *self); void nm_ip4_config_mdns_set(NMIP4Config *self, NMSettingConnectionMdns mdns); NMSettingConnectionLlmnr nm_ip4_config_llmnr_get(const NMIP4Config *self); void nm_ip4_config_llmnr_set(NMIP4Config *self, NMSettingConnectionLlmnr llmnr); +NMSettingConnectionDnsOverTls nm_ip4_config_dns_over_tls_get(const NMIP4Config *self); +void nm_ip4_config_dns_over_tls_set(NMIP4Config *self, NMSettingConnectionDnsOverTls dns_over_tls); void nm_ip4_config_set_config_flags(NMIP4Config *self, NMIPConfigFlags flags, NMIPConfigFlags mask); NMIPConfigFlags nm_ip4_config_get_config_flags(const NMIP4Config *self); diff --git a/src/core/vpn/nm-vpn-connection.c b/src/core/vpn/nm-vpn-connection.c index d06ca46adc..d2034278c0 100644 --- a/src/core/vpn/nm-vpn-connection.c +++ b/src/core/vpn/nm-vpn-connection.c @@ -1659,6 +1659,7 @@ nm_vpn_connection_ip4_config_get(NMVpnConnection *self, GVariant *dict) s_ip, nm_setting_connection_get_mdns(s_con), nm_setting_connection_get_llmnr(s_con), + nm_setting_connection_get_dns_over_tls(s_con), route_table, route_metric);