summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2014-10-12 22:25:15 +0200
committerThomas Haller <thaller@redhat.com>2014-10-12 22:25:32 +0200
commitec84e4f00a9607ccea0139d728d24c2c2d714e6b (patch)
tree29b02c0c6d066405411a3fa490ad0a138a4b78f3
parenta7c8e5c6e9aad100b782f0be62916e8d99399aca (diff)
parent30b1afd73bd3cb7a772e8fadaa99354218fa773f (diff)
downloadNetworkManager-ec84e4f00a9607ccea0139d728d24c2c2d714e6b.tar.gz
merge branch 'th/bgo737380_log_connection_diff'
https://bugzilla.gnome.org/show_bug.cgi?id=737380 Signed-off-by: Thomas Haller <thaller@redhat.com>
-rw-r--r--libnm-core/nm-connection.c2
-rw-r--r--libnm-core/nm-core-internal.h3
-rw-r--r--libnm-core/nm-setting-private.h2
-rw-r--r--libnm-core/nm-setting-vpn.c10
-rw-r--r--libnm-core/nm-setting.c154
-rw-r--r--libnm-core/nm-setting.h32
-rw-r--r--libnm-util/nm-setting-private.h3
-rw-r--r--libnm-util/nm-setting-vpn.c10
-rw-r--r--libnm-util/nm-setting.c127
-rw-r--r--libnm-util/nm-setting.h24
-rw-r--r--libnm/libnm.ver3
-rw-r--r--src/NetworkManagerUtils.c248
-rw-r--r--src/NetworkManagerUtils.h2
-rw-r--r--src/devices/wifi/nm-device-wifi.c18
-rw-r--r--src/settings/nm-agent-manager.c3
-rw-r--r--src/settings/nm-settings-connection.c22
-rw-r--r--src/settings/nm-settings.c2
-rw-r--r--src/settings/plugins/ifnet/connection_parser.c25
-rw-r--r--src/settings/plugins/keyfile/writer.c3
-rw-r--r--src/tests/test-general.c55
20 files changed, 645 insertions, 103 deletions
diff --git a/libnm-core/nm-connection.c b/libnm-core/nm-connection.c
index 23e9f2159c..1e0cdbf934 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-core-internal.h b/libnm-core/nm-core-internal.h
index c7f31f1957..f83b486c12 100644
--- a/libnm-core/nm-core-internal.h
+++ b/libnm-core/nm-core-internal.h
@@ -60,6 +60,9 @@ 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);
+
+gboolean _nm_setting_get_property (NMSetting *setting, const char *name, GValue *value);
GSList * _nm_utils_hash_values_to_slist (GHashTable *hash);
diff --git a/libnm-core/nm-setting-private.h b/libnm-core/nm-setting-private.h
index f277992481..9f0c51a983 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-vpn.c b/libnm-core/nm-setting-vpn.c
index 6ce4145029..667b83d78b 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 f4ad8bbd16..14c5f404ce 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;
@@ -872,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,
@@ -1002,8 +1035,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 +1145,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))
@@ -1160,6 +1206,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);
@@ -1169,6 +1217,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:
*
@@ -1181,6 +1235,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) {
@@ -1193,8 +1249,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))
@@ -1203,28 +1258,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);
@@ -1274,19 +1359,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)
{
@@ -1330,8 +1411,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;
@@ -1349,22 +1434,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,
@@ -1394,7 +1473,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
@@ -1408,7 +1487,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;
@@ -1549,8 +1628,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-core/nm-setting.h b/libnm-core/nm-setting.h
index 5ed3e6b4f7..8e179f2a4f 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,
@@ -269,14 +291,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-util/nm-setting-private.h b/libnm-util/nm-setting-private.h
index 9dad7eada5..1b271d0c76 100644
--- a/libnm-util/nm-setting-private.h
+++ b/libnm-util/nm-setting-private.h
@@ -55,10 +55,13 @@ 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);
+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-vpn.c b/libnm-util/nm-setting-vpn.c
index be892da485..70f955b010 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 2508a401fa..5c3dc1e105 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;
@@ -412,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,
@@ -542,8 +574,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 +684,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))
@@ -700,6 +745,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);
@@ -709,6 +756,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:
*
@@ -721,6 +774,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) {
@@ -733,8 +788,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))
@@ -743,28 +797,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;
+
+ 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;
- 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_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);
@@ -870,8 +954,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 +1178,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.h b/libnm-util/nm-setting.h
index b58137a6e7..28c6975a8d 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,
diff --git a/libnm/libnm.ver b/libnm/libnm.ver
index ca8283abb4..e0c4795f9e 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;
diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c
index bdf03557a1..66da861daf 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 88de6dd208..d7fcb53033 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/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c
index 8508097886..6d93833792 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 0de63ffb16..1076ae2143 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 1e0106d07b..fe3ba3af06 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;
}
@@ -460,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,
@@ -764,7 +776,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 +788,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 +798,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 +817,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/nm-settings.c b/src/settings/nm-settings.c
index 5a7bf4159e..e3f0d33f75 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.
*/
diff --git a/src/settings/plugins/ifnet/connection_parser.c b/src/settings/plugins/ifnet/connection_parser.c
index 15dd3874a5..25b958fd4f 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 ae8f0a912b..2661d50066 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;
}
diff --git a/src/tests/test-general.c b/src/tests/test-general.c
index ec771bc55b..f61732bb47 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);