summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBeniamino Galvani <bgalvani@redhat.com>2021-06-10 18:10:11 +0200
committerBeniamino Galvani <bgalvani@redhat.com>2021-06-10 18:10:11 +0200
commit08d9341b0c5eb5000dfa57c1371094ff3a707dcd (patch)
treeb19bbe8a98f6137e86a344f5061bb1404588e1eb
parentf8624ea2e5dbe993645d9ea6c8ae68e8dd43d299 (diff)
parentcdc1e9ecff0b3fef3c6e64f666c386a07c09310f (diff)
downloadNetworkManager-08d9341b0c5eb5000dfa57c1371094ff3a707dcd.tar.gz
merge: branch 'bg/dns-update-on-sigusr1'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/832 (cherry picked from commit a3306d538c7aa3a8040c11a029578ca71f9f11ef)
-rw-r--r--clients/cli/connections.c43
-rw-r--r--clients/cli/general.c58
-rw-r--r--man/NetworkManager.xml14
-rw-r--r--man/nmcli.xml61
-rw-r--r--shared/nm-glib-aux/nm-dbus-aux.c113
-rw-r--r--shared/nm-glib-aux/nm-dbus-aux.h16
-rw-r--r--src/core/dns/nm-dns-manager.c14
7 files changed, 274 insertions, 45 deletions
diff --git a/clients/cli/connections.c b/clients/cli/connections.c
index ee7b8fbbe9..fe4f8855cb 100644
--- a/clients/cli/connections.c
+++ b/clients/cli/connections.c
@@ -19,6 +19,7 @@
#include "nm-vpn-helpers.h"
#include "nm-meta-setting-access.h"
#include "nm-secret-agent-simple.h"
+#include "nm-glib-aux/nm-dbus-aux.h"
#include "utils.h"
#include "common.h"
@@ -9184,28 +9185,42 @@ do_connection_monitor(const NMCCommand *cmd, NmCli *nmc, int argc, const char *c
}
static void
-do_connection_reload(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *argv)
+connection_reload_cb(GObject *source, GAsyncResult *result, gpointer user_data)
{
- gs_unref_variant GVariant *result = NULL;
- gs_free_error GError *error = NULL;
-
- next_arg(nmc, &argc, &argv, NULL);
- if (nmc->complete)
- return;
+ NmCli * nmc = user_data;
+ gs_free_error GError *error = NULL;
+ gs_unref_variant GVariant *ret = NULL;
- result = nmc_dbus_call_sync(nmc,
- "/org/freedesktop/NetworkManager/Settings",
- "org.freedesktop.NetworkManager.Settings",
- "ReloadConnections",
- g_variant_new("()"),
- G_VARIANT_TYPE("(b)"),
- &error);
+ ret = nm_dbus_call_finish(result, &error);
if (error) {
g_string_printf(nmc->return_text,
_("Error: failed to reload connections: %s."),
nmc_error_get_simple_message(error));
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
}
+
+ quit();
+}
+
+static void
+do_connection_reload(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *argv)
+{
+ next_arg(nmc, &argc, &argv, NULL);
+ if (nmc->complete)
+ return;
+
+ nmc->should_wait++;
+ nm_dbus_call(G_BUS_TYPE_SYSTEM,
+ NM_DBUS_SERVICE,
+ NM_DBUS_PATH_SETTINGS,
+ NM_DBUS_INTERFACE_SETTINGS,
+ "ReloadConnections",
+ g_variant_new("()"),
+ G_VARIANT_TYPE("(b)"),
+ NULL,
+ (nmc->timeout == -1 ? 90 : nmc->timeout) * 1000,
+ connection_reload_cb,
+ nmc);
}
static void
diff --git a/clients/cli/general.c b/clients/cli/general.c
index 1dae57e116..b1182709f7 100644
--- a/clients/cli/general.c
+++ b/clients/cli/general.c
@@ -10,6 +10,7 @@
#include "nm-libnm-core-intern/nm-common-macros.h"
#include "nm-client-utils.h"
+#include "nm-glib-aux/nm-dbus-aux.h"
#include "polkit-agent.h"
#include "utils.h"
@@ -344,7 +345,8 @@ usage_general_reload(void)
" can be reloaded through 'nmcli connection reload' instead.\n"
"\n"
" 'dns-rc' Update DNS configuration, which usually involves writing\n"
- " /etc/resolv.conf anew.\n"
+ " /etc/resolv.conf anew. This is equivalent to sending the\n"
+ " SIGUSR1 signal to the NetworkManager process.\n"
"\n"
" 'dns-full' Restart the DNS plugin. This is for example useful when\n"
" using dnsmasq plugin, which uses additional configuration\n"
@@ -599,14 +601,30 @@ show_nm_permissions(NmCli *nmc)
}
static void
+reload_cb(GObject *source, GAsyncResult *result, gpointer user_data)
+{
+ NmCli * nmc = user_data;
+ gs_free_error GError *error = NULL;
+ gs_unref_variant GVariant *ret = NULL;
+
+ ret = nm_dbus_call_finish(result, &error);
+ if (error) {
+ g_string_printf(nmc->return_text,
+ _("Error: failed to reload: %s"),
+ nmc_error_get_simple_message(error));
+ nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
+ }
+
+ quit();
+}
+
+static void
do_general_reload(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *argv)
{
- gs_unref_variant GVariant *result = NULL;
- gs_free_error GError *error = NULL;
- gs_free const char ** values = NULL;
- gs_free char * err_token = NULL;
- gs_free char * joined = NULL;
- int flags = 0;
+ gs_free const char **values = NULL;
+ gs_free char * err_token = NULL;
+ gs_free char * joined = NULL;
+ int flags = 0;
next_arg(nmc, &argc, &argv, NULL);
@@ -649,20 +667,18 @@ do_general_reload(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const
return;
}
- result = nmc_dbus_call_sync(nmc,
- "/org/freedesktop/NetworkManager",
- "org.freedesktop.NetworkManager",
- "Reload",
- g_variant_new("(u)", flags),
- G_VARIANT_TYPE("()"),
- &error);
-
- if (error) {
- g_string_printf(nmc->return_text,
- _("Error: failed to reload: %s"),
- nmc_error_get_simple_message(error));
- nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
- }
+ nmc->should_wait++;
+ nm_dbus_call(G_BUS_TYPE_SYSTEM,
+ NM_DBUS_SERVICE,
+ NM_DBUS_PATH,
+ NM_DBUS_INTERFACE,
+ "Reload",
+ g_variant_new("(u)", flags),
+ G_VARIANT_TYPE("()"),
+ NULL,
+ (nmc->timeout == -1 ? 90 : nmc->timeout) * 1000,
+ reload_cb,
+ nmc);
}
static void
diff --git a/man/NetworkManager.xml b/man/NetworkManager.xml
index e2ac82547c..1c6b240ce0 100644
--- a/man/NetworkManager.xml
+++ b/man/NetworkManager.xml
@@ -475,9 +475,17 @@
<varlistentry>
<term><varname>SIGUSR1</varname></term>
<listitem><para>
- The signal forces a rewrite of DNS configuration. Contrary to
- SIGHUP, this does not restart the DNS plugin and will not interrupt
- name resolution.
+ The signal forces a rewrite of DNS configuration. Contrary
+ to SIGHUP, this does not restart the DNS plugin and will not
+ interrupt name resolution.
+
+ When NetworkManager is not managing DNS, the signal forces
+ a restart of operations that depend on the DNS
+ configuration (like the resolution of the system hostname
+ via reverse DNS, or the resolution of WireGuard peers);
+ therefore, it can be used to tell NetworkManager that the
+ content of resolv.conf was changed externally.
+
In the future, further actions may be added. A SIGUSR1
means to write out data like resolv.conf, or refresh a cache.
It is a subset of what is done for SIGHUP without reloading
diff --git a/man/nmcli.xml b/man/nmcli.xml
index b0665efd69..bc72c3110b 100644
--- a/man/nmcli.xml
+++ b/man/nmcli.xml
@@ -356,6 +356,7 @@
<arg choice='plain'><command>hostname</command></arg>
<arg choice='plain'><command>permissions</command></arg>
<arg choice='plain'><command>logging</command></arg>
+ <arg choice='plain'><command>reload</command></arg>
</group>
<arg rep='repeat'><replaceable>ARGUMENTS</replaceable></arg>
</cmdsynopsis>
@@ -419,6 +420,66 @@
for available level and domain values.</para>
</listitem>
</varlistentry>
+
+ <varlistentry>
+ <term>
+ <command>reload</command>
+ <arg rep='repeat'><replaceable>flags</replaceable></arg>
+ </term>
+
+ <listitem>
+ <para>
+ Reload NetworkManager's configuration and perform certain
+ updates, like flushing caches or rewriting external state to
+ disk. This is similar to sending SIGHUP to NetworkManager
+ but it allows for more fine-grained control over what to
+ reload through the flags argument. It also allows non-root
+ access via PolicyKit and contrary to signals it is
+ synchronous. Available flags are:
+ </para>
+ <variablelist>
+ <varlistentry>
+ <term><option>conf</option></term>
+ <listitem><para>
+ Reload the NetworkManager.conf configuration from
+ disk. Note that this does not include connections, which
+ can be reloaded through <command>nmcli connection
+ reload</command> instead.
+ </para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>dns-rc</option></term>
+ <listitem><para>
+ Update DNS configuration, which usually involves writing
+ /etc/resolv.conf anew. This is equivalent to sending the
+ SIGUSR1 signal to the NetworkManager process.
+ </para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>dns-full</option></term>
+ <listitem><para>
+ Restart the DNS plugin. This is for example useful when
+ using dnsmasq plugin, which uses additional
+ configuration in
+ <filename>/etc/NetworkManager/dnsmasq.d</filename>. If
+ you edit those files, you can restart the DNS
+ plugin. This action shortly interrupts name resolution.
+ </para></listitem>
+ </varlistentry>
+ </variablelist>
+ <para>
+ With no flags, everything that is supported is reloaded,
+ which is identical to sending a SIGHUP. See
+ <citerefentry>
+ <refentrytitle>NetworkManager</refentrytitle>
+ <manvolnum>8</manvolnum>
+ </citerefentry>
+ for more details about signals.
+ </para>
+ </listitem>
+ </varlistentry>
</variablelist>
</refsect1>
diff --git a/shared/nm-glib-aux/nm-dbus-aux.c b/shared/nm-glib-aux/nm-dbus-aux.c
index ec409ff1fa..9fb02a3fcd 100644
--- a/shared/nm-glib-aux/nm-dbus-aux.c
+++ b/shared/nm-glib-aux/nm-dbus-aux.c
@@ -268,6 +268,119 @@ nm_dbus_connection_call_finish_variant_strip_dbus_error_cb(GObject * source,
/*****************************************************************************/
+typedef struct {
+ char * bus_name;
+ char * object_path;
+ char * interface_name;
+ char * method_name;
+ GVariant * parameters;
+ GDBusConnection * connection;
+ const GVariantType *reply_type;
+ int timeout_msec;
+} CallAsyncInfo;
+
+static void
+call_async_info_destroy(CallAsyncInfo *info)
+{
+ g_free(info->bus_name);
+ g_free(info->object_path);
+ g_free(info->interface_name);
+ g_free(info->method_name);
+ g_variant_unref(info->parameters);
+ nm_g_object_unref(info->connection);
+ g_free(info);
+}
+
+static void
+call_cb(GObject *source, GAsyncResult *result, gpointer user_data)
+{
+ gs_unref_object GTask *task = user_data;
+ GError * error = NULL;
+ GVariant * ret;
+
+ ret = g_dbus_connection_call_finish(G_DBUS_CONNECTION(source), result, &error);
+ if (!ret) {
+ g_task_return_error(task, error);
+ return;
+ }
+
+ g_task_return_pointer(task, ret, (GDestroyNotify) g_variant_unref);
+}
+
+static void
+call_bus_get_cb(GObject *source, GAsyncResult *result, gpointer user_data)
+{
+ gs_unref_object GTask *task = user_data;
+ GCancellable * cancellable;
+ CallAsyncInfo * info;
+ GError * error = NULL;
+
+ info = g_task_get_task_data(task);
+ info->connection = g_bus_get_finish(result, &error);
+ cancellable = g_task_get_cancellable(task);
+
+ if (!info->connection) {
+ g_task_return_error(task, g_steal_pointer(&error));
+ return;
+ }
+
+ g_dbus_connection_call(info->connection,
+ info->bus_name,
+ info->object_path,
+ info->interface_name,
+ info->method_name,
+ info->parameters,
+ info->reply_type,
+ G_DBUS_CALL_FLAGS_NONE,
+ info->timeout_msec,
+ cancellable,
+ call_cb,
+ g_steal_pointer(&task));
+}
+
+void
+nm_dbus_call(GBusType bus_type,
+ const char * bus_name,
+ const char * object_path,
+ const char * interface_name,
+ const char * method_name,
+ GVariant * parameters,
+ const GVariantType *reply_type,
+ GCancellable * cancellable,
+ int timeout_msec,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GTask * task;
+ CallAsyncInfo *info;
+
+ info = g_new(CallAsyncInfo, 1);
+ *info = (CallAsyncInfo){
+ .bus_name = g_strdup(bus_name),
+ .object_path = g_strdup(object_path),
+ .interface_name = g_strdup(interface_name),
+ .method_name = g_strdup(method_name),
+ .parameters = g_variant_ref_sink(parameters),
+ .reply_type = reply_type,
+ .timeout_msec = timeout_msec,
+ };
+
+ task = nm_g_task_new(NULL, cancellable, nm_dbus_call, callback, user_data);
+ g_task_set_task_data(task, info, (GDestroyNotify) call_async_info_destroy);
+
+ g_bus_get(bus_type, cancellable, call_bus_get_cb, task);
+}
+
+GVariant *
+nm_dbus_call_finish(GAsyncResult *result, GError **error)
+{
+ nm_assert(nm_g_task_is_valid(result, NULL, nm_dbus_call));
+
+ return g_task_propagate_pointer(G_TASK(result), error);
+}
+
+/*****************************************************************************/
+
gboolean
_nm_dbus_error_is(GError *error, ...)
{
diff --git a/shared/nm-glib-aux/nm-dbus-aux.h b/shared/nm-glib-aux/nm-dbus-aux.h
index 4e3ae22d82..c810708260 100644
--- a/shared/nm-glib-aux/nm-dbus-aux.h
+++ b/shared/nm-glib-aux/nm-dbus-aux.h
@@ -186,6 +186,22 @@ void nm_dbus_connection_call_finish_variant_strip_dbus_error_cb(GObject * so
/*****************************************************************************/
+void nm_dbus_call(GBusType bus_type,
+ const char * bus_name,
+ const char * object_path,
+ const char * interface_name,
+ const char * method_name,
+ GVariant * parameters,
+ const GVariantType *reply_type,
+ GCancellable * cancellable,
+ int timeout_msec,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GVariant *nm_dbus_call_finish(GAsyncResult *result, GError **error);
+
+/*****************************************************************************/
+
gboolean _nm_dbus_error_is(GError *error, ...) G_GNUC_NULL_TERMINATED;
#define nm_dbus_error_is(error, ...) \
diff --git a/src/core/dns/nm-dns-manager.c b/src/core/dns/nm-dns-manager.c
index f7c30fe34c..59c8898a03 100644
--- a/src/core/dns/nm-dns-manager.c
+++ b/src/core/dns/nm-dns-manager.c
@@ -1624,7 +1624,7 @@ _mgr_configs_data_clear(NMDnsManager *self)
/*****************************************************************************/
static gboolean
-update_dns(NMDnsManager *self, gboolean no_caching, GError **error)
+update_dns(NMDnsManager *self, gboolean no_caching, gboolean force_emit, GError **error)
{
NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE(self);
const char * nis_domain = NULL;
@@ -1816,7 +1816,7 @@ plugin_skip:;
}
/* signal that DNS resolution configs were changed */
- if ((do_update || caching) && result == SR_SUCCESS)
+ if ((do_update || caching || force_emit) && result == SR_SUCCESS)
g_signal_emit(self, signals[CONFIG_CHANGED], 0);
nm_clear_pointer(&priv->config_variant, g_variant_unref);
@@ -1924,7 +1924,7 @@ changed:
if (!priv->updates_queue) {
gs_free_error GError *error = NULL;
- if (!update_dns(self, FALSE, &error))
+ if (!update_dns(self, FALSE, FALSE, &error))
_LOGW("could not commit DNS changes: %s", error->message);
}
@@ -1965,7 +1965,7 @@ nm_dns_manager_set_hostname(NMDnsManager *self, const char *hostname, gboolean s
if (!priv->updates_queue) {
gs_free_error GError *error = NULL;
- if (!update_dns(self, FALSE, &error))
+ if (!update_dns(self, FALSE, FALSE, &error))
_LOGW("could not commit DNS changes: %s", error->message);
}
}
@@ -2012,7 +2012,7 @@ 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, FALSE, &error))
_LOGW("could not commit DNS changes: %s", error->message);
memset(priv->prev_hash, 0, sizeof(priv->prev_hash));
@@ -2038,7 +2038,7 @@ nm_dns_manager_stop(NMDnsManager *self)
if (priv->dns_touched && priv->plugin && NM_IS_DNS_DNSMASQ(priv->plugin)) {
gs_free_error GError *error = NULL;
- if (!update_dns(self, TRUE, &error))
+ if (!update_dns(self, TRUE, FALSE, &error))
_LOGW("could not commit DNS changes on shutdown: %s", error->message);
priv->dns_touched = FALSE;
@@ -2363,7 +2363,7 @@ config_changed_cb(NMConfig * config,
| NM_CONFIG_CHANGE_GLOBAL_DNS_CONFIG)) {
gs_free_error GError *error = NULL;
- if (!update_dns(self, FALSE, &error))
+ if (!update_dns(self, FALSE, TRUE, &error))
_LOGW("could not commit DNS changes: %s", error->message);
}
}