diff options
author | Thomas Haller <thaller@redhat.com> | 2017-12-05 21:07:31 +0100 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2017-12-05 21:07:31 +0100 |
commit | 632e693251715526817b6fb27872df66b23595a4 (patch) | |
tree | b2d8c5946633f9da0cc2ef37326fc9208d8c4fe4 | |
parent | 9b23f972900acb0734f27564c9edefaf8f2a4245 (diff) | |
parent | 35dc6421de78cffd1761cfb6edf9e94233f99966 (diff) | |
download | NetworkManager-632e693251715526817b6fb27872df66b23595a4.tar.gz |
core: merge branch 'th/user-block-autoconnect-rh1401515'
https://bugzilla.redhat.com/show_bug.cgi?id=1401515
30 files changed, 1082 insertions, 586 deletions
diff --git a/Makefile.am b/Makefile.am index 3f60ea5b3f..1a3d8b134b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1503,8 +1503,6 @@ src_libNetworkManager_la_SOURCES = \ \ src/settings/nm-agent-manager.c \ src/settings/nm-agent-manager.h \ - src/settings/nm-inotify-helper.c \ - src/settings/nm-inotify-helper.h \ src/settings/nm-secret-agent.c \ src/settings/nm-secret-agent.h \ src/settings/nm-settings-connection.c \ @@ -2021,6 +2019,8 @@ src_settings_plugins_ifcfg_rh_libnms_ifcfg_rh_core_la_SOURCES = \ src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-common.h \ src/settings/plugins/ifcfg-rh/shvar.c \ src/settings/plugins/ifcfg-rh/shvar.h \ + src/settings/plugins/ifcfg-rh/nm-inotify-helper.c \ + src/plugins/ifcfg-rh/settings/nm-inotify-helper.h \ src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c \ src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h \ src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c \ diff --git a/Makefile.examples b/Makefile.examples index fc08851ca6..79f2482d9f 100644 --- a/Makefile.examples +++ b/Makefile.examples @@ -173,6 +173,7 @@ EXTRA_DIST += \ examples/python/gi/get-active-connections.py \ examples/python/gi/get_ips.py \ examples/python/gi/list-connections.py \ + examples/python/gi/nm-connection-update-stable-id.py \ examples/python/gi/setting-user-data.py \ examples/python/gi/show-wifi-networks.py \ examples/python/gi/update-ip4-method.py \ diff --git a/examples/python/gi/nm-connection-update-stable-id.py b/examples/python/gi/nm-connection-update-stable-id.py new file mode 100755 index 0000000000..ad852f7712 --- /dev/null +++ b/examples/python/gi/nm-connection-update-stable-id.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python +# -*- Mode: Python; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +# vim: ft=python ts=4 sts=4 sw=4 et ai +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Copyright 2017 Red Hat, Inc. +# + +# +# This example updates a connection's stable-id by appending -#number. + +import sys +import re + +import gi +gi.require_version('NM', '1.0') +from gi.repository import GLib, NM + +def usage(): + print('Usage: %s [[id] <id>]' % (sys.argv[0])) + print(' %s [[uuid] <uuid>]' % (sys.argv[0])) + return 1 + +def find_connection(nm_client, arg_type, arg_id): + for c in nm_client.get_connections(): + if arg_type in [None, 'id'] and c.get_id() == arg_id: + return c + if arg_type in [None, 'uuid'] and c.get_uuid() == arg_id: + return c + +def main(): + if len(sys.argv) < 2 or len(sys.argv) > 3: + return usage() + if len(sys.argv) == 3: + arg_type = sys.argv[1] + arg_id = sys.argv[2] + if arg_type not in ['id', 'uuid']: + return usage() + else: + arg_type = None + arg_id = sys.argv[1] + arg_log = '%s"%s"' % ((' with %s ' % (arg_type)) if arg_type else '', arg_id) + + main_loop = GLib.MainLoop() + + nm_client = NM.Client.new(None) + + con = find_connection(nm_client, arg_type, arg_id) + if con is None: + print('could not find a connection %s' % (arg_log)) + return 1 + + s_con = con.get_setting_connection() + if s_con is None: + print('connection %s has no [connection] setting' % (arg_log)) + return 1 + + arg_log = '"%s" (%s)' % (s_con.get_id(), s_con.get_uuid()) + + stable_id = s_con.get_stable_id() + if not stable_id: + print('connection %s has no stable-id set' % (arg_log)) + return 1 + + re_match = re.search('\A(.*)-([0-9]+)\Z', stable_id) + if not re_match: + stable_id = stable_id + '-1' + else: + stable_id = re_match.group(1) + '-' + str(int(re_match.group(2)) + 1) + + con2 = NM.SimpleConnection.new_clone(con) + s_con = con2.get_setting_connection() + s_con.set_property(NM.SETTING_CONNECTION_STABLE_ID, stable_id) + + result = {} + def _update2_cb(con, async_result, user_data): + try: + r = con.update2_finish(async_result) + except Exception as e: + result['error'] = e + else: + result['result'] = r + main_loop.quit() + + con.update2(con2.to_dbus(NM.ConnectionSerializationFlags.ALL), + NM.SettingsUpdate2Flags.BLOCK_AUTOCONNECT, + None, + None, + _update2_cb, + None) + + main_loop.run() + + if 'error' in result: + print('update connection %s failed: %s' % (arg_log, result['error'])) + return 1 + + print('update connection %s succeeded: %s' % (arg_log, result['result'])) + print('set stable-id to "%s"' % (stable_id)) + return 0 + +if __name__ == '__main__': + sys.exit(main()) diff --git a/introspection/org.freedesktop.NetworkManager.Settings.Connection.xml b/introspection/org.freedesktop.NetworkManager.Settings.Connection.xml index 61bd26ddc6..ec596fd1e9 100644 --- a/introspection/org.freedesktop.NetworkManager.Settings.Connection.xml +++ b/introspection/org.freedesktop.NetworkManager.Settings.Connection.xml @@ -102,6 +102,44 @@ <signal name="Updated"/> <!-- + Update2: + @settings: New connection settings, properties, and (optionally) secrets. + Provide an empty array, to use the current settings. + @flags: optional flags argument. Currently supported flags are: + "0x1" (to-disk), + "0x2" (in-memory), + "0x4" (in-memory-detached), + "0x8" (in-memory-only), + "0x10" (volatile), + "0x20" (block-autoconnect). + Unknown flags cause the call to fail. + @args: optional arguments dictionary, for extensibility. Currently no + arguments are accepted. Specifying unknown keys causes the call + to fail. + @result: output argument, currently no results are returned. + + Update the connection with new settings and properties (replacing all + previous settings and properties). If the flag 0x1 is present, + the connection is persisted to disk. If the flag 0x2 is present, + the change is only made in memory (without touching an eventual + profile on disk). If neither 0x1 nor 0x2 is set, the change is made + in memory only, if the connection is already in memory only. + Secrets may be part of the update request, and will be either stored in persistent + storage or sent to a Secret Agent for storage, depending on the flags + associated with each secret. + + Update2 is a extensible alternative to Update, UpdateUnsaved and Save. + + Since: 1.12 + --> + <method name="Update2"> + <arg name="settings" type="a{sa{sv}}" direction="in"/> + <arg name="flags" type="u" direction="in"/> + <arg name="args" type="a{sv}" direction="in"/> + <arg name="result" type="a{sv}" direction="out"/> + </method> + + <!-- Removed: Emitted when this connection is no longer available. This happens when the diff --git a/libnm-core/nm-dbus-interface.h b/libnm-core/nm-dbus-interface.h index 6a0d3def2a..4c586d5d8d 100644 --- a/libnm-core/nm-dbus-interface.h +++ b/libnm-core/nm-dbus-interface.h @@ -896,4 +896,48 @@ typedef enum { /*< flags >*/ NM_ACTIVATION_STATE_FLAG_MASTER_HAS_SLAVES = (1LL << 5), } NMActivationStateFlags; +/** + * NMSettingsUpdate2Flags: + * @NM_SETTINGS_UPDATE2_FLAG_NONE: an alias for numeric zero, no flags set. + * @NM_SETTINGS_UPDATE2_FLAG_TO_DISK: to persist the connection to disk. + * @NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY: to make the connection in-memory only. + * If the connection was previously persistent, the corresponding file on disk + * is not deleted but merely the connection is decoupled from the file + * on disk. If you later delete an in-memory connection, the connection + * on disk will be deleted as well. + * @NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_DETACHED: this is like @NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY, + * but if the connection has a corresponding file on disk, the association between + * the connection and the file is forgotten but the file is not modified. + * The difference to %NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY is if you later + * save the connection again to disk, a new file name will be chosen without + * overwriting the remaining file on disk. Also, if you delete the connection + * later, the file on disk will not be deleted. + * @NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_ONLY: this is like @NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY, + * but if the connection has a corresponding file on disk, the file on + * disk will be deleted. + * @NM_SETTINGS_UPDATE2_FLAG_VOLATILE: This can be specified with either + * %NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_DETACHED or %NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_ONLY. + * After making the connection in-memory only, the connection is marked + * as volatile. That means, if the connection is currently not active + * it will be deleted right away. Otherwise, it is marked to for deletion + * once the connection deactivates. A volatile connection cannot autoactivate + * again (because it's about to be deleted), but a manual activation will + * clear the volatile flag. + * @NM_SETTINGS_UPDATE2_FLAG_BLOCK_AUTOCONNECT: usually, when the connection + * has autoconnect enabled and is modified, it becomes elegible to autoconnect + * right away. Setting this flag, disables autoconnect until the connection + * is manually activated. + * + * Since: 1.12 + */ +typedef enum { /*< flags >*/ + NM_SETTINGS_UPDATE2_FLAG_NONE = 0, + NM_SETTINGS_UPDATE2_FLAG_TO_DISK = (1LL << 0), + NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY = (1LL << 1), + NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_DETACHED = (1LL << 2), + NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_ONLY = (1LL << 3), + NM_SETTINGS_UPDATE2_FLAG_VOLATILE = (1LL << 4), + NM_SETTINGS_UPDATE2_FLAG_BLOCK_AUTOCONNECT = (1LL << 5), +} NMSettingsUpdate2Flags; + #endif /* __NM_DBUS_INTERFACE_H__ */ diff --git a/libnm-core/nm-errors.h b/libnm-core/nm-errors.h index 6bacc8da56..bdd6c2234f 100644 --- a/libnm-core/nm-errors.h +++ b/libnm-core/nm-errors.h @@ -261,6 +261,7 @@ GQuark nm_secret_agent_error_quark (void); * @NM_SETTINGS_ERROR_READ_ONLY_CONNECTION: attempted to modify a read-only connection * @NM_SETTINGS_ERROR_UUID_EXISTS: a connection with that UUID already exists * @NM_SETTINGS_ERROR_INVALID_HOSTNAME: attempted to set an invalid hostname + * @NM_SETTINGS_ERROR_INVALID_ARGUMENTS: invalid arguments * * Errors related to the settings/persistent configuration interface of * NetworkManager. @@ -277,6 +278,7 @@ typedef enum { NM_SETTINGS_ERROR_READ_ONLY_CONNECTION, /*< nick=ReadOnlyConnection >*/ NM_SETTINGS_ERROR_UUID_EXISTS, /*< nick=UuidExists >*/ NM_SETTINGS_ERROR_INVALID_HOSTNAME, /*< nick=InvalidHostname >*/ + NM_SETTINGS_ERROR_INVALID_ARGUMENTS, /*< nick=InvalidArguments >*/ } NMSettingsError; GQuark nm_settings_error_quark (void); diff --git a/libnm/libnm.ver b/libnm/libnm.ver index aad581698b..06e5e4c8d7 100644 --- a/libnm/libnm.ver +++ b/libnm/libnm.ver @@ -1235,6 +1235,8 @@ global: nm_client_checkpoint_rollback_async; nm_client_checkpoint_rollback_finish; nm_client_get_checkpoints; + nm_remote_connection_update2; + nm_remote_connection_update2_finish; nm_setting_team_add_runner_tx_hash; nm_setting_team_get_mcast_rejoin_count; nm_setting_team_get_mcast_rejoin_interval; @@ -1260,4 +1262,5 @@ global: nm_setting_team_remove_runner_tx_hash_by_value; nm_setting_vpn_get_data_keys; nm_setting_vpn_get_secret_keys; + nm_settings_update2_flags_get_type; } libnm_1_10_0; diff --git a/libnm/nm-remote-connection.c b/libnm/nm-remote-connection.c index 5cd42555f5..3f6ebb3b20 100644 --- a/libnm/nm-remote-connection.c +++ b/libnm/nm-remote-connection.c @@ -67,6 +67,111 @@ typedef struct { /*****************************************************************************/ +static void +update2_cb (GObject *proxy, GAsyncResult *result, gpointer user_data) +{ + GSimpleAsyncResult *simple = user_data; + GError *error = NULL; + GVariant *v; + + if (nmdbus_settings_connection_call_update2_finish (NMDBUS_SETTINGS_CONNECTION (proxy), + &v, + result, + &error)) + g_simple_async_result_set_op_res_gpointer (simple, + v, + (GDestroyNotify) g_variant_unref); + 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_remote_connection_update2: + * @connection: the #NMRemoteConnection + * @settings: (allow-none): optional connection to update the settings. + * @flags: update-flags + * @args: (allow-none): optional arguments. + * @cancellable: a #GCancellable, or %NULL + * @callback: callback to be called when the commit operation completes + * @user_data: caller-specific data passed to @callback + * + * Asynchronously calls the Update2() D-Bus method. + * + * Since: 1.12 + **/ +void +nm_remote_connection_update2 (NMRemoteConnection *connection, + GVariant *settings, + NMSettingsUpdate2Flags flags, + GVariant *args, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + NMRemoteConnectionPrivate *priv; + GSimpleAsyncResult *simple; + GVariantBuilder builder; + + g_return_if_fail (NM_IS_REMOTE_CONNECTION (connection)); + g_return_if_fail (!settings || g_variant_is_of_type (settings, NM_VARIANT_TYPE_CONNECTION)); + g_return_if_fail (!args || g_variant_is_of_type (args, G_VARIANT_TYPE ("a{sv}"))); + g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable)); + + priv = NM_REMOTE_CONNECTION_GET_PRIVATE (connection); + + simple = g_simple_async_result_new (G_OBJECT (connection), callback, user_data, + nm_remote_connection_update2); + + if (!settings) { + g_variant_builder_init (&builder, NM_VARIANT_TYPE_CONNECTION); + settings = g_variant_builder_end (&builder); + } + if (!args) { + g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}")); + args = g_variant_builder_end (&builder); + } + nmdbus_settings_connection_call_update2 (priv->proxy, + settings, + flags, + args, + cancellable, + update2_cb, + simple); +} + +/** + * nm_remote_connection_update2_finish: + * @connection: the #NMRemoteConnection + * @result: the result passed to the #GAsyncReadyCallback + * @error: location for a #GError, or %NULL + * + * Gets the result of a call to nm_remote_connection_commit_changes_async(). + * + * Returns: on success, a #GVariant of type "a{sv}" with the result. On failure, + * %NULL. + **/ +GVariant * +nm_remote_connection_update2_finish (NMRemoteConnection *connection, + GAsyncResult *result, + GError **error) +{ + GSimpleAsyncResult *simple; + + g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (connection), nm_remote_connection_update2), FALSE); + + simple = G_SIMPLE_ASYNC_RESULT (result); + if (g_simple_async_result_propagate_error (simple, error)) + return NULL; + else + return g_variant_ref (g_simple_async_result_get_op_res_gpointer (simple)); +} + +/*****************************************************************************/ + /** * nm_remote_connection_commit_changes: * @connection: the #NMRemoteConnection @@ -87,23 +192,25 @@ nm_remote_connection_commit_changes (NMRemoteConnection *connection, GError **error) { NMRemoteConnectionPrivate *priv; - GVariant *settings; + gs_unref_variant GVariant *result = NULL; gboolean ret; + GVariantBuilder args; g_return_val_if_fail (NM_IS_REMOTE_CONNECTION (connection), FALSE); priv = NM_REMOTE_CONNECTION_GET_PRIVATE (connection); - settings = nm_connection_to_dbus (NM_CONNECTION (connection), NM_CONNECTION_SERIALIZE_ALL); - if (save_to_disk) { - ret = nmdbus_settings_connection_call_update_sync (priv->proxy, - settings, - cancellable, error); - } else { - ret = nmdbus_settings_connection_call_update_unsaved_sync (priv->proxy, - settings, - cancellable, error); - } + g_variant_builder_init (&args, G_VARIANT_TYPE ("a{sv}")); + ret = nmdbus_settings_connection_call_update2_sync (priv->proxy, + nm_connection_to_dbus (NM_CONNECTION (connection), + NM_CONNECTION_SERIALIZE_ALL), + save_to_disk + ? NM_SETTINGS_UPDATE2_FLAG_TO_DISK + : NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY, + g_variant_builder_end (&args), + &result, + cancellable, + error); if (error && *error) g_dbus_error_strip_remote_error (*error); return ret; @@ -113,11 +220,13 @@ static void update_cb (GObject *proxy, GAsyncResult *result, gpointer user_data) { GSimpleAsyncResult *simple = user_data; - gboolean (*finish_func) (NMDBusSettingsConnection *, GAsyncResult *, GError **); GError *error = NULL; + gs_unref_variant GVariant *v = NULL; - finish_func = g_object_get_data (G_OBJECT (simple), "finish_func"); - if (finish_func (NMDBUS_SETTINGS_CONNECTION (proxy), result, &error)) + if (nmdbus_settings_connection_call_update2_finish (NMDBUS_SETTINGS_CONNECTION (proxy), + &v, + result, + &error)) g_simple_async_result_set_op_res_gboolean (simple, TRUE); else { g_dbus_error_strip_remote_error (error); @@ -149,7 +258,7 @@ nm_remote_connection_commit_changes_async (NMRemoteConnection *connection, { NMRemoteConnectionPrivate *priv; GSimpleAsyncResult *simple; - GVariant *settings; + GVariantBuilder args; g_return_if_fail (NM_IS_REMOTE_CONNECTION (connection)); @@ -158,22 +267,17 @@ nm_remote_connection_commit_changes_async (NMRemoteConnection *connection, simple = g_simple_async_result_new (G_OBJECT (connection), callback, user_data, nm_remote_connection_commit_changes_async); - settings = nm_connection_to_dbus (NM_CONNECTION (connection), NM_CONNECTION_SERIALIZE_ALL); - if (save_to_disk) { - g_object_set_data (G_OBJECT (simple), "finish_func", - nmdbus_settings_connection_call_update_finish); - nmdbus_settings_connection_call_update (priv->proxy, - settings, - cancellable, - update_cb, simple); - } else { - g_object_set_data (G_OBJECT (simple), "finish_func", - nmdbus_settings_connection_call_update_unsaved_finish); - nmdbus_settings_connection_call_update_unsaved (priv->proxy, - settings, - cancellable, - update_cb, simple); - } + g_variant_builder_init (&args, G_VARIANT_TYPE ("a{sv}")); + nmdbus_settings_connection_call_update2 (priv->proxy, + nm_connection_to_dbus (NM_CONNECTION (connection), + NM_CONNECTION_SERIALIZE_ALL), + save_to_disk + ? NM_SETTINGS_UPDATE2_FLAG_TO_DISK + : NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY, + g_variant_builder_end (&args), + cancellable, + update_cb, + simple); } /** @@ -202,6 +306,8 @@ nm_remote_connection_commit_changes_finish (NMRemoteConnection *connection, return g_simple_async_result_get_op_res_gboolean (simple); } +/*****************************************************************************/ + /** * nm_remote_connection_save: * @connection: the #NMRemoteConnection @@ -302,6 +408,8 @@ nm_remote_connection_save_finish (NMRemoteConnection *connection, return g_simple_async_result_get_op_res_gboolean (simple); } +/*****************************************************************************/ + /** * nm_remote_connection_delete: * @connection: the #NMRemoteConnection diff --git a/libnm/nm-remote-connection.h b/libnm/nm-remote-connection.h index c04ae36779..1e7d7618b5 100644 --- a/libnm/nm-remote-connection.h +++ b/libnm/nm-remote-connection.h @@ -60,6 +60,19 @@ typedef struct { GType nm_remote_connection_get_type (void); +NM_AVAILABLE_IN_1_12 +void nm_remote_connection_update2 (NMRemoteConnection *connection, + GVariant *settings, + NMSettingsUpdate2Flags flags, + GVariant *args, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +NM_AVAILABLE_IN_1_12 +GVariant *nm_remote_connection_update2_finish (NMRemoteConnection *connection, + GAsyncResult *result, + GError **error); + gboolean nm_remote_connection_commit_changes (NMRemoteConnection *connection, gboolean save_to_disk, GCancellable *cancellable, diff --git a/shared/nm-utils/nm-macros-internal.h b/shared/nm-utils/nm-macros-internal.h index cf9142fe99..8005375c9d 100644 --- a/shared/nm-utils/nm-macros-internal.h +++ b/shared/nm-utils/nm-macros-internal.h @@ -577,7 +577,7 @@ _NM_IN_STRSET_streq (const char *x, const char *s) /* NM_CACHED_QUARK_FCN() is essentially the same as G_DEFINE_QUARK * with two differences: - * - @string must be a quited string-literal + * - @string must be a quoted string-literal * - @fcn must be the full function name, while G_DEFINE_QUARK() appends * "_quark" to the function name. * Both properties of G_DEFINE_QUARK() are non favorable, because you can no diff --git a/src/devices/bluetooth/nm-bluez-device.c b/src/devices/bluetooth/nm-bluez-device.c index 182527d9f5..bd3cf18a67 100644 --- a/src/devices/bluetooth/nm-bluez-device.c +++ b/src/devices/bluetooth/nm-bluez-device.c @@ -1185,7 +1185,8 @@ dispose (GObject *object) if (priv->pan_connection) { /* Check whether we want to remove the created connection. If so, we take a reference * and delete it at the end of dispose(). */ - if (nm_settings_connection_get_nm_generated (NM_SETTINGS_CONNECTION (priv->pan_connection))) + if (NM_FLAGS_HAS (nm_settings_connection_get_flags (NM_SETTINGS_CONNECTION (priv->pan_connection)), + NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED)) to_delete = g_object_ref (priv->pan_connection); priv->pan_connection = NULL; diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 2e034cc47a..f79b85e8c2 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -10174,7 +10174,8 @@ nm_device_set_ip4_config (NMDevice *self, if ( nm_device_sys_iface_state_is_external (self) && (settings_connection = nm_device_get_settings_connection (self)) - && nm_settings_connection_get_nm_generated (settings_connection) + && NM_FLAGS_HAS (nm_settings_connection_get_flags (settings_connection), + NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED) && nm_active_connection_get_activation_type (NM_ACTIVE_CONNECTION (priv->act_request)) == NM_ACTIVATION_TYPE_EXTERNAL) { NMSetting *s_ip4; @@ -10345,7 +10346,8 @@ nm_device_set_ip6_config (NMDevice *self, if ( nm_device_sys_iface_state_is_external (self) && (settings_connection = nm_device_get_settings_connection (self)) - && nm_settings_connection_get_nm_generated (settings_connection) + && NM_FLAGS_HAS (nm_settings_connection_get_flags (settings_connection), + NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED) && nm_active_connection_get_activation_type (NM_ACTIVE_CONNECTION (priv->act_request)) == NM_ACTIVATION_TYPE_EXTERNAL) { NMSetting *s_ip6; diff --git a/src/nm-active-connection.c b/src/nm-active-connection.c index c27f6548eb..2286a74b4f 100644 --- a/src/nm-active-connection.c +++ b/src/nm-active-connection.c @@ -866,7 +866,8 @@ _settings_connection_notify_flags (NMSettingsConnection *settings_connection, nm_assert (nm_active_connection_get_activation_type (self) == NM_ACTIVATION_TYPE_EXTERNAL); nm_assert (NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->settings_connection == settings_connection); - if (nm_settings_connection_get_nm_generated (settings_connection)) + if (NM_FLAGS_HAS (nm_settings_connection_get_flags (settings_connection), + NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED)) return; _set_activation_type_managed (self); diff --git a/src/nm-checkpoint.c b/src/nm-checkpoint.c index af56bf26e6..5bde924c27 100644 --- a/src/nm-checkpoint.c +++ b/src/nm-checkpoint.c @@ -254,12 +254,12 @@ activate: if (need_update) { _LOGD ("rollback: updating connection %s", nm_settings_connection_get_uuid (connection)); - nm_connection_replace_settings_from_connection (NM_CONNECTION (connection), - dev_checkpoint->settings_connection); - nm_settings_connection_commit_changes (connection, - NULL, - NM_SETTINGS_CONNECTION_COMMIT_REASON_NONE, - NULL); + nm_settings_connection_update (connection, + dev_checkpoint->settings_connection, + NM_SETTINGS_CONNECTION_PERSIST_MODE_DISK, + NM_SETTINGS_CONNECTION_COMMIT_REASON_NONE, + "checkpoint-rollback", + NULL); } } else { /* The connection was deleted, recreate it */ diff --git a/src/nm-manager.c b/src/nm-manager.c index 871ed310f1..04d17f9b23 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -62,41 +62,7 @@ #include "introspection/org.freedesktop.NetworkManager.h" #include "introspection/org.freedesktop.NetworkManager.Device.h" -static gboolean add_device (NMManager *self, NMDevice *device, GError **error); - -static NMActiveConnection *_new_active_connection (NMManager *self, - NMConnection *connection, - NMConnection *applied, - const char *specific_object, - NMDevice *device, - NMAuthSubject *subject, - NMActivationType activation_type, - GError **error); - -static void policy_activating_device_changed (GObject *object, GParamSpec *pspec, gpointer user_data); - -static gboolean find_master (NMManager *self, - NMConnection *connection, - NMDevice *device, - NMSettingsConnection **out_master_connection, - NMDevice **out_master_device, - NMActiveConnection **out_master_ac, - GError **error); - -static void nm_manager_update_state (NMManager *manager); - -static void connection_changed (NMManager *self, NMConnection *connection); -static void device_sleep_cb (NMDevice *device, - GParamSpec *pspec, - NMManager *self); - -static void settings_startup_complete_changed (NMSettings *settings, - GParamSpec *pspec, - NMManager *self); - -static void retry_connections_for_parent_device (NMManager *self, NMDevice *device); - -static NM_CACHED_QUARK_FCN ("active-connection-add-and-activate", active_connection_add_and_activate_quark) +/*****************************************************************************/ typedef struct { gboolean user_enabled; @@ -109,6 +75,51 @@ typedef struct { const char *hw_prop; } RadioState; +enum { + DEVICE_ADDED, + INTERNAL_DEVICE_ADDED, + DEVICE_REMOVED, + INTERNAL_DEVICE_REMOVED, + STATE_CHANGED, + CHECK_PERMISSIONS, + ACTIVE_CONNECTION_ADDED, + ACTIVE_CONNECTION_REMOVED, + CONFIGURE_QUIT, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +NM_GOBJECT_PROPERTIES_DEFINE (NMManager, + PROP_VERSION, + PROP_CAPABILITIES, + PROP_STATE, + PROP_STARTUP, + PROP_NETWORKING_ENABLED, + PROP_WIRELESS_ENABLED, + PROP_WIRELESS_HARDWARE_ENABLED, + PROP_WWAN_ENABLED, + PROP_WWAN_HARDWARE_ENABLED, + PROP_WIMAX_ENABLED, + PROP_WIMAX_HARDWARE_ENABLED, + PROP_ACTIVE_CONNECTIONS, + PROP_CONNECTIVITY, + PROP_CONNECTIVITY_CHECK_AVAILABLE, + PROP_CONNECTIVITY_CHECK_ENABLED, + PROP_PRIMARY_CONNECTION, + PROP_PRIMARY_CONNECTION_TYPE, + PROP_ACTIVATING_CONNECTION, + PROP_DEVICES, + PROP_METERED, + PROP_GLOBAL_DNS_CONFIGURATION, + PROP_ALL_DEVICES, + PROP_CHECKPOINTS, + + /* Not exported */ + PROP_SLEEPING, +); + typedef struct { NMPlatform *platform; @@ -166,6 +177,9 @@ typedef struct { bool sleeping:1; bool net_enabled:1; + + guint delete_volatile_connection_idle_id; + CList delete_volatile_connection_lst_head; } NMManagerPrivate; struct _NMManager { @@ -181,50 +195,7 @@ G_DEFINE_TYPE (NMManager, nm_manager, NM_TYPE_EXPORTED_OBJECT) #define NM_MANAGER_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMManager, NM_IS_MANAGER) -enum { - DEVICE_ADDED, - INTERNAL_DEVICE_ADDED, - DEVICE_REMOVED, - INTERNAL_DEVICE_REMOVED, - STATE_CHANGED, - CHECK_PERMISSIONS, - ACTIVE_CONNECTION_ADDED, - ACTIVE_CONNECTION_REMOVED, - CONFIGURE_QUIT, - - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -NM_GOBJECT_PROPERTIES_DEFINE (NMManager, - PROP_VERSION, - PROP_CAPABILITIES, - PROP_STATE, - PROP_STARTUP, - PROP_NETWORKING_ENABLED, - PROP_WIRELESS_ENABLED, - PROP_WIRELESS_HARDWARE_ENABLED, - PROP_WWAN_ENABLED, - PROP_WWAN_HARDWARE_ENABLED, - PROP_WIMAX_ENABLED, - PROP_WIMAX_HARDWARE_ENABLED, - PROP_ACTIVE_CONNECTIONS, - PROP_CONNECTIVITY, - PROP_CONNECTIVITY_CHECK_AVAILABLE, - PROP_CONNECTIVITY_CHECK_ENABLED, - PROP_PRIMARY_CONNECTION, - PROP_PRIMARY_CONNECTION_TYPE, - PROP_ACTIVATING_CONNECTION, - PROP_DEVICES, - PROP_METERED, - PROP_GLOBAL_DNS_CONFIGURATION, - PROP_ALL_DEVICES, - PROP_CHECKPOINTS, - - /* Not exported */ - PROP_SLEEPING, -); +/*****************************************************************************/ NM_DEFINE_SINGLETON_INSTANCE (NMManager); @@ -297,7 +268,39 @@ NM_DEFINE_SINGLETON_INSTANCE (NMManager); /*****************************************************************************/ -static NM_CACHED_QUARK_FCN ("autoconnect-root", autoconnect_root_quark) +static gboolean add_device (NMManager *self, NMDevice *device, GError **error); + +static NMActiveConnection *_new_active_connection (NMManager *self, + NMConnection *connection, + NMConnection *applied, + const char *specific_object, + NMDevice *device, + NMAuthSubject *subject, + NMActivationType activation_type, + GError **error); + +static void policy_activating_device_changed (GObject *object, GParamSpec *pspec, gpointer user_data); + +static gboolean find_master (NMManager *self, + NMConnection *connection, + NMDevice *device, + NMSettingsConnection **out_master_connection, + NMDevice **out_master_device, + NMActiveConnection **out_master_ac, + GError **error); + +static void nm_manager_update_state (NMManager *manager); + +static void connection_changed (NMManager *self, NMConnection *connection); +static void device_sleep_cb (NMDevice *device, + GParamSpec *pspec, + NMManager *self); + +static void settings_startup_complete_changed (NMSettings *settings, + GParamSpec *pspec, + NMManager *self); + +static void retry_connections_for_parent_device (NMManager *self, NMDevice *device); static void active_connection_state_changed (NMActiveConnection *active, GParamSpec *pspec, @@ -309,12 +312,47 @@ static void active_connection_parent_active (NMActiveConnection *active, NMActiveConnection *parent_ac, NMManager *self); +static NMActiveConnection *active_connection_find_first (NMManager *self, + NMSettingsConnection *settings_connection, + const char *uuid, + NMActiveConnectionState max_state); + +/*****************************************************************************/ + +static NM_CACHED_QUARK_FCN ("active-connection-add-and-activate", active_connection_add_and_activate_quark) + +static NM_CACHED_QUARK_FCN ("autoconnect-root", autoconnect_root_quark) + +/*****************************************************************************/ + +static void +_delete_volatile_connection_do (NMManager *self, + NMSettingsConnection *connection) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + + if (!NM_FLAGS_HAS (nm_settings_connection_get_flags (connection), + NM_SETTINGS_CONNECTION_FLAGS_VOLATILE)) + return; + if (active_connection_find_first (self, + connection, + NULL, + NM_ACTIVE_CONNECTION_STATE_DEACTIVATED)) + return; + if (!nm_settings_has_connection (priv->settings, connection)) + return; + + _LOGD (LOGD_DEVICE, "volatile connection disconnected. Deleting connection '%s' (%s)", + nm_settings_connection_get_id (connection), nm_settings_connection_get_uuid (connection)); + nm_settings_connection_delete (connection, NULL); +} + /* Returns: whether to notify D-Bus of the removal or not */ static gboolean active_connection_remove (NMManager *self, NMActiveConnection *active) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMSettingsConnection *connection; + gs_unref_object NMSettingsConnection *connection = NULL; gboolean notify; nm_assert (NM_IS_ACTIVE_CONNECTION (active)); @@ -328,22 +366,12 @@ active_connection_remove (NMManager *self, NMActiveConnection *active) g_signal_handlers_disconnect_by_func (active, active_connection_default_changed, self); g_signal_handlers_disconnect_by_func (active, active_connection_parent_active, self); - if ( (connection = nm_active_connection_get_settings_connection (active)) - && nm_settings_connection_get_volatile (connection)) - g_object_ref (connection); - else - connection = NULL; + connection = nm_g_object_ref (nm_active_connection_get_settings_connection (active)); nm_exported_object_clear_and_unexport (&active); - if (connection) { - if (nm_settings_has_connection (priv->settings, connection)) { - _LOGD (LOGD_DEVICE, "assumed connection disconnected. Deleting generated connection '%s' (%s)", - nm_settings_connection_get_id (connection), nm_settings_connection_get_uuid (connection)); - nm_settings_connection_delete (connection, NULL); - } - g_object_unref (connection); - } + if (connection) + _delete_volatile_connection_do (self, connection); return notify; } @@ -498,7 +526,8 @@ _get_activatable_connections_filter (NMSettings *settings, NMSettingsConnection *connection, gpointer user_data) { - if (nm_settings_connection_get_volatile (connection)) + if (NM_FLAGS_HAS (nm_settings_connection_get_flags (connection), + NM_SETTINGS_CONNECTION_FLAGS_VOLATILE)) return FALSE; return !active_connection_find_first (user_data, connection, NULL, NM_ACTIVE_CONNECTION_STATE_DEACTIVATING); } @@ -1473,6 +1502,74 @@ connection_updated_cb (NMSettings *settings, connection_changed (self, connection); } +/*****************************************************************************/ + +typedef struct { + CList delete_volatile_connection_lst; + NMSettingsConnection *connection; +} DeleteVolatileConnectionData; + +static void +_delete_volatile_connection_all (NMManager *self, gboolean do_delete) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + CList *lst; + DeleteVolatileConnectionData *data; + + while ((lst = c_list_first (&priv->delete_volatile_connection_lst_head))) { + gs_unref_object NMSettingsConnection *connection = NULL; + + data = c_list_entry (lst, + DeleteVolatileConnectionData, + delete_volatile_connection_lst); + connection = data->connection; + c_list_unlink_stale (&data->delete_volatile_connection_lst); + g_slice_free (DeleteVolatileConnectionData, data); + + if (do_delete) + _delete_volatile_connection_do (self, connection); + } +} + +static gboolean +_delete_volatile_connection_cb (gpointer user_data) +{ + NMManager *self = user_data; + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + + priv->delete_volatile_connection_idle_id = 0; + _delete_volatile_connection_all (self, TRUE); + return G_SOURCE_REMOVE; +} + +static void +connection_flags_changed (NMSettings *settings, + NMSettingsConnection *connection, + gpointer user_data) +{ + NMManager *self = user_data; + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + DeleteVolatileConnectionData *data; + + if (!NM_FLAGS_HAS (nm_settings_connection_get_flags (connection), + NM_SETTINGS_CONNECTION_FLAGS_VOLATILE)) + return; + + if (active_connection_find_first (self, connection, NULL, NM_ACTIVE_CONNECTION_STATE_DEACTIVATED)) { + /* the connection still have an active-connection. It will be purged + * when the active connection(s) get(s) removed. */ + return; + } + + data = g_slice_new (DeleteVolatileConnectionData); + data->connection = g_object_ref (connection); + c_list_link_tail (&priv->delete_volatile_connection_lst_head, &data->delete_volatile_connection_lst); + if (!priv->delete_volatile_connection_idle_id) + priv->delete_volatile_connection_idle_id = g_idle_add (_delete_volatile_connection_cb, self); +} + +/*****************************************************************************/ + static void system_unmanaged_devices_changed_cb (NMSettings *settings, GParamSpec *pspec, @@ -3876,6 +3973,9 @@ _activation_auth_done (NMActiveConnection *active, if (success) { if (_internal_activate_generic (self, active, &error)) { + nm_settings_connection_autoconnect_blocked_reason_set (connection, + NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_USER_REQUEST, + FALSE); g_dbus_method_invocation_return_value (context, g_variant_new ("(o)", nm_exported_object_get_path (NM_EXPORTED_OBJECT (active)))); @@ -4019,10 +4119,12 @@ activation_add_done (NMSettings *settings, nm_active_connection_set_settings_connection (active, new_connection); if (_internal_activate_generic (self, active, &local)) { - nm_settings_connection_commit_changes (new_connection, - NULL, - NM_SETTINGS_CONNECTION_COMMIT_REASON_USER_ACTION | NM_SETTINGS_CONNECTION_COMMIT_REASON_ID_CHANGED, - NULL); + nm_settings_connection_update (new_connection, + NULL, + NM_SETTINGS_CONNECTION_PERSIST_MODE_DISK, + NM_SETTINGS_CONNECTION_COMMIT_REASON_USER_ACTION | NM_SETTINGS_CONNECTION_COMMIT_REASON_ID_CHANGED, + "add-and-activate", + NULL); g_dbus_method_invocation_return_value ( context, g_variant_new ("(oo)", @@ -6087,6 +6189,7 @@ constructed (GObject *object) G_CALLBACK (connection_added_cb), self); g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_UPDATED, G_CALLBACK (connection_updated_cb), self); + g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_FLAGS_CHANGED, G_CALLBACK (connection_flags_changed), self); priv->hostname_manager = g_object_ref (nm_hostname_manager_get ()); g_signal_connect (priv->hostname_manager, "notify::" NM_HOSTNAME_MANAGER_HOSTNAME, @@ -6145,6 +6248,7 @@ nm_manager_init (NMManager *self) c_list_init (&priv->link_cb_lst); c_list_init (&priv->active_connections_lst_head); + c_list_init (&priv->delete_volatile_connection_lst_head); priv->platform = g_object_ref (NM_PLATFORM_GET); @@ -6405,6 +6509,11 @@ dispose (GObject *object) CList *iter, *iter_safe; NMActiveConnection *ac, *ac_safe; + nm_clear_g_source (&priv->delete_volatile_connection_idle_id); + _delete_volatile_connection_all (self, FALSE); + nm_assert (!priv->delete_volatile_connection_idle_id); + nm_assert (c_list_is_empty (&priv->delete_volatile_connection_lst_head)); + g_signal_handlers_disconnect_by_func (priv->platform, G_CALLBACK (platform_link_cb), self); @@ -6459,6 +6568,7 @@ dispose (GObject *object) g_signal_handlers_disconnect_by_func (priv->settings, system_unmanaged_devices_changed_cb, self); g_signal_handlers_disconnect_by_func (priv->settings, connection_added_cb, self); g_signal_handlers_disconnect_by_func (priv->settings, connection_updated_cb, self); + g_signal_handlers_disconnect_by_func (priv->settings, connection_flags_changed, self); g_clear_object (&priv->settings); } diff --git a/src/nm-policy.c b/src/nm-policy.c index 5a0b148cd5..81a19feee7 100644 --- a/src/nm-policy.c +++ b/src/nm-policy.c @@ -1224,8 +1224,7 @@ auto_activate_device (NMPolicy *self, NMSettingConnection *s_con; const char *permission; - if ( !nm_settings_connection_is_visible (candidate) - || nm_settings_connection_autoconnect_is_blocked (candidate)) + if (nm_settings_connection_autoconnect_is_blocked (candidate)) continue; s_con = nm_connection_get_setting_connection (NM_CONNECTION (candidate)); @@ -2375,16 +2374,18 @@ connection_removed (NMSettings *settings, } static void -connection_visibility_changed (NMSettings *settings, - NMSettingsConnection *connection, - gpointer user_data) +connection_flags_changed (NMSettings *settings, + NMSettingsConnection *connection, + gpointer user_data) { NMPolicyPrivate *priv = user_data; NMPolicy *self = _PRIV_TO_SELF (priv); - if (nm_settings_connection_is_visible (connection)) - schedule_activate_all (self); - else + if (NM_FLAGS_HAS (nm_settings_connection_get_flags (connection), + NM_SETTINGS_CONNECTION_FLAGS_VISIBLE)) { + if (!nm_settings_connection_autoconnect_is_blocked (connection)) + schedule_activate_all (self); + } else _deactivate_if_active (self, connection); } @@ -2560,10 +2561,10 @@ constructed (GObject *object) g_signal_connect (priv->manager, NM_MANAGER_ACTIVE_CONNECTION_ADDED, (GCallback) active_connection_added, priv); g_signal_connect (priv->manager, NM_MANAGER_ACTIVE_CONNECTION_REMOVED, (GCallback) active_connection_removed, priv); - g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_ADDED, (GCallback) connection_added, priv); - g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_UPDATED, (GCallback) connection_updated, priv); - g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_REMOVED, (GCallback) connection_removed, priv); - g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_VISIBILITY_CHANGED, (GCallback) connection_visibility_changed, priv); + g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_ADDED, (GCallback) connection_added, priv); + g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_UPDATED, (GCallback) connection_updated, priv); + g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_REMOVED, (GCallback) connection_removed, priv); + g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_FLAGS_CHANGED, (GCallback) connection_flags_changed, priv); g_signal_connect (priv->agent_mgr, NM_AGENT_MANAGER_AGENT_REGISTERED, G_CALLBACK (secret_agent_registered), self); diff --git a/src/settings/nm-settings-connection.c b/src/settings/nm-settings-connection.c index 9b289f9f21..3afe7de820 100644 --- a/src/settings/nm-settings-connection.c +++ b/src/settings/nm-settings-connection.c @@ -53,7 +53,6 @@ static void nm_settings_connection_connection_interface_init (NMConnectionInterface *iface); NM_GOBJECT_PROPERTIES_DEFINE (NMSettingsConnection, - PROP_VISIBLE, PROP_UNSAVED, PROP_READY, PROP_FLAGS, @@ -75,14 +74,11 @@ typedef struct _NMSettingsConnectionPrivate { NMSessionMonitor *session_monitor; gulong session_changed_id; - NMSettingsConnectionFlags flags; + NMSettingsConnectionFlags flags:5; bool removed:1; bool ready:1; - /* Is this connection visible by some session? */ - bool visible:1; - bool timestamp_set:1; NMSettingsAutoconnectBlockedReason autoconnect_blocked_reason:4; @@ -323,20 +319,9 @@ find_secret (NMConnection *self, static void set_visible (NMSettingsConnection *self, gboolean new_visible) { - NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self); - - if (new_visible == priv->visible) - return; - priv->visible = new_visible; - _notify (self, PROP_VISIBLE); -} - -gboolean -nm_settings_connection_is_visible (NMSettingsConnection *self) -{ - g_return_val_if_fail (NM_IS_SETTINGS_CONNECTION (self), FALSE); - - return NM_SETTINGS_CONNECTION_GET_PRIVATE (self)->visible; + nm_settings_connection_set_flags (self, + NM_SETTINGS_CONNECTION_FLAGS_VISIBLE, + new_visible); } void @@ -404,7 +389,8 @@ nm_settings_connection_check_permission (NMSettingsConnection *self, priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self); - if (priv->visible == FALSE) + if (!NM_FLAGS_HAS (nm_settings_connection_get_flags (self), + NM_SETTINGS_CONNECTION_FLAGS_VISIBLE)) return FALSE; s_con = nm_connection_get_setting_connection (NM_CONNECTION (self)); @@ -502,33 +488,82 @@ secrets_cleared_cb (NMSettingsConnection *self) } static void -set_unsaved (NMSettingsConnection *self, gboolean now_unsaved) +set_persist_mode (NMSettingsConnection *self, NMSettingsConnectionPersistMode persist_mode) { - NMSettingsConnectionFlags flags = nm_settings_connection_get_flags (self); + NMSettingsConnectionFlags flags = NM_SETTINGS_CONNECTION_FLAGS_NONE; + const NMSettingsConnectionFlags ALL = NM_SETTINGS_CONNECTION_FLAGS_UNSAVED + | NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED + | NM_SETTINGS_CONNECTION_FLAGS_VOLATILE; - if (NM_FLAGS_HAS (flags, NM_SETTINGS_CONNECTION_FLAGS_UNSAVED) != !!now_unsaved) { - if (now_unsaved) - flags |= NM_SETTINGS_CONNECTION_FLAGS_UNSAVED; - else { - flags &= ~(NM_SETTINGS_CONNECTION_FLAGS_UNSAVED | - NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED | - NM_SETTINGS_CONNECTION_FLAGS_VOLATILE); - } - nm_settings_connection_set_flags_all (self, flags); + if (persist_mode == NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP) + return; + + switch (persist_mode) { + case NM_SETTINGS_CONNECTION_PERSIST_MODE_DISK: + flags = NM_SETTINGS_CONNECTION_FLAGS_NONE; + break; + case NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY: + case NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_DETACHED: + case NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY: + flags = NM_SETTINGS_CONNECTION_FLAGS_UNSAVED; + break; + case NM_SETTINGS_CONNECTION_PERSIST_MODE_VOLATILE_DETACHED: + case NM_SETTINGS_CONNECTION_PERSIST_MODE_VOLATILE_ONLY: + flags = NM_SETTINGS_CONNECTION_FLAGS_UNSAVED | + NM_SETTINGS_CONNECTION_FLAGS_VOLATILE; + break; + case NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP: + g_return_if_reached (); } + + nm_settings_connection_set_flags_full (self, ALL, flags); } static void connection_changed_cb (NMSettingsConnection *self, gpointer unused) { - set_unsaved (self, TRUE); + set_persist_mode (self, NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY); _emit_updated (self, FALSE); } -gboolean -nm_settings_connection_replace_settings_prepare (NMSettingsConnection *self, - NMConnection *new_connection, - GError **error) +static gboolean +_delete (NMSettingsConnection *self, GError **error) +{ + NMSettingsConnectionClass *klass; + GError *local = NULL; + const char *filename; + + nm_assert (NM_IS_SETTINGS_CONNECTION (self)); + + klass = NM_SETTINGS_CONNECTION_GET_CLASS (self); + if (!klass->delete) { + g_set_error (&local, + NM_SETTINGS_ERROR, + NM_SETTINGS_ERROR_FAILED, + "delete not supported"); + goto fail; + } + if (!klass->delete (self, + &local)) + goto fail; + + filename = nm_settings_connection_get_filename (self); + if (filename) { + _LOGD ("delete: success deleting connection (\"%s\")", filename); + nm_settings_connection_set_filename (self, NULL); + } else + _LOGT ("delete: success deleting connection (no-file)"); + return TRUE; +fail: + _LOGD ("delete: failure deleting connection: %s", local->message); + g_propagate_error (error, local); + return FALSE; +} + +static gboolean +_update_prepare (NMSettingsConnection *self, + NMConnection *new_connection, + GError **error) { NMSettingsConnectionPrivate *priv; @@ -553,173 +588,137 @@ nm_settings_connection_replace_settings_prepare (NMSettingsConnection *self, } gboolean -nm_settings_connection_replace_settings_full (NMSettingsConnection *self, - NMConnection *new_connection, - gboolean prepare_new_connection, - gboolean update_unsaved, - const char *log_diff_name, - GError **error) +nm_settings_connection_update (NMSettingsConnection *self, + NMConnection *new_connection, + NMSettingsConnectionPersistMode persist_mode, + NMSettingsConnectionCommitReason commit_reason, + const char *log_diff_name, + GError **error) { NMSettingsConnectionPrivate *priv; + NMSettingsConnectionClass *klass = NULL; + gs_unref_object NMConnection *reread_connection = NULL; + NMConnection *replace_connection; + gboolean replaced = FALSE; + gs_free char *logmsg_change = NULL; + GError *local = NULL; + gboolean save_to_disk; g_return_val_if_fail (NM_IS_SETTINGS_CONNECTION (self), FALSE); - g_return_val_if_fail (NM_IS_CONNECTION (new_connection), FALSE); priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self); - if ( prepare_new_connection - && !nm_settings_connection_replace_settings_prepare (self, - new_connection, - error)) - return FALSE; + save_to_disk = (persist_mode == NM_SETTINGS_CONNECTION_PERSIST_MODE_DISK) + || ( persist_mode == NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP + && !nm_settings_connection_get_unsaved (self)); + + if (save_to_disk) { + klass = NM_SETTINGS_CONNECTION_GET_CLASS (self); + if (!klass->commit_changes) { + g_set_error (&local, + NM_SETTINGS_ERROR, + NM_SETTINGS_ERROR_FAILED, + "writing settings not supported"); + goto out; + } + } - /* Do nothing if there's nothing to update */ - if (nm_connection_compare (NM_CONNECTION (self), - new_connection, - NM_SETTING_COMPARE_FLAG_EXACT)) { - return TRUE; + if ( new_connection + && !_update_prepare (self, + new_connection, + &local)) + goto out; + + if (save_to_disk) { + if (!klass->commit_changes (self, + new_connection ?: NM_CONNECTION (self), + commit_reason, + &reread_connection, + &logmsg_change, + &local)) + goto out; + + if ( reread_connection + && !_update_prepare (self, + reread_connection, + &local)) + goto out; } + replace_connection = reread_connection ?: new_connection; + /* Disconnect the changed signal to ensure we don't set Unsaved when * it's not required. */ g_signal_handlers_block_by_func (self, G_CALLBACK (connection_changed_cb), NULL); - if (log_diff_name) - nm_utils_log_connection_diff (new_connection, NM_CONNECTION (self), LOGL_DEBUG, LOGD_CORE, log_diff_name, "++ "); + /* Do nothing if there's nothing to update */ + if ( replace_connection + && !nm_connection_compare (NM_CONNECTION (self), + replace_connection, + NM_SETTING_COMPARE_FLAG_EXACT)) { + if (log_diff_name) + nm_utils_log_connection_diff (replace_connection, NM_CONNECTION (self), LOGL_DEBUG, LOGD_CORE, log_diff_name, "++ "); - nm_connection_replace_settings_from_connection (NM_CONNECTION (self), new_connection); + nm_connection_replace_settings_from_connection (NM_CONNECTION (self), replace_connection); - _LOGD ("replace settings from connection %p (%s)", new_connection, nm_connection_get_id (NM_CONNECTION (self))); + replaced = TRUE; + } nm_settings_connection_set_flags (self, NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED | NM_SETTINGS_CONNECTION_FLAGS_VOLATILE, FALSE); - /* Cache the just-updated system secrets in case something calls - * nm_connection_clear_secrets() and clears them. - */ - update_system_secrets_cache (self); + if (replaced) { + /* Cache the just-updated system secrets in case something calls + * nm_connection_clear_secrets() and clears them. + */ + update_system_secrets_cache (self); - /* Add agent and always-ask secrets back; they won't necessarily be - * in the replacement connection data if it was eg reread from disk. - */ - if (priv->agent_secrets) { - GVariant *dict; + /* Add agent and always-ask secrets back; they won't necessarily be + * in the replacement connection data if it was eg reread from disk. + */ + if (priv->agent_secrets) { + GVariant *dict; - dict = nm_connection_to_dbus (priv->agent_secrets, NM_CONNECTION_SERIALIZE_ONLY_SECRETS); - if (dict) { - (void) nm_connection_update_secrets (NM_CONNECTION (self), NULL, dict, NULL); - g_variant_unref (dict); + dict = nm_connection_to_dbus (priv->agent_secrets, NM_CONNECTION_SERIALIZE_ONLY_SECRETS); + if (dict) { + (void) nm_connection_update_secrets (NM_CONNECTION (self), NULL, dict, NULL); + g_variant_unref (dict); + } } } nm_settings_connection_recheck_visibility (self); - /* Manually emit changed signal since we disconnected the handler, but - * only update Unsaved if the caller wanted us to. - */ - if (update_unsaved) - set_unsaved (self, TRUE); + set_persist_mode (self, persist_mode); + + if (NM_IN_SET (persist_mode, NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY, + NM_SETTINGS_CONNECTION_PERSIST_MODE_VOLATILE_ONLY)) + _delete (self, NULL); + else if (NM_IN_SET (persist_mode, NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_DETACHED, + NM_SETTINGS_CONNECTION_PERSIST_MODE_VOLATILE_DETACHED)) + nm_settings_connection_set_filename (self, NULL); g_signal_handlers_unblock_by_func (self, G_CALLBACK (connection_changed_cb), NULL); _emit_updated (self, TRUE); - return TRUE; -} - -/* Update the settings of this connection to match that of 'new_connection', - * taking care to make a private copy of secrets. - */ -gboolean -nm_settings_connection_replace_settings (NMSettingsConnection *self, - NMConnection *new_connection, - gboolean update_unsaved, - const char *log_diff_name, - GError **error) -{ - return nm_settings_connection_replace_settings_full (self, - new_connection, - TRUE, - update_unsaved, - log_diff_name, - error); -} - -gboolean -nm_settings_connection_commit_changes (NMSettingsConnection *self, - NMConnection *new_connection, - NMSettingsConnectionCommitReason commit_reason, - GError **error) -{ - NMSettingsConnectionClass *klass; - gs_free_error GError *local = NULL; - gs_unref_object NMConnection *reread_connection = NULL; - gs_free char *logmsg_change = NULL; - - g_return_val_if_fail (NM_IS_SETTINGS_CONNECTION (self), FALSE); - - klass = NM_SETTINGS_CONNECTION_GET_CLASS (self); - if (!klass->commit_changes) { - _LOGW ("write: setting plugin %s does not support to write connection", - G_OBJECT_TYPE_NAME (self)); - g_set_error (error, - NM_SETTINGS_ERROR, - NM_SETTINGS_ERROR_FAILED, - "writing settings not supported"); - return FALSE; - } - - if ( new_connection - && !nm_settings_connection_replace_settings_prepare (self, - new_connection, - &local)) { - _LOGW ("write: failed to prepare connection for writing: %s", - local->message); - g_propagate_error (error, g_steal_pointer (&local)); +out: + if (local) { + _LOGI ("write: failure to update connection: %s", local->message); + g_propagate_error (error, local); return FALSE; } - if (!klass->commit_changes (self, - new_connection, - commit_reason, - &reread_connection, - &logmsg_change, - &local)) { - _LOGW ("write: failure to write setting: %s", - local->message); - g_propagate_error (error, g_steal_pointer (&local)); - return FALSE; + if (persist_mode == NM_SETTINGS_CONNECTION_PERSIST_MODE_DISK) { + if (reread_connection) + _LOGI ("write: successfully updated (%s), connection was modified in the process", logmsg_change); + else if (new_connection) + _LOGI ("write: successfully updated (%s)", logmsg_change); + else + _LOGI ("write: successfully commited (%s)", logmsg_change); } - - if (reread_connection || new_connection) { - if (!nm_settings_connection_replace_settings_full (self, - reread_connection ?: new_connection, - !reread_connection, - FALSE, - new_connection - ? "update-during-write" - : "replace-and-commit-disk", - &local)) { - /* this can't really happen, because at this point replace-settings - * is no longer supposed to fail. It's a bug. */ - _LOGE ("write: replacing setting failed: %s", - local->message); - g_propagate_error (error, g_steal_pointer (&local)); - g_return_val_if_reached (FALSE); - } - } - - set_unsaved (self, FALSE); - - if (reread_connection) - _LOGI ("write: successfully updated (%s), connection was modified in the process", logmsg_change); - else if (new_connection) - _LOGI ("write: successfully updated (%s)", logmsg_change); - else - _LOGI ("write: successfully commited (%s)", logmsg_change); - return TRUE; } @@ -764,25 +763,14 @@ nm_settings_connection_delete (NMSettingsConnection *self, GError **error) { gs_unref_object NMSettingsConnection *self_keep_alive = NULL; - NMSettingsConnectionClass *klass; NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self); NMConnection *for_agents; g_return_val_if_fail (NM_IS_SETTINGS_CONNECTION (self), FALSE); - klass = NM_SETTINGS_CONNECTION_GET_CLASS (self); - self_keep_alive = g_object_ref (self); - if (!klass->delete) { - g_set_error (error, - NM_SETTINGS_ERROR, - NM_SETTINGS_ERROR_FAILED, - "delete not supported"); - return FALSE; - } - if (!klass->delete (self, - error)) + if (!_delete (self, error)) return FALSE; set_visible (self, FALSE); @@ -997,10 +985,12 @@ nm_settings_connection_new_secrets (NMSettingsConnection *self, update_system_secrets_cache (self); update_agent_secrets_cache (self, NULL); - nm_settings_connection_commit_changes (self, - NULL, - NM_SETTINGS_CONNECTION_COMMIT_REASON_NONE, - NULL); + nm_settings_connection_update (self, + NULL, + NM_SETTINGS_CONNECTION_PERSIST_MODE_DISK, + NM_SETTINGS_CONNECTION_COMMIT_REASON_NONE, + "new-secrets", + NULL); return TRUE; } @@ -1114,10 +1104,12 @@ get_secrets_done_cb (NMAgentManager *manager, setting_name, call_id); - nm_settings_connection_commit_changes (self, - NULL, - NM_SETTINGS_CONNECTION_COMMIT_REASON_NONE, - NULL); + nm_settings_connection_update (self, + NULL, + NM_SETTINGS_CONNECTION_PERSIST_MODE_DISK, + NM_SETTINGS_CONNECTION_COMMIT_REASON_NONE, + "get-new-secrets", + NULL); } else { _LOGD ("(%s:%p) new agent secrets processed", setting_name, @@ -1585,8 +1577,9 @@ typedef struct { NMAgentManager *agent_mgr; NMAuthSubject *subject; NMConnection *new_settings; - gboolean save_to_disk; + NMSettingsUpdate2Flags flags; char *audit_args; + bool is_update2:1; } UpdateInfo; static void @@ -1650,7 +1643,13 @@ update_complete (NMSettingsConnection *self, { if (error) g_dbus_method_invocation_return_gerror (info->context, error); - else + else if (info->is_update2) { + GVariantBuilder result; + + g_variant_builder_init (&result, G_VARIANT_TYPE ("a{sv}")); + g_dbus_method_invocation_return_value (info->context, + g_variant_new ("(@a{sv})", g_variant_builder_end (&result))); + } else g_dbus_method_invocation_return_value (info->context, NULL); nm_audit_log_connection_op (NM_AUDIT_OP_CONN_UPDATE, self, !error, info->audit_args, @@ -1673,6 +1672,8 @@ update_auth_cb (NMSettingsConnection *self, UpdateInfo *info = data; NMSettingsConnectionCommitReason commit_reason; gs_free_error GError *local = NULL; + NMSettingsConnectionPersistMode persist_mode; + const char *log_diff_name; if (error) { update_complete (self, info, error); @@ -1693,7 +1694,9 @@ update_auth_cb (NMSettingsConnection *self, */ update_agent_secrets_cache (self, info->new_settings); } + } + if (info->new_settings) { if (nm_audit_manager_audit_enabled (nm_audit_manager_get ())) { gs_unref_hashtable GHashTable *diff = NULL; gboolean same; @@ -1707,36 +1710,47 @@ update_auth_cb (NMSettingsConnection *self, } } - if (!info->save_to_disk) { - if (info->new_settings) { - nm_settings_connection_replace_settings (self, - info->new_settings, - TRUE, - "replace-unsaved", - &local); - } - goto out; - } - - if (info->new_settings) { - if (!nm_settings_connection_replace_settings_prepare (self, - info->new_settings, - &local)) - goto out; - } - commit_reason = NM_SETTINGS_CONNECTION_COMMIT_REASON_USER_ACTION; if ( info->new_settings && !nm_streq0 (nm_connection_get_id (NM_CONNECTION (self)), nm_connection_get_id (info->new_settings))) commit_reason |= NM_SETTINGS_CONNECTION_COMMIT_REASON_ID_CHANGED; - nm_settings_connection_commit_changes (self, - info->new_settings, - commit_reason, - &local); + if (NM_FLAGS_HAS (info->flags, NM_SETTINGS_UPDATE2_FLAG_TO_DISK)) + persist_mode = NM_SETTINGS_CONNECTION_PERSIST_MODE_DISK; + else if (NM_FLAGS_HAS (info->flags, NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY)) + persist_mode = NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY; + else if (NM_FLAGS_HAS (info->flags, NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_DETACHED)) { + persist_mode = NM_FLAGS_HAS (info->flags, NM_SETTINGS_UPDATE2_FLAG_VOLATILE) + ? NM_SETTINGS_CONNECTION_PERSIST_MODE_VOLATILE_DETACHED + : NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_DETACHED; + } else if (NM_FLAGS_HAS (info->flags, NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_ONLY)) { + persist_mode = NM_FLAGS_HAS (info->flags, NM_SETTINGS_UPDATE2_FLAG_VOLATILE) + ? NM_SETTINGS_CONNECTION_PERSIST_MODE_VOLATILE_ONLY + : NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY; + } else + persist_mode = NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP; + + if ( persist_mode == NM_SETTINGS_CONNECTION_PERSIST_MODE_DISK + || ( persist_mode == NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP + && !nm_settings_connection_get_unsaved (self))) + log_diff_name = info->new_settings ? "update-settings" : "write-out-to-disk"; + else + log_diff_name = info->new_settings ? "update-unsaved" : "make-unsaved"; + + if (NM_FLAGS_HAS (info->flags, NM_SETTINGS_UPDATE2_FLAG_BLOCK_AUTOCONNECT)) { + nm_settings_connection_autoconnect_blocked_reason_set (self, + NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_USER_REQUEST, + TRUE); + } + + nm_settings_connection_update (self, + info->new_settings, + persist_mode, + commit_reason, + log_diff_name, + &local); -out: if (!local) { gs_unref_object NMConnection *for_agent = NULL; @@ -1785,10 +1799,11 @@ get_update_modify_permission (NMConnection *old, NMConnection *new) } static void -settings_connection_update_helper (NMSettingsConnection *self, - GDBusMethodInvocation *context, - GVariant *new_settings, - gboolean save_to_disk) +settings_connection_update (NMSettingsConnection *self, + gboolean is_update2, + GDBusMethodInvocation *context, + GVariant *new_settings, + NMSettingsUpdate2Flags flags) { NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self); NMAuthSubject *subject = NULL; @@ -1798,8 +1813,6 @@ settings_connection_update_helper (NMSettingsConnection *self, const char *permission; char *error_desc = NULL; - g_assert (new_settings != NULL || save_to_disk == TRUE); - /* If the connection is read-only, that has to be changed at the source of * the problem (ex a system settings plugin that can't write connections out) * instead of over D-Bus. @@ -1809,12 +1822,22 @@ settings_connection_update_helper (NMSettingsConnection *self, /* Check if the settings are valid first */ if (new_settings) { - tmp = _nm_simple_connection_new_from_dbus (new_settings, - NM_SETTING_PARSE_FLAGS_STRICT - | NM_SETTING_PARSE_FLAGS_NORMALIZE, - &error); - if (!tmp) + if (!g_variant_is_of_type (new_settings, NM_VARIANT_TYPE_CONNECTION)) { + g_set_error_literal (&error, + NM_SETTINGS_ERROR, + NM_SETTINGS_ERROR_INVALID_ARGUMENTS, + "settings is of invalid type"); goto error; + } + + if (g_variant_n_children (new_settings) > 0) { + tmp = _nm_simple_connection_new_from_dbus (new_settings, + NM_SETTING_PARSE_FLAGS_STRICT + | NM_SETTING_PARSE_FLAGS_NORMALIZE, + &error); + if (!tmp) + goto error; + } } subject = _new_auth_subject (context, &error); @@ -1836,10 +1859,11 @@ settings_connection_update_helper (NMSettingsConnection *self, } info = g_slice_new0 (UpdateInfo); + info->is_update2 = is_update2; info->context = context; info->agent_mgr = g_object_ref (priv->agent_mgr); info->subject = subject; - info->save_to_disk = save_to_disk; + info->flags = flags; info->new_settings = tmp; permission = get_update_modify_permission (NM_CONNECTION (self), @@ -1862,7 +1886,7 @@ impl_settings_connection_update (NMSettingsConnection *self, GDBusMethodInvocation *context, GVariant *new_settings) { - settings_connection_update_helper (self, context, new_settings, TRUE); + settings_connection_update (self, FALSE, context, new_settings, NM_SETTINGS_UPDATE2_FLAG_TO_DISK); } static void @@ -1870,14 +1894,76 @@ impl_settings_connection_update_unsaved (NMSettingsConnection *self, GDBusMethodInvocation *context, GVariant *new_settings) { - settings_connection_update_helper (self, context, new_settings, FALSE); + settings_connection_update (self, FALSE, context, new_settings, NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY); } static void impl_settings_connection_save (NMSettingsConnection *self, GDBusMethodInvocation *context) { - settings_connection_update_helper (self, context, NULL, TRUE); + settings_connection_update (self, FALSE, context, NULL, NM_SETTINGS_UPDATE2_FLAG_TO_DISK); +} + +static void +impl_settings_connection_update2 (NMSettingsConnection *self, + GDBusMethodInvocation *context, + GVariant *settings, + guint32 flags_u, + GVariant *args) +{ + GError *error = NULL; + GVariantIter iter; + const char *args_name; + const NMSettingsUpdate2Flags flags = (NMSettingsUpdate2Flags) flags_u; + const NMSettingsUpdate2Flags ALL_PERSIST_MODES = NM_SETTINGS_UPDATE2_FLAG_TO_DISK + | NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY + | NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_DETACHED + | NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_ONLY; + + if (NM_FLAGS_ANY (flags_u, ~((guint32) (ALL_PERSIST_MODES | + NM_SETTINGS_UPDATE2_FLAG_VOLATILE | + NM_SETTINGS_UPDATE2_FLAG_BLOCK_AUTOCONNECT)))) { + error = g_error_new_literal (NM_SETTINGS_ERROR, + NM_SETTINGS_ERROR_INVALID_ARGUMENTS, + "Unknown flags"); + g_dbus_method_invocation_take_error (context, error); + return; + } + + if ( ( NM_FLAGS_ANY (flags, ALL_PERSIST_MODES) + && !nm_utils_is_power_of_two (flags & ALL_PERSIST_MODES)) + || ( NM_FLAGS_HAS (flags, NM_SETTINGS_UPDATE2_FLAG_VOLATILE) + && !NM_FLAGS_ANY (flags, NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_DETACHED | + NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_ONLY))) { + error = g_error_new_literal (NM_SETTINGS_ERROR, + NM_SETTINGS_ERROR_INVALID_ARGUMENTS, + "Conflicting flags"); + g_dbus_method_invocation_take_error (context, error); + return; + } + + if (!g_variant_is_of_type (args, G_VARIANT_TYPE ("a{sv}"))) { + error = g_error_new_literal (NM_SETTINGS_ERROR, + NM_SETTINGS_ERROR_INVALID_ARGUMENTS, + "args is of invalid type"); + g_dbus_method_invocation_take_error (context, error); + return; + } + + g_variant_iter_init (&iter, args); + while (g_variant_iter_next (&iter, "{&sv}", &args_name, NULL)) { + error = g_error_new (NM_SETTINGS_ERROR, + NM_SETTINGS_ERROR_INVALID_ARGUMENTS, + "Unsupported argument '%s'", args_name); + g_dbus_method_invocation_take_error (context, error); + return; + } + + settings_connection_update (self, + TRUE, + context, + settings, + flags); } static void @@ -2055,10 +2141,12 @@ dbus_clear_secrets_auth_cb (NMSettingsConnection *self, nm_connection_get_path (NM_CONNECTION (self)), NM_CONNECTION (self)); - nm_settings_connection_commit_changes (self, - NULL, - NM_SETTINGS_CONNECTION_COMMIT_REASON_NONE, - &local); + nm_settings_connection_update (self, + NULL, + NM_SETTINGS_CONNECTION_PERSIST_MODE_DISK, + NM_SETTINGS_CONNECTION_COMMIT_REASON_NONE, + "clear-secrets", + &local); nm_audit_log_connection_op (NM_AUDIT_OP_CONN_CLEAR_SECRETS, self, !local, NULL, subject, local ? local->message : NULL); @@ -2115,6 +2203,14 @@ nm_settings_connection_get_unsaved (NMSettingsConnection *self) /*****************************************************************************/ +NM_UTILS_FLAGS2STR_DEFINE_STATIC (_settings_connection_flags_to_string, NMSettingsConnectionFlags, + NM_UTILS_FLAGS2STR (NM_SETTINGS_CONNECTION_FLAGS_NONE, "none"), + NM_UTILS_FLAGS2STR (NM_SETTINGS_CONNECTION_FLAGS_UNSAVED, "unsaved"), + NM_UTILS_FLAGS2STR (NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED, "nm-generatd"), + NM_UTILS_FLAGS2STR (NM_SETTINGS_CONNECTION_FLAGS_VOLATILE, "volatile"), + NM_UTILS_FLAGS2STR (NM_SETTINGS_CONNECTION_FLAGS_VISIBLE, "visible"), +); + NMSettingsConnectionFlags nm_settings_connection_get_flags (NMSettingsConnection *self) { @@ -2126,35 +2222,38 @@ nm_settings_connection_get_flags (NMSettingsConnection *self) NMSettingsConnectionFlags nm_settings_connection_set_flags (NMSettingsConnection *self, NMSettingsConnectionFlags flags, gboolean set) { - NMSettingsConnectionFlags new_flags; - - g_return_val_if_fail (NM_IS_SETTINGS_CONNECTION (self), NM_SETTINGS_CONNECTION_FLAGS_NONE); - g_return_val_if_fail ((flags & ~NM_SETTINGS_CONNECTION_FLAGS_ALL) == 0, NM_SETTINGS_CONNECTION_FLAGS_NONE); - - new_flags = NM_SETTINGS_CONNECTION_GET_PRIVATE (self)->flags; - if (set) - new_flags |= flags; - else - new_flags &= ~flags; - return nm_settings_connection_set_flags_all (self, new_flags); + return nm_settings_connection_set_flags_full (self, + flags, + set ? flags : NM_SETTINGS_CONNECTION_FLAGS_NONE); } NMSettingsConnectionFlags -nm_settings_connection_set_flags_all (NMSettingsConnection *self, NMSettingsConnectionFlags flags) +nm_settings_connection_set_flags_full (NMSettingsConnection *self, + NMSettingsConnectionFlags mask, + NMSettingsConnectionFlags value) { NMSettingsConnectionPrivate *priv; NMSettingsConnectionFlags old_flags; g_return_val_if_fail (NM_IS_SETTINGS_CONNECTION (self), NM_SETTINGS_CONNECTION_FLAGS_NONE); - g_return_val_if_fail ((flags & ~NM_SETTINGS_CONNECTION_FLAGS_ALL) == 0, NM_SETTINGS_CONNECTION_FLAGS_NONE); + nm_assert (mask && !NM_FLAGS_ANY (mask, ~NM_SETTINGS_CONNECTION_FLAGS_ALL)); + nm_assert (!NM_FLAGS_ANY (value, ~mask)); + priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self); + value = (priv->flags & ~mask) | value; + old_flags = priv->flags; - if (old_flags != flags) { - _LOGT ("update settings-connection flags to 0x%x (was 0x%x)", (guint) flags, (guint) priv->flags); - priv->flags = flags; + if (old_flags != value) { + char buf1[255], buf2[255]; + + _LOGT ("update settings-connection flags to %s (was %s)", + _settings_connection_flags_to_string (value, buf1, sizeof (buf1)), + _settings_connection_flags_to_string (priv->flags, buf2, sizeof (buf2))); + priv->flags = value; + nm_assert (priv->flags == value); _notify (self, PROP_FLAGS); - if (NM_FLAGS_HAS (old_flags, NM_SETTINGS_CONNECTION_FLAGS_UNSAVED) != NM_FLAGS_HAS (flags, NM_SETTINGS_CONNECTION_FLAGS_UNSAVED)) + if (NM_FLAGS_HAS (old_flags, NM_SETTINGS_CONNECTION_FLAGS_UNSAVED) != NM_FLAGS_HAS (value, NM_SETTINGS_CONNECTION_FLAGS_UNSAVED)) _notify (self, PROP_UNSAVED); } return old_flags; @@ -2670,45 +2769,29 @@ nm_settings_connection_autoconnect_blocked_reason_set_full (NMSettingsConnection gboolean nm_settings_connection_autoconnect_is_blocked (NMSettingsConnection *self) { - NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self); + NMSettingsConnectionPrivate *priv; + NMSettingsConnectionFlags flags; - return priv->autoconnect_blocked_reason != NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_NONE - || priv->autoconnect_retries == 0; -} + g_return_val_if_fail (NM_IS_SETTINGS_CONNECTION (self), TRUE); -/*****************************************************************************/ + priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self); -/** - * nm_settings_connection_get_nm_generated: - * @self: an #NMSettingsConnection - * - * Gets the "nm-generated" flag on @self. - * - * A connection is "nm-generated" if it was generated by - * nm_device_generate_connection() and has not been modified or - * saved by the user since then. - */ -gboolean -nm_settings_connection_get_nm_generated (NMSettingsConnection *self) -{ - return NM_FLAGS_HAS (nm_settings_connection_get_flags (self), NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED); -} + if (priv->autoconnect_blocked_reason != NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_NONE) + return TRUE; + if (priv->autoconnect_retries == 0) + return TRUE; -/** - * nm_settings_connection_get_volatile: - * @self: an #NMSettingsConnection - * - * Gets the "volatile" flag on @self. - * - * The connection is marked as volatile and will be removed when - * it disconnects. - */ -gboolean -nm_settings_connection_get_volatile (NMSettingsConnection *self) -{ - return NM_FLAGS_HAS (nm_settings_connection_get_flags (self), NM_SETTINGS_CONNECTION_FLAGS_VOLATILE); + flags = priv->flags; + if (NM_FLAGS_HAS (flags, NM_SETTINGS_CONNECTION_FLAGS_VOLATILE)) + return TRUE; + if (!NM_FLAGS_HAS (flags, NM_SETTINGS_CONNECTION_FLAGS_VISIBLE)) + return TRUE; + + return FALSE; } +/*****************************************************************************/ + gboolean nm_settings_connection_get_ready (NMSettingsConnection *self) { @@ -2789,7 +2872,6 @@ nm_settings_connection_init (NMSettingsConnection *self) priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NM_TYPE_SETTINGS_CONNECTION, NMSettingsConnectionPrivate); self->_priv = priv; - priv->visible = FALSE; priv->ready = TRUE; c_list_init (&priv->call_ids_lst_head); @@ -2867,12 +2949,8 @@ get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { NMSettingsConnection *self = NM_SETTINGS_CONNECTION (object); - NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self); switch (prop_id) { - case PROP_VISIBLE: - g_value_set_boolean (value, priv->visible); - break; case PROP_UNSAVED: g_value_set_boolean (value, nm_settings_connection_get_unsaved (self)); break; @@ -2925,12 +3003,6 @@ nm_settings_connection_class_init (NMSettingsConnectionClass *class) class->supports_secrets = supports_secrets; - obj_properties[PROP_VISIBLE] = - g_param_spec_boolean (NM_SETTINGS_CONNECTION_VISIBLE, "", "", - FALSE, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS); - obj_properties[PROP_UNSAVED] = g_param_spec_boolean (NM_SETTINGS_CONNECTION_UNSAVED, "", "", FALSE, @@ -2997,6 +3069,7 @@ nm_settings_connection_class_init (NMSettingsConnectionClass *class) "GetSecrets", impl_settings_connection_get_secrets, "ClearSecrets", impl_settings_connection_clear_secrets, "Save", impl_settings_connection_save, + "Update2", impl_settings_connection_update2, NULL); } diff --git a/src/settings/nm-settings-connection.h b/src/settings/nm-settings-connection.h index 3672bc08c1..051fcf7ff9 100644 --- a/src/settings/nm-settings-connection.h +++ b/src/settings/nm-settings-connection.h @@ -44,8 +44,9 @@ #define NM_SETTINGS_CONNECTION_UPDATED_INTERNAL "updated-internal" /* Properties */ -#define NM_SETTINGS_CONNECTION_VISIBLE "visible" #define NM_SETTINGS_CONNECTION_UNSAVED "unsaved" + +/* Internal properties */ #define NM_SETTINGS_CONNECTION_READY "ready" #define NM_SETTINGS_CONNECTION_FLAGS "flags" #define NM_SETTINGS_CONNECTION_FILENAME "filename" @@ -61,22 +62,25 @@ * @NM_SETTINGS_CONNECTION_FLAGS_VOLATILE: The connection will be deleted * when it disconnects. That is for in-memory connections (unsaved), which are * currently active but cleanup on disconnect. + * @NM_SETTINGS_CONNECTION_FLAGS_VISIBLE: The connection is visible * @NM_SETTINGS_CONNECTION_FLAGS_ALL: special mask, for all known flags * * #NMSettingsConnection flags. **/ -typedef enum -{ - NM_SETTINGS_CONNECTION_FLAGS_NONE = 0x00, - NM_SETTINGS_CONNECTION_FLAGS_UNSAVED = 0x01, - NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED = 0x02, - NM_SETTINGS_CONNECTION_FLAGS_VOLATILE = 0x04, +typedef enum { + NM_SETTINGS_CONNECTION_FLAGS_NONE = 0, + + NM_SETTINGS_CONNECTION_FLAGS_UNSAVED = (1LL << 0), + NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED = (1LL << 1), + NM_SETTINGS_CONNECTION_FLAGS_VOLATILE = (1LL << 2), + + NM_SETTINGS_CONNECTION_FLAGS_VISIBLE = (1LL << 3), __NM_SETTINGS_CONNECTION_FLAGS_LAST, NM_SETTINGS_CONNECTION_FLAGS_ALL = ((__NM_SETTINGS_CONNECTION_FLAGS_LAST - 1) << 1) - 1, } NMSettingsConnectionFlags; -typedef enum { /*< skip >*/ +typedef enum { NM_SETTINGS_CONNECTION_COMMIT_REASON_NONE = 0, NM_SETTINGS_CONNECTION_COMMIT_REASON_USER_ACTION = (1LL << 0), NM_SETTINGS_CONNECTION_COMMIT_REASON_ID_CHANGED = (1LL << 1), @@ -131,27 +135,22 @@ gboolean nm_settings_connection_has_unmodified_applied_connection (NMSettingsCon NMConnection *applied_connection, NMSettingCompareFlags compare_flage); -gboolean nm_settings_connection_commit_changes (NMSettingsConnection *self, - NMConnection *new_connection, - NMSettingsConnectionCommitReason commit_reason, - GError **error); - -gboolean nm_settings_connection_replace_settings_prepare (NMSettingsConnection *self, - NMConnection *new_connection, - GError **error); - -gboolean nm_settings_connection_replace_settings (NMSettingsConnection *self, - NMConnection *new_connection, - gboolean update_unsaved, - const char *log_diff_name, - GError **error); - -gboolean nm_settings_connection_replace_settings_full (NMSettingsConnection *self, - NMConnection *new_connection, - gboolean prepare_new_connection, - gboolean update_unsaved, - const char *log_diff_name, - GError **error); +typedef enum { + NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP, + NM_SETTINGS_CONNECTION_PERSIST_MODE_DISK, + NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY, + NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_DETACHED, + NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY, + NM_SETTINGS_CONNECTION_PERSIST_MODE_VOLATILE_DETACHED, + NM_SETTINGS_CONNECTION_PERSIST_MODE_VOLATILE_ONLY, +} NMSettingsConnectionPersistMode; + +gboolean nm_settings_connection_update (NMSettingsConnection *self, + NMConnection *new_connection, + NMSettingsConnectionPersistMode persist_mode, + NMSettingsConnectionCommitReason commit_reason, + const char *log_diff_name, + GError **error); gboolean nm_settings_connection_delete (NMSettingsConnection *self, GError **error); @@ -181,8 +180,6 @@ NMSettingsConnectionCallId *nm_settings_connection_get_secrets (NMSettingsConnec void nm_settings_connection_cancel_secrets (NMSettingsConnection *self, NMSettingsConnectionCallId *call_id); -gboolean nm_settings_connection_is_visible (NMSettingsConnection *self); - void nm_settings_connection_recheck_visibility (NMSettingsConnection *self); gboolean nm_settings_connection_check_permission (NMSettingsConnection *self, @@ -194,7 +191,7 @@ gboolean nm_settings_connection_get_unsaved (NMSettingsConnection *self); NMSettingsConnectionFlags nm_settings_connection_get_flags (NMSettingsConnection *self); NMSettingsConnectionFlags nm_settings_connection_set_flags (NMSettingsConnection *self, NMSettingsConnectionFlags flags, gboolean set); -NMSettingsConnectionFlags nm_settings_connection_set_flags_all (NMSettingsConnection *self, NMSettingsConnectionFlags flags); +NMSettingsConnectionFlags nm_settings_connection_set_flags_full (NMSettingsConnection *self, NMSettingsConnectionFlags mask, NMSettingsConnectionFlags value); int nm_settings_connection_cmp_timestamp (NMSettingsConnection *ac, NMSettingsConnection *ab); int nm_settings_connection_cmp_timestamp_p_with_data (gconstpointer pa, gconstpointer pb, gpointer user_data); @@ -243,9 +240,6 @@ nm_settings_connection_autoconnect_blocked_reason_set (NMSettingsConnection *sel gboolean nm_settings_connection_autoconnect_is_blocked (NMSettingsConnection *self); -gboolean nm_settings_connection_get_nm_generated (NMSettingsConnection *self); -gboolean nm_settings_connection_get_volatile (NMSettingsConnection *self); - gboolean nm_settings_connection_get_ready (NMSettingsConnection *self); void nm_settings_connection_set_ready (NMSettingsConnection *self, gboolean ready); diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c index 081997058f..21fdf9e067 100644 --- a/src/settings/nm-settings.c +++ b/src/settings/nm-settings.c @@ -75,7 +75,6 @@ #include "nm-audit-manager.h" #include "NetworkManagerUtils.h" #include "nm-dispatcher.h" -#include "nm-inotify-helper.h" #include "nm-hostname-manager.h" #include "introspection/org.freedesktop.NetworkManager.Settings.h" @@ -84,13 +83,8 @@ #define EXPORT(sym) void * __export_##sym = &sym; -EXPORT(nm_inotify_helper_get_type) -EXPORT(nm_inotify_helper_get) -EXPORT(nm_inotify_helper_add_watch) -EXPORT(nm_inotify_helper_remove_watch) - EXPORT(nm_settings_connection_get_type) -EXPORT(nm_settings_connection_replace_settings) +EXPORT(nm_settings_connection_update) /*****************************************************************************/ @@ -127,7 +121,7 @@ enum { CONNECTION_ADDED, CONNECTION_UPDATED, CONNECTION_REMOVED, - CONNECTION_VISIBILITY_CHANGED, + CONNECTION_FLAGS_CHANGED, NEW_CONNECTION, /* exported, not used internally */ LAST_SIGNAL }; @@ -826,13 +820,12 @@ connection_updated (NMSettingsConnection *connection, gboolean by_user, gpointer } static void -connection_visibility_changed (NMSettingsConnection *connection, - GParamSpec *pspec, - gpointer user_data) +connection_flags_changed (NMSettingsConnection *connection, + GParamSpec *pspec, + gpointer user_data) { - /* Re-emit for listeners like NMPolicy */ g_signal_emit (NM_SETTINGS (user_data), - signals[CONNECTION_VISIBILITY_CHANGED], + signals[CONNECTION_FLAGS_CHANGED], 0, connection); } @@ -855,7 +848,7 @@ connection_removed (NMSettingsConnection *connection, gpointer user_data) g_signal_handlers_disconnect_by_func (connection, G_CALLBACK (connection_removed), self); g_signal_handlers_disconnect_by_func (connection, G_CALLBACK (connection_updated), self); - g_signal_handlers_disconnect_by_func (connection, G_CALLBACK (connection_visibility_changed), self); + g_signal_handlers_disconnect_by_func (connection, G_CALLBACK (connection_flags_changed), self); if (!priv->startup_complete) g_signal_handlers_disconnect_by_func (connection, G_CALLBACK (connection_ready_changed), self); g_object_unref (self); @@ -979,8 +972,8 @@ claim_connection (NMSettings *self, NMSettingsConnection *connection) G_CALLBACK (connection_removed), self); g_signal_connect (connection, NM_SETTINGS_CONNECTION_UPDATED_INTERNAL, G_CALLBACK (connection_updated), self); - g_signal_connect (connection, "notify::" NM_SETTINGS_CONNECTION_VISIBLE, - G_CALLBACK (connection_visibility_changed), + g_signal_connect (connection, "notify::" NM_SETTINGS_CONNECTION_FLAGS, + G_CALLBACK (connection_flags_changed), self); if (!priv->startup_complete) { g_signal_connect (connection, "notify::" NM_SETTINGS_CONNECTION_READY, @@ -1993,8 +1986,8 @@ nm_settings_class_init (NMSettingsClass *class) g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, NM_TYPE_SETTINGS_CONNECTION); - signals[CONNECTION_VISIBILITY_CHANGED] = - g_signal_new (NM_SETTINGS_SIGNAL_CONNECTION_VISIBILITY_CHANGED, + signals[CONNECTION_FLAGS_CHANGED] = + g_signal_new (NM_SETTINGS_SIGNAL_CONNECTION_FLAGS_CHANGED, G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, diff --git a/src/settings/nm-settings.h b/src/settings/nm-settings.h index cbd8afa9c3..0ecffb708a 100644 --- a/src/settings/nm-settings.h +++ b/src/settings/nm-settings.h @@ -46,7 +46,7 @@ #define NM_SETTINGS_SIGNAL_CONNECTION_ADDED "connection-added" #define NM_SETTINGS_SIGNAL_CONNECTION_UPDATED "connection-updated" #define NM_SETTINGS_SIGNAL_CONNECTION_REMOVED "connection-removed" -#define NM_SETTINGS_SIGNAL_CONNECTION_VISIBILITY_CHANGED "connection-visibility-changed" +#define NM_SETTINGS_SIGNAL_CONNECTION_FLAGS_CHANGED "connection-flags-changed" /** * NMConnectionFilterFunc: diff --git a/src/settings/plugins/ibft/nms-ibft-connection.c b/src/settings/plugins/ibft/nms-ibft-connection.c index 834ba83408..2a7c5f4a02 100644 --- a/src/settings/plugins/ibft/nms-ibft-connection.c +++ b/src/settings/plugins/ibft/nms-ibft-connection.c @@ -60,11 +60,12 @@ nms_ibft_connection_new (const GPtrArray *block, GError **error) object = g_object_new (NMS_TYPE_IBFT_CONNECTION, NULL); /* Update settings with what was read from iscsiadm */ - if (!nm_settings_connection_replace_settings (NM_SETTINGS_CONNECTION (object), - source, - FALSE, - NULL, - error)) + if (!nm_settings_connection_update (NM_SETTINGS_CONNECTION (object), + source, + NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP, + NM_SETTINGS_CONNECTION_COMMIT_REASON_NONE, + NULL, + error)) g_clear_object (&object); return (NMSIbftConnection *) object; diff --git a/src/settings/nm-inotify-helper.c b/src/settings/plugins/ifcfg-rh/nm-inotify-helper.c index 51b180b233..51b180b233 100644 --- a/src/settings/nm-inotify-helper.c +++ b/src/settings/plugins/ifcfg-rh/nm-inotify-helper.c diff --git a/src/settings/nm-inotify-helper.h b/src/settings/plugins/ifcfg-rh/nm-inotify-helper.h index 2715f3eec5..b887ae378a 100644 --- a/src/settings/nm-inotify-helper.h +++ b/src/settings/plugins/ifcfg-rh/nm-inotify-helper.h @@ -43,4 +43,17 @@ int nm_inotify_helper_add_watch (NMInotifyHelper *helper, const char *path); void nm_inotify_helper_remove_watch (NMInotifyHelper *helper, int wd); +static inline gboolean +nm_inotify_helper_clear_watch (NMInotifyHelper *helper, int *wd) +{ + int x; + + if (wd && ((x = *wd) >= 0)) { + *wd = -1; + nm_inotify_helper_remove_watch (helper, x); + return TRUE; + } + return FALSE; +} + #endif /* __NM_INOTIFY_HELPER_H__ */ diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-connection.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-connection.c index 4c1d02ae08..5d3428d6bf 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-connection.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-connection.c @@ -36,13 +36,13 @@ #include "nm-setting-wireless-security.h" #include "nm-setting-8021x.h" #include "platform/nm-platform.h" -#include "settings/nm-inotify-helper.h" #include "nm-config.h" #include "nms-ifcfg-rh-common.h" #include "nms-ifcfg-rh-reader.h" #include "nms-ifcfg-rh-writer.h" #include "nms-ifcfg-rh-utils.h" +#include "nm-inotify-helper.h" /*****************************************************************************/ @@ -96,14 +96,6 @@ G_DEFINE_TYPE (NMIfcfgConnection, nm_ifcfg_connection, NM_TYPE_SETTINGS_CONNECTI /*****************************************************************************/ -static NMInotifyHelper * -_get_inotify_helper (NMIfcfgConnectionPrivate *priv) -{ - if (!priv->inotify_helper) - priv->inotify_helper = g_object_ref (nm_inotify_helper_get ()); - return priv->inotify_helper; -} - static gboolean devtimeout_ready (gpointer user_data) { @@ -225,37 +217,17 @@ static void path_watch_stop (NMIfcfgConnection *self) { NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (self); - NMInotifyHelper *ih; - - ih = _get_inotify_helper (priv); - - nm_clear_g_signal_handler (ih, &priv->ih_event_id); - - if (priv->file_wd >= 0) { - nm_inotify_helper_remove_watch (ih, priv->file_wd); - priv->file_wd = -1; - } - g_free (priv->keyfile); - priv->keyfile = NULL; - if (priv->keyfile_wd >= 0) { - nm_inotify_helper_remove_watch (ih, priv->keyfile_wd); - priv->keyfile_wd = -1; - } + nm_clear_g_signal_handler (priv->inotify_helper, &priv->ih_event_id); - g_free (priv->routefile); - priv->routefile = NULL; - if (priv->routefile_wd >= 0) { - nm_inotify_helper_remove_watch (ih, priv->routefile_wd); - priv->routefile_wd = -1; - } + nm_inotify_helper_clear_watch (priv->inotify_helper, &priv->file_wd); + nm_inotify_helper_clear_watch (priv->inotify_helper, &priv->keyfile_wd); + nm_inotify_helper_clear_watch (priv->inotify_helper, &priv->routefile_wd); + nm_inotify_helper_clear_watch (priv->inotify_helper, &priv->route6file_wd); - g_free (priv->route6file); - priv->route6file = NULL; - if (priv->route6file_wd >= 0) { - nm_inotify_helper_remove_watch (ih, priv->route6file_wd); - priv->route6file_wd = -1; - } + nm_clear_g_free (&priv->keyfile); + nm_clear_g_free (&priv->routefile); + nm_clear_g_free (&priv->route6file); } static void @@ -280,7 +252,9 @@ filename_changed (GObject *object, if (nm_config_get_monitor_connection_files (nm_config_get ())) { NMInotifyHelper *ih; - ih = _get_inotify_helper (priv); + if (!priv->inotify_helper) + priv->inotify_helper = g_object_ref (nm_inotify_helper_get ()); + ih = priv->inotify_helper; priv->ih_event_id = g_signal_connect (ih, "event", G_CALLBACK (files_changed_cb), self); priv->file_wd = nm_inotify_helper_add_watch (ih, ifcfg_path); @@ -324,7 +298,7 @@ commit_changes (NMSettingsConnection *connection, nm_assert (!out_logmsg_change || !*out_logmsg_change); filename = nm_settings_connection_get_filename (connection); - if (!nms_ifcfg_rh_writer_write_connection (new_connection ?: NM_CONNECTION (connection), + if (!nms_ifcfg_rh_writer_write_connection (new_connection, IFCFG_DIR, filename, &ifcfg_path, @@ -429,18 +403,12 @@ nm_ifcfg_connection_new (NMConnection *source, NMConnection *tmp; char *unhandled_spec = NULL; const char *unmanaged_spec = NULL, *unrecognized_spec = NULL; - gboolean update_unsaved = TRUE; g_assert (source || full_path); if (out_ignore_error) *out_ignore_error = FALSE; - if (full_path) { - /* The connection already is on the disk */ - update_unsaved = FALSE; - } - /* If we're given a connection already, prefer that instead of re-reading */ if (source) tmp = g_object_ref (source); @@ -464,11 +432,14 @@ nm_ifcfg_connection_new (NMConnection *source, NM_IFCFG_CONNECTION_UNRECOGNIZED_SPEC, unrecognized_spec, NULL); /* Update our settings with what was read from the file */ - if (nm_settings_connection_replace_settings (NM_SETTINGS_CONNECTION (object), - tmp, - update_unsaved, - NULL, - error)) + if (nm_settings_connection_update (NM_SETTINGS_CONNECTION (object), + tmp, + full_path + ? NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP /* connection is already on disk */ + : NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY, + NM_SETTINGS_CONNECTION_COMMIT_REASON_NONE, + NULL, + error)) nm_ifcfg_connection_check_devtimeout (NM_IFCFG_CONNECTION (object)); else g_clear_object (&object); diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c index 1ebdeafa7f..8ad3a53f3d 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c @@ -313,11 +313,12 @@ update_connection (SettingsPluginIfcfg *self, NM_IFCFG_CONNECTION_UNRECOGNIZED_SPEC, new_unrecognized, NULL); - if (!nm_settings_connection_replace_settings (NM_SETTINGS_CONNECTION (connection_by_uuid), - NM_CONNECTION (connection_new), - FALSE, /* don't set Unsaved */ - "ifcfg-update", - &local)) { + if (!nm_settings_connection_update (NM_SETTINGS_CONNECTION (connection_by_uuid), + NM_CONNECTION (connection_new), + NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP, + NM_SETTINGS_CONNECTION_COMMIT_REASON_NONE, + "ifcfg-update", + &local)) { /* Shouldn't ever get here as 'connection_new' was verified by the reader already * and the UUID did not change. */ g_assert_not_reached (); diff --git a/src/settings/plugins/ifnet/nms-ifnet-connection.c b/src/settings/plugins/ifnet/nms-ifnet-connection.c index 5dbb124c30..aeb4467472 100644 --- a/src/settings/plugins/ifnet/nms-ifnet-connection.c +++ b/src/settings/plugins/ifnet/nms-ifnet-connection.c @@ -93,7 +93,7 @@ commit_changes (NMSettingsConnection *connection, g_signal_emit (connection, signals[IFNET_CANCEL_MONITORS], 0); if (priv->conn_name) { - success = ifnet_update_parsers_by_connection (NM_CONNECTION (connection), + success = ifnet_update_parsers_by_connection (new_connection, priv->conn_name, CONF_NET_FILE, WPA_SUPPLICANT_CONF, @@ -102,7 +102,7 @@ commit_changes (NMSettingsConnection *connection, error); } else { added = TRUE; - success = ifnet_add_new_connection (NM_CONNECTION (connection), + success = ifnet_add_new_connection (new_connection, CONF_NET_FILE, WPA_SUPPLICANT_CONF, &new_name, @@ -186,11 +186,14 @@ nm_ifnet_connection_new (NMConnection *source, const char *conn_name) object = (GObject *) g_object_new (NM_TYPE_IFNET_CONNECTION, NULL); NM_IFNET_CONNECTION_GET_PRIVATE ((NMIfnetConnection *) object)->conn_name = g_strdup (conn_name); - if (!nm_settings_connection_replace_settings (NM_SETTINGS_CONNECTION (object), - tmp, - update_unsaved, - NULL, - NULL)) { + if (!nm_settings_connection_update (NM_SETTINGS_CONNECTION (object), + tmp, + update_unsaved + ? NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY + : NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP, + NM_SETTINGS_CONNECTION_COMMIT_REASON_NONE, + NULL, + NULL)) { g_object_unref (object); return NULL; } diff --git a/src/settings/plugins/ifnet/nms-ifnet-plugin.c b/src/settings/plugins/ifnet/nms-ifnet-plugin.c index 998b04b47a..98e56e449a 100644 --- a/src/settings/plugins/ifnet/nms-ifnet-plugin.c +++ b/src/settings/plugins/ifnet/nms-ifnet-plugin.c @@ -269,11 +269,12 @@ reload_connections (NMSettingsPlugin *config) } } else { /* Update existing connection with new settings */ - if (!nm_settings_connection_replace_settings (NM_SETTINGS_CONNECTION (old), - NM_CONNECTION (new), - FALSE, /* don't set Unsaved */ - "ifnet-update", - &error)) { + if (!nm_settings_connection_update (NM_SETTINGS_CONNECTION (old), + NM_CONNECTION (new), + NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP, + NM_SETTINGS_CONNECTION_COMMIT_REASON_NONE, + "ifnet-update", + &error)) { /* Shouldn't ever get here as 'new' was verified by the reader already * and the UUID did not change. */ g_assert_not_reached (); diff --git a/src/settings/plugins/ifupdown/nms-ifupdown-plugin.c b/src/settings/plugins/ifupdown/nms-ifupdown-plugin.c index 0928772afa..87afb6c8e9 100644 --- a/src/settings/plugins/ifupdown/nms-ifupdown-plugin.c +++ b/src/settings/plugins/ifupdown/nms-ifupdown-plugin.c @@ -139,10 +139,12 @@ bind_device_to_connection (SettingsPluginIfupdown *self, g_object_set (s_wifi, NM_SETTING_WIRELESS_MAC_ADDRESS, address, NULL); } - nm_settings_connection_commit_changes (NM_SETTINGS_CONNECTION (exported), - NULL, - NM_SETTINGS_CONNECTION_COMMIT_REASON_NONE, - NULL); + nm_settings_connection_update (NM_SETTINGS_CONNECTION (exported), + NULL, + NM_SETTINGS_CONNECTION_PERSIST_MODE_DISK, + NM_SETTINGS_CONNECTION_COMMIT_REASON_NONE, + "ifupdown-new", + NULL); } static void diff --git a/src/settings/plugins/keyfile/nms-keyfile-connection.c b/src/settings/plugins/keyfile/nms-keyfile-connection.c index 300aa9f7b3..9e9ab9621b 100644 --- a/src/settings/plugins/keyfile/nms-keyfile-connection.c +++ b/src/settings/plugins/keyfile/nms-keyfile-connection.c @@ -65,7 +65,7 @@ commit_changes (NMSettingsConnection *connection, nm_assert (out_reread_connection && !*out_reread_connection); nm_assert (!out_logmsg_change || !*out_logmsg_change); - if (!nms_keyfile_writer_connection (new_connection ?: NM_CONNECTION (connection), + if (!nms_keyfile_writer_connection (new_connection, nm_settings_connection_get_filename (connection), NM_FLAGS_ALL (commit_reason, NM_SETTINGS_CONNECTION_COMMIT_REASON_USER_ACTION | NM_SETTINGS_CONNECTION_COMMIT_REASON_ID_CHANGED), @@ -159,11 +159,14 @@ nms_keyfile_connection_new (NMConnection *source, NULL); /* Update our settings with what was read from the file */ - if (!nm_settings_connection_replace_settings (NM_SETTINGS_CONNECTION (object), - tmp, - update_unsaved, - NULL, - error)) { + if (!nm_settings_connection_update (NM_SETTINGS_CONNECTION (object), + tmp, + update_unsaved + ? NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY + : NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP, + NM_SETTINGS_CONNECTION_COMMIT_REASON_NONE, + NULL, + error)) { g_object_unref (object); object = NULL; } diff --git a/src/settings/plugins/keyfile/nms-keyfile-plugin.c b/src/settings/plugins/keyfile/nms-keyfile-plugin.c index dfc311af33..dd179565a2 100644 --- a/src/settings/plugins/keyfile/nms-keyfile-plugin.c +++ b/src/settings/plugins/keyfile/nms-keyfile-plugin.c @@ -258,11 +258,12 @@ update_connection (NMSKeyfilePlugin *self, else _LOGI ("update and persist "NMS_KEYFILE_CONNECTION_LOG_FMT, NMS_KEYFILE_CONNECTION_LOG_ARG (connection_new)); - if (!nm_settings_connection_replace_settings (NM_SETTINGS_CONNECTION (connection_by_uuid), - NM_CONNECTION (connection_new), - FALSE, /* don't set Unsaved */ - "keyfile-update", - &local)) { + if (!nm_settings_connection_update (NM_SETTINGS_CONNECTION (connection_by_uuid), + NM_CONNECTION (connection_new), + NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP, + NM_SETTINGS_CONNECTION_COMMIT_REASON_NONE, + "keyfile-update", + &local)) { /* Shouldn't ever get here as 'connection_new' was verified by the reader already * and the UUID did not change. */ g_assert_not_reached (); |