From 8d6dd4856c27cd9b6f79fcc9d69cfbc7d7472bb4 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 26 Nov 2020 13:49:35 +0100 Subject: [PATCH] dns: preserve DNS settings for systemd-resolved to resend When the DNS settings change, we update the request_queue_lst_head list, with all the requests we want to send. Then, send_updates() will try to send it. It might not do it right away, if resolved is not on the bus or the D-Bus connection is not fully inialized (meaning, we don't know the name owner yet). In those cases, we would keep the list of requests, and send them later. However, when sending them, we would also forget about the configuration. That means, if you restart systemd-resolved, then the daemon drops off the bus and reappears. I think that systemd-resolved in fact persists the configuration during restart. So, usually the settings are still the same after restart. However, we should do better here: if the service appears, we should send the settings again. This means to not forget the requests after we send them once -- at least, until a new update replaces them. (cherry picked from commit 4fc44952f7fd44771a1c006529cea6db937290ec) (cherry picked from commit 3f16b988a49a731eb0fd94d2f96b0fc505cd62da) (cherry picked from commit cb8737e5a523838fe0bf53008a463d06836e6844) --- src/dns/nm-dns-systemd-resolved.c | 37 +++++++++++++++++-------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/src/dns/nm-dns-systemd-resolved.c b/src/dns/nm-dns-systemd-resolved.c index de70a60d0f..fe8cd9c2eb 100644 --- a/src/dns/nm-dns-systemd-resolved.c +++ b/src/dns/nm-dns-systemd-resolved.c @@ -64,6 +64,7 @@ typedef struct { bool try_start_blocked:1; bool dbus_has_owner:1; bool dbus_initied:1; + bool request_queue_to_send:1; } NMDnsSystemdResolvedPrivate; struct _NMDnsSystemdResolved { @@ -132,18 +133,17 @@ call_done (GObject *source, GAsyncResult *r, gpointer user_data) RequestItem *request_item; NMLogLevel log_level; - request_item = user_data; - v = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), r, &error); if (nm_utils_error_is_cancelled (error)) - goto out; + return; + request_item = user_data; self = request_item->self; priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE (self); if (v) { priv->send_updates_warn_ratelimited = FALSE; - goto out; + return; } log_level = LOGL_DEBUG; @@ -158,9 +158,6 @@ call_done (GObject *source, GAsyncResult *r, gpointer user_data) request_item->operation, request_item->ifindex, error->message); - -out: - _request_item_free (request_item); } static gboolean @@ -327,7 +324,7 @@ send_updates (NMDnsSystemdResolved *self) NMDnsSystemdResolvedPrivate *priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE (self); RequestItem *request_item; - if (c_list_is_empty (&priv->request_queue_lst_head)) { + if (!priv->request_queue_to_send) { /* nothing to do. */ return; } @@ -357,16 +354,21 @@ send_updates (NMDnsSystemdResolved *self) return; } - _LOGT ("send-updates: start %lu requests", - c_list_length (&priv->request_queue_lst_head)); - nm_clear_g_cancellable (&priv->cancellable); + if (c_list_is_empty (&priv->request_queue_lst_head)) { + _LOGT ("send-updates: no requests to send"); + priv->request_queue_to_send = FALSE; + return; + } + + _LOGT ("send-updates: start %lu requests", c_list_length (&priv->request_queue_lst_head)); + priv->cancellable = g_cancellable_new (); - while ((request_item = c_list_first_entry (&priv->request_queue_lst_head, - RequestItem, - request_queue_lst))) { + priv->request_queue_to_send = FALSE; + + c_list_for_each_entry (request_item, &priv->request_queue_lst_head, request_queue_lst) { /* Above we explicitly call "StartServiceByName" trying to avoid D-Bus activating systmd-resolved * multiple times. There is still a race, were we might hit this line although actually * the service just quit this very moment. In that case, we would try to D-Bus activate the @@ -387,7 +389,6 @@ send_updates (NMDnsSystemdResolved *self) priv->cancellable, call_done, request_item); - c_list_unlink (&request_item->request_queue_lst); } } @@ -462,8 +463,8 @@ update (NMDnsPlugin *plugin, } } + priv->request_queue_to_send = TRUE; send_updates (self); - return TRUE; } @@ -483,8 +484,10 @@ name_owner_changed (NMDnsSystemdResolved *self, _LOGT ("D-Bus name for systemd-resolved has owner %s", owner); priv->dbus_has_owner = !!owner; - if (owner) + if (owner) { priv->try_start_blocked = FALSE; + priv->request_queue_to_send = TRUE; + } send_updates (self); }