diff options
author | Beniamino Galvani <bgalvani@redhat.com> | 2020-10-28 10:12:29 +0100 |
---|---|---|
committer | Beniamino Galvani <bgalvani@redhat.com> | 2020-10-29 17:23:28 +0100 |
commit | f70ee67058c92a97549dc4aca11ef0567373efbf (patch) | |
tree | 32c993ebbfd9602af421e0c4d1d2a8fc539997e9 | |
parent | 545d5a4e70d470e54228ada8155ab9d94c039bcd (diff) | |
download | NetworkManager-f70ee67058c92a97549dc4aca11ef0567373efbf.tar.gz |
dns: sd-resolved: reset interface configuration on deactivation
If an update doesn't contain an interface but the previous update did,
the systemd-resolved DNS plugin must send a request to clear the
previous configuration. Otherwise the previous DNS configuration would
persist even after interface deactivation.
https://bugzilla.redhat.com/show_bug.cgi?id=1888229
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/662
-rw-r--r-- | src/dns/nm-dns-systemd-resolved.c | 54 |
1 files changed, 46 insertions, 8 deletions
diff --git a/src/dns/nm-dns-systemd-resolved.c b/src/dns/nm-dns-systemd-resolved.c index 24c0ddb5ba..8bbfd6a4cd 100644 --- a/src/dns/nm-dns-systemd-resolved.c +++ b/src/dns/nm-dns-systemd-resolved.c @@ -51,6 +51,7 @@ typedef struct { typedef struct { GDBusConnection *dbus_connection; + GHashTable * dirty_interfaces; GCancellable * cancellable; CList request_queue_lst_head; guint name_owner_changed_id; @@ -134,7 +135,7 @@ call_done(GObject *source, GAsyncResult *r, gpointer user_data) priv->send_updates_warn_ratelimited = FALSE; } -static void +static gboolean update_add_ip_config(NMDnsSystemdResolved *self, GVariantBuilder * dns, GVariantBuilder * domains, @@ -146,12 +147,13 @@ update_add_ip_config(NMDnsSystemdResolved *self, gboolean is_routing; const char **iter; const char * domain; + gboolean has_config = FALSE; addr_family = nm_ip_config_get_addr_family(data->ip_config); addr_size = nm_utils_addr_family_to_size(addr_family); if (!data->domains.search || !data->domains.search[0]) - return; + return FALSE; n = nm_ip_config_get_num_nameservers(data->ip_config); for (i = 0; i < n; i++) { @@ -164,12 +166,16 @@ update_add_ip_config(NMDnsSystemdResolved *self, addr_size, 1)); g_variant_builder_close(dns); + has_config = TRUE; } for (iter = data->domains.search; *iter; iter++) { domain = nm_utils_parse_dns_domain(*iter, &is_routing); g_variant_builder_add(domains, "(sb)", domain[0] ? domain : ".", is_routing); + has_config = TRUE; } + + return has_config; } static void @@ -183,7 +189,7 @@ free_pending_updates(NMDnsSystemdResolved *self) _request_item_free(request_item); } -static void +static gboolean prepare_one_interface(NMDnsSystemdResolved *self, InterfaceConfig *ic) { NMDnsSystemdResolvedPrivate *priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE(self); @@ -192,6 +198,7 @@ prepare_one_interface(NMDnsSystemdResolved *self, InterfaceConfig *ic) 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; g_variant_builder_init(&dns, G_VARIANT_TYPE("(ia(iay))")); g_variant_builder_add(&dns, "i", ic->ifindex); @@ -205,7 +212,7 @@ prepare_one_interface(NMDnsSystemdResolved *self, InterfaceConfig *ic) NMDnsIPConfigData *data = elem->data; NMIPConfig * ip_config = data->ip_config; - update_add_ip_config(self, &dns, &domains, data); + has_config |= update_add_ip_config(self, &dns, &domains, data); if (NM_IS_IP4_CONFIG(ip_config)) { mdns = NM_MAX(mdns, nm_ip4_config_mdns_get(NM_IP4_CONFIG(ip_config))); @@ -248,6 +255,9 @@ prepare_one_interface(NMDnsSystemdResolved *self, InterfaceConfig *ic) } nm_assert(llmnr_arg); + if (!nm_str_is_empty(mdns_arg) || !nm_str_is_empty(llmnr_arg)) + has_config = TRUE; + _request_item_append(&priv->request_queue_lst_head, "SetLinkDNS", g_variant_builder_end(&dns)); _request_item_append(&priv->request_queue_lst_head, "SetLinkDomains", @@ -258,6 +268,8 @@ prepare_one_interface(NMDnsSystemdResolved *self, InterfaceConfig *ic) _request_item_append(&priv->request_queue_lst_head, "SetLinkLLMNR", g_variant_new("(is)", ic->ifindex, llmnr_arg ?: "")); + + return has_config; } static void @@ -336,19 +348,21 @@ update(NMDnsPlugin * plugin, const char * hostname, GError ** error) { - NMDnsSystemdResolved *self = NM_DNS_SYSTEMD_RESOLVED(plugin); + NMDnsSystemdResolved * self = NM_DNS_SYSTEMD_RESOLVED(plugin); + NMDnsSystemdResolvedPrivate *priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE(self); gs_unref_hashtable GHashTable *interfaces = NULL; gs_free gpointer * interfaces_keys = NULL; guint interfaces_len; - guint i; + int ifindex; NMDnsIPConfigData *ip_data; + GHashTableIter iter; + guint i; interfaces = g_hash_table_new_full(nm_direct_hash, NULL, NULL, (GDestroyNotify) _interface_config_free); c_list_for_each_entry (ip_data, ip_config_lst_head, ip_config_lst) { InterfaceConfig *ic = NULL; - int ifindex; ifindex = ip_data->data->ifindex; nm_assert(ifindex == nm_ip_config_get_ifindex(ip_data->ip_config)); @@ -371,7 +385,28 @@ update(NMDnsPlugin * plugin, for (i = 0; i < interfaces_len; i++) { InterfaceConfig *ic = g_hash_table_lookup(interfaces, GINT_TO_POINTER(interfaces_keys[i])); - prepare_one_interface(self, ic); + if (prepare_one_interface(self, ic)) + g_hash_table_add(priv->dirty_interfaces, GINT_TO_POINTER(ic->ifindex)); + else + g_hash_table_remove(priv->dirty_interfaces, GINT_TO_POINTER(ic->ifindex)); + } + + /* If we previously configured an ifindex with non-empty values in + * resolved, and the current update doesn't contain that interface, + * reset the resolved configuration for that ifindex. */ + g_hash_table_iter_init(&iter, priv->dirty_interfaces); + while (g_hash_table_iter_next(&iter, (gpointer *) &ifindex, NULL)) { + if (!g_hash_table_contains(interfaces, GINT_TO_POINTER(ifindex))) { + InterfaceConfig ic; + + _LOGT("clear previously configured ifindex %d", ifindex); + ic = (InterfaceConfig){ + .ifindex = ifindex, + .configs_lst_head = C_LIST_INIT(ic.configs_lst_head), + }; + prepare_one_interface(self, &ic); + g_hash_table_iter_remove(&iter); + } } send_updates(self); @@ -489,6 +524,8 @@ nm_dns_systemd_resolved_init(NMDnsSystemdResolved *self) priv->cancellable, get_name_owner_cb, self); + + priv->dirty_interfaces = g_hash_table_new(nm_direct_hash, NULL); } NMDnsPlugin * @@ -510,6 +547,7 @@ dispose(GObject *object) nm_clear_g_cancellable(&priv->cancellable); g_clear_object(&priv->dbus_connection); + nm_clear_pointer(&priv->dirty_interfaces, g_hash_table_unref); G_OBJECT_CLASS(nm_dns_systemd_resolved_parent_class)->dispose(object); } |