manager: add Reload() D-Bus command

Add new Reload D-Bus command to reload NetworkManager configuration.

For now, this is like sending SIGHUP to the process. There are several
advantages here:

  - it is guarded via PolicyKit authentication while signals
    can only be sent by root.

  - the user can wait for the reload to be complete instead of sending
    an asynchronous signal. For now, we operation completes after
    nm_config_reload() returns, but later we could delay the response
    further until specific parts are fully reloaded.

  - SIGHUP reloads everything including re-reading configuration from
    disk while SIGUSR1 reloads just certain parts such as writing out DNS
    configuration anew.
    Now, the Reload command has a flags argument which is more granular
    in selecting parts which are to be reloaded. For example, via
    signals the user can:

      1) send SIGUSR1: this writes out the DNS configuration to
         resolv.conf and possibly reloads other parts without
         re-reading configuration and without restarting the DNS plugin.
      2) send SIGHUP: this reloads configuration from disk,
         writes out resolv.conf and restarts the DNS plugin.

    There is no way, to only restart the DNS plugin without also reloading
    everything else.
This commit is contained in:
Thomas Haller 2016-05-30 15:42:44 +02:00
parent 8913585397
commit 1d0e0eeffd
15 changed files with 130 additions and 3 deletions

View File

@ -399,6 +399,7 @@ show_nm_status (NmCli *nmc, const char *pretty_header_name, const char *print_fl
#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN "org.freedesktop.NetworkManager.settings.modify.own"
#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME "org.freedesktop.NetworkManager.settings.modify.hostname"
#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS "org.freedesktop.NetworkManager.settings.modify.global-dns"
#define NM_AUTH_PERMISSION_RELOAD "org.freedesktop.NetworkManager.reload"
static const char *
permission_to_string (NMClientPermission perm)
@ -428,6 +429,8 @@ permission_to_string (NMClientPermission perm)
return NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME;
case NM_CLIENT_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS:
return NM_AUTH_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS;
case NM_CLIENT_PERMISSION_RELOAD:
return NM_AUTH_PERMISSION_RELOAD;
default:
return _("unknown");
}

View File

@ -7,6 +7,7 @@ Before=network.target @DISTRO_NETWORK_SERVICE@
[Service]
Type=dbus
BusName=org.freedesktop.NetworkManager
#ExecReload=/usr/bin/dbus-send --print-reply --system --type=method_call --dest=org.freedesktop.NetworkManager /org/freedesktop/NetworkManager org.freedesktop.NetworkManager.Reload uint32:0
ExecReload=/bin/kill -HUP $MAINPID
ExecStart=@sbindir@/NetworkManager --no-daemon
Restart=on-failure

View File

@ -3,6 +3,15 @@
<interface name="org.freedesktop.NetworkManager">
<annotation name="org.gtk.GDBus.C.Name" value="Manager"/>
<!--
Reload:
@flags: optional flags to specify which parts shall be reloaded. A default of zero
means to reload everything.
-->
<method name="Reload">
<arg name="flags" type="u" direction="in"/>
</method>
<!--
GetDevices:
@devices: List of object paths of network devices known to the system. This list does not include device placeholders (see GetAllDevices()).

View File

@ -185,6 +185,7 @@ GQuark nm_device_error_quark (void);
* enabled/disabled.
* @NM_MANAGER_ERROR_UNKNOWN_LOG_LEVEL: Unknown log level in SetLogging
* @NM_MANAGER_ERROR_UNKNOWN_LOG_DOMAIN: Unknown log domain in SetLogging
* @NM_MANAGER_ERROR_INVALID_ARGUMENTS: Invalid arguments for D-Bus request
*
* Errors related to the main "network management" interface of NetworkManager.
* These may be returned from #NMClient methods that invoke D-Bus operations on
@ -204,6 +205,7 @@ typedef enum {
NM_MANAGER_ERROR_ALREADY_ENABLED_OR_DISABLED, /*< nick=AlreadyEnabledOrDisabled >*/
NM_MANAGER_ERROR_UNKNOWN_LOG_LEVEL, /*< nick=UnknownLogLevel >*/
NM_MANAGER_ERROR_UNKNOWN_LOG_DOMAIN, /*< nick=UnknownLogDomain >*/
NM_MANAGER_ERROR_INVALID_ARGUMENTS, /*< nick=InvalidArguments >*/
} NMManagerError;
GQuark nm_manager_error_quark (void);

View File

@ -220,6 +220,7 @@ register_properties (NMClient *client)
#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN "org.freedesktop.NetworkManager.settings.modify.own"
#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME "org.freedesktop.NetworkManager.settings.modify.hostname"
#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS "org.freedesktop.NetworkManager.settings.modify.global-dns"
#define NM_AUTH_PERMISSION_RELOAD "org.freedesktop.NetworkManager.reload"
static NMClientPermission
nm_permission_to_client (const char *nm)
@ -248,6 +249,8 @@ nm_permission_to_client (const char *nm)
return NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME;
else if (!strcmp (nm, NM_AUTH_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS))
return NM_CLIENT_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS;
else if (!strcmp (nm, NM_AUTH_PERMISSION_RELOAD))
return NM_CLIENT_PERMISSION_RELOAD;
return NM_CLIENT_PERMISSION_NONE;
}

View File

@ -86,6 +86,8 @@ G_BEGIN_DECLS
* persistent hostname can be changed
* @NM_CLIENT_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS: modify persistent global
* DNS configuration
* @NM_CLIENT_PERMISSION_RELOAD: controls access to Reload.
* persistent hostname can be changed
* @NM_CLIENT_PERMISSION_LAST: a reserved boundary value
*
* #NMClientPermission values indicate various permissions that NetworkManager
@ -105,8 +107,9 @@ typedef enum {
NM_CLIENT_PERMISSION_SETTINGS_MODIFY_OWN = 10,
NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME = 11,
NM_CLIENT_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS = 12,
NM_CLIENT_PERMISSION_RELOAD = 13,
NM_CLIENT_PERMISSION_LAST = 12,
NM_CLIENT_PERMISSION_LAST = 13,
} NMClientPermission;
/**

View File

@ -94,6 +94,7 @@ G_BEGIN_DECLS
* persistent hostname can be changed
* @NM_CLIENT_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS: modify persistent global
* DNS configuration
* @NM_CLIENT_PERMISSION_RELOAD: controls access to Reload.
* @NM_CLIENT_PERMISSION_LAST: a reserved boundary value
*
* #NMClientPermission values indicate various permissions that NetworkManager
@ -113,8 +114,9 @@ typedef enum {
NM_CLIENT_PERMISSION_SETTINGS_MODIFY_OWN = 10,
NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME = 11,
NM_CLIENT_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS = 12,
NM_CLIENT_PERMISSION_RELOAD = 13,
NM_CLIENT_PERMISSION_LAST = 12,
NM_CLIENT_PERMISSION_LAST = 13,
} NMClientPermission;
/**

View File

@ -214,6 +214,7 @@ init_dbus (NMObject *object)
#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN "org.freedesktop.NetworkManager.settings.modify.own"
#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME "org.freedesktop.NetworkManager.settings.modify.hostname"
#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS "org.freedesktop.NetworkManager.settings.modify.global-dns"
#define NM_AUTH_PERMISSION_RELOAD "org.freedesktop.NetworkManager.reload"
static NMClientPermission
nm_permission_to_client (const char *nm)
@ -242,6 +243,8 @@ nm_permission_to_client (const char *nm)
return NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME;
else if (!strcmp (nm, NM_AUTH_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS))
return NM_CLIENT_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS;
else if (!strcmp (nm, NM_AUTH_PERMISSION_RELOAD))
return NM_CLIENT_PERMISSION_RELOAD;
return NM_CLIENT_PERMISSION_NONE;
}

View File

@ -140,7 +140,8 @@ org.freedesktop.NetworkManager.wifi.share.protected yes
org.freedesktop.NetworkManager.wifi.share.open yes
org.freedesktop.NetworkManager.settings.modify.system yes
org.freedesktop.NetworkManager.settings.modify.own yes
org.freedesktop.NetworkManager.settings.modify.hostname auth</screen>
org.freedesktop.NetworkManager.settings.modify.hostname auth
org.freedesktop.NetworkManager.reload no</screen>
<para>
This command shows configured polkit permissions for various NetworkManager
operations. These permissions or actions (using polkit language) are configured

View File

@ -1,3 +1,4 @@
data/NetworkManager.service.in
examples/python/NetworkManager.py
examples/python/systray/eggtrayicon.c
policy/org.freedesktop.NetworkManager.policy.in

View File

@ -18,6 +18,16 @@
</defaults>
</action>
<action id="org.freedesktop.NetworkManager.reload">
<_description>Reload NetworkManager configuration</_description>
<_message>System policy prevents reloading NetworkManager</_message>
<defaults>
<allow_any>auth_admin_keep</allow_any>
<allow_inactive>auth_admin_keep</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
</action>
<action id="org.freedesktop.NetworkManager.sleep-wake">
<_description>Put NetworkManager to sleep or wake it up (should only be used by system power management)</_description>
<_message>System policy prevents putting NetworkManager to sleep or waking it up</_message>

View File

@ -53,6 +53,7 @@ typedef struct {
#define NM_AUDIT_OP_CONN_DEACTIVATE "connection-deactivate"
#define NM_AUDIT_OP_CONN_CLEAR_SECRETS "connection-clear-secrets"
#define NM_AUDIT_OP_RELOAD "reload"
#define NM_AUDIT_OP_SLEEP_CONTROL "sleep-control"
#define NM_AUDIT_OP_NET_CONTROL "networking-control"
#define NM_AUDIT_OP_RADIO_CONTROL "radio-control"

View File

@ -36,6 +36,7 @@
#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN "org.freedesktop.NetworkManager.settings.modify.own"
#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME "org.freedesktop.NetworkManager.settings.modify.hostname"
#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS "org.freedesktop.NetworkManager.settings.modify.global-dns"
#define NM_AUTH_PERMISSION_RELOAD "org.freedesktop.NetworkManager.reload"
typedef struct NMAuthChain NMAuthChain;

View File

@ -464,6 +464,89 @@ _config_changed_cb (NMConfig *config, NMConfigData *config_data, NMConfigChangeF
_notify (self, PROP_GLOBAL_DNS_CONFIGURATION);
}
static void
_reload_auth_cb (NMAuthChain *chain,
GError *error,
GDBusMethodInvocation *context,
gpointer user_data)
{
NMManager *self = NM_MANAGER (user_data);
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
GError *ret_error = NULL;
NMAuthCallResult result;
guint32 flags;
NMAuthSubject *subject;
char s_buf[60];
g_assert (context);
priv->auth_chains = g_slist_remove (priv->auth_chains, chain);
flags = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, "flags"));
subject = nm_auth_chain_get_subject (chain);
result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_RELOAD);
if (error) {
_LOGD (LOGD_CORE, "Reload request failed: %s", error->message);
ret_error = g_error_new (NM_MANAGER_ERROR,
NM_MANAGER_ERROR_PERMISSION_DENIED,
"Reload request failed: %s",
error->message);
} else if (result != NM_AUTH_CALL_RESULT_YES) {
ret_error = g_error_new_literal (NM_MANAGER_ERROR,
NM_MANAGER_ERROR_PERMISSION_DENIED,
"Not authorized to reload configuration");
} else if (flags != 0) {
ret_error = g_error_new_literal (NM_MANAGER_ERROR,
NM_MANAGER_ERROR_INVALID_ARGUMENTS,
"Invalid flags for reload");
}
nm_audit_log_control_op (NM_AUDIT_OP_RELOAD,
nm_sprintf_buf (s_buf, "%u", flags),
ret_error == NULL, subject,
ret_error ? ret_error->message : NULL);
if (ret_error) {
g_dbus_method_invocation_take_error (context, ret_error);
goto out;
}
nm_config_reload (priv->config, NM_CONFIG_CHANGE_CAUSE_SIGHUP);
g_dbus_method_invocation_return_value (context, NULL);
out:
nm_auth_chain_unref (chain);
}
static void
impl_manager_reload (NMManager *self,
GDBusMethodInvocation *context,
guint32 flags)
{
NMManagerPrivate *priv;
NMAuthChain *chain;
GError *error = NULL;
g_return_if_fail (NM_IS_MANAGER (self));
priv = NM_MANAGER_GET_PRIVATE (self);
chain = nm_auth_chain_new_context (context, _reload_auth_cb, self);
if (!chain) {
error = g_error_new_literal (NM_MANAGER_ERROR,
NM_MANAGER_ERROR_PERMISSION_DENIED,
"Unable to authenticate request");
g_dbus_method_invocation_take_error (context, error);
return;
}
priv->auth_chains = g_slist_append (priv->auth_chains, chain);
nm_auth_chain_set_data (chain, "flags", GUINT_TO_POINTER (flags), NULL);
nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_RELOAD, TRUE);
}
/************************************************************************/
static NMDevice *
@ -4312,6 +4395,7 @@ get_permissions_done_cb (NMAuthChain *chain,
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_RELOAD);
g_dbus_method_invocation_return_value (context,
g_variant_new ("(a{ss})", &results));
@ -4349,6 +4433,7 @@ impl_manager_get_permissions (NMManager *self,
nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM, FALSE);
nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN, FALSE);
nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME, FALSE);
nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_RELOAD, FALSE);
}
static void
@ -5818,6 +5903,7 @@ nm_manager_class_init (NMManagerClass *manager_class)
nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (manager_class),
NMDBUS_TYPE_MANAGER_SKELETON,
"Reload", impl_manager_reload,
"GetDevices", impl_manager_get_devices,
"GetAllDevices", impl_manager_get_all_devices,
"GetDeviceByIpIface", impl_manager_get_device_by_ip_iface,

View File

@ -785,6 +785,7 @@ class NetworkManager(ExportedObj):
"org.freedesktop.NetworkManager.settings.modify.system": "yes",
"org.freedesktop.NetworkManager.settings.modify.hostname": "yes",
"org.freedesktop.NetworkManager.settings.modify.global-dns": "no",
"org.freedesktop.NetworkManager.reload": "no",
}
@dbus.service.method(dbus_interface=IFACE_NM, in_signature='ss', out_signature='')