merge: branch 'lr/reapply'

https://bugzilla.gnome.org/show_bug.cgi?id=758463
This commit is contained in:
Lubomir Rintel 2016-01-10 23:23:58 +01:00
commit 4059b253b7
10 changed files with 637 additions and 40 deletions

View file

@ -282,11 +282,12 @@ static void
usage (void)
{
g_printerr (_("Usage: nmcli device { COMMAND | help }\n\n"
"COMMAND := { status | show | connect | disconnect | delete | monitor | wifi | lldp }\n\n"
"COMMAND := { status | show | connect | reapply | disconnect | delete | monitor | wifi | lldp }\n\n"
" status\n\n"
" show [<ifname>]\n\n"
" set [ifname] <ifname> [autoconnect yes|no] [managed yes|no]\n\n"
" connect <ifname>\n\n"
" reapply <ifname> ...\n\n"
" disconnect <ifname> ...\n\n"
" delete <ifname> ...\n\n"
" monitor <ifname> ...\n\n"
@ -337,6 +338,17 @@ usage_device_connect (void)
"It will also consider connections that are not set to auto-connect.\n\n"));
}
static void
usage_device_reapply (void)
{
g_printerr (_("Usage: nmcli device reapply { ARGUMENTS | help }\n"
"\n"
"ARGUMENTS := <ifname> ...\n"
"\n"
"Attempts to update device with changes to the currently active connection\n"
"made since it was last applied.\n\n"));
}
static void
usage_device_disconnect (void)
{
@ -1813,6 +1825,116 @@ device_cb_info_finish (DeviceCbInfo *info, NMDevice *device)
quit ();
}
static void
reapply_device_cb (GObject *object, GAsyncResult *result, gpointer user_data)
{
NMDevice *device = NM_DEVICE (object);
DeviceCbInfo *info = (DeviceCbInfo *) user_data;
NmCli *nmc = info->nmc;
GError *error = NULL;
if (!nm_device_reapply_finish (device, result, &error)) {
g_string_printf (nmc->return_text, _("Error: not all connections reapplied."));
g_printerr (_("Error: Reapplying connection to device '%s' (%s) failed: %s\n"),
nm_device_get_iface (device),
nm_object_get_path (NM_OBJECT (device)),
error->message);
g_error_free (error);
nmc->return_value = NMC_RESULT_ERROR_DEV_DISCONNECT;
device_cb_info_finish (info, device);
} else {
if (nmc->print_output == NMC_PRINT_PRETTY)
nmc_terminal_erase_line ();
g_print (_("Connection successfully reapplied to device '%s'.\n"),
nm_device_get_iface (device));
device_cb_info_finish (info, device);
}
}
static NMCResultCode
do_device_reapply (NmCli *nmc, int argc, char **argv)
{
NMDevice **devices;
NMDevice *device;
DeviceCbInfo *info = NULL;
GSList *queue = NULL, *iter;
char **arg_arr = NULL;
char **arg_ptr = argv;
int arg_num = argc;
int i;
/* Set default timeout for reapply operation. */
if (nmc->timeout == -1)
nmc->timeout = 10;
if (argc == 0) {
if (nmc->ask) {
char *line = nmc_readline (PROMPT_INTERFACES);
nmc_string_to_arg_array (line, NULL, FALSE, &arg_arr, &arg_num);
g_free (line);
arg_ptr = arg_arr;
}
if (arg_num == 0) {
g_string_printf (nmc->return_text, _("Error: No interface specified."));
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
goto error;
}
}
devices = get_devices_sorted (nmc->client);
while (arg_num > 0) {
device = NULL;
for (i = 0; devices[i]; i++) {
if (!g_strcmp0 (nm_device_get_iface (devices[i]), *arg_ptr)) {
device = devices[i];
break;
}
}
if (device) {
if (!g_slist_find (queue, device))
queue = g_slist_prepend (queue, device);
else
g_printerr (_("Warning: argument '%s' is duplicated.\n"), *arg_ptr);
} else {
g_printerr (_("Error: Device '%s' not found.\n"), *arg_ptr);
g_string_printf (nmc->return_text, _("Error: not all devices found."));
nmc->return_value = NMC_RESULT_ERROR_NOT_FOUND;
}
/* Take next argument */
next_arg (&arg_num, &arg_ptr);
}
g_free (devices);
if (!queue) {
g_string_printf (nmc->return_text, _("Error: no valid device provided."));
nmc->return_value = NMC_RESULT_ERROR_NOT_FOUND;
goto error;
}
queue = g_slist_reverse (queue);
info = g_slice_new0 (DeviceCbInfo);
info->nmc = nmc;
nmc->nowait_flag = (nmc->timeout == 0);
nmc->should_wait = TRUE;
for (iter = queue; iter; iter = g_slist_next (iter)) {
device = iter->data;
info->queue = g_slist_prepend (info->queue, g_object_ref (device));
/* Now reapply the connection to the device */
nm_device_reapply_async (device, NULL, 0, NULL, reapply_device_cb, info);
}
error:
g_strfreev (arg_arr);
g_slist_free (queue);
return nmc->return_value;
}
static void
disconnect_device_cb (GObject *object, GAsyncResult *result, gpointer user_data)
{
@ -3593,6 +3715,13 @@ do_devices (NmCli *nmc, int argc, char **argv)
}
nmc->return_value = do_device_connect (nmc, argc-1, argv+1);
}
else if (matches (*argv, "reapply") == 0) {
if (nmc_arg_is_help (*(argv+1))) {
usage_device_reapply ();
goto usage_exit;
}
nmc->return_value = do_device_reapply (nmc, argc-1, argv+1);
}
else if (matches (*argv, "disconnect") == 0) {
if (nmc_arg_is_help (*(argv+1))) {
usage_device_disconnect ();

View file

@ -1419,7 +1419,7 @@ _nmcli()
;;
d|de|dev|devi|devic|device)
if [[ ${#words[@]} -eq 2 ]]; then
_nmcli_compl_COMMAND "$command" status show connect disconnect delete monitor wifi set lldp
_nmcli_compl_COMMAND "$command" status show connect reapply disconnect delete monitor wifi set lldp
elif [[ ${#words[@]} -gt 2 ]]; then
case "$command" in
s|st|sta|stat|statu|status)
@ -1433,6 +1433,7 @@ _nmcli()
_nmcli_compl_COMMAND_nl "${words[2]}" "$(_nmcli_dev_status DEVICE)"
fi
;;
r|re|rea|reap|reapp|reappl|reapply| \
d|di|dis|disc|disco|discon|disconn|disconne|disconnec|disconnect| \
de|del|dele|delet|delete| \
m|mo|mon|moni|monit|monito|monitor)

View file

@ -169,6 +169,27 @@
</tp:docstring>
</property>
<method name="Reapply">
<arg name="connection" type="a{sa{sv}}" direction="in">
<tp:docstring>
The effective connection settings and properties to use. If empty, the connection
settings from the connection that is active on the device will be used.
</tp:docstring>
</arg>
<arg name="flags" type="u" direction="in">
<tp:docstring>
Flags which would modify the behavior of the Reapply call.
There are no flags defined currently and the users should use the value of 0.
</tp:docstring>
</arg>
<tp:docstring>
Attempts to update the configuration of a device without deactivating it.
You can either modify the configuration by passing the desired setup via "connection"
argument or just omit the argument to bring it in sync with the connection that
has been activated but could have been modified since.
</tp:docstring>
</method>
<method name="Disconnect">
<tp:docstring>
Disconnects a device and prevents the device from automatically activating further connections without user intervention.

View file

@ -1037,4 +1037,7 @@ global:
nm_vpn_service_plugin_set_ip4_config;
nm_vpn_service_plugin_set_ip6_config;
nm_vpn_service_plugin_set_login_banner;
nm_device_reapply;
nm_device_reapply_async;
nm_device_reapply_finish;
} libnm_1_0_0;

View file

@ -2164,6 +2164,128 @@ nm_device_is_software (NMDevice *device)
return !!(NM_DEVICE_GET_PRIVATE (device)->capabilities & NM_DEVICE_CAP_IS_SOFTWARE);
}
/**
* nm_device_reapply:
* @device: a #NMDevice
* @connection: the #NMConnection to replace the applied settings with or %NULL to reuse existing
* @flags: always set this to zero
* @cancellable: a #GCancellable, or %NULL
* @error: location for a #GError, or %NULL
*
* Attempts to update device with changes to the currently active connection
* made since it was last applied.
*
* Returns: %TRUE on success, %FALSE on error, in which case @error will be set.
**/
gboolean
nm_device_reapply (NMDevice *device,
NMConnection *connection,
guint flags,
GCancellable *cancellable,
GError **error)
{
GVariant *dict = NULL;
gboolean ret;
g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);
if (connection)
dict = nm_connection_to_dbus (connection, NM_CONNECTION_SERIALIZE_ALL);
if (!dict)
dict = g_variant_new_array (G_VARIANT_TYPE ("{sa{sv}}"), NULL, 0);
ret = nmdbus_device_call_reapply_sync (NM_DEVICE_GET_PRIVATE (device)->proxy,
dict, flags, cancellable, error);
if (error && *error)
g_dbus_error_strip_remote_error (*error);
return ret;
}
static void
device_reapply_cb (GObject *proxy,
GAsyncResult *result,
gpointer user_data)
{
GSimpleAsyncResult *simple = user_data;
GError *error = NULL;
if (nmdbus_device_call_reapply_finish (NMDBUS_DEVICE (proxy), result, &error))
g_simple_async_result_set_op_res_gboolean (simple, TRUE);
else {
g_dbus_error_strip_remote_error (error);
g_simple_async_result_take_error (simple, error);
}
g_simple_async_result_complete (simple);
g_object_unref (simple);
}
/**
* nm_device_reapply_async:
* @device: a #NMDevice
* @connection: the #NMConnection to replace the applied settings with or %NULL to reuse existing
* @flags: always set this to zero
* @cancellable: a #GCancellable, or %NULL
* @callback: callback to be called when the reapply operation completes
* @user_data: caller-specific data passed to @callback
*
* Asynchronously begins an attempt to update device with changes to the
* currently active connection made since it was last applied.
**/
void
nm_device_reapply_async (NMDevice *device,
NMConnection *connection,
guint flags,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GVariant *dict = NULL;
GSimpleAsyncResult *simple;
g_return_if_fail (NM_IS_DEVICE (device));
if (connection)
dict = nm_connection_to_dbus (connection, NM_CONNECTION_SERIALIZE_ALL);
if (!dict)
dict = g_variant_new_array (G_VARIANT_TYPE ("{sa{sv}}"), NULL, 0);
simple = g_simple_async_result_new (G_OBJECT (device), callback, user_data,
nm_device_reapply_async);
nmdbus_device_call_reapply (NM_DEVICE_GET_PRIVATE (device)->proxy,
dict, flags, cancellable,
device_reapply_cb, simple);
}
/**
* nm_device_reapply_finish:
* @device: a #NMDevice
* @result: the result passed to the #GAsyncReadyCallback
* @error: location for a #GError, or %NULL
*
* Gets the result of a call to nm_device_reapply_async().
*
* Returns: %TRUE on success, %FALSE on error, in which case @error
* will be set.
**/
gboolean
nm_device_reapply_finish (NMDevice *device,
GAsyncResult *result,
GError **error)
{
GSimpleAsyncResult *simple;
g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (device), nm_device_reapply_async), FALSE);
simple = G_SIMPLE_ASYNC_RESULT (result);
if (g_simple_async_result_propagate_error (simple, error))
return FALSE;
else
return g_simple_async_result_get_op_res_gboolean (simple);
}
/**
* nm_device_disconnect:
* @device: a #NMDevice

View file

@ -138,6 +138,21 @@ GPtrArray * nm_device_get_lldp_neighbors (NMDevice *device);
char ** nm_device_disambiguate_names (NMDevice **devices,
int num_devices);
gboolean nm_device_reapply (NMDevice *device,
NMConnection *connection,
guint flags,
GCancellable *cancellable,
GError **error);
void nm_device_reapply_async (NMDevice *device,
NMConnection *connection,
guint flags,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean nm_device_reapply_finish (NMDevice *device,
GAsyncResult *result,
GError **error);
gboolean nm_device_disconnect (NMDevice *device,
GCancellable *cancellable,
GError **error);

View file

@ -892,7 +892,7 @@ provided, the VPN configuration data will be printed to standard output.
.B device - show and manage network interfaces
.br
.TP
.SS \fICOMMAND\fP := { status | show | set | connect | disconnect | delete | monitor | wifi | lldp }
.SS \fICOMMAND\fP := { status | show | set | connect | reapply | disconnect | delete | monitor | wifi | lldp }
.sp
.RS
.TP
@ -920,6 +920,11 @@ will be activated. It will also consider connections that are not set to auto co
.br
If '--wait' option is not specified, the default timeout will be 90 seconds.
.TP
.B reapply <ifname>
.br
Attempt to update device with changes to the currently active connection
made since it was last applied.
.TP
.B disconnect <ifname> ...
.br
Disconnect a device and prevent the device from automatically activating further

View file

@ -6528,7 +6528,7 @@ activate_stage5_ip4_config_commit (NMDevice *self)
}
static void
nm_device_queued_ip_config_change_clear (NMDevice *self)
queued_ip4_config_change_clear (NMDevice *self)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
@ -6537,6 +6537,13 @@ nm_device_queued_ip_config_change_clear (NMDevice *self)
g_source_remove (priv->queued_ip4_config_id);
priv->queued_ip4_config_id = 0;
}
}
static void
queued_ip6_config_change_clear (NMDevice *self)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
if (priv->queued_ip6_config_id) {
_LOGD (LOGD_DEVICE, "clearing queued IP6 config change");
g_source_remove (priv->queued_ip6_config_id);
@ -6556,7 +6563,7 @@ nm_device_activate_schedule_ip4_config_result (NMDevice *self, NMIP4Config *conf
if (config)
priv->dev_ip4_config = g_object_ref (config);
nm_device_queued_ip_config_change_clear (self);
queued_ip4_config_change_clear (self);
activation_source_schedule (self, activate_stage5_ip4_config_commit, AF_INET);
}
@ -6795,6 +6802,301 @@ delete_on_deactivate_check_and_schedule (NMDevice *self, int ifindex)
ifindex, data->idle_add_id);
}
static void
_cleanup_ip4_pre (NMDevice *self, CleanupType cleanup_type)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
priv->ip4_state = IP_NONE;
queued_ip4_config_change_clear (self);
dhcp4_cleanup (self, cleanup_type, FALSE);
arp_cleanup (self);
dnsmasq_cleanup (self);
ipv4ll_cleanup (self);
}
static void
_cleanup_ip6_pre (NMDevice *self, CleanupType cleanup_type)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
priv->ip6_state = IP_NONE;
queued_ip6_config_change_clear (self);
dhcp6_cleanup (self, cleanup_type, FALSE);
linklocal6_cleanup (self);
addrconf6_cleanup (self);
}
G_GNUC_NULL_TERMINATED
static gboolean
_hash_check_invalid_keys (GHashTable *hash, const char *setting_name, GError **error, ...)
{
va_list ap;
const char *key;
guint found_keys = 0;
#if NM_MORE_ASSERTS > 10
/* Assert that the keys are unique. */
{
gs_unref_hashtable GHashTable *check_dups = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL);
va_start (ap, error);
while ((key = va_arg (ap, const char *))) {
if (!g_hash_table_add (check_dups, (char *) key))
nm_assert (FALSE);
}
va_end (ap);
nm_assert (g_hash_table_size (check_dups) > 0);
}
#endif
if (!hash || g_hash_table_size (hash) == 0)
return TRUE;
va_start (ap, error);
while ((key = va_arg (ap, const char *))) {
if (g_hash_table_contains (hash, key))
found_keys++;
}
va_end (ap);
if (found_keys != g_hash_table_size (hash)) {
GHashTableIter iter;
const char *k = NULL;
const char *first_invalid_key = NULL;
if (!error)
return FALSE;
g_hash_table_iter_init (&iter, hash);
while (g_hash_table_iter_next (&iter, (gpointer *) &k, NULL)) {
va_start (ap, error);
while ((key = va_arg (ap, const char *))) {
if (!strcmp (key, k)) {
first_invalid_key = k;
break;
}
}
va_end (ap);
if (first_invalid_key)
break;
}
g_set_error (error,
NM_DEVICE_ERROR,
NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION,
"Can't reapply changes to '%s%s%s' setting",
setting_name ? : "",
setting_name ? "." : "",
first_invalid_key ? : "<UNKNOWN>");
g_return_val_if_fail (first_invalid_key, FALSE);
return FALSE;
}
return TRUE;
}
/* reapply_connection:
* @connection: the new connection settings to be applied or %NULL to reapply
* the current settings connection
* @error: the error if %FALSE is returned
*
* Change configuration of an already configured device if possible.
* Updates the device's applied connection upon success.
*
* Return: %FALSE if the new configuration can not be reapplied.
*/
static gboolean
reapply_connection (NMDevice *self,
NMConnection *connection,
GError **error)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
NMConnection *applied = nm_device_get_applied_connection (self);
gs_unref_object NMConnection *applied_clone = NULL;
gs_unref_hashtable GHashTable *diffs = NULL;
NMConnection *con_old, *con_new;
NMSettingIPConfig *s_ip4_old, *s_ip4_new;
NMSettingIPConfig *s_ip6_old, *s_ip6_new;
if (priv->state != NM_DEVICE_STATE_ACTIVATED) {
g_set_error_literal (error,
NM_DEVICE_ERROR,
NM_DEVICE_ERROR_NOT_ACTIVE,
"Device is not activated");
return FALSE;
}
nm_connection_diff (connection,
applied,
NM_SETTING_COMPARE_FLAG_IGNORE_TIMESTAMP |
NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS,
&diffs);
/**************************************************************************
* check for unsupported changes and reject to reapply
*************************************************************************/
if (!_hash_check_invalid_keys (diffs, NULL, error,
NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_CONNECTION_SETTING_NAME,
NULL))
return FALSE;
if (!_hash_check_invalid_keys (diffs ? g_hash_table_lookup (diffs, NM_SETTING_CONNECTION_SETTING_NAME) : NULL,
NM_SETTING_CONNECTION_SETTING_NAME,
error,
NM_SETTING_CONNECTION_ZONE,
NM_SETTING_CONNECTION_METERED,
NULL))
return FALSE;
_LOGD (LOGD_DEVICE, "reapply");
/**************************************************************************
* Update applied connection
*************************************************************************/
if (diffs) {
con_old = applied_clone = nm_simple_connection_new_clone (applied);
con_new = applied;
nm_connection_replace_settings_from_connection (applied, connection);
} else
con_old = con_new = applied;
s_ip4_new = nm_connection_get_setting_ip4_config (con_new);
s_ip4_old = nm_connection_get_setting_ip4_config (con_old);
s_ip6_new = nm_connection_get_setting_ip6_config (con_new);
s_ip6_old = nm_connection_get_setting_ip6_config (con_old);
/**************************************************************************
* Reapply changes
*************************************************************************/
nm_device_update_firewall_zone (self);
nm_device_update_metered (self);
if (priv->ip4_state != IP_NONE) {
g_clear_object (&priv->con_ip4_config);
priv->con_ip4_config = nm_ip4_config_new (nm_device_get_ip_ifindex (self));
nm_ip4_config_merge_setting (priv->con_ip4_config,
s_ip4_new,
nm_device_get_ip4_route_metric (self));
if (strcmp (nm_setting_ip_config_get_method (s_ip4_new),
nm_setting_ip_config_get_method (s_ip4_old))) {
_cleanup_ip4_pre (self, CLEANUP_TYPE_DECONFIGURE);
priv->ip4_state = IP_WAIT;
if (!nm_device_activate_stage3_ip4_start (self))
_LOGW (LOGD_IP4, "Failed to apply IPv4 configuration");
} else
ip4_config_merge_and_apply (self, NULL, TRUE, NULL);
}
if (priv->ip6_state != IP_NONE) {
g_clear_object (&priv->con_ip6_config);
priv->con_ip6_config = nm_ip6_config_new (nm_device_get_ip_ifindex (self));
nm_ip6_config_merge_setting (priv->con_ip6_config,
s_ip6_new,
nm_device_get_ip6_route_metric (self));
if (strcmp (nm_setting_ip_config_get_method (s_ip6_new),
nm_setting_ip_config_get_method (s_ip6_old))) {
_cleanup_ip6_pre (self, CLEANUP_TYPE_DECONFIGURE);
priv->ip6_state = IP_WAIT;
if (!nm_device_activate_stage3_ip6_start (self))
_LOGW (LOGD_IP6, "Failed to apply IPv6 configuration");
} else
ip6_config_merge_and_apply (self, TRUE, NULL);
}
return TRUE;
}
static void
reapply_cb (NMDevice *self,
GDBusMethodInvocation *context,
NMAuthSubject *subject,
GError *error,
gpointer user_data)
{
gs_unref_object NMConnection *connection = NM_CONNECTION (user_data);
GError *local = NULL;
if (error) {
nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, FALSE, subject, error->message);
g_dbus_method_invocation_return_gerror (context, error);
return;
}
if (!reapply_connection (self,
connection ? : (NMConnection *) nm_device_get_settings_connection (self),
&local)) {
nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, FALSE, subject, local->message);
g_dbus_method_invocation_take_error (context, local);
local = NULL;
} else {
nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, TRUE, subject, NULL);
g_dbus_method_invocation_return_value (context, NULL);
}
}
static void
impl_device_reapply (NMDevice *self,
GDBusMethodInvocation *context,
GVariant *settings,
guint flags)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
NMSettingsConnection *settings_connection;
NMConnection *connection = NULL;
GError *error = NULL;
/* No flags supported as of now. */
if (flags != 0) {
error = g_error_new_literal (NM_DEVICE_ERROR,
NM_DEVICE_ERROR_NOT_ACTIVE,
"Invalid flags specified");
nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, FALSE, context, error->message);
g_dbus_method_invocation_take_error (context, error);
return;
}
if (priv->state != NM_DEVICE_STATE_ACTIVATED) {
error = g_error_new_literal (NM_DEVICE_ERROR,
NM_DEVICE_ERROR_NOT_ACTIVE,
"Device is not activated");
nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, FALSE, context, error->message);
g_dbus_method_invocation_take_error (context, error);
return;
}
settings_connection = nm_device_get_settings_connection (self);
g_return_if_fail (settings_connection);
if (settings && g_variant_n_children (settings)) {
/* New settings specified inline. */
connection = nm_simple_connection_new_from_dbus (settings, &error);
if (!connection) {
g_prefix_error (&error, "The settings specified are invalid: ");
nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, FALSE, context, error->message);
g_dbus_method_invocation_take_error (context, error);
return;
}
nm_connection_clear_secrets (connection);
}
/* Ask the manager to authenticate this request for us */
g_signal_emit (self, signals[AUTH_REQUEST], 0,
context,
nm_device_get_applied_connection (self),
NM_AUTH_PERMISSION_NETWORK_CONTROL,
TRUE,
reapply_cb,
connection);
}
static void
disconnect_cb (NMDevice *self,
GDBusMethodInvocation *context,
@ -8939,23 +9241,6 @@ nm_device_has_pending_action (NMDevice *self)
/***********************************************************/
static void
_cleanup_ip_pre (NMDevice *self, CleanupType cleanup_type)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
priv->ip4_state = priv->ip6_state = IP_NONE;
nm_device_queued_ip_config_change_clear (self);
dhcp4_cleanup (self, cleanup_type, FALSE);
arp_cleanup (self);
dhcp6_cleanup (self, cleanup_type, FALSE);
linklocal6_cleanup (self);
addrconf6_cleanup (self);
dnsmasq_cleanup (self);
ipv4ll_cleanup (self);
}
static void
_cancel_activation (NMDevice *self)
{
@ -8997,7 +9282,8 @@ _cleanup_generic_pre (NMDevice *self, CleanupType cleanup_type)
/* Clear any queued transitions */
nm_device_queued_state_clear (self);
_cleanup_ip_pre (self, cleanup_type);
_cleanup_ip4_pre (self, cleanup_type);
_cleanup_ip6_pre (self, cleanup_type);
}
static void
@ -9536,7 +9822,8 @@ _set_state_full (NMDevice *self,
/* Clean up any half-done IP operations if the device's layer2
* finds out it needs authentication during IP config.
*/
_cleanup_ip_pre (self, CLEANUP_TYPE_DECONFIGURE);
_cleanup_ip4_pre (self, CLEANUP_TYPE_DECONFIGURE);
_cleanup_ip6_pre (self, CLEANUP_TYPE_DECONFIGURE);
}
break;
default:
@ -10905,6 +11192,7 @@ nm_device_class_init (NMDeviceClass *klass)
nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass),
NMDBUS_TYPE_DEVICE_SKELETON,
"Reapply", impl_device_reapply,
"Disconnect", impl_device_disconnect,
"Delete", impl_device_delete,
NULL);

View file

@ -165,15 +165,27 @@ nm_audit_log (NMAuditManager *self, GPtrArray *fields, const char *file,
static void
_audit_log_helper (NMAuditManager *self, GPtrArray *fields, const char *file,
guint line, const char *func, const char *op, gboolean result,
NMAuthSubject *subject, const char *reason)
gpointer subject_context, const char *reason)
{
AuditField op_field = { }, pid_field = { }, uid_field = { };
AuditField result_field = { }, reason_field = { };
gulong pid, uid;
NMAuthSubject *subject = NULL;
gs_unref_object NMAuthSubject *subject_free = NULL;
_audit_field_init_string (&op_field, "op", op, FALSE, BACKEND_ALL);
g_ptr_array_insert (fields, 0, &op_field);
if (subject_context) {
if (NM_IS_AUTH_SUBJECT (subject_context))
subject = subject_context;
else if (G_IS_DBUS_METHOD_INVOCATION (subject_context)) {
GDBusMethodInvocation *context = subject_context;
subject = subject_free = nm_auth_subject_new_unix_process_from_context (context);
} else
g_warn_if_reached ();
}
if (subject && nm_auth_subject_is_unix_process (subject)) {
pid = nm_auth_subject_get_unix_process_pid (subject);
uid = nm_auth_subject_get_unix_process_uid (subject);
@ -215,7 +227,7 @@ nm_audit_manager_audit_enabled (NMAuditManager *self)
void
_nm_audit_manager_log_connection_op (NMAuditManager *self, const char *file, guint line,
const char *func, const char *op, NMSettingsConnection *connection,
gboolean result, NMAuthSubject *subject, const char *reason)
gboolean result, gpointer subject_context, const char *reason)
{
gs_unref_ptrarray GPtrArray *fields = NULL;
AuditField uuid_field = { }, name_field = { };
@ -234,13 +246,13 @@ _nm_audit_manager_log_connection_op (NMAuditManager *self, const char *file, gui
g_ptr_array_add (fields, &name_field);
}
_audit_log_helper (self, fields, file, line, func, op, result, subject, reason);
_audit_log_helper (self, fields, file, line, func, op, result, subject_context, reason);
}
void
_nm_audit_manager_log_control_op (NMAuditManager *self, const char *file, guint line,
const char *func, const char *op, const char *arg,
gboolean result, NMAuthSubject *subject,
gboolean result, gpointer subject_context,
const char *reason)
{
gs_unref_ptrarray GPtrArray *fields = NULL;
@ -254,13 +266,13 @@ _nm_audit_manager_log_control_op (NMAuditManager *self, const char *file, guint
_audit_field_init_string (&arg_field, "arg", arg, TRUE, BACKEND_ALL);
g_ptr_array_add (fields, &arg_field);
_audit_log_helper (self, fields, file, line, func, op, result, subject, reason);
_audit_log_helper (self, fields, file, line, func, op, result, subject_context, reason);
}
void
_nm_audit_manager_log_device_op (NMAuditManager *self, const char *file, guint line,
const char *func, const char *op, NMDevice *device,
gboolean result, NMAuthSubject *subject,
gboolean result, gpointer subject_context,
const char *reason)
{
gs_unref_ptrarray GPtrArray *fields = NULL;
@ -282,7 +294,7 @@ _nm_audit_manager_log_device_op (NMAuditManager *self, const char *file, guint l
g_ptr_array_add (fields, &ifindex_field);
}
_audit_log_helper (self, fields, file, line, func, op, result, subject, reason);
_audit_log_helper (self, fields, file, line, func, op, result, subject_context, reason);
}
#if HAVE_LIBAUDIT

View file

@ -61,53 +61,54 @@ typedef struct {
#define NM_AUDIT_OP_DEVICE_DISCONNECT "device-disconnect"
#define NM_AUDIT_OP_DEVICE_DELETE "device-delete"
#define NM_AUDIT_OP_DEVICE_MANAGED "device-managed"
#define NM_AUDIT_OP_DEVICE_REAPPLY "device-reapply"
GType nm_audit_manager_get_type (void);
NMAuditManager *nm_audit_manager_get (void);
gboolean nm_audit_manager_audit_enabled (NMAuditManager *self);
#define nm_audit_log_connection_op(op, connection, result, subject, reason) \
#define nm_audit_log_connection_op(op, connection, result, subject_context, reason) \
G_STMT_START { \
NMAuditManager *_audit = nm_audit_manager_get (); \
\
if (nm_audit_manager_audit_enabled (_audit)) { \
_nm_audit_manager_log_connection_op (_audit, __FILE__, __LINE__, G_STRFUNC, \
(op), (connection), (result), (subject), \
(op), (connection), (result), (subject_context), \
(reason)); \
} \
} G_STMT_END
#define nm_audit_log_control_op(op, arg, result, subject, reason) \
#define nm_audit_log_control_op(op, arg, result, subject_context, reason) \
G_STMT_START { \
NMAuditManager *_audit = nm_audit_manager_get (); \
\
if (nm_audit_manager_audit_enabled (_audit)) { \
_nm_audit_manager_log_control_op (_audit, __FILE__, __LINE__, G_STRFUNC, \
(op), (arg), (result), (subject), (reason)); \
(op), (arg), (result), (subject_context), (reason)); \
} \
} G_STMT_END
#define nm_audit_log_device_op(op, device, result, subject, reason) \
#define nm_audit_log_device_op(op, device, result, subject_context, reason) \
G_STMT_START { \
NMAuditManager *_audit = nm_audit_manager_get (); \
\
if (nm_audit_manager_audit_enabled (_audit)) { \
_nm_audit_manager_log_device_op (_audit, __FILE__, __LINE__, G_STRFUNC, \
(op), (device), (result), (subject), (reason)); \
(op), (device), (result), (subject_context), (reason)); \
} \
} G_STMT_END
void _nm_audit_manager_log_connection_op (NMAuditManager *self, const char *file, guint line,
const char *func, const char *op, NMSettingsConnection *connection,
gboolean result, NMAuthSubject *subject, const char *reason);
gboolean result, gpointer subject_context, const char *reason);
void _nm_audit_manager_log_control_op (NMAuditManager *self, const char *file, guint line,
const char *func, const char *op, const char *arg,
gboolean result, NMAuthSubject *subject, const char *reason);
gboolean result, gpointer subject_context, const char *reason);
void _nm_audit_manager_log_device_op (NMAuditManager *self, const char *file, guint line,
const char *func, const char *op, NMDevice *device,
gboolean result, NMAuthSubject *subject, const char *reason);
gboolean result, gpointer subject_context, const char *reason);
G_END_DECLS
#endif /* __NM_AUDIT_MANAGER_H__ */