From 978724da96b9750e2e91387e4fc4ed0aeb0c235d Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Sun, 23 Feb 2014 17:03:01 +0100 Subject: [PATCH 1/7] libnm-util: don't assert in nm_setting_get_secret_flags() and avoid assertion in agent_secrets_done_cb() When secret providers return the connection hash in GetSecrets(), this hash should only contain secrets. However, some providers also return non-secret properties. for_each_secret() iterated over all entries of the @secrets hash and triggered the assertion in nm_setting_get_secret_flags() (see below). NM should not assert against user provided input. Change nm_setting_get_secret_flags() to silently return FALSE, if the property is not a secret. Indeed, handling of secrets is very different for NMSettingVpn and others. Hence nm_setting_get_secret_flags() has only an inconsistent behavior and we have to fix all call sites to do the right thing (depending on whether we have a VPN setting or not). Now for_each_secret() checks whether the property is a secret without hitting the assertion. Adjust all other calls of nm_setting_get_secret_flags(), to anticipate non-secret flags and assert/warn where appropriate. Also, agent_secrets_done_cb() clears now all non-secrets properties from the hash, using the new argument @remove_non_secrets when calling for_each_secret(). #0 0x0000003370c504e9 in g_logv () from /lib64/libglib-2.0.so.0 #1 0x0000003370c5063f in g_log () from /lib64/libglib-2.0.so.0 #2 0x00007fa4b0c1c156 in get_secret_flags (setting=0x1e3ac60, secret_name=0x1ea9180 "security", verify_secret=1, out_flags=0x7fff7507857c, error=0x0) at nm-setting.c:1091 #3 0x00007fa4b0c1c2b2 in nm_setting_get_secret_flags (setting=0x1e3ac60, secret_name=0x1ea9180 "security", out_flags=0x7fff7507857c, error=0x0) at nm-setting.c:1124 #4 0x0000000000463d03 in for_each_secret (connection=0x1deb2f0, secrets=0x1e9f860, callback=0x464f1b , callback_data=0x7fff7507865c) at settings/nm-settings-connection.c:203 #5 0x000000000046525f in agent_secrets_done_cb (manager=0x1dddf50, call_id=1, agent_dbus_owner=0x1ddb9e0 ":1.39", agent_username=0x1e51710 "thom", agent_has_modify=1, setting_name=0x1e91f90 "802-11-wireless-security", flags=NM_SETTINGS_GET_SECRETS_FLAG_ALLOW_INTERACTION, secrets=0x1e9f860, error=0x0, user_data=0x1deb2f0, other_data2=0x477d61 , other_data3=0x1ea92a0) at settings/nm-settings-connection.c:757 #6 0x00000000004dc4fd in get_complete_cb (parent=0x1ea6300, secrets=0x1e9f860, agent_dbus_owner=0x1ddb9e0 ":1.39", agent_username=0x1e51710 "thom", error=0x0, user_data=0x1dddf50) at settings/nm-agent-manager.c:1139 #7 0x00000000004dab54 in req_complete_success (req=0x1ea6300, secrets=0x1e9f860, agent_dbus_owner=0x1ddb9e0 ":1.39", agent_uname=0x1e51710 "thom") at settings/nm-agent-manager.c:502 #8 0x00000000004db86e in get_done_cb (agent=0x1e89530, call_id=0x1, secrets=0x1e9f860, error=0x0, user_data=0x1ea6300) at settings/nm-agent-manager.c:856 #9 0x00000000004de9d0 in get_callback (proxy=0x1e47530, call=0x1, user_data=0x1ea10f0) at settings/nm-secret-agent.c:267 #10 0x000000337380cad2 in complete_pending_call_and_unlock () from /lib64/libdbus-1.so.3 #11 0x000000337380fdc1 in dbus_connection_dispatch () from /lib64/libdbus-1.so.3 #12 0x000000342800ad65 in message_queue_dispatch () from /lib64/libdbus-glib-1.so.2 #13 0x0000003370c492a6 in g_main_context_dispatch () from /lib64/libglib-2.0.so.0 #14 0x0000003370c49628 in g_main_context_iterate.isra.24 () from /lib64/libglib-2.0.so.0 #15 0x0000003370c49a3a in g_main_loop_run () from /lib64/libglib-2.0.so.0 #16 0x000000000042e5c6 in main (argc=1, argv=0x7fff75078e88) at main.c:644 Signed-off-by: Thomas Haller --- libnm-core/nm-setting-vpn.c | 10 +++--- libnm-core/nm-setting.c | 32 +++++++++++++++---- libnm-util/nm-setting-vpn.c | 10 +++--- libnm-util/nm-setting.c | 32 +++++++++++++++---- src/devices/wifi/nm-device-wifi.c | 18 ++++++----- src/settings/nm-agent-manager.c | 3 +- src/settings/nm-settings-connection.c | 20 +++++++++--- .../plugins/ifnet/connection_parser.c | 25 ++++++++------- src/settings/plugins/keyfile/writer.c | 3 +- 9 files changed, 106 insertions(+), 47 deletions(-) diff --git a/libnm-core/nm-setting-vpn.c b/libnm-core/nm-setting-vpn.c index 6ce414502..667b83d78 100644 --- a/libnm-core/nm-setting-vpn.c +++ b/libnm-core/nm-setting-vpn.c @@ -539,29 +539,31 @@ get_secret_flags (NMSetting *setting, char *flags_key; gpointer val; unsigned long tmp; + NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE; flags_key = g_strdup_printf ("%s-flags", secret_name); if (g_hash_table_lookup_extended (priv->data, flags_key, NULL, &val)) { errno = 0; tmp = strtoul ((const char *) val, NULL, 10); if ((errno == 0) && (tmp <= NM_SETTING_SECRET_FLAGS_ALL)) { - if (out_flags) - *out_flags = (guint32) tmp; + flags = (NMSettingSecretFlags) tmp; success = TRUE; } else { g_set_error (error, NM_SETTING_ERROR, NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH, - "Failed to convert '%s' value '%s' to uint", + _("Failed to convert '%s' value '%s' to uint"), flags_key, (const char *) val); } } else { g_set_error (error, NM_SETTING_ERROR, NM_SETTING_ERROR_PROPERTY_NOT_FOUND, - "Secret flags property '%s' not found", flags_key); + _("Secret flags property '%s' not found"), flags_key); } g_free (flags_key); + if (out_flags) + *out_flags = flags; return success; } diff --git a/libnm-core/nm-setting.c b/libnm-core/nm-setting.c index f4ad8bbd1..3de330901 100644 --- a/libnm-core/nm-setting.c +++ b/libnm-core/nm-setting.c @@ -1002,8 +1002,12 @@ compare_property (NMSetting *setting, NMSettingSecretFlags a_secret_flags = NM_SETTING_SECRET_FLAG_NONE; NMSettingSecretFlags b_secret_flags = NM_SETTING_SECRET_FLAG_NONE; - nm_setting_get_secret_flags (setting, prop_spec->name, &a_secret_flags, NULL); - nm_setting_get_secret_flags (other, prop_spec->name, &b_secret_flags, NULL); + g_return_val_if_fail (!NM_IS_SETTING_VPN (setting), FALSE); + + if (!nm_setting_get_secret_flags (setting, prop_spec->name, &a_secret_flags, NULL)) + g_return_val_if_reached (FALSE); + if (!nm_setting_get_secret_flags (other, prop_spec->name, &b_secret_flags, NULL)) + g_return_val_if_reached (FALSE); /* If the secret flags aren't the same the settings aren't the same */ if (a_secret_flags != b_secret_flags) @@ -1108,7 +1112,16 @@ should_compare_prop (NMSetting *setting, if (comp_flags & NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS) return FALSE; - nm_setting_get_secret_flags (setting, prop_name, &secret_flags, NULL); + if ( NM_IS_SETTING_VPN (setting) + && g_strcmp0 (prop_name, NM_SETTING_VPN_SECRETS) == 0) { + /* FIXME: NMSettingVPN:NM_SETTING_VPN_SECRETS has NM_SETTING_PARAM_SECRET. + * nm_setting_get_secret_flags() quite possibly fails, but it might succeed if the + * setting accidently uses a key "secrets". */ + return TRUE; + } + + if (!nm_setting_get_secret_flags (setting, prop_name, &secret_flags, NULL)) + g_return_val_if_reached (FALSE); if ( (comp_flags & NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS) && (secret_flags & NM_SETTING_SECRET_FLAG_AGENT_OWNED)) @@ -1330,8 +1343,12 @@ clear_secrets_with_flags (NMSetting *setting, NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE; gboolean changed = FALSE; + g_return_val_if_fail (!NM_IS_SETTING_VPN (setting), FALSE); + /* Clear the secret if the user function says to do so */ - nm_setting_get_secret_flags (setting, pspec->name, &flags, NULL); + if (!nm_setting_get_secret_flags (setting, pspec->name, &flags, NULL)) + g_return_val_if_reached (FALSE); + if (func (setting, pspec->name, flags, user_data) == TRUE) { GValue value = G_VALUE_INIT; @@ -1549,8 +1566,11 @@ get_secret_flags (NMSetting *setting, char *flags_prop; NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE; - if (verify_secret) - g_return_val_if_fail (is_secret_prop (setting, secret_name, error), FALSE); + if (verify_secret && !is_secret_prop (setting, secret_name, error)) { + if (out_flags) + *out_flags = NM_SETTING_SECRET_FLAG_NONE; + return FALSE; + } flags_prop = g_strdup_printf ("%s-flags", secret_name); g_object_get (G_OBJECT (setting), flags_prop, &flags, NULL); diff --git a/libnm-util/nm-setting-vpn.c b/libnm-util/nm-setting-vpn.c index be892da48..70f955b01 100644 --- a/libnm-util/nm-setting-vpn.c +++ b/libnm-util/nm-setting-vpn.c @@ -545,29 +545,31 @@ get_secret_flags (NMSetting *setting, char *flags_key; gpointer val; unsigned long tmp; + NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE; flags_key = g_strdup_printf ("%s-flags", secret_name); if (g_hash_table_lookup_extended (priv->data, flags_key, NULL, &val)) { errno = 0; tmp = strtoul ((const char *) val, NULL, 10); if ((errno == 0) && (tmp <= NM_SETTING_SECRET_FLAGS_ALL)) { - if (out_flags) - *out_flags = (guint32) tmp; + flags = (NMSettingSecretFlags) tmp; success = TRUE; } else { g_set_error (error, NM_SETTING_ERROR, NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH, - "Failed to convert '%s' value '%s' to uint", + _("Failed to convert '%s' value '%s' to uint"), flags_key, (const char *) val); } } else { g_set_error (error, NM_SETTING_ERROR, NM_SETTING_ERROR_PROPERTY_NOT_FOUND, - "Secret flags property '%s' not found", flags_key); + _("Secret flags property '%s' not found"), flags_key); } g_free (flags_key); + if (out_flags) + *out_flags = flags; return success; } diff --git a/libnm-util/nm-setting.c b/libnm-util/nm-setting.c index 2508a401f..0ca28dba1 100644 --- a/libnm-util/nm-setting.c +++ b/libnm-util/nm-setting.c @@ -542,8 +542,12 @@ compare_property (NMSetting *setting, NMSettingSecretFlags a_secret_flags = NM_SETTING_SECRET_FLAG_NONE; NMSettingSecretFlags b_secret_flags = NM_SETTING_SECRET_FLAG_NONE; - nm_setting_get_secret_flags (setting, prop_spec->name, &a_secret_flags, NULL); - nm_setting_get_secret_flags (other, prop_spec->name, &b_secret_flags, NULL); + g_return_val_if_fail (!NM_IS_SETTING_VPN (setting), FALSE); + + if (!nm_setting_get_secret_flags (setting, prop_spec->name, &a_secret_flags, NULL)) + g_return_val_if_reached (FALSE); + if (!nm_setting_get_secret_flags (other, prop_spec->name, &b_secret_flags, NULL)) + g_return_val_if_reached (FALSE); /* If the secret flags aren't the same the settings aren't the same */ if (a_secret_flags != b_secret_flags) @@ -648,7 +652,16 @@ should_compare_prop (NMSetting *setting, if (comp_flags & NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS) return FALSE; - nm_setting_get_secret_flags (setting, prop_name, &secret_flags, NULL); + if ( NM_IS_SETTING_VPN (setting) + && g_strcmp0 (prop_name, NM_SETTING_VPN_SECRETS) == 0) { + /* FIXME: NMSettingVPN:NM_SETTING_VPN_SECRETS has NM_SETTING_PARAM_SECRET. + * nm_setting_get_secret_flags() quite possibly fails, but it might succeed if the + * setting accidently uses a key "secrets". */ + return FALSE; + } + + if (!nm_setting_get_secret_flags (setting, prop_name, &secret_flags, NULL)) + g_return_val_if_reached (FALSE); if ( (comp_flags & NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS) && (secret_flags & NM_SETTING_SECRET_FLAG_AGENT_OWNED)) @@ -870,8 +883,12 @@ clear_secrets_with_flags (NMSetting *setting, NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE; gboolean changed = FALSE; + g_return_val_if_fail (!NM_IS_SETTING_VPN (setting), FALSE); + /* Clear the secret if the user function says to do so */ - nm_setting_get_secret_flags (setting, pspec->name, &flags, NULL); + if (!nm_setting_get_secret_flags (setting, pspec->name, &flags, NULL)) + g_return_val_if_reached (FALSE); + if (func (setting, pspec->name, flags, user_data) == TRUE) { GValue value = G_VALUE_INIT; @@ -1090,8 +1107,11 @@ get_secret_flags (NMSetting *setting, char *flags_prop; NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE; - if (verify_secret) - g_return_val_if_fail (is_secret_prop (setting, secret_name, error), FALSE); + if (verify_secret && !is_secret_prop (setting, secret_name, error)) { + if (out_flags) + *out_flags = NM_SETTING_SECRET_FLAG_NONE; + return FALSE; + } flags_prop = g_strdup_printf ("%s-flags", secret_name); g_object_get (G_OBJECT (setting), flags_prop, &flags, NULL); diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c index 850809788..6d9383379 100644 --- a/src/devices/wifi/nm-device-wifi.c +++ b/src/devices/wifi/nm-device-wifi.c @@ -2053,10 +2053,11 @@ need_new_8021x_secrets (NMDeviceWifi *self, s_8021x = nm_connection_get_setting_802_1x (connection); if (s_8021x) { - nm_setting_get_secret_flags (NM_SETTING (s_8021x), - NM_SETTING_802_1X_PASSWORD, - &secret_flags, - NULL); + if (!nm_setting_get_secret_flags (NM_SETTING (s_8021x), + NM_SETTING_802_1X_PASSWORD, + &secret_flags, + NULL)) + g_assert_not_reached (); if (secret_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED) *setting_name = NM_SETTING_802_1X_SETTING_NAME; return *setting_name ? TRUE : FALSE; @@ -2064,10 +2065,11 @@ need_new_8021x_secrets (NMDeviceWifi *self, s_wsec = nm_connection_get_setting_wireless_security (connection); if (s_wsec) { - nm_setting_get_secret_flags (NM_SETTING (s_wsec), - NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD, - &secret_flags, - NULL); + if (!nm_setting_get_secret_flags (NM_SETTING (s_wsec), + NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD, + &secret_flags, + NULL)) + g_assert_not_reached (); if (secret_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED) *setting_name = NM_SETTING_WIRELESS_SECURITY_SETTING_NAME; return *setting_name ? TRUE : FALSE; diff --git a/src/settings/nm-agent-manager.c b/src/settings/nm-agent-manager.c index 0de63ffb1..1076ae214 100644 --- a/src/settings/nm-agent-manager.c +++ b/src/settings/nm-agent-manager.c @@ -1010,7 +1010,8 @@ check_system_secrets_cb (NMSetting *setting, *has_system = TRUE; } } else { - nm_setting_get_secret_flags (setting, key, &secret_flags, NULL); + if (!nm_setting_get_secret_flags (setting, key, &secret_flags, NULL)) + g_return_if_reached (); if (secret_flags == NM_SETTING_SECRET_FLAG_NONE) *has_system = TRUE; } diff --git a/src/settings/nm-settings-connection.c b/src/settings/nm-settings-connection.c index 1e0106d07..859581139 100644 --- a/src/settings/nm-settings-connection.c +++ b/src/settings/nm-settings-connection.c @@ -144,6 +144,7 @@ typedef gboolean (*ForEachSecretFunc) (GHashTableIter *iter, static void for_each_secret (NMConnection *connection, GHashTable *secrets, + gboolean remove_non_secrets, ForEachSecretFunc callback, gpointer callback_data) { @@ -167,6 +168,8 @@ for_each_secret (NMConnection *connection, * each time. */ + g_return_if_fail (callback); + /* Walk through the list of setting hashes */ g_hash_table_iter_init (&iter, secrets); while (g_hash_table_iter_next (&iter, (gpointer) &setting_name, (gpointer) &setting_hash)) { @@ -175,6 +178,9 @@ for_each_secret (NMConnection *connection, const char *secret_name; GValue *val; + if (g_hash_table_size (setting_hash) == 0) + continue; + /* Get the actual NMSetting from the connection so we can get secret flags * from the connection data, since flags aren't secrets. What we're * iterating here is just the secrets, not a whole connection. @@ -203,7 +209,11 @@ for_each_secret (NMConnection *connection, return; } } else { - nm_setting_get_secret_flags (setting, secret_name, &secret_flags, NULL); + if (!nm_setting_get_secret_flags (setting, secret_name, &secret_flags, NULL)) { + if (remove_non_secrets) + g_hash_table_iter_remove (&secret_iter); + continue; + } if (callback (&secret_iter, secret_flags, callback_data) == FALSE) return; } @@ -764,7 +774,7 @@ agent_secrets_done_cb (NMAgentManager *manager, * save those system-owned secrets. If not, discard them and use the * existing secrets, or fail the connection. */ - for_each_secret (NM_CONNECTION (self), secrets, has_system_owned_secrets, &agent_had_system); + for_each_secret (NM_CONNECTION (self), secrets, TRUE, has_system_owned_secrets, &agent_had_system); if (agent_had_system) { if (flags == NM_SECRET_AGENT_GET_SECRETS_FLAG_NONE) { /* No user interaction was allowed when requesting secrets; the @@ -776,7 +786,7 @@ agent_secrets_done_cb (NMAgentManager *manager, call_id, agent_dbus_owner); - for_each_secret (NM_CONNECTION (self), secrets, clear_nonagent_secrets, NULL); + for_each_secret (NM_CONNECTION (self), secrets, FALSE, clear_nonagent_secrets, NULL); } else if (agent_has_modify == FALSE) { /* Agent didn't successfully authenticate; clear system-owned secrets * from the secrets the agent returned. @@ -786,7 +796,7 @@ agent_secrets_done_cb (NMAgentManager *manager, setting_name, call_id); - for_each_secret (NM_CONNECTION (self), secrets, clear_nonagent_secrets, NULL); + for_each_secret (NM_CONNECTION (self), secrets, FALSE, clear_nonagent_secrets, NULL); } } } else { @@ -805,7 +815,7 @@ agent_secrets_done_cb (NMAgentManager *manager, * came back. Unsaved secrets by definition require user interaction. */ if (flags == NM_SECRET_AGENT_GET_SECRETS_FLAG_NONE) - for_each_secret (NM_CONNECTION (self), secrets, clear_unsaved_secrets, NULL); + for_each_secret (NM_CONNECTION (self), secrets, TRUE, clear_unsaved_secrets, NULL); /* Update the connection with our existing secrets from backing storage */ nm_connection_clear_secrets (NM_CONNECTION (self)); diff --git a/src/settings/plugins/ifnet/connection_parser.c b/src/settings/plugins/ifnet/connection_parser.c index 15dd3874a..25b958fd4 100644 --- a/src/settings/plugins/ifnet/connection_parser.c +++ b/src/settings/plugins/ifnet/connection_parser.c @@ -2846,7 +2846,8 @@ check_unsupported_secrets (NMSetting *setting, if (flags & NM_SETTING_PARAM_SECRET) { NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE; - nm_setting_get_secret_flags (setting, key, &secret_flags, NULL); + if (!nm_setting_get_secret_flags (setting, key, &secret_flags, NULL)) + g_return_if_reached (); if (secret_flags != NM_SETTING_SECRET_FLAG_NONE) *unsupported_secret = TRUE; } @@ -2869,17 +2870,6 @@ ifnet_can_write_connection (NMConnection *connection, GError **error) return FALSE; } - /* If the connection has flagged secrets, ignore - * it as this plugin does not deal with user agent service */ - nm_connection_for_each_setting_value (connection, - check_unsupported_secrets, - &has_unsupported_secrets); - if (has_unsupported_secrets) { - g_set_error_literal (error, IFNET_PLUGIN_ERROR, 0, - "The ifnet plugin only supports persistent system secrets."); - return FALSE; - } - /* Only support wired, wifi, and PPPoE */ if ( !nm_connection_is_type (connection, NM_SETTING_WIRED_SETTING_NAME) && !nm_connection_is_type (connection, NM_SETTING_WIRELESS_SETTING_NAME) @@ -2891,6 +2881,17 @@ ifnet_can_write_connection (NMConnection *connection, GError **error) return FALSE; } + /* If the connection has flagged secrets, ignore + * it as this plugin does not deal with user agent service */ + nm_connection_for_each_setting_value (connection, + check_unsupported_secrets, + &has_unsupported_secrets); + if (has_unsupported_secrets) { + g_set_error_literal (error, IFNET_PLUGIN_ERROR, 0, + "The ifnet plugin only supports persistent system secrets."); + return FALSE; + } + return TRUE; } diff --git a/src/settings/plugins/keyfile/writer.c b/src/settings/plugins/keyfile/writer.c index ae8f0a912..2661d5006 100644 --- a/src/settings/plugins/keyfile/writer.c +++ b/src/settings/plugins/keyfile/writer.c @@ -797,7 +797,8 @@ write_setting_value (NMSetting *setting, if (pspec && (pspec->flags & NM_SETTING_PARAM_SECRET) && !NM_IS_SETTING_VPN (setting)) { NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE; - nm_setting_get_secret_flags (setting, key, &secret_flags, NULL); + if (!nm_setting_get_secret_flags (setting, key, &secret_flags, NULL)) + g_assert_not_reached (); if (secret_flags != NM_SETTING_SECRET_FLAG_NONE) return; } From e5194fd346d3736851c6ca03f391e919e249fd51 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 7 Oct 2014 08:46:36 +0200 Subject: [PATCH 2/7] libnm: hide API for generic handling of secrets The functions nm_setting_clear_secrets(), nm_setting_clear_secrets_with_flags(), and nm_setting_need_secrets() are not used outside of libnm-core. Remove them from public API. Signed-off-by: Thomas Haller --- libnm-core/nm-connection.c | 2 +- libnm-core/nm-setting-private.h | 2 ++ libnm-core/nm-setting.c | 26 ++++++++------------------ libnm-core/nm-setting.h | 8 -------- libnm/libnm.ver | 3 --- 5 files changed, 11 insertions(+), 30 deletions(-) diff --git a/libnm-core/nm-connection.c b/libnm-core/nm-connection.c index 23e9f2159..1e0cdbf93 100644 --- a/libnm-core/nm-connection.c +++ b/libnm-core/nm-connection.c @@ -1104,7 +1104,7 @@ nm_connection_need_secrets (NMConnection *connection, GPtrArray *secrets; setting = NM_SETTING (iter->data); - secrets = nm_setting_need_secrets (setting); + secrets = _nm_setting_need_secrets (setting); if (secrets) { if (hints) *hints = secrets; diff --git a/libnm-core/nm-setting-private.h b/libnm-core/nm-setting-private.h index f27799248..9f0c51a98 100644 --- a/libnm-core/nm-setting-private.h +++ b/libnm-core/nm-setting-private.h @@ -158,4 +158,6 @@ void _nm_setting_class_transform_property (NMSettingClass *setting_class, NMSettingPropertyTransformToFunc to_dbus, NMSettingPropertyTransformFromFunc from_dbus); +GPtrArray *_nm_setting_need_secrets (NMSetting *setting); + #endif /* NM_SETTING_PRIVATE_H */ diff --git a/libnm-core/nm-setting.c b/libnm-core/nm-setting.c index 3de330901..ede4635a3 100644 --- a/libnm-core/nm-setting.c +++ b/libnm-core/nm-setting.c @@ -1287,19 +1287,15 @@ nm_setting_enumerate_values (NMSetting *setting, } /** - * nm_setting_clear_secrets: + * _nm_setting_clear_secrets: * @setting: the #NMSetting * * Resets and clears any secrets in the setting. Secrets should be added to the * setting only when needed, and cleared immediately after use to prevent * leakage of information. + * + * Returns: %TRUE if the setting changed at all **/ -void -nm_setting_clear_secrets (NMSetting *setting) -{ - _nm_setting_clear_secrets (setting); -} - gboolean _nm_setting_clear_secrets (NMSetting *setting) { @@ -1366,22 +1362,16 @@ clear_secrets_with_flags (NMSetting *setting, } /** - * nm_setting_clear_secrets_with_flags: + * _nm_setting_clear_secrets_with_flags: * @setting: the #NMSetting * @func: (scope call): function to be called to determine whether a * specific secret should be cleared or not * @user_data: caller-supplied data passed to @func * * Clears and frees secrets determined by @func. + * + * Returns: %TRUE if the setting changed at all **/ -void -nm_setting_clear_secrets_with_flags (NMSetting *setting, - NMSettingClearSecretsWithFlagsFn func, - gpointer user_data) -{ - _nm_setting_clear_secrets_with_flags (setting, func, user_data); -} - gboolean _nm_setting_clear_secrets_with_flags (NMSetting *setting, NMSettingClearSecretsWithFlagsFn func, @@ -1411,7 +1401,7 @@ _nm_setting_clear_secrets_with_flags (NMSetting *setting, } /** - * nm_setting_need_secrets: + * _nm_setting_need_secrets: * @setting: the #NMSetting * * Returns an array of property names for each secret which may be required @@ -1425,7 +1415,7 @@ _nm_setting_clear_secrets_with_flags (NMSetting *setting, * free the elements. **/ GPtrArray * -nm_setting_need_secrets (NMSetting *setting) +_nm_setting_need_secrets (NMSetting *setting) { GPtrArray *secrets = NULL; diff --git a/libnm-core/nm-setting.h b/libnm-core/nm-setting.h index 5ed3e6b4f..bf8dd2336 100644 --- a/libnm-core/nm-setting.h +++ b/libnm-core/nm-setting.h @@ -269,14 +269,6 @@ void nm_setting_enumerate_values (NMSetting *setting, char *nm_setting_to_string (NMSetting *setting); /* Secrets */ -void nm_setting_clear_secrets (NMSetting *setting); - -void nm_setting_clear_secrets_with_flags (NMSetting *setting, - NMSettingClearSecretsWithFlagsFn func, - gpointer user_data); - -GPtrArray *nm_setting_need_secrets (NMSetting *setting); - gboolean nm_setting_get_secret_flags (NMSetting *setting, const char *secret_name, NMSettingSecretFlags *out_flags, diff --git a/libnm/libnm.ver b/libnm/libnm.ver index ca8283abb..e0c4795f9 100644 --- a/libnm/libnm.ver +++ b/libnm/libnm.ver @@ -521,8 +521,6 @@ global: nm_setting_cdma_get_type; nm_setting_cdma_get_username; nm_setting_cdma_new; - nm_setting_clear_secrets; - nm_setting_clear_secrets_with_flags; nm_setting_compare; nm_setting_compare_flags_get_type; nm_setting_connection_add_permission; @@ -689,7 +687,6 @@ global: nm_setting_ip6_config_remove_route_by_value; nm_setting_lookup_type; nm_setting_lookup_type_by_quark; - nm_setting_need_secrets; nm_setting_olpc_mesh_error_get_type; nm_setting_olpc_mesh_error_quark; nm_setting_olpc_mesh_get_channel; From 68bc95c12f64df1973e7c3f63131cedc6fae280d Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 26 Feb 2014 11:26:25 +0100 Subject: [PATCH 3/7] libnm-util: let nm_setting_diff() be symetric not to return properties that are set to default Previously, nm_setting_diff() (and thus nm_connection_diff()), returned only properties that are different AND not set to the default value. However, if the opposite setting 'B' was missing, it would always include all properties from 'A', even the default ones. This behaviour was asymetric. Add two new compare flags @NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT and @NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT to control the behaviour of whether to include default properties. Signed-off-by: Thomas Haller --- libnm-core/nm-setting.c | 59 ++++++++++++++++++++++++++++++++++------- libnm-core/nm-setting.h | 24 ++++++++++++++++- libnm-util/nm-setting.c | 59 ++++++++++++++++++++++++++++++++++------- libnm-util/nm-setting.h | 24 ++++++++++++++++- 4 files changed, 144 insertions(+), 22 deletions(-) diff --git a/libnm-core/nm-setting.c b/libnm-core/nm-setting.c index ede4635a3..f103b753f 100644 --- a/libnm-core/nm-setting.c +++ b/libnm-core/nm-setting.c @@ -1173,6 +1173,8 @@ nm_setting_diff (NMSetting *a, guint i; NMSettingDiffResult a_result = NM_SETTING_DIFF_RESULT_IN_A; NMSettingDiffResult b_result = NM_SETTING_DIFF_RESULT_IN_B; + NMSettingDiffResult a_result_default = NM_SETTING_DIFF_RESULT_IN_A_DEFAULT; + NMSettingDiffResult b_result_default = NM_SETTING_DIFF_RESULT_IN_B_DEFAULT; gboolean results_created = FALSE; g_return_val_if_fail (results != NULL, FALSE); @@ -1182,6 +1184,12 @@ nm_setting_diff (NMSetting *a, g_return_val_if_fail (G_OBJECT_TYPE (a) == G_OBJECT_TYPE (b), FALSE); } + if ((flags & (NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT | NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT)) == + (NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT | NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT)) { + /* conflicting flags: default to WITH_DEFAULT (clearing NO_DEFAULT). */ + flags &= ~NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT; + } + /* If the caller is calling this function in a pattern like this to get * complete diffs: * @@ -1194,6 +1202,8 @@ nm_setting_diff (NMSetting *a, if (invert_results) { a_result = NM_SETTING_DIFF_RESULT_IN_B; b_result = NM_SETTING_DIFF_RESULT_IN_A; + a_result_default = NM_SETTING_DIFF_RESULT_IN_B_DEFAULT; + b_result_default = NM_SETTING_DIFF_RESULT_IN_A_DEFAULT; } if (*results == NULL) { @@ -1206,8 +1216,7 @@ nm_setting_diff (NMSetting *a, for (i = 0; i < n_property_specs; i++) { GParamSpec *prop_spec = property_specs[i]; - NMSettingDiffResult r = NM_SETTING_DIFF_RESULT_UNKNOWN, tmp; - gboolean different = TRUE; + NMSettingDiffResult r = NM_SETTING_DIFF_RESULT_UNKNOWN; /* Handle compare flags */ if (!should_compare_prop (a, prop_spec->name, flags, prop_spec->flags)) @@ -1216,28 +1225,58 @@ nm_setting_diff (NMSetting *a, continue; if (b) { + gboolean different; + different = !NM_SETTING_GET_CLASS (a)->compare_property (a, b, prop_spec, flags); if (different) { + gboolean a_is_default, b_is_default; GValue value = G_VALUE_INIT; g_value_init (&value, prop_spec->value_type); g_object_get_property (G_OBJECT (a), prop_spec->name, &value); - if (!g_param_value_defaults (prop_spec, &value)) - r |= a_result; + a_is_default = g_param_value_defaults (prop_spec, &value); g_value_reset (&value); g_object_get_property (G_OBJECT (b), prop_spec->name, &value); - if (!g_param_value_defaults (prop_spec, &value)) - r |= b_result; + b_is_default = g_param_value_defaults (prop_spec, &value); g_value_unset (&value); + if ((flags & NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT) == 0) { + if (!a_is_default) + r |= a_result; + if (!b_is_default) + r |= b_result; + } else { + r |= a_result | b_result; + if (a_is_default) + r |= a_result_default; + if (b_is_default) + r |= b_result_default; + } } - } else + } else if ((flags & (NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT | NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT)) == 0) r = a_result; /* only in A */ + else { + GValue value = G_VALUE_INIT; - if (different) { - tmp = GPOINTER_TO_UINT (g_hash_table_lookup (*results, prop_spec->name)); - g_hash_table_insert (*results, g_strdup (prop_spec->name), GUINT_TO_POINTER (tmp | r)); + g_value_init (&value, prop_spec->value_type); + g_object_get_property (G_OBJECT (a), prop_spec->name, &value); + if (!g_param_value_defaults (prop_spec, &value)) + r |= a_result; + else if (flags & NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT) + r |= a_result | a_result_default; + + g_value_unset (&value); + } + + if (r != NM_SETTING_DIFF_RESULT_UNKNOWN) { + void *p; + + if (g_hash_table_lookup_extended (*results, prop_spec->name, NULL, &p)) { + if ((r & GPOINTER_TO_UINT (p)) != r) + g_hash_table_insert (*results, g_strdup (prop_spec->name), GUINT_TO_POINTER (r | GPOINTER_TO_UINT (p))); + } else + g_hash_table_insert (*results, g_strdup (prop_spec->name), GUINT_TO_POINTER (r)); } } g_free (property_specs); diff --git a/libnm-core/nm-setting.h b/libnm-core/nm-setting.h index bf8dd2336..8e179f2a4 100644 --- a/libnm-core/nm-setting.h +++ b/libnm-core/nm-setting.h @@ -125,6 +125,20 @@ typedef enum { /*< flags >*/ * @NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS: ignore secrets for which * the secret's flags indicate the secret should not be saved to persistent * storage (ie, the secret's flag includes @NM_SETTING_SECRET_FLAG_NOT_SAVED) + * @NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT: if this flag is set, + * nm_setting_diff() and nm_connection_diff() will also include properties that + * are set to their default value. See also @NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT. + * @NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT: if this flag is set, + * nm_setting_diff() and nm_connection_diff() will not include properties that + * are set to their default value. This is the opposite of + * @NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT. If both flags are set together, + * @NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT wins. If both flags are unset, + * this means to exclude default properties if there is a setting to compare, + * but include all properties, if the setting 'b' is missing. This is the legacy + * behaviour of libnm-util, where nm_setting_diff() behaved differently depending + * on whether the setting 'b' was available. If @NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT + * is set, nm_setting_diff() will also set the flags @NM_SETTING_DIFF_RESULT_IN_A_DEFAULT + * and @NM_SETTING_DIFF_RESULT_IN_B_DEFAULT, if the values are default values. * * These flags modify the comparison behavior when comparing two settings or * two connections. @@ -136,7 +150,9 @@ typedef enum { NM_SETTING_COMPARE_FLAG_IGNORE_ID = 0x00000002, NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS = 0x00000004, NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS = 0x00000008, - NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS = 0x00000010 + NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS = 0x00000010, + NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT = 0x00000020, + NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT = 0x00000040, /* 0x80000000 is used for a private flag */ } NMSettingCompareFlags; @@ -247,6 +263,10 @@ gboolean nm_setting_compare (NMSetting *a, * @NM_SETTING_DIFF_RESULT_UNKNOWN: unknown result * @NM_SETTING_DIFF_RESULT_IN_A: the property is present in setting A * @NM_SETTING_DIFF_RESULT_IN_B: the property is present in setting B + * @NM_SETTING_DIFF_RESULT_IN_A_DEFAULT: the property is present in + * setting A but is set to the default value. This flag is only set, + * if you specify @NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT. + * @NM_SETTING_DIFF_RESULT_IN_B_DEFAULT: analog to @NM_SETTING_DIFF_RESULT_IN_A_DEFAULT. * * These values indicate the result of a setting difference operation. **/ @@ -254,6 +274,8 @@ typedef enum { NM_SETTING_DIFF_RESULT_UNKNOWN = 0x00000000, NM_SETTING_DIFF_RESULT_IN_A = 0x00000001, NM_SETTING_DIFF_RESULT_IN_B = 0x00000002, + NM_SETTING_DIFF_RESULT_IN_A_DEFAULT = 0x00000004, + NM_SETTING_DIFF_RESULT_IN_B_DEFAULT = 0x00000004, } NMSettingDiffResult; gboolean nm_setting_diff (NMSetting *a, diff --git a/libnm-util/nm-setting.c b/libnm-util/nm-setting.c index 0ca28dba1..160858d93 100644 --- a/libnm-util/nm-setting.c +++ b/libnm-util/nm-setting.c @@ -713,6 +713,8 @@ nm_setting_diff (NMSetting *a, guint i; NMSettingDiffResult a_result = NM_SETTING_DIFF_RESULT_IN_A; NMSettingDiffResult b_result = NM_SETTING_DIFF_RESULT_IN_B; + NMSettingDiffResult a_result_default = NM_SETTING_DIFF_RESULT_IN_A_DEFAULT; + NMSettingDiffResult b_result_default = NM_SETTING_DIFF_RESULT_IN_B_DEFAULT; gboolean results_created = FALSE; g_return_val_if_fail (results != NULL, FALSE); @@ -722,6 +724,12 @@ nm_setting_diff (NMSetting *a, g_return_val_if_fail (G_OBJECT_TYPE (a) == G_OBJECT_TYPE (b), FALSE); } + if ((flags & (NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT | NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT)) == + (NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT | NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT)) { + /* conflicting flags: default to WITH_DEFAULT (clearing NO_DEFAULT). */ + flags &= ~NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT; + } + /* If the caller is calling this function in a pattern like this to get * complete diffs: * @@ -734,6 +742,8 @@ nm_setting_diff (NMSetting *a, if (invert_results) { a_result = NM_SETTING_DIFF_RESULT_IN_B; b_result = NM_SETTING_DIFF_RESULT_IN_A; + a_result_default = NM_SETTING_DIFF_RESULT_IN_B_DEFAULT; + b_result_default = NM_SETTING_DIFF_RESULT_IN_A_DEFAULT; } if (*results == NULL) { @@ -746,8 +756,7 @@ nm_setting_diff (NMSetting *a, for (i = 0; i < n_property_specs; i++) { GParamSpec *prop_spec = property_specs[i]; - NMSettingDiffResult r = NM_SETTING_DIFF_RESULT_UNKNOWN, tmp; - gboolean different = TRUE; + NMSettingDiffResult r = NM_SETTING_DIFF_RESULT_UNKNOWN; /* Handle compare flags */ if (!should_compare_prop (a, prop_spec->name, flags, prop_spec->flags)) @@ -756,28 +765,58 @@ nm_setting_diff (NMSetting *a, continue; if (b) { + gboolean different; + different = !NM_SETTING_GET_CLASS (a)->compare_property (a, b, prop_spec, flags); if (different) { + gboolean a_is_default, b_is_default; GValue value = G_VALUE_INIT; g_value_init (&value, prop_spec->value_type); g_object_get_property (G_OBJECT (a), prop_spec->name, &value); - if (!g_param_value_defaults (prop_spec, &value)) - r |= a_result; + a_is_default = g_param_value_defaults (prop_spec, &value); g_value_reset (&value); g_object_get_property (G_OBJECT (b), prop_spec->name, &value); - if (!g_param_value_defaults (prop_spec, &value)) - r |= b_result; + b_is_default = g_param_value_defaults (prop_spec, &value); g_value_unset (&value); + if ((flags & NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT) == 0) { + if (!a_is_default) + r |= a_result; + if (!b_is_default) + r |= b_result; + } else { + r |= a_result | b_result; + if (a_is_default) + r |= a_result_default; + if (b_is_default) + r |= b_result_default; + } } - } else + } else if ((flags & (NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT | NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT)) == 0) r = a_result; /* only in A */ + else { + GValue value = G_VALUE_INIT; - if (different) { - tmp = GPOINTER_TO_UINT (g_hash_table_lookup (*results, prop_spec->name)); - g_hash_table_insert (*results, g_strdup (prop_spec->name), GUINT_TO_POINTER (tmp | r)); + g_value_init (&value, prop_spec->value_type); + g_object_get_property (G_OBJECT (a), prop_spec->name, &value); + if (!g_param_value_defaults (prop_spec, &value)) + r |= a_result; + else if (flags & NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT) + r |= a_result | a_result_default; + + g_value_unset (&value); + } + + if (r != NM_SETTING_DIFF_RESULT_UNKNOWN) { + void *p; + + if (g_hash_table_lookup_extended (*results, prop_spec->name, NULL, &p)) { + if ((r & GPOINTER_TO_UINT (p)) != r) + g_hash_table_insert (*results, g_strdup (prop_spec->name), GUINT_TO_POINTER (r | GPOINTER_TO_UINT (p))); + } else + g_hash_table_insert (*results, g_strdup (prop_spec->name), GUINT_TO_POINTER (r)); } } g_free (property_specs); diff --git a/libnm-util/nm-setting.h b/libnm-util/nm-setting.h index b58137a6e..28c6975a8 100644 --- a/libnm-util/nm-setting.h +++ b/libnm-util/nm-setting.h @@ -124,6 +124,20 @@ typedef enum { * @NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS: ignore secrets for which * the secret's flags indicate the secret should not be saved to persistent * storage (ie, the secret's flag includes @NM_SETTING_SECRET_FLAG_NOT_SAVED) + * @NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT: if this flag is set, + * nm_setting_diff() and nm_connection_diff() will also include properties that + * are set to their default value. See also @NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT. + * @NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT: if this flag is set, + * nm_setting_diff() and nm_connection_diff() will not include properties that + * are set to their default value. This is the opposite of + * @NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT. If both flags are set together, + * @NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT wins. If both flags are unset, + * this means to exclude default properties if there is a setting to compare, + * but include all properties, if the setting 'b' is missing. This is the legacy + * behaviour of libnm-util, where nm_setting_diff() behaved differently depending + * on whether the setting 'b' was available. If @NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT + * is set, nm_setting_diff() will also set the flags @NM_SETTING_DIFF_RESULT_IN_A_DEFAULT + * and @NM_SETTING_DIFF_RESULT_IN_B_DEFAULT, if the values are default values. * * These flags modify the comparison behavior when comparing two settings or * two connections. @@ -135,7 +149,9 @@ typedef enum { NM_SETTING_COMPARE_FLAG_IGNORE_ID = 0x00000002, NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS = 0x00000004, NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS = 0x00000008, - NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS = 0x00000010 + NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS = 0x00000010, + NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT = 0x00000020, + NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT = 0x00000040, /* 0x80000000 is used for a private flag */ } NMSettingCompareFlags; @@ -267,6 +283,10 @@ gboolean nm_setting_compare (NMSetting *a, * @NM_SETTING_DIFF_RESULT_UNKNOWN: unknown result * @NM_SETTING_DIFF_RESULT_IN_A: the property is present in setting A * @NM_SETTING_DIFF_RESULT_IN_B: the property is present in setting B + * @NM_SETTING_DIFF_RESULT_IN_A_DEFAULT: the property is present in + * setting A but is set to the default value. This flag is only set, + * if you specify @NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT. + * @NM_SETTING_DIFF_RESULT_IN_B_DEFAULT: analog to @NM_SETTING_DIFF_RESULT_IN_A_DEFAULT. * * These values indicate the result of a setting difference operation. **/ @@ -274,6 +294,8 @@ typedef enum { NM_SETTING_DIFF_RESULT_UNKNOWN = 0x00000000, NM_SETTING_DIFF_RESULT_IN_A = 0x00000001, NM_SETTING_DIFF_RESULT_IN_B = 0x00000002, + NM_SETTING_DIFF_RESULT_IN_A_DEFAULT = 0x00000004, + NM_SETTING_DIFF_RESULT_IN_B_DEFAULT = 0x00000004, } NMSettingDiffResult; gboolean nm_setting_diff (NMSetting *a, From 1464c5a11ee8594b557eb3a7e72323444ed30d14 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 25 Feb 2014 20:30:27 +0100 Subject: [PATCH 4/7] libnm: add function _nm_setting_get_setting_priority() Signed-off-by: Thomas Haller --- libnm-core/nm-core-internal.h | 1 + libnm-core/nm-setting.c | 16 ++++++++++++++-- libnm-util/nm-setting-private.h | 1 + libnm-util/nm-setting.c | 15 +++++++++++++-- 4 files changed, 29 insertions(+), 4 deletions(-) diff --git a/libnm-core/nm-core-internal.h b/libnm-core/nm-core-internal.h index c7f31f195..02c1dca70 100644 --- a/libnm-core/nm-core-internal.h +++ b/libnm-core/nm-core-internal.h @@ -60,6 +60,7 @@ gboolean _nm_setting_ip4_config_add_address_with_label (NMSettingIP4Config *s NM_SETTING_SECRET_FLAG_NOT_SAVED | \ NM_SETTING_SECRET_FLAG_NOT_REQUIRED) +guint32 _nm_setting_get_setting_priority (NMSetting *setting); GSList * _nm_utils_hash_values_to_slist (GHashTable *hash); diff --git a/libnm-core/nm-setting.c b/libnm-core/nm-setting.c index f103b753f..17a02b9e7 100644 --- a/libnm-core/nm-setting.c +++ b/libnm-core/nm-setting.c @@ -28,6 +28,7 @@ #include "nm-setting-private.h" #include "nm-setting-connection.h" #include "nm-utils.h" +#include "nm-core-internal.h" #include "nm-utils-private.h" #include "nm-property-compare.h" @@ -209,6 +210,17 @@ _get_setting_type_priority (GType type) return info->priority; } +guint32 +_nm_setting_get_setting_priority (NMSetting *setting) +{ + NMSettingPrivate *priv; + + g_return_val_if_fail (NM_IS_SETTING (setting), G_MAXUINT32); + priv = NM_SETTING_GET_PRIVATE (setting); + _ensure_setting_info (setting, priv); + return priv->info->priority; +} + gboolean _nm_setting_type_is_base_type (GType type) { @@ -279,8 +291,8 @@ _nm_setting_compare_priority (gconstpointer a, gconstpointer b) { guint32 prio_a, prio_b; - prio_a = _get_setting_type_priority (G_OBJECT_TYPE (a)); - prio_b = _get_setting_type_priority (G_OBJECT_TYPE (b)); + prio_a = _nm_setting_get_setting_priority ((NMSetting *) a); + prio_b = _nm_setting_get_setting_priority ((NMSetting *) b); if (prio_a < prio_b) return -1; diff --git a/libnm-util/nm-setting-private.h b/libnm-util/nm-setting-private.h index 9dad7eada..904827ff4 100644 --- a/libnm-util/nm-setting-private.h +++ b/libnm-util/nm-setting-private.h @@ -55,6 +55,7 @@ void _nm_register_setting (const char *name, gboolean _nm_setting_is_base_type (NMSetting *setting); gboolean _nm_setting_type_is_base_type (GType type); +guint32 _nm_setting_get_setting_priority (NMSetting *setting); GType _nm_setting_lookup_setting_type (const char *name); GType _nm_setting_lookup_setting_type_by_quark (GQuark error_quark); gint _nm_setting_compare_priority (gconstpointer a, gconstpointer b); diff --git a/libnm-util/nm-setting.c b/libnm-util/nm-setting.c index 160858d93..6f68e171a 100644 --- a/libnm-util/nm-setting.c +++ b/libnm-util/nm-setting.c @@ -209,6 +209,17 @@ _get_setting_type_priority (GType type) return info->priority; } +guint32 +_nm_setting_get_setting_priority (NMSetting *setting) +{ + NMSettingPrivate *priv; + + g_return_val_if_fail (NM_IS_SETTING (setting), G_MAXUINT32); + priv = NM_SETTING_GET_PRIVATE (setting); + _ensure_setting_info (setting, priv); + return priv->info->priority; +} + gboolean _nm_setting_type_is_base_type (GType type) { @@ -260,8 +271,8 @@ _nm_setting_compare_priority (gconstpointer a, gconstpointer b) { guint32 prio_a, prio_b; - prio_a = _get_setting_type_priority (G_OBJECT_TYPE (a)); - prio_b = _get_setting_type_priority (G_OBJECT_TYPE (b)); + prio_a = _nm_setting_get_setting_priority ((NMSetting *) a); + prio_b = _nm_setting_get_setting_priority ((NMSetting *) b); if (prio_a < prio_b) return -1; From 1cc7b8d0270148999765626e1c5e5c0992d089aa Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 26 Feb 2014 10:09:54 +0100 Subject: [PATCH 5/7] libnm-util: add _nm_setting_get_property() function Signed-off-by: Thomas Haller --- libnm-core/nm-core-internal.h | 2 ++ libnm-core/nm-setting.c | 21 +++++++++++++++++++++ libnm-util/nm-setting-private.h | 2 ++ libnm-util/nm-setting.c | 21 +++++++++++++++++++++ 4 files changed, 46 insertions(+) diff --git a/libnm-core/nm-core-internal.h b/libnm-core/nm-core-internal.h index 02c1dca70..f83b486c1 100644 --- a/libnm-core/nm-core-internal.h +++ b/libnm-core/nm-core-internal.h @@ -62,6 +62,8 @@ gboolean _nm_setting_ip4_config_add_address_with_label (NMSettingIP4Config *s guint32 _nm_setting_get_setting_priority (NMSetting *setting); +gboolean _nm_setting_get_property (NMSetting *setting, const char *name, GValue *value); + GSList * _nm_utils_hash_values_to_slist (GHashTable *hash); GHashTable *_nm_utils_copy_strdict (GHashTable *strdict); diff --git a/libnm-core/nm-setting.c b/libnm-core/nm-setting.c index 17a02b9e7..14c5f404c 100644 --- a/libnm-core/nm-setting.c +++ b/libnm-core/nm-setting.c @@ -884,6 +884,27 @@ _nm_setting_new_from_dbus (GType setting_type, return setting; } +gboolean +_nm_setting_get_property (NMSetting *setting, const char *property_name, GValue *value) +{ + GParamSpec *prop_spec; + + g_return_val_if_fail (NM_IS_SETTING (setting), FALSE); + g_return_val_if_fail (property_name, FALSE); + g_return_val_if_fail (value, FALSE); + + prop_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (setting), property_name); + + if (!prop_spec) { + g_value_unset (value); + return FALSE; + } + + g_value_init (value, prop_spec->value_type); + g_object_get_property (G_OBJECT (setting), property_name, value); + return TRUE; +} + static void duplicate_setting (NMSetting *setting, const char *name, diff --git a/libnm-util/nm-setting-private.h b/libnm-util/nm-setting-private.h index 904827ff4..1b271d0c7 100644 --- a/libnm-util/nm-setting-private.h +++ b/libnm-util/nm-setting-private.h @@ -60,6 +60,8 @@ GType _nm_setting_lookup_setting_type (const char *name); GType _nm_setting_lookup_setting_type_by_quark (GQuark error_quark); gint _nm_setting_compare_priority (gconstpointer a, gconstpointer b); +gboolean _nm_setting_get_property (NMSetting *setting, const char *name, GValue *value); + typedef enum NMSettingUpdateSecretResult { NM_SETTING_UPDATE_SECRET_ERROR = FALSE, NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED = TRUE, diff --git a/libnm-util/nm-setting.c b/libnm-util/nm-setting.c index 6f68e171a..5c3dc1e10 100644 --- a/libnm-util/nm-setting.c +++ b/libnm-util/nm-setting.c @@ -423,6 +423,27 @@ nm_setting_new_from_hash (GType setting_type, GHashTable *hash) return setting; } +gboolean +_nm_setting_get_property (NMSetting *setting, const char *property_name, GValue *value) +{ + GParamSpec *prop_spec; + + g_return_val_if_fail (NM_IS_SETTING (setting), FALSE); + g_return_val_if_fail (property_name, FALSE); + g_return_val_if_fail (value, FALSE); + + prop_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (setting), property_name); + + if (!prop_spec) { + g_value_unset (value); + return FALSE; + } + + g_value_init (value, prop_spec->value_type); + g_object_get_property (G_OBJECT (setting), property_name, value); + return TRUE; +} + static void duplicate_setting (NMSetting *setting, const char *name, From 41e0d5b9cec95347976f5cf85ea6e55ed2ab9090 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 26 Feb 2014 09:51:09 +0100 Subject: [PATCH 6/7] core: add nm_utils_log_connection_diff Signed-off-by: Thomas Haller --- src/NetworkManagerUtils.c | 248 ++++++++++++++++++++++++++++++++++++++ src/NetworkManagerUtils.h | 2 + src/tests/test-general.c | 55 +++++++++ 3 files changed, 305 insertions(+) diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c index bdf03557a..66da861da 100644 --- a/src/NetworkManagerUtils.c +++ b/src/NetworkManagerUtils.c @@ -1881,6 +1881,254 @@ nm_utils_get_monotonic_timestamp_s (void) return (((gint64) tp.tv_sec) + monotonic_timestamp_offset_sec); } +typedef struct +{ + const char *name; + NMSetting *setting; + NMSetting *diff_base_setting; + GHashTable *setting_diff; +} LogConnectionSettingData; + +typedef struct +{ + const char *item_name; + NMSettingDiffResult diff_result; +} LogConnectionSettingItem; + +static gint +_log_connection_sort_hashes_fcn (gconstpointer a, gconstpointer b) +{ + const LogConnectionSettingData *v1 = a; + const LogConnectionSettingData *v2 = b; + guint32 p1, p2; + NMSetting *s1, *s2; + + s1 = v1->setting ? v1->setting : v1->diff_base_setting; + s2 = v2->setting ? v2->setting : v2->diff_base_setting; + + g_assert (s1 && s2); + + p1 = _nm_setting_get_setting_priority (s1); + p2 = _nm_setting_get_setting_priority (s2); + + if (p1 != p2) + return p1 > p2 ? 1 : -1; + + return strcmp (v1->name, v2->name); +} + +static GArray * +_log_connection_sort_hashes (NMConnection *connection, NMConnection *diff_base, GHashTable *connection_diff) +{ + GHashTableIter iter; + GArray *sorted_hashes; + LogConnectionSettingData setting_data; + + sorted_hashes = g_array_sized_new (TRUE, FALSE, sizeof (LogConnectionSettingData), g_hash_table_size (connection_diff)); + + g_hash_table_iter_init (&iter, connection_diff); + while (g_hash_table_iter_next (&iter, (gpointer) &setting_data.name, (gpointer) &setting_data.setting_diff)) { + setting_data.setting = nm_connection_get_setting_by_name (connection, setting_data.name); + setting_data.diff_base_setting = diff_base ? nm_connection_get_setting_by_name (diff_base, setting_data.name) : NULL; + g_assert (setting_data.setting || setting_data.diff_base_setting); + g_array_append_val (sorted_hashes, setting_data); + } + + g_array_sort (sorted_hashes, _log_connection_sort_hashes_fcn); + return sorted_hashes; +} + +static gint +_log_connection_sort_names_fcn (gconstpointer a, gconstpointer b) +{ + const LogConnectionSettingItem *v1 = a; + const LogConnectionSettingItem *v2 = b; + + /* we want to first show the items, that disappeared, then the one that changed and + * then the ones that were added. */ + + if ((v1->diff_result & NM_SETTING_DIFF_RESULT_IN_A) != (v1->diff_result & NM_SETTING_DIFF_RESULT_IN_A)) + return (v1->diff_result & NM_SETTING_DIFF_RESULT_IN_A) ? -1 : 1; + if ((v1->diff_result & NM_SETTING_DIFF_RESULT_IN_B) != (v1->diff_result & NM_SETTING_DIFF_RESULT_IN_B)) + return (v1->diff_result & NM_SETTING_DIFF_RESULT_IN_B) ? 1 : -1; + return strcmp (v1->item_name, v2->item_name); +} + +static char * +_log_connection_get_property (NMSetting *setting, const char *name) +{ + GValue val = G_VALUE_INIT; + char *s; + + g_return_val_if_fail (setting, NULL); + + if ( !NM_IS_SETTING_VPN (setting) + && nm_setting_get_secret_flags (setting, name, NULL, NULL)) + return g_strdup ("****"); + + if (!_nm_setting_get_property (setting, name, &val)) + g_return_val_if_reached (FALSE); + + if (G_VALUE_HOLDS_STRING (&val)) { + const char *val_s; + + val_s = g_value_get_string (&val); + if (!val_s) { + /* for NULL, we want to return the unquoted string "NULL". */ + s = g_strdup ("NULL"); + } else { + char *escaped = g_strescape (val_s, "'"); + + s = g_strdup_printf ("'%s'", escaped); + g_free (escaped); + } + } else { + s = g_strdup_value_contents (&val); + if (s == NULL) + s = g_strdup ("NULL"); + else { + char *escaped = g_strescape (s, "'"); + + g_free (s); + s = escaped; + } + } + g_value_unset(&val); + return s; +} + +static void +_log_connection_sort_names (LogConnectionSettingData *setting_data, GArray *sorted_names) +{ + GHashTableIter iter; + LogConnectionSettingItem item; + gpointer p; + + g_array_set_size (sorted_names, 0); + + g_hash_table_iter_init (&iter, setting_data->setting_diff); + while (g_hash_table_iter_next (&iter, (gpointer) &item.item_name, &p)) { + item.diff_result = GPOINTER_TO_UINT (p); + g_array_append_val (sorted_names, item); + } + + g_array_sort (sorted_names, _log_connection_sort_names_fcn); +} + +void +nm_utils_log_connection_diff (NMConnection *connection, NMConnection *diff_base, guint32 level, guint64 domain, const char *name, const char *prefix) +{ + GHashTable *connection_diff = NULL; + GArray *sorted_hashes; + GArray *sorted_names = NULL; + int i, j; + gboolean connection_diff_are_same; + gboolean print_header = TRUE; + gboolean print_setting_header; + GString *str1; + + g_return_if_fail (NM_IS_CONNECTION (connection)); + g_return_if_fail (!diff_base || (NM_IS_CONNECTION (diff_base) && diff_base != connection)); + + /* For VPN setting types, this is broken, because we cannot (generically) print the content of data/secrets. Bummer... */ + + if (!nm_logging_enabled (level, domain)) + return; + + if (!prefix) + prefix = ""; + if (!name) + name = ""; + + connection_diff_are_same = nm_connection_diff (connection, diff_base, NM_SETTING_COMPARE_FLAG_EXACT | NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT, &connection_diff); + if (connection_diff_are_same) { + if (diff_base) + nm_log (level, domain, "%sconnection '%s' (%p and %p): no difference", prefix, name, connection, diff_base); + else + nm_log (level, domain, "%sconnection '%s' (%p): no properties set", prefix, name, connection); + g_assert (!connection_diff); + return; + } + + /* FIXME: it doesn't nicely show the content of NMSettingVpn, becuase nm_connection_diff() does not + * expand the hash values. */ + + sorted_hashes = _log_connection_sort_hashes (connection, diff_base, connection_diff); + if (sorted_hashes->len <= 0) + goto out; + + sorted_names = g_array_new (FALSE, FALSE, sizeof (LogConnectionSettingItem)); + str1 = g_string_new (NULL); + + for (i = 0; i < sorted_hashes->len; i++) { + LogConnectionSettingData *setting_data = &g_array_index (sorted_hashes, LogConnectionSettingData, i); + + _log_connection_sort_names (setting_data, sorted_names); + print_setting_header = TRUE; + for (j = 0; j < sorted_names->len; j++) { + char *str_conn, *str_diff; + LogConnectionSettingItem *item = &g_array_index (sorted_names, LogConnectionSettingItem, j); + + str_conn = (item->diff_result & NM_SETTING_DIFF_RESULT_IN_A) + ? _log_connection_get_property (setting_data->setting, item->item_name) + : NULL; + str_diff = (item->diff_result & NM_SETTING_DIFF_RESULT_IN_B) + ? _log_connection_get_property (setting_data->diff_base_setting, item->item_name) + : NULL; + + if (print_header) { + GError *err_verify = NULL; + + if (diff_base) + nm_log (level, domain, "%sconnection '%s' (%p < %p):", prefix, name, connection, diff_base); + else + nm_log (level, domain, "%sconnection '%s' (%p):", prefix, name, connection); + print_header = FALSE; + + if (!nm_connection_verify (connection, &err_verify)) { + nm_log (level, domain, "%sconnection %p does not verify: %s", prefix, connection, err_verify->message); + g_clear_error (&err_verify); + } + } +#define _NM_LOG_ALIGN "-25" + if (print_setting_header) { + if (diff_base) { + if (setting_data->setting && setting_data->diff_base_setting) + g_string_printf (str1, "%p < %p", setting_data->setting, setting_data->diff_base_setting); + else if (setting_data->diff_base_setting) + g_string_printf (str1, "*missing* < %p", setting_data->diff_base_setting); + else + g_string_printf (str1, "%p < *missing*", setting_data->setting); + nm_log (level, domain, "%s%"_NM_LOG_ALIGN"s [ %s ]", prefix, setting_data->name, str1->str); + } else + nm_log (level, domain, "%s%"_NM_LOG_ALIGN"s [ %p ]", prefix, setting_data->name, setting_data->setting); + print_setting_header = FALSE; + } + g_string_printf (str1, "%s.%s", setting_data->name, item->item_name); + switch (item->diff_result & (NM_SETTING_DIFF_RESULT_IN_A | NM_SETTING_DIFF_RESULT_IN_B)) { + case NM_SETTING_DIFF_RESULT_IN_B: + nm_log (level, domain, "%s%"_NM_LOG_ALIGN"s < %s", prefix, str1->str, str_diff ? str_diff : "NULL"); + break; + case NM_SETTING_DIFF_RESULT_IN_A: + nm_log (level, domain, "%s%"_NM_LOG_ALIGN"s = %s", prefix, str1->str, str_conn ? str_conn : "NULL"); + break; + default: + nm_log (level, domain, "%s%"_NM_LOG_ALIGN"s = %s < %s", prefix, str1->str, str_conn ? str_conn : "NULL", str_diff ? str_diff : "NULL"); + break; +#undef _NM_LOG_ALIGN + } + g_free (str_conn); + g_free (str_diff); + } + } + + g_array_free (sorted_names, TRUE); + g_string_free (str1, TRUE); +out: + g_hash_table_destroy (connection_diff); + g_array_free (sorted_hashes, TRUE); +} + /** * nm_utils_ip6_property_path: diff --git a/src/NetworkManagerUtils.h b/src/NetworkManagerUtils.h index 88de6dd20..d7fcb5303 100644 --- a/src/NetworkManagerUtils.h +++ b/src/NetworkManagerUtils.h @@ -140,6 +140,8 @@ NMConnection *nm_utils_match_connection (GSList *connections, int nm_utils_cmp_connection_by_autoconnect_priority (NMConnection **a, NMConnection **b); +void nm_utils_log_connection_diff (NMConnection *connection, NMConnection *diff_base, guint32 level, guint64 domain, const char *name, const char *prefix); + gint64 nm_utils_ascii_str_to_int64 (const char *str, guint base, gint64 min, gint64 max, gint64 fallback); #define NM_UTILS_NS_PER_SECOND ((gint64) 1000000000) diff --git a/src/tests/test-general.c b/src/tests/test-general.c index ec771bc55..f61732bb4 100644 --- a/src/tests/test-general.c +++ b/src/tests/test-general.c @@ -24,6 +24,7 @@ #include "NetworkManagerUtils.h" #include "nm-logging.h" +#include "nm-utils.h" #include "nm-test-utils.h" @@ -226,6 +227,59 @@ test_nm_utils_ip6_address_clear_host_address (void) g_rand_free (r); } + +static void +test_nm_utils_log_connection_diff() +{ + NMConnection *connection; + NMConnection *connection2; + + /* if logging is disabled (the default), nm_utils_log_connection_diff() returns + * early without doing anything. Hence, in the normal testing, this test does nothing. + * It only gets interesting, when run verbosely with NMTST_DEBUG=debug ... */ + + nm_log (LOGL_DEBUG, LOGD_CORE, "START TEST test_nm_utils_log_connection_diff..."); + + connection = nm_simple_connection_new (); + nm_connection_add_setting (connection, nm_setting_connection_new ()); + nm_utils_log_connection_diff (connection, NULL, LOGL_DEBUG, LOGD_CORE, "test1", ">>> "); + + nm_connection_add_setting (connection, nm_setting_wired_new ()); + nm_utils_log_connection_diff (connection, NULL, LOGL_DEBUG, LOGD_CORE, "test2", ">>> "); + + connection2 = nm_simple_connection_new_clone (connection); + nm_utils_log_connection_diff (connection, connection2, LOGL_DEBUG, LOGD_CORE, "test3", ">>> "); + + g_object_set (nm_connection_get_setting_connection (connection), + NM_SETTING_CONNECTION_ID, "id", + NM_SETTING_CONNECTION_UUID, "uuid", + NULL); + g_object_set (nm_connection_get_setting_connection (connection2), + NM_SETTING_CONNECTION_ID, "id2", + NM_SETTING_CONNECTION_MASTER, "master2", + NULL); + nm_utils_log_connection_diff (connection, connection2, LOGL_DEBUG, LOGD_CORE, "test4", ">>> "); + + nm_connection_add_setting (connection, nm_setting_802_1x_new ()); + nm_utils_log_connection_diff (connection, connection2, LOGL_DEBUG, LOGD_CORE, "test5", ">>> "); + + g_object_set (nm_connection_get_setting_802_1x (connection), + NM_SETTING_802_1X_PASSWORD, "id2", + NM_SETTING_802_1X_PASSWORD_FLAGS, NM_SETTING_SECRET_FLAG_NOT_SAVED, + NULL); + nm_utils_log_connection_diff (connection, NULL, LOGL_DEBUG, LOGD_CORE, "test6", ">>> "); + nm_utils_log_connection_diff (connection, connection2, LOGL_DEBUG, LOGD_CORE, "test7", ">>> "); + nm_utils_log_connection_diff (connection2, connection, LOGL_DEBUG, LOGD_CORE, "test8", ">>> "); + + g_clear_object (&connection); + g_clear_object (&connection2); + + connection = nmtst_create_minimal_connection ("id-vpn-1", NULL, NM_SETTING_VPN_SETTING_NAME, NULL); + nm_utils_log_connection_diff (connection, NULL, LOGL_DEBUG, LOGD_CORE, "test-vpn-1", ">>> "); + + g_clear_object (&connection); +} + /*******************************************/ static NMConnection * @@ -690,6 +744,7 @@ main (int argc, char **argv) g_test_add_func ("/general/nm_utils_ascii_str_to_int64", test_nm_utils_ascii_str_to_int64); g_test_add_func ("/general/nm_utils_ip6_address_clear_host_address", test_nm_utils_ip6_address_clear_host_address); + g_test_add_func ("/general/nm_utils_log_connection_diff", test_nm_utils_log_connection_diff); g_test_add_func ("/general/connection-match/basic", test_connection_match_basic); g_test_add_func ("/general/connection-match/ip6-method", test_connection_match_ip6_method); From 30b1afd73bd3cb7a772e8fadaa99354218fa773f Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 26 Feb 2014 20:54:49 +0100 Subject: [PATCH 7/7] core: log connection change with nm_utils_log_connection_diff() Signed-off-by: Thomas Haller --- src/settings/nm-settings-connection.c | 2 ++ src/settings/nm-settings.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/settings/nm-settings-connection.c b/src/settings/nm-settings-connection.c index 859581139..fe3ba3af0 100644 --- a/src/settings/nm-settings-connection.c +++ b/src/settings/nm-settings-connection.c @@ -470,6 +470,8 @@ nm_settings_connection_replace_settings (NMSettingsConnection *self, */ g_signal_handlers_block_by_func (self, G_CALLBACK (changed_cb), GUINT_TO_POINTER (TRUE)); + nm_utils_log_connection_diff (new_connection, NM_CONNECTION (self), LOGL_DEBUG, LOGD_CORE, "update connection", "++ "); + nm_connection_replace_settings_from_connection (NM_CONNECTION (self), new_connection); nm_settings_connection_set_flags (self, NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED | NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED_ASSUMED, diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c index 5a7bf4159..e3f0d33f7 100644 --- a/src/settings/nm-settings.c +++ b/src/settings/nm-settings.c @@ -874,6 +874,8 @@ claim_connection (NMSettings *self, (gpointer) nm_connection_get_path (NM_CONNECTION (connection)), g_object_ref (connection)); + nm_utils_log_connection_diff (NM_CONNECTION (connection), NULL, LOGL_DEBUG, LOGD_CORE, "new connection", "++ "); + /* Only emit the individual connection-added signal after connections * have been initially loaded. */