diff --git a/src/dns/nm-dns-manager.c b/src/dns/nm-dns-manager.c index 666bad60ca..144ab8029f 100644 --- a/src/dns/nm-dns-manager.c +++ b/src/dns/nm-dns-manager.c @@ -1299,18 +1299,36 @@ rebuild_domain_lists (NMDnsManager *self) { NMDnsIPConfigData *ip_data; gs_unref_hashtable GHashTable *ht = NULL; - gboolean default_route_found = FALSE; + gs_unref_hashtable GHashTable *wildcard_entries = NULL; CList *head; head = _ip_config_lst_head (self); c_list_for_each_entry (ip_data, head, ip_config_lst) { NMIPConfig *ip_config = ip_data->ip_config; + gboolean add_wildcard = FALSE; if (!nm_ip_config_get_num_nameservers (ip_config)) continue; - if (nm_ip_config_best_default_route_get (ip_config)) { - default_route_found = TRUE; - break; + if (nm_ip_config_best_default_route_get (ip_config)) + add_wildcard = TRUE; + else { + /* If a VPN has never-default=no but doesn't get a default + * route (this can happen for example when the server + * pushes routes with openconnect), and there are no + * search or routing domains, then the name servers pushed + * by the server would be unused. It is preferable in this + * case to use the VPN DNS server for all queries. */ + if ( ip_data->ip_config_type == NM_DNS_IP_CONFIG_TYPE_VPN + && !nm_ip_config_get_never_default (ip_data->ip_config) + && nm_ip_config_get_num_searches (ip_data->ip_config) == 0 + && nm_ip_config_get_num_domains (ip_data->ip_config) == 0) + add_wildcard = TRUE; + } + + if (add_wildcard) { + if (!wildcard_entries) + wildcard_entries = g_hash_table_new (nm_direct_hash, NULL); + g_hash_table_add (wildcard_entries, ip_data); } } @@ -1345,13 +1363,13 @@ rebuild_domain_lists (NMDnsManager *self) /* Add wildcard lookup domain to connections with the default route. * If there is no default route, add the wildcard domain to all non-VPN * connections */ - if (default_route_found) { + if (wildcard_entries) { /* FIXME: this heuristic of which device has a default route does * not work with policy routing (as used by default with WireGuard). * We should have a more stable mechanism where an NMIPConfig indicates * whether it is suitable for certain operations (like having an automatically * added "~" domain). */ - if (nm_ip_config_best_default_route_get (ip_config)) + if (g_hash_table_contains (wildcard_entries, ip_data)) domains[num_dom1++] = "~"; } else { if (ip_data->ip_config_type != NM_DNS_IP_CONFIG_TYPE_VPN) diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c index 23c0d3f9d5..b178cfa2a3 100644 --- a/src/nm-ip4-config.c +++ b/src/nm-ip4-config.c @@ -276,6 +276,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMIP4Config, typedef struct { bool metered:1; + bool never_default:1; guint32 mtu; int ifindex; NMIPConfigSource mtu_source; @@ -1086,6 +1087,8 @@ nm_ip4_config_merge_setting (NMIP4Config *self, nm_ip4_config_mdns_set (self, mdns); nm_ip4_config_llmnr_set (self, llmnr); + nm_ip4_config_set_never_default (self, nm_setting_ip_config_get_never_default (setting)); + g_object_thaw_notify (G_OBJECT (self)); } @@ -1310,6 +1313,11 @@ nm_ip4_config_merge (NMIP4Config *dst, nm_ip4_config_set_metered (dst, nm_ip4_config_get_metered (dst) || nm_ip4_config_get_metered (src)); + /* never default */ + nm_ip4_config_set_never_default (dst, + nm_ip4_config_get_never_default (dst) + || nm_ip4_config_get_never_default (src)); + /* DNS priority */ if (nm_ip4_config_get_dns_priority (src)) nm_ip4_config_set_dns_priority (dst, nm_ip4_config_get_dns_priority (src)); @@ -2047,6 +2055,12 @@ nm_ip4_config_replace (NMIP4Config *dst, const NMIP4Config *src, gboolean *relev has_minor_changes = TRUE; } + /* never default */ + if (src_priv->never_default != dst_priv->never_default) { + dst_priv->never_default = src_priv->never_default; + has_minor_changes = TRUE; + } + #if NM_MORE_ASSERTS /* config_equal does not compare *all* the fields, therefore, we might have has_minor_changes * regardless of config_equal. But config_equal must correspond to has_relevant_changes. */ @@ -2925,6 +2939,24 @@ nm_ip4_config_get_metered (const NMIP4Config *self) /*****************************************************************************/ +void +nm_ip4_config_set_never_default (NMIP4Config *self, gboolean never_default) +{ + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self); + + priv->never_default = never_default; +} + +gboolean +nm_ip4_config_get_never_default (const NMIP4Config *self) +{ + const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self); + + return priv->never_default; +} + +/*****************************************************************************/ + const NMPObject * nm_ip4_config_nmpobj_lookup (const NMIP4Config *self, const NMPObject *needle) { diff --git a/src/nm-ip4-config.h b/src/nm-ip4-config.h index ea06174976..177583808f 100644 --- a/src/nm-ip4-config.h +++ b/src/nm-ip4-config.h @@ -288,6 +288,9 @@ NMIPConfigSource nm_ip4_config_get_mtu_source (const NMIP4Config *self); void nm_ip4_config_set_metered (NMIP4Config *self, gboolean metered); gboolean nm_ip4_config_get_metered (const NMIP4Config *self); +void nm_ip4_config_set_never_default (NMIP4Config *self, gboolean never_default); +gboolean nm_ip4_config_get_never_default (const NMIP4Config *self); + const NMPObject *nm_ip4_config_nmpobj_lookup (const NMIP4Config *self, const NMPObject *needle); gboolean nm_ip4_config_nmpobj_remove (NMIP4Config *self, @@ -538,6 +541,21 @@ nm_ip_config_set_config_flags (NMIPConfig *self, NMIPConfigFlags flags, NMIPConf _NM_IP_CONFIG_DISPATCH_VOID (self, nm_ip4_config_set_config_flags, nm_ip6_config_set_config_flags, flags, mask); } +static inline gboolean +nm_ip_config_get_never_default (const NMIPConfig *self) +{ + _NM_IP_CONFIG_DISPATCH (self, nm_ip4_config_get_never_default, nm_ip6_config_get_never_default); +} + +static inline void +nm_ip_config_set_never_default (NMIPConfig *self, gboolean never_default) +{ + _NM_IP_CONFIG_DISPATCH_VOID(self, + nm_ip4_config_set_never_default, + nm_ip6_config_set_never_default, + never_default); +} + #define _NM_IP_CONFIG_DISPATCH_SET_OP(_return, dst, src, v4_func, v6_func, ...) \ G_STMT_START { \ gpointer _dst = (dst); \ diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c index deb30e77d7..d069d497dc 100644 --- a/src/nm-ip6-config.c +++ b/src/nm-ip6-config.c @@ -64,7 +64,8 @@ typedef struct { NMDedupMultiIdxType idx_ip6_routes; }; NMIPConfigFlags config_flags; - bool ipv6_disabled; + bool ipv6_disabled:1; + bool never_default:1; } NMIP6ConfigPrivate; struct _NMIP6Config { @@ -127,6 +128,24 @@ nm_ip6_config_set_privacy (NMIP6Config *self, NMSettingIP6ConfigPrivacy privacy) /*****************************************************************************/ +void +nm_ip6_config_set_never_default (NMIP6Config *self, gboolean never_default) +{ + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self); + + priv->never_default = never_default; +} + +gboolean +nm_ip6_config_get_never_default (const NMIP6Config *self) +{ + const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self); + + return priv->never_default; +} + +/*****************************************************************************/ + const NMDedupMultiHeadEntry * nm_ip6_config_lookup_addresses (const NMIP6Config *self) { @@ -753,6 +772,8 @@ nm_ip6_config_merge_setting (NMIP6Config *self, if (priority) nm_ip6_config_set_dns_priority (self, priority); + nm_ip6_config_set_never_default (self, nm_setting_ip_config_get_never_default (setting)); + g_object_thaw_notify (G_OBJECT (self)); } diff --git a/src/nm-ip6-config.h b/src/nm-ip6-config.h index b6f461b29f..23b173da9c 100644 --- a/src/nm-ip6-config.h +++ b/src/nm-ip6-config.h @@ -191,6 +191,9 @@ const char * nm_ip6_config_get_dns_option (const NMIP6Config *self, guint i); void nm_ip6_config_set_dns_priority (NMIP6Config *self, int priority); int nm_ip6_config_get_dns_priority (const NMIP6Config *self); +void nm_ip6_config_set_never_default (NMIP6Config *self, gboolean never_default); +gboolean nm_ip6_config_get_never_default (const NMIP6Config *self); + const NMPObject *nm_ip6_config_nmpobj_lookup (const NMIP6Config *self, const NMPObject *needle); gboolean nm_ip6_config_nmpobj_remove (NMIP6Config *self,