diff options
Diffstat (limited to 'src/dns/nm-dns-manager.c')
| -rw-r--r-- | src/dns/nm-dns-manager.c | 210 |
1 files changed, 126 insertions, 84 deletions
diff --git a/src/dns/nm-dns-manager.c b/src/dns/nm-dns-manager.c index d731e7bf..b40dd6b6 100644 --- a/src/dns/nm-dns-manager.c +++ b/src/dns/nm-dns-manager.c @@ -178,7 +178,8 @@ domain_is_routing (const char *domain) /*****************************************************************************/ -NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_rc_manager_to_string, NMDnsManagerResolvConfManager, +static +NM_UTILS_LOOKUP_STR_DEFINE (_rc_manager_to_string, NMDnsManagerResolvConfManager, NM_UTILS_LOOKUP_DEFAULT_WARN (NULL), NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_MANAGER_RESOLV_CONF_MAN_UNKNOWN, "unknown"), NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_MANAGER_RESOLV_CONF_MAN_UNMANAGED, "unmanaged"), @@ -189,7 +190,8 @@ NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_rc_manager_to_string, NMDnsManagerResolvConf NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_MANAGER_RESOLV_CONF_MAN_NETCONFIG, "netconfig"), ); -NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_config_type_to_string, NMDnsIPConfigType, +static +NM_UTILS_LOOKUP_STR_DEFINE (_config_type_to_string, NMDnsIPConfigType, NM_UTILS_LOOKUP_DEFAULT_WARN ("<unknown>"), NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_IP_CONFIG_TYPE_REMOVED, "removed"), NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_IP_CONFIG_TYPE_DEFAULT, "default"), @@ -425,9 +427,9 @@ merge_one_ip_config (NMResolvConfData *rc, if (addr_family == AF_INET) nm_utils_inet_ntop (addr_family, addr, buf); else if (IN6_IS_ADDR_V4MAPPED (addr)) - nm_utils_inet4_ntop (addr->addr6.s6_addr32[3], buf); + _nm_utils_inet4_ntop (addr->addr6.s6_addr32[3], buf); else { - nm_utils_inet6_ntop (&addr->addr6, buf); + _nm_utils_inet6_ntop (&addr->addr6, buf); if (IN6_IS_ADDR_LINKLOCAL (addr)) { const char *ifname; @@ -457,7 +459,7 @@ merge_one_ip_config (NMResolvConfData *rc, num = nm_ip4_config_get_num_nis_servers (ip4_config); for (i = 0; i < num; i++) { add_string_item (rc->nis_servers, - nm_utils_inet4_ntop (nm_ip4_config_get_nis_server (ip4_config, i), buf), + _nm_utils_inet4_ntop (nm_ip4_config_get_nis_server (ip4_config, i), buf), TRUE); } @@ -858,9 +860,11 @@ update_resolv_conf (NMDnsManager *self, if (!g_file_set_contents (rc_path, content, -1, &local)) { _LOGT ("update-resolv-conf: write to %s failed (rc-manager=%s, %s)", rc_path, _rc_manager_to_string (rc_manager), local->message); - write_file_result = SR_ERROR; g_propagate_error (error, local); + /* clear @error, so that we don't try reset it. This is the error + * we want to propagate to the caller. */ error = NULL; + write_file_result = SR_ERROR; } else { _LOGT ("update-resolv-conf: write to %s succeeded (rc-manager=%s)", rc_path, _rc_manager_to_string (rc_manager)); @@ -928,7 +932,7 @@ update_resolv_conf (NMDnsManager *self, if ( rc_manager != NM_DNS_MANAGER_RESOLV_CONF_MAN_SYMLINK || !_read_link_cached (_PATH_RESCONF, &resconf_link_cached, &resconf_link)) { _LOGT ("update-resolv-conf: write internal file %s succeeded", MY_RESOLV_CONF); - return SR_SUCCESS; + return write_file_result; } if (!nm_streq0 (_read_link_cached (_PATH_RESCONF, &resconf_link_cached, &resconf_link), @@ -936,7 +940,7 @@ update_resolv_conf (NMDnsManager *self, _LOGT ("update-resolv-conf: write internal file %s succeeded (don't touch symlink %s linking to %s)", MY_RESOLV_CONF, _PATH_RESCONF, _read_link_cached (_PATH_RESCONF, &resconf_link_cached, &resconf_link)); - return SR_SUCCESS; + return write_file_result; } /* By this point, /etc/resolv.conf exists and is a symlink to our internal @@ -989,7 +993,7 @@ update_resolv_conf (NMDnsManager *self, _LOGT ("update-resolv-conf: write internal file %s succeeded and update symlink %s", MY_RESOLV_CONF, _PATH_RESCONF); - return SR_SUCCESS; + return write_file_result; } static void @@ -1161,7 +1165,7 @@ _collect_resolv_conf_data (NMDnsManager *self, const char *hostdomain = strchr (priv->hostname, '.'); if ( hostdomain - && !nm_utils_ipaddr_valid (AF_UNSPEC, priv->hostname)) { + && !nm_utils_ipaddr_is_valid (AF_UNSPEC, priv->hostname)) { hostdomain++; if (domain_is_valid (hostdomain, TRUE)) add_string_item (rc.searches, hostdomain, TRUE); @@ -1227,26 +1231,34 @@ get_ip_rdns_domains (NMIPConfig *ip_config) /* Check if the domain is shadowed by a parent domain with more negative priority */ static gboolean domain_is_shadowed (GHashTable *ht, - const char *domain, int priority, - const char **out_parent, int *out_parent_priority) + const char *domain, + int priority, + const char **out_parent, + int *out_parent_priority) { char *parent; int parent_priority; + if (!ht) + return FALSE; + nm_assert (!g_hash_table_contains (ht, domain)); parent_priority = GPOINTER_TO_INT (g_hash_table_lookup (ht, "")); - if (parent_priority < 0 && parent_priority < priority) { + if ( parent_priority < 0 + && parent_priority < priority) { *out_parent = ""; *out_parent_priority = parent_priority; return TRUE; } parent = strchr (domain, '.'); - while (parent && parent[1]) { + while ( parent + && parent[1]) { parent++; parent_priority = GPOINTER_TO_INT (g_hash_table_lookup (ht, parent)); - if (parent_priority < 0 && parent_priority < priority) { + if ( parent_priority < 0 + && parent_priority < priority) { *out_parent = parent; *out_parent_priority = parent_priority; return TRUE; @@ -1265,8 +1277,6 @@ rebuild_domain_lists (NMDnsManager *self) gboolean default_route_found = FALSE; CList *head; - ht = g_hash_table_new (nm_str_hash, g_str_equal); - head = _ip_config_lst_head (self); c_list_for_each_entry (ip_data, head, ip_config_lst) { NMIPConfig *ip_config = ip_data->ip_config; @@ -1281,55 +1291,71 @@ rebuild_domain_lists (NMDnsManager *self) c_list_for_each_entry (ip_data, head, ip_config_lst) { NMIPConfig *ip_config = ip_data->ip_config; - int priority, old_priority; - guint i, n, n_domains = 0; + int priority; const char **domains; + guint n_searches; + guint n_domains; + guint num_dom1; + guint num_dom2; + guint cap_dom; + guint i; if (!nm_ip_config_get_num_nameservers (ip_config)) continue; + n_searches = nm_ip_config_get_num_searches (ip_config); + n_domains = nm_ip_config_get_num_domains (ip_config); + priority = nm_ip_config_get_dns_priority (ip_config); nm_assert (priority != 0); + + cap_dom = 2u + NM_MAX (n_domains, n_searches); + g_free (ip_data->domains.search); - domains = g_new0 (const char *, - 2 + NM_MAX (nm_ip_config_get_num_searches (ip_config), - nm_ip_config_get_num_domains (ip_config))); + domains = g_new (const char *, cap_dom); ip_data->domains.search = domains; + num_dom1 = 0; + /* 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) { + /* 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)) - domains[n_domains++] = "~"; + domains[num_dom1++] = "~"; } else { if (ip_data->ip_config_type != NM_DNS_IP_CONFIG_TYPE_VPN) - domains[n_domains++] = "~"; + domains[num_dom1++] = "~"; } /* searches are preferred over domains */ - n = nm_ip_config_get_num_searches (ip_config); - for (i = 0; i < n; i++) - domains[n_domains++] = nm_ip_config_get_search (ip_config, i); - - if (n == 0) { - /* If not searches, use any domains */ - n = nm_ip_config_get_num_domains (ip_config); - for (i = 0; i < n; i++) - domains[n_domains++] = nm_ip_config_get_domain (ip_config, i); + if (n_searches > 0) { + for (i = 0; i < n_searches; i++) + domains[num_dom1++] = nm_ip_config_get_search (ip_config, i); + } else { + for (i = 0; i < n_domains; i++) + domains[num_dom1++] = nm_ip_config_get_domain (ip_config, i); } - n = 0; - for (i = 0; i < n_domains; i++) { + nm_assert (num_dom1 < cap_dom); + + num_dom2 = 0; + for (i = 0; i < num_dom1; i++) { const char *domain_clean; const char *parent; + int old_priority; int parent_priority; domain_clean = nm_utils_parse_dns_domain (domains[i], NULL); /* Remove domains with lower priority */ - old_priority = GPOINTER_TO_INT (g_hash_table_lookup (ht, domain_clean)); - if (old_priority) { + old_priority = GPOINTER_TO_INT (nm_g_hash_table_lookup (ht, domain_clean)); + if (old_priority != 0) { if (old_priority < priority) { _LOGT ("plugin: drop domain '%s' (i=%d, p=%d) because it already exists with p=%d", domains[i], ip_data->data->ifindex, @@ -1345,10 +1371,13 @@ rebuild_domain_lists (NMDnsManager *self) } _LOGT ("plugin: add domain '%s' (i=%d, p=%d)", domains[i], ip_data->data->ifindex, priority); + if (!ht) + ht = g_hash_table_new (nm_str_hash, g_str_equal); g_hash_table_insert (ht, (gpointer) domain_clean, GINT_TO_POINTER (priority)); - domains[n++] = domains[i]; + domains[num_dom2++] = domains[i]; } - domains[n] = NULL; + nm_assert (num_dom2 < cap_dom); + domains[num_dom2] = NULL; g_strfreev (ip_data->domains.reverse); ip_data->domains.reverse = get_ip_rdns_domains (ip_config); @@ -1363,8 +1392,8 @@ clear_domain_lists (NMDnsManager *self) head = _ip_config_lst_head (self); c_list_for_each_entry (ip_data, head, ip_config_lst) { - g_clear_pointer (&ip_data->domains.search, g_free); - g_clear_pointer (&ip_data->domains.reverse, g_strfreev); + nm_clear_g_free (&ip_data->domains.search); + nm_clear_pointer (&ip_data->domains.reverse, g_strfreev); } } @@ -1373,21 +1402,24 @@ update_dns (NMDnsManager *self, gboolean no_caching, GError **error) { - NMDnsManagerPrivate *priv; + NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); const char *nis_domain = NULL; gs_strfreev char **searches = NULL; gs_strfreev char **options = NULL; gs_strfreev char **nameservers = NULL; gs_strfreev char **nis_servers = NULL; - gboolean caching = FALSE, update = TRUE; + gboolean caching = FALSE; + gboolean do_update = TRUE; gboolean resolv_conf_updated = FALSE; - SpawnResult result = SR_ERROR; + SpawnResult result = SR_SUCCESS; NMConfigData *data; NMGlobalDnsConfig *global_config; + gs_free_error GError *local_error = NULL; + GError **const p_local_error = error + ? &local_error + : NULL; - g_return_val_if_fail (!error || !*error, FALSE); - - priv = NM_DNS_MANAGER_GET_PRIVATE (self); + nm_assert (!error || !*error); if (priv->is_stopped) { _LOGD ("update-dns: not updating resolv.conf (is stopped)"); @@ -1398,7 +1430,7 @@ update_dns (NMDnsManager *self, if (NM_IN_SET (priv->rc_manager, NM_DNS_MANAGER_RESOLV_CONF_MAN_UNMANAGED, NM_DNS_MANAGER_RESOLV_CONF_MAN_IMMUTABLE)) { - update = FALSE; + do_update = FALSE; _LOGD ("update-dns: not updating resolv.conf"); } else { priv->dns_touched = TRUE; @@ -1436,7 +1468,7 @@ update_dns (NMDnsManager *self, if (no_caching) { _LOGD ("update-dns: plugin %s ignored (caching disabled)", plugin_name); - goto skip; + goto plugin_skip; } caching = TRUE; } @@ -1455,7 +1487,7 @@ update_dns (NMDnsManager *self, caching = FALSE; } - skip: +plugin_skip: ; } @@ -1486,7 +1518,7 @@ update_dns (NMDnsManager *self, nameservers[0] = g_strdup (lladdr); } - if (update) { + if (do_update) { switch (priv->rc_manager) { case NM_DNS_MANAGER_RESOLV_CONF_MAN_SYMLINK: case NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE: @@ -1494,7 +1526,7 @@ update_dns (NMDnsManager *self, NM_CAST_STRV_CC (searches), NM_CAST_STRV_CC (nameservers), NM_CAST_STRV_CC (options), - error, + p_local_error, priv->rc_manager); resolv_conf_updated = TRUE; /* If we have ended with no nameservers avoid updating again resolv.conf @@ -1503,7 +1535,11 @@ update_dns (NMDnsManager *self, priv->dns_touched = FALSE; break; case NM_DNS_MANAGER_RESOLV_CONF_MAN_RESOLVCONF: - result = dispatch_resolvconf (self, searches, nameservers, options, error); + result = dispatch_resolvconf (self, + searches, + nameservers, + options, + p_local_error); break; case NM_DNS_MANAGER_RESOLV_CONF_MAN_NETCONFIG: result = dispatch_netconfig (self, @@ -1511,20 +1547,20 @@ update_dns (NMDnsManager *self, (const char *const*) nameservers, nis_domain, (const char *const*) nis_servers, - error); + p_local_error); break; default: - g_assert_not_reached (); + nm_assert_not_reached (); } if (result == SR_NOTFOUND) { _LOGD ("update-dns: program not available, writing to resolv.conf"); - g_clear_error (error); + g_clear_error (&local_error); result = update_resolv_conf (self, NM_CAST_STRV_CC (searches), NM_CAST_STRV_CC (nameservers), NM_CAST_STRV_CC (options), - error, + p_local_error, NM_DNS_MANAGER_RESOLV_CONF_MAN_SYMLINK); resolv_conf_updated = TRUE; } @@ -1542,13 +1578,21 @@ update_dns (NMDnsManager *self, } /* signal that resolv.conf was changed */ - if (update && result == SR_SUCCESS) + if ( do_update + && result == SR_SUCCESS) g_signal_emit (self, signals[CONFIG_CHANGED], 0); - g_clear_pointer (&priv->config_variant, g_variant_unref); + nm_clear_pointer (&priv->config_variant, g_variant_unref); _notify (self, PROP_CONFIGURATION); - return !update || result == SR_SUCCESS; + if (result != SR_SUCCESS) { + if (error) + g_propagate_error (error, g_steal_pointer (&local_error)); + return FALSE; + } + + nm_assert (!local_error); + return TRUE; } /*****************************************************************************/ @@ -1569,7 +1613,6 @@ nm_dns_manager_set_ip_config (NMDnsManager *self, NMDnsIPConfigType ip_config_type) { NMDnsManagerPrivate *priv; - GError *error = NULL; NMDnsIPConfigData *ip_data; NMDnsConfigData *data; int ifindex; @@ -1642,10 +1685,11 @@ nm_dns_manager_set_ip_config (NMDnsManager *self, } changed: - if ( !priv->updates_queue - && !update_dns (self, FALSE, &error)) { - _LOGW ("could not commit DNS changes: %s", error->message); - g_clear_error (&error); + if (!priv->updates_queue) { + gs_free_error GError *error = NULL; + + if (!update_dns (self, FALSE, &error)) + _LOGW ("could not commit DNS changes: %s", error->message); } return TRUE; @@ -1667,7 +1711,6 @@ nm_dns_manager_set_hostname (NMDnsManager *self, gboolean skip_update) { NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); - GError *error = NULL; const char *filtered = NULL; /* Certain hostnames we don't want to include in resolv.conf 'searches' */ @@ -1687,9 +1730,12 @@ nm_dns_manager_set_hostname (NMDnsManager *self, if (skip_update) return; - if (!priv->updates_queue && !update_dns (self, FALSE, &error)) { - _LOGW ("could not commit DNS changes: %s", error->message); - g_clear_error (&error); + + if (!priv->updates_queue) { + gs_free_error GError *error = NULL; + + if (!update_dns (self, FALSE, &error)) + _LOGW ("could not commit DNS changes: %s", error->message); } } @@ -1714,7 +1760,7 @@ void nm_dns_manager_end_updates (NMDnsManager *self, const char *func) { NMDnsManagerPrivate *priv; - GError *error = NULL; + gs_free_error GError *error = NULL; gboolean changed; guint8 new[HASH_LEN]; @@ -1735,10 +1781,8 @@ nm_dns_manager_end_updates (NMDnsManager *self, const char *func) /* Commit all the outstanding changes */ _LOGD ("(%s): committing DNS changes (%d)", func, priv->updates_queue); - if (!update_dns (self, FALSE, &error)) { + if (!update_dns (self, FALSE, &error)) _LOGW ("could not commit DNS changes: %s", error->message); - g_clear_error (&error); - } memset (priv->prev_hash, 0, sizeof (priv->prev_hash)); } @@ -1747,7 +1791,6 @@ void nm_dns_manager_stop (NMDnsManager *self) { NMDnsManagerPrivate *priv; - GError *error = NULL; priv = NM_DNS_MANAGER_GET_PRIVATE (self); @@ -1764,10 +1807,11 @@ nm_dns_manager_stop (NMDnsManager *self) if ( priv->dns_touched && priv->plugin && NM_IS_DNS_DNSMASQ (priv->plugin)) { - if (!update_dns (self, TRUE, &error)) { + gs_free_error GError *error = NULL; + + if (!update_dns (self, TRUE, &error)) _LOGW ("could not commit DNS changes on shutdown: %s", error->message); - g_clear_error (&error); - } + priv->dns_touched = FALSE; } @@ -2041,8 +2085,6 @@ config_changed_cb (NMConfig *config, NMConfigData *old_data, NMDnsManager *self) { - GError *error = NULL; - if (NM_FLAGS_ANY (changes, NM_CONFIG_CHANGE_DNS_MODE | NM_CONFIG_CHANGE_RC_MANAGER | NM_CONFIG_CHANGE_CAUSE_SIGHUP | @@ -2063,10 +2105,10 @@ config_changed_cb (NMConfig *config, NM_CONFIG_CHANGE_DNS_MODE | NM_CONFIG_CHANGE_RC_MANAGER | NM_CONFIG_CHANGE_GLOBAL_DNS_CONFIG)) { - if (!update_dns (self, FALSE, &error)) { + gs_free_error GError *error = NULL; + + if (!update_dns (self, FALSE, &error)) _LOGW ("could not commit DNS changes: %s", error->message); - g_clear_error (&error); - } } } @@ -2296,7 +2338,7 @@ dispose (GObject *object) c_list_for_each_entry_safe (ip_data, ip_data_safe, &priv->ip_config_lst_head, ip_config_lst) _ip_config_data_free (ip_data); - g_clear_pointer (&priv->configs, g_hash_table_destroy); + nm_clear_pointer (&priv->configs, g_hash_table_destroy); nm_clear_g_source (&priv->plugin_ratelimit.timer); @@ -2304,7 +2346,7 @@ dispose (GObject *object) G_OBJECT_CLASS (nm_dns_manager_parent_class)->dispose (object); - g_clear_pointer (&priv->config_variant, g_variant_unref); + nm_clear_pointer (&priv->config_variant, g_variant_unref); } static void |