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
This commit is contained in:
@@ -51,6 +51,7 @@ typedef struct {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
GDBusConnection *dbus_connection;
|
GDBusConnection *dbus_connection;
|
||||||
|
GHashTable * dirty_interfaces;
|
||||||
GCancellable * cancellable;
|
GCancellable * cancellable;
|
||||||
CList request_queue_lst_head;
|
CList request_queue_lst_head;
|
||||||
guint name_owner_changed_id;
|
guint name_owner_changed_id;
|
||||||
@@ -134,7 +135,7 @@ call_done(GObject *source, GAsyncResult *r, gpointer user_data)
|
|||||||
priv->send_updates_warn_ratelimited = FALSE;
|
priv->send_updates_warn_ratelimited = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static gboolean
|
||||||
update_add_ip_config(NMDnsSystemdResolved *self,
|
update_add_ip_config(NMDnsSystemdResolved *self,
|
||||||
GVariantBuilder * dns,
|
GVariantBuilder * dns,
|
||||||
GVariantBuilder * domains,
|
GVariantBuilder * domains,
|
||||||
@@ -146,12 +147,13 @@ update_add_ip_config(NMDnsSystemdResolved *self,
|
|||||||
gboolean is_routing;
|
gboolean is_routing;
|
||||||
const char **iter;
|
const char **iter;
|
||||||
const char * domain;
|
const char * domain;
|
||||||
|
gboolean has_config = FALSE;
|
||||||
|
|
||||||
addr_family = nm_ip_config_get_addr_family(data->ip_config);
|
addr_family = nm_ip_config_get_addr_family(data->ip_config);
|
||||||
addr_size = nm_utils_addr_family_to_size(addr_family);
|
addr_size = nm_utils_addr_family_to_size(addr_family);
|
||||||
|
|
||||||
if (!data->domains.search || !data->domains.search[0])
|
if (!data->domains.search || !data->domains.search[0])
|
||||||
return;
|
return FALSE;
|
||||||
|
|
||||||
n = nm_ip_config_get_num_nameservers(data->ip_config);
|
n = nm_ip_config_get_num_nameservers(data->ip_config);
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
@@ -164,12 +166,16 @@ update_add_ip_config(NMDnsSystemdResolved *self,
|
|||||||
addr_size,
|
addr_size,
|
||||||
1));
|
1));
|
||||||
g_variant_builder_close(dns);
|
g_variant_builder_close(dns);
|
||||||
|
has_config = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (iter = data->domains.search; *iter; iter++) {
|
for (iter = data->domains.search; *iter; iter++) {
|
||||||
domain = nm_utils_parse_dns_domain(*iter, &is_routing);
|
domain = nm_utils_parse_dns_domain(*iter, &is_routing);
|
||||||
g_variant_builder_add(domains, "(sb)", domain[0] ? domain : ".", is_routing);
|
g_variant_builder_add(domains, "(sb)", domain[0] ? domain : ".", is_routing);
|
||||||
|
has_config = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return has_config;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -183,7 +189,7 @@ free_pending_updates(NMDnsSystemdResolved *self)
|
|||||||
_request_item_free(request_item);
|
_request_item_free(request_item);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static gboolean
|
||||||
prepare_one_interface(NMDnsSystemdResolved *self, InterfaceConfig *ic)
|
prepare_one_interface(NMDnsSystemdResolved *self, InterfaceConfig *ic)
|
||||||
{
|
{
|
||||||
NMDnsSystemdResolvedPrivate *priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE(self);
|
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;
|
NMSettingConnectionMdns mdns = NM_SETTING_CONNECTION_MDNS_DEFAULT;
|
||||||
NMSettingConnectionLlmnr llmnr = NM_SETTING_CONNECTION_LLMNR_DEFAULT;
|
NMSettingConnectionLlmnr llmnr = NM_SETTING_CONNECTION_LLMNR_DEFAULT;
|
||||||
const char * mdns_arg = NULL, *llmnr_arg = NULL;
|
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_init(&dns, G_VARIANT_TYPE("(ia(iay))"));
|
||||||
g_variant_builder_add(&dns, "i", ic->ifindex);
|
g_variant_builder_add(&dns, "i", ic->ifindex);
|
||||||
@@ -205,7 +212,7 @@ prepare_one_interface(NMDnsSystemdResolved *self, InterfaceConfig *ic)
|
|||||||
NMDnsIPConfigData *data = elem->data;
|
NMDnsIPConfigData *data = elem->data;
|
||||||
NMIPConfig * ip_config = data->ip_config;
|
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)) {
|
if (NM_IS_IP4_CONFIG(ip_config)) {
|
||||||
mdns = NM_MAX(mdns, nm_ip4_config_mdns_get(NM_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);
|
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, "SetLinkDNS", g_variant_builder_end(&dns));
|
||||||
_request_item_append(&priv->request_queue_lst_head,
|
_request_item_append(&priv->request_queue_lst_head,
|
||||||
"SetLinkDomains",
|
"SetLinkDomains",
|
||||||
@@ -258,6 +268,8 @@ prepare_one_interface(NMDnsSystemdResolved *self, InterfaceConfig *ic)
|
|||||||
_request_item_append(&priv->request_queue_lst_head,
|
_request_item_append(&priv->request_queue_lst_head,
|
||||||
"SetLinkLLMNR",
|
"SetLinkLLMNR",
|
||||||
g_variant_new("(is)", ic->ifindex, llmnr_arg ?: ""));
|
g_variant_new("(is)", ic->ifindex, llmnr_arg ?: ""));
|
||||||
|
|
||||||
|
return has_config;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -336,19 +348,21 @@ update(NMDnsPlugin * plugin,
|
|||||||
const char * hostname,
|
const char * hostname,
|
||||||
GError ** error)
|
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_unref_hashtable GHashTable *interfaces = NULL;
|
||||||
gs_free gpointer * interfaces_keys = NULL;
|
gs_free gpointer * interfaces_keys = NULL;
|
||||||
guint interfaces_len;
|
guint interfaces_len;
|
||||||
guint i;
|
int ifindex;
|
||||||
NMDnsIPConfigData *ip_data;
|
NMDnsIPConfigData *ip_data;
|
||||||
|
GHashTableIter iter;
|
||||||
|
guint i;
|
||||||
|
|
||||||
interfaces =
|
interfaces =
|
||||||
g_hash_table_new_full(nm_direct_hash, NULL, NULL, (GDestroyNotify) _interface_config_free);
|
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) {
|
c_list_for_each_entry (ip_data, ip_config_lst_head, ip_config_lst) {
|
||||||
InterfaceConfig *ic = NULL;
|
InterfaceConfig *ic = NULL;
|
||||||
int ifindex;
|
|
||||||
|
|
||||||
ifindex = ip_data->data->ifindex;
|
ifindex = ip_data->data->ifindex;
|
||||||
nm_assert(ifindex == nm_ip_config_get_ifindex(ip_data->ip_config));
|
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++) {
|
for (i = 0; i < interfaces_len; i++) {
|
||||||
InterfaceConfig *ic = g_hash_table_lookup(interfaces, GINT_TO_POINTER(interfaces_keys[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);
|
send_updates(self);
|
||||||
@@ -489,6 +524,8 @@ nm_dns_systemd_resolved_init(NMDnsSystemdResolved *self)
|
|||||||
priv->cancellable,
|
priv->cancellable,
|
||||||
get_name_owner_cb,
|
get_name_owner_cb,
|
||||||
self);
|
self);
|
||||||
|
|
||||||
|
priv->dirty_interfaces = g_hash_table_new(nm_direct_hash, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
NMDnsPlugin *
|
NMDnsPlugin *
|
||||||
@@ -510,6 +547,7 @@ dispose(GObject *object)
|
|||||||
nm_clear_g_cancellable(&priv->cancellable);
|
nm_clear_g_cancellable(&priv->cancellable);
|
||||||
|
|
||||||
g_clear_object(&priv->dbus_connection);
|
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);
|
G_OBJECT_CLASS(nm_dns_systemd_resolved_parent_class)->dispose(object);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user