summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2017-03-02 15:06:28 +0100
committerThomas Haller <thaller@redhat.com>2017-03-02 15:06:28 +0100
commit9d39569287f6770b951e30f68d88e14f9ec68ac7 (patch)
treef4f5ea1bc392838fd1ffcdedae196af198cab01d
parentd63b67b0e0254c0a1d39b5ed8b7b15ce4f9ad259 (diff)
parent24be1fd913887464e1ed0c0a523df7302140fc99 (diff)
downloadNetworkManager-9d39569287f6770b951e30f68d88e14f9ec68ac7.tar.gz
ifcfg-rh,keyfile: merge branch 'th/ifcfg-reread-rh1427482'
https://bugzilla.redhat.com/show_bug.cgi?id=1427482
-rw-r--r--libnm-core/nm-connection.c78
-rw-r--r--libnm-core/nm-core-internal.h20
-rw-r--r--libnm-core/nm-setting-connection.c39
-rw-r--r--libnm-core/nm-setting-private.h16
-rw-r--r--libnm-core/nm-setting-vlan.c14
-rw-r--r--src/NetworkManagerUtils.c8
-rw-r--r--src/devices/bluetooth/nm-bluez-device.c6
-rw-r--r--src/devices/nm-device.c5
-rw-r--r--src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-connection.c4
-rw-r--r--src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c2
-rw-r--r--src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c11
-rw-r--r--src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c159
-rw-r--r--src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.h4
-rw-r--r--src/settings/plugins/ifcfg-rh/shvar.c8
-rw-r--r--src/settings/plugins/ifcfg-rh/shvar.h4
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c220
-rw-r--r--src/settings/plugins/keyfile/nms-keyfile-connection.c16
-rw-r--r--src/settings/plugins/keyfile/nms-keyfile-plugin.c11
-rw-r--r--src/settings/plugins/keyfile/nms-keyfile-reader.c24
-rw-r--r--src/settings/plugins/keyfile/nms-keyfile-reader.h5
-rw-r--r--src/settings/plugins/keyfile/nms-keyfile-writer.c72
-rw-r--r--src/settings/plugins/keyfile/nms-keyfile-writer.h4
-rw-r--r--src/settings/plugins/keyfile/tests/test-keyfile.c75
23 files changed, 625 insertions, 180 deletions
diff --git a/libnm-core/nm-connection.c b/libnm-core/nm-connection.c
index ce6f405c35..fa195402e3 100644
--- a/libnm-core/nm-connection.c
+++ b/libnm-core/nm-connection.c
@@ -73,10 +73,6 @@ enum {
static guint signals[LAST_SIGNAL] = { 0 };
-
-static NMSettingVerifyResult _nm_connection_verify (NMConnection *connection, GError **error);
-
-
/*****************************************************************************/
static void
@@ -136,15 +132,15 @@ nm_connection_add_setting (NMConnection *connection, NMSetting *setting)
* Removes the #NMSetting with the given #GType from the #NMConnection. This
* operation dereferences the #NMSetting object.
**/
-void
-nm_connection_remove_setting (NMConnection *connection, GType setting_type)
+gboolean
+_nm_connection_remove_setting (NMConnection *connection, GType setting_type)
{
NMConnectionPrivate *priv;
NMSetting *setting;
const char *setting_name;
- g_return_if_fail (NM_IS_CONNECTION (connection));
- g_return_if_fail (g_type_is_a (setting_type, NM_TYPE_SETTING));
+ g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
+ g_return_val_if_fail (g_type_is_a (setting_type, NM_TYPE_SETTING), FALSE);
priv = NM_CONNECTION_GET_PRIVATE (connection);
setting_name = g_type_name (setting_type);
@@ -153,7 +149,23 @@ nm_connection_remove_setting (NMConnection *connection, GType setting_type)
g_signal_handlers_disconnect_by_func (setting, setting_changed_cb, connection);
g_hash_table_remove (priv->settings, setting_name);
g_signal_emit (connection, signals[CHANGED], 0);
+ return TRUE;
}
+ return FALSE;
+}
+
+/**
+ * nm_connection_remove_setting:
+ * @connection: a #NMConnection
+ * @setting_type: the #GType of the setting object to remove
+ *
+ * Removes the #NMSetting with the given #GType from the #NMConnection. This
+ * operation dereferences the #NMSetting object.
+ **/
+void
+nm_connection_remove_setting (NMConnection *connection, GType setting_type)
+{
+ _nm_connection_remove_setting (connection, setting_type);
}
/**
@@ -602,17 +614,17 @@ static gboolean
_normalize_connection_uuid (NMConnection *self)
{
NMSettingConnection *s_con = nm_connection_get_setting_connection (self);
- char *uuid;
+ char uuid[37];
- g_assert (s_con);
+ nm_assert (s_con);
if (nm_setting_connection_get_uuid (s_con))
return FALSE;
- uuid = nm_utils_uuid_generate ();
- g_object_set (s_con, NM_SETTING_CONNECTION_UUID, uuid, NULL);
- g_free (uuid);
-
+ g_object_set (s_con,
+ NM_SETTING_CONNECTION_UUID,
+ nm_utils_uuid_generate_buf (uuid),
+ NULL);
return TRUE;
}
@@ -986,6 +998,38 @@ _normalize_team_port_config (NMConnection *self, GHashTable *parameters)
return FALSE;
}
+static gboolean
+_normalize_required_settings (NMConnection *self, GHashTable *parameters)
+{
+ if (nm_connection_get_setting_vlan (self)) {
+ if (!nm_connection_get_setting_wired (self)) {
+ nm_connection_add_setting (self, nm_setting_wired_new ());
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static gboolean
+_normalize_invalid_slave_port_settings (NMConnection *self, GHashTable *parameters)
+{
+ NMSettingConnection *s_con = nm_connection_get_setting_connection (self);
+ const char *slave_type;
+ gboolean changed = FALSE;
+
+ slave_type = nm_setting_connection_get_slave_type (s_con);
+
+ if ( !nm_streq0 (slave_type, NM_SETTING_BRIDGE_SETTING_NAME)
+ && _nm_connection_remove_setting (self, NM_TYPE_SETTING_BRIDGE_PORT))
+ changed = TRUE;
+
+ if ( !nm_streq0 (slave_type, NM_SETTING_TEAM_SETTING_NAME)
+ && _nm_connection_remove_setting (self, NM_TYPE_SETTING_TEAM_PORT))
+ changed = TRUE;
+
+ return changed;
+}
+
/**
* nm_connection_verify:
* @connection: the #NMConnection to verify
@@ -1017,7 +1061,7 @@ nm_connection_verify (NMConnection *connection, GError **error)
return result == NM_SETTING_VERIFY_SUCCESS || result == NM_SETTING_VERIFY_NORMALIZABLE;
}
-static NMSettingVerifyResult
+NMSettingVerifyResult
_nm_connection_verify (NMConnection *connection, GError **error)
{
NMConnectionPrivate *priv;
@@ -1233,8 +1277,10 @@ nm_connection_normalize (NMConnection *connection,
was_modified |= _normalize_connection_uuid (connection);
was_modified |= _normalize_connection_type (connection);
was_modified |= _normalize_connection_slave_type (connection);
- was_modified |= _normalize_ethernet_link_neg (connection);
+ was_modified |= _normalize_required_settings (connection, parameters);
+ was_modified |= _normalize_invalid_slave_port_settings (connection, parameters);
was_modified |= _normalize_ip_config (connection, parameters);
+ was_modified |= _normalize_ethernet_link_neg (connection);
was_modified |= _normalize_infiniband_mtu (connection, parameters);
was_modified |= _normalize_bond_mode (connection, parameters);
was_modified |= _normalize_wireless_mac_address_randomization (connection, parameters);
diff --git a/libnm-core/nm-core-internal.h b/libnm-core/nm-core-internal.h
index 71e0ff893b..ac292bfc18 100644
--- a/libnm-core/nm-core-internal.h
+++ b/libnm-core/nm-core-internal.h
@@ -118,6 +118,26 @@ gboolean _nm_connection_replace_settings (NMConnection *connection,
NMSettingParseFlags parse_flags,
GError **error);
+/**
+ * NMSettingVerifyResult:
+ * @NM_SETTING_VERIFY_SUCCESS: the setting verifies successfully
+ * @NM_SETTING_VERIFY_ERROR: the setting has a serious misconfiguration
+ * @NM_SETTING_VERIFY_NORMALIZABLE: the setting is valid but has properties
+ * that should be normalized
+ * @NM_SETTING_VERIFY_NORMALIZABLE_ERROR: the setting is invalid but the
+ * errors can be fixed by nm_connection_normalize().
+ */
+typedef enum {
+ NM_SETTING_VERIFY_SUCCESS = TRUE,
+ NM_SETTING_VERIFY_ERROR = FALSE,
+ NM_SETTING_VERIFY_NORMALIZABLE = 2,
+ NM_SETTING_VERIFY_NORMALIZABLE_ERROR = 3,
+} NMSettingVerifyResult;
+
+NMSettingVerifyResult _nm_connection_verify (NMConnection *connection, GError **error);
+
+gboolean _nm_connection_remove_setting (NMConnection *connection, GType setting_type);
+
NMConnection *_nm_simple_connection_new_from_dbus (GVariant *dict,
NMSettingParseFlags parse_flags,
GError **error);
diff --git a/libnm-core/nm-setting-connection.c b/libnm-core/nm-setting-connection.c
index ac8bdf2d2d..376da69f4e 100644
--- a/libnm-core/nm-setting-connection.c
+++ b/libnm-core/nm-setting-connection.c
@@ -857,7 +857,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
{
NMSettingConnectionPrivate *priv = NM_SETTING_CONNECTION_GET_PRIVATE (setting);
gboolean is_slave;
- const char *slave_setting_type = NULL;
+ const char *slave_setting_type;
NMSetting *normerr_base_type = NULL;
const char *normerr_slave_setting_type = NULL;
const char *normerr_missing_slave_type = NULL;
@@ -958,16 +958,17 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
}
is_slave = FALSE;
- if (priv->slave_type)
+ slave_setting_type = NULL;
+ if (priv->slave_type) {
is_slave = _nm_setting_slave_type_is_valid (priv->slave_type, &slave_setting_type);
-
- if (priv->slave_type && !is_slave) {
- g_set_error (error,
- NM_CONNECTION_ERROR,
- NM_CONNECTION_ERROR_INVALID_PROPERTY,
- _("Unknown slave type '%s'"), priv->slave_type);
- g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_SLAVE_TYPE);
- return FALSE;
+ if (!is_slave) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("Unknown slave type '%s'"), priv->slave_type);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_SLAVE_TYPE);
+ return FALSE;
+ }
}
if (is_slave) {
@@ -1063,6 +1064,24 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
return NM_SETTING_VERIFY_NORMALIZABLE_ERROR;
}
+ if (connection) {
+ gboolean has_bridge_port = FALSE;
+
+ if ( ( !nm_streq0 (priv->slave_type, NM_SETTING_BRIDGE_SETTING_NAME)
+ && (has_bridge_port = !!nm_connection_get_setting_by_name (connection, NM_SETTING_BRIDGE_PORT_SETTING_NAME)))
+ || ( !nm_streq0 (priv->slave_type, NM_SETTING_TEAM_SETTING_NAME)
+ && nm_connection_get_setting_by_name (connection, NM_SETTING_TEAM_PORT_SETTING_NAME))) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_SETTING,
+ _("A slave connection with '%s' set to '%s' cannot have a '%s' setting"),
+ NM_SETTING_CONNECTION_SLAVE_TYPE, priv->slave_type ?: "",
+ has_bridge_port ? NM_SETTING_BRIDGE_PORT_SETTING_NAME : NM_SETTING_TEAM_PORT_SETTING_NAME);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_SLAVE_TYPE);
+ return NM_SETTING_VERIFY_NORMALIZABLE_ERROR;
+ }
+ }
+
return TRUE;
}
diff --git a/libnm-core/nm-setting-private.h b/libnm-core/nm-setting-private.h
index 8d09e3d759..79b6ac8712 100644
--- a/libnm-core/nm-setting-private.h
+++ b/libnm-core/nm-setting-private.h
@@ -27,22 +27,6 @@
#include "nm-core-internal.h"
-/**
- * NMSettingVerifyResult:
- * @NM_SETTING_VERIFY_SUCCESS: the setting verifies successfully
- * @NM_SETTING_VERIFY_ERROR: the setting has a serious misconfiguration
- * @NM_SETTING_VERIFY_NORMALIZABLE: the setting is valid but has properties
- * that should be normalized
- * @NM_SETTING_VERIFY_NORMALIZABLE_ERROR: the setting is invalid but the
- * errors can be fixed by nm_connection_normalize().
- */
-typedef enum {
- NM_SETTING_VERIFY_SUCCESS = TRUE,
- NM_SETTING_VERIFY_ERROR = FALSE,
- NM_SETTING_VERIFY_NORMALIZABLE = 2,
- NM_SETTING_VERIFY_NORMALIZABLE_ERROR = 3,
-} NMSettingVerifyResult;
-
void _nm_register_setting (const char *name,
const GType type,
const guint32 priority);
diff --git a/libnm-core/nm-setting-vlan.c b/libnm-core/nm-setting-vlan.c
index 6126478479..bbda72d7bb 100644
--- a/libnm-core/nm-setting-vlan.c
+++ b/libnm-core/nm-setting-vlan.c
@@ -600,7 +600,7 @@ nm_setting_vlan_init (NMSettingVlan *setting)
{
}
-static gboolean
+static int
verify (NMSetting *setting, NMConnection *connection, GError **error)
{
NMSettingVlanPrivate *priv = NM_SETTING_VLAN_GET_PRIVATE (setting);
@@ -681,6 +681,18 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
return FALSE;
}
+ if (connection && !s_wired) {
+ /* technically, a VLAN setting does not require an ethernet setting. However,
+ * the ifcfg-rh reader always adds a ethernet setting when reading a vlan setting.
+ * Thus, in order to be consistent, always add one via normalization. */
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_SETTING_NOT_FOUND,
+ _("vlan setting should have a ethernet setting as well"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_VLAN_SETTING_NAME, NM_SETTING_VLAN_FLAGS);
+ return NM_SETTING_VERIFY_NORMALIZABLE;
+ }
+
return TRUE;
}
diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c
index 55b660db83..20b871622e 100644
--- a/src/NetworkManagerUtils.c
+++ b/src/NetworkManagerUtils.c
@@ -217,7 +217,7 @@ nm_utils_complete_generic (NMPlatform *platform,
gboolean default_enable_ipv6)
{
NMSettingConnection *s_con;
- char *id, *uuid, *ifname;
+ char *id, *ifname;
GHashTable *parameters;
g_assert (fallback_id_prefix);
@@ -230,9 +230,9 @@ nm_utils_complete_generic (NMPlatform *platform,
g_object_set (G_OBJECT (s_con), NM_SETTING_CONNECTION_TYPE, ctype, NULL);
if (!nm_setting_connection_get_uuid (s_con)) {
- uuid = nm_utils_uuid_generate ();
- g_object_set (G_OBJECT (s_con), NM_SETTING_CONNECTION_UUID, uuid, NULL);
- g_free (uuid);
+ char uuid[37];
+
+ g_object_set (G_OBJECT (s_con), NM_SETTING_CONNECTION_UUID, nm_utils_uuid_generate_buf (uuid), NULL);
}
/* Add a connection ID if absent */
diff --git a/src/devices/bluetooth/nm-bluez-device.c b/src/devices/bluetooth/nm-bluez-device.c
index 92b2c91895..ebfa0d647e 100644
--- a/src/devices/bluetooth/nm-bluez-device.c
+++ b/src/devices/bluetooth/nm-bluez-device.c
@@ -183,7 +183,8 @@ pan_connection_check_create (NMBluezDevice *self)
NMConnection *connection;
NMConnection *added;
NMSetting *setting;
- char *uuid, *id;
+ char *id;
+ char uuid[37];
GError *error = NULL;
NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self);
@@ -205,7 +206,7 @@ pan_connection_check_create (NMBluezDevice *self)
connection = nm_simple_connection_new ();
/* Setting: Connection */
- uuid = nm_utils_uuid_generate ();
+ nm_utils_uuid_generate_buf (uuid);
id = g_strdup_printf (_("%s Network"), priv->name);
setting = nm_setting_connection_new ();
g_object_set (setting,
@@ -266,7 +267,6 @@ pan_connection_check_create (NMBluezDevice *self)
g_object_unref (connection);
g_free (id);
- g_free (uuid);
}
static gboolean
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index a0a5ed2aec..ef96243b2f 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -3629,7 +3629,7 @@ nm_device_generate_connection (NMDevice *self, NMDevice *master)
NMSetting *s_con;
NMSetting *s_ip4;
NMSetting *s_ip6;
- gs_free char *uuid = NULL;
+ char uuid[37];
const char *ip4_method, *ip6_method;
GError *error = NULL;
const NMPlatformLink *pllink;
@@ -3646,10 +3646,9 @@ nm_device_generate_connection (NMDevice *self, NMDevice *master)
connection = nm_simple_connection_new ();
s_con = nm_setting_connection_new ();
- uuid = nm_utils_uuid_generate ();
g_object_set (s_con,
- NM_SETTING_CONNECTION_UUID, uuid,
+ NM_SETTING_CONNECTION_UUID, nm_utils_uuid_generate_buf (uuid),
NM_SETTING_CONNECTION_ID, ifname,
NM_SETTING_CONNECTION_AUTOCONNECT, FALSE,
NM_SETTING_CONNECTION_INTERFACE_NAME, ifname,
diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-connection.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-connection.c
index ba8ea323e3..b54f9549a6 100644
--- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-connection.c
+++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-connection.c
@@ -345,11 +345,15 @@ commit_changes (NMSettingsConnection *connection,
success = writer_update_connection (NM_CONNECTION (connection),
IFCFG_DIR,
filename,
+ NULL,
+ NULL,
&error);
} else {
success = writer_new_connection (NM_CONNECTION (connection),
IFCFG_DIR,
&ifcfg_path,
+ NULL,
+ NULL,
&error);
if (success) {
nm_settings_connection_set_filename (connection, ifcfg_path);
diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c
index 414f593b65..3c5ae91ffc 100644
--- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c
+++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c
@@ -687,7 +687,7 @@ add_connection (NMSettingsPlugin *config,
return NULL;
if (save_to_disk) {
- if (!writer_new_connection (connection, IFCFG_DIR, &path, error))
+ if (!writer_new_connection (connection, IFCFG_DIR, &path, NULL, NULL, error))
return NULL;
}
return NM_SETTINGS_CONNECTION (update_connection (self, connection, path, NULL, FALSE, NULL, error));
diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c
index bbe990336f..4a128024c7 100644
--- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c
+++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c
@@ -5087,8 +5087,15 @@ connection_from_file_full (const char *filename,
if (devtype) {
if (!strcasecmp (devtype, TYPE_TEAM))
type = g_strdup (TYPE_TEAM);
- else if (!strcasecmp (devtype, TYPE_TEAM_PORT))
- type = g_strdup (TYPE_ETHERNET);
+ else if (!strcasecmp (devtype, TYPE_TEAM_PORT)) {
+ gs_free char *device = NULL;
+
+ device = svGetValueStr_cp (parsed, "DEVICE");
+ if (device && is_vlan_device (device, parsed))
+ type = g_strdup (TYPE_VLAN);
+ else
+ type = g_strdup (TYPE_ETHERNET);
+ }
g_free (devtype);
}
if (!type) {
diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c
index 6d4d5a3f9c..620e89e4ba 100644
--- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c
+++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c
@@ -307,7 +307,6 @@ write_8021x_certs (NMSetting8021x *s_8021x,
shvarFile *ifcfg,
GError **error)
{
- gboolean success = FALSE;
const Setting8021xSchemeVtable *otype = NULL;
/* CA certificate */
@@ -326,7 +325,7 @@ write_8021x_certs (NMSetting8021x *s_8021x,
/* Save the private key */
if (!write_object (s_8021x, ifcfg, otype, error))
- goto out;
+ return FALSE;
/* Client certificate */
if (otype->vtable->format_func (s_8021x) == NM_SETTING_802_1X_CK_FORMAT_PKCS12) {
@@ -343,13 +342,10 @@ write_8021x_certs (NMSetting8021x *s_8021x,
? &setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_CLIENT_CERT]
: &setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_CLIENT_CERT],
error))
- goto out;
+ return FALSE;
}
- success = TRUE;
-
-out:
- return success;
+ return TRUE;
}
static gboolean
@@ -362,7 +358,6 @@ write_8021x_setting (NMConnection *connection,
NMSetting8021xAuthFlags auth_flags;
const char *value, *match;
char *tmp = NULL;
- gboolean success = FALSE;
GString *phase2_auth;
GString *str;
guint32 i, num;
@@ -511,13 +506,14 @@ write_8021x_setting (NMConnection *connection,
else
svUnsetValue (ifcfg, "IEEE_8021X_AUTH_TIMEOUT");
- success = write_8021x_certs (s_8021x, FALSE, ifcfg, error);
- if (success) {
- /* phase2/inner certs */
- success = write_8021x_certs (s_8021x, TRUE, ifcfg, error);
- }
+ if (!write_8021x_certs (s_8021x, FALSE, ifcfg, error))
+ return FALSE;
+
+ /* phase2/inner certs */
+ if (!write_8021x_certs (s_8021x, TRUE, ifcfg, error))
+ return FALSE;
- return success;
+ return TRUE;
}
static gboolean
@@ -1876,12 +1872,11 @@ write_route_file_legacy (const char *filename, NMSettingIPConfig *s_ip4, GError
{
const char *dest, *next_hop;
char **route_items;
- char *route_contents;
+ gs_free char *route_contents = NULL;
NMIPRoute *route;
guint32 prefix;
gint64 metric;
guint32 i, num;
- gboolean success = FALSE;
g_return_val_if_fail (filename != NULL, FALSE);
g_return_val_if_fail (s_ip4 != NULL, FALSE);
@@ -1915,15 +1910,10 @@ write_route_file_legacy (const char *filename, NMSettingIPConfig *s_ip4, GError
if (!g_file_set_contents (filename, route_contents, -1, NULL)) {
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
"Writing route file '%s' failed", filename);
- goto error;
+ return FALSE;
}
- success = TRUE;
-
-error:
- g_free (route_contents);
-
- return success;
+ return TRUE;
}
static gboolean
@@ -2382,10 +2372,9 @@ static gboolean
write_route6_file (const char *filename, NMSettingIPConfig *s_ip6, GError **error)
{
char **route_items;
- char *route_contents;
+ gs_free char *route_contents = NULL;
NMIPRoute *route;
guint32 i, num;
- gboolean success = FALSE;
g_return_val_if_fail (filename != NULL, FALSE);
g_return_val_if_fail (s_ip6 != NULL, FALSE);
@@ -2422,14 +2411,10 @@ write_route6_file (const char *filename, NMSettingIPConfig *s_ip6, GError **erro
if (!g_file_set_contents (filename, route_contents, -1, NULL)) {
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
"Writing route6 file '%s' failed", filename);
- goto error;
+ return FALSE;
}
- success = TRUE;
-
-error:
- g_free (route_contents);
- return success;
+ return TRUE;
}
static void
@@ -2637,17 +2622,14 @@ write_ip6_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
if (!route6_path) {
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
"Could not get route6 file path for '%s'", svFileGetName (ifcfg));
- goto error;
+ return FALSE;
}
write_route6_file (route6_path, s_ip6, error);
g_free (route6_path);
if (error && *error)
- goto error;
+ return FALSE;
return TRUE;
-
-error:
- return FALSE;
}
static void
@@ -2732,18 +2714,20 @@ write_connection (NMConnection *connection,
const char *ifcfg_dir,
const char *filename,
char **out_filename,
+ NMConnection **out_reread,
+ gboolean *out_reread_same,
GError **error)
{
NMSettingConnection *s_con;
- gboolean success = FALSE;
- shvarFile *ifcfg = NULL;
- char *ifcfg_name = NULL;
+ nm_auto_shvar_file_close shvarFile *ifcfg = NULL;
+ gs_free char *ifcfg_name = NULL;
const char *type;
gboolean no_8021x = FALSE;
gboolean wired = FALSE;
nm_assert (NM_IS_CONNECTION (connection));
- nm_assert (nm_connection_verify (connection, NULL));
+ nm_assert (_nm_connection_verify (connection, NULL) == NM_SETTING_VERIFY_SUCCESS);
+ nm_assert (!out_reread || !*out_reread);
if (!writer_can_write_connection (connection, error))
return FALSE;
@@ -2772,13 +2756,12 @@ write_connection (NMConnection *connection,
if (g_file_test (ifcfg_name, G_FILE_TEST_EXISTS)) {
guint32 idx = 0;
- g_free (ifcfg_name);
+ nm_clear_g_free (&ifcfg_name);
while (idx++ < 500) {
ifcfg_name = g_strdup_printf ("%s/ifcfg-%s-%u", ifcfg_dir, escaped, idx);
if (g_file_test (ifcfg_name, G_FILE_TEST_EXISTS) == FALSE)
break;
- g_free (ifcfg_name);
- ifcfg_name = NULL;
+ nm_clear_g_free (&ifcfg_name);
}
}
g_free (escaped);
@@ -2796,7 +2779,7 @@ write_connection (NMConnection *connection,
if (!type) {
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
"Missing connection type!");
- goto out;
+ return FALSE;
}
if (!strcmp (type, NM_SETTING_WIRED_SETTING_NAME)) {
@@ -2805,82 +2788,110 @@ write_connection (NMConnection *connection,
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
"Can't write connection type '%s'",
NM_SETTING_PPPOE_SETTING_NAME);
- goto out;
+ return FALSE;
}
if (!write_wired_setting (connection, ifcfg, error))
- goto out;
+ return FALSE;
wired = TRUE;
} else if (!strcmp (type, NM_SETTING_VLAN_SETTING_NAME)) {
if (!write_vlan_setting (connection, ifcfg, &wired, error))
- goto out;
+ return FALSE;
} else if (!strcmp (type, NM_SETTING_WIRELESS_SETTING_NAME)) {
if (!write_wireless_setting (connection, ifcfg, &no_8021x, error))
- goto out;
+ return FALSE;
} else if (!strcmp (type, NM_SETTING_INFINIBAND_SETTING_NAME)) {
if (!write_infiniband_setting (connection, ifcfg, error))
- goto out;
+ return FALSE;
} else if (!strcmp (type, NM_SETTING_BOND_SETTING_NAME)) {
if (!write_bonding_setting (connection, ifcfg, &wired, error))
- goto out;
+ return FALSE;
} else if (!strcmp (type, NM_SETTING_TEAM_SETTING_NAME)) {
if (!write_team_setting (connection, ifcfg, &wired, error))
- goto out;
+ return FALSE;
} else if (!strcmp (type, NM_SETTING_BRIDGE_SETTING_NAME)) {
if (!write_bridge_setting (connection, ifcfg, error))
- goto out;
+ return FALSE;
} else {
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
"Can't write connection type '%s'", type);
- goto out;
+ return FALSE;
}
if (!no_8021x) {
if (!write_8021x_setting (connection, ifcfg, wired, error))
- goto out;
+ return FALSE;
}
if (!write_bridge_port_setting (connection, ifcfg, error))
- goto out;
+ return FALSE;
if (!write_team_port_setting (connection, ifcfg, error))
- goto out;
+ return FALSE;
if (!write_dcb_setting (connection, ifcfg, error))
- goto out;
+ return FALSE;
if (!write_proxy_setting (connection, ifcfg, error))
- goto out;
+ return FALSE;
svUnsetValue (ifcfg, "DHCP_HOSTNAME");
svUnsetValue (ifcfg, "DHCP_FQDN");
if (!write_ip4_setting (connection, ifcfg, error))
- goto out;
+ return FALSE;
write_ip4_aliases (connection, ifcfg_name);
if (!write_ip6_setting (connection, ifcfg, error))
- goto out;
+ return FALSE;
if (!write_res_options (connection, ifcfg, error))
- goto out;
+ return FALSE;
write_connection_setting (s_con, ifcfg);
if (!svWriteFile (ifcfg, 0644, error))
- goto out;
+ return FALSE;
+
+ if (out_reread || out_reread_same) {
+ gs_unref_object NMConnection *reread = NULL;
+ gs_free_error GError *local = NULL;
+ gs_free char *unhandled = NULL;
+ gboolean reread_same = FALSE;
+
+ reread = connection_from_file (ifcfg_name, &unhandled, &local, NULL);
+
+ if (unhandled) {
+ _LOGW ("failure to re-read the new connection from file \"%s\": %s",
+ ifcfg_name, "connection is unhandled");
+ g_clear_object (&reread);
+ } else if (!reread) {
+ _LOGW ("failure to re-read the new connection from file \"%s\": %s",
+ ifcfg_name, local ? local->message : "<unknown>");
+ } else {
+ if (out_reread_same) {
+ if (nm_connection_compare (reread, connection, NM_SETTING_COMPARE_FLAG_EXACT))
+ reread_same = TRUE;
+
+ nm_assert (reread_same == nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT));
+ nm_assert (reread_same == ({
+ gs_unref_hashtable GHashTable *_settings = NULL;
+
+ ( nm_connection_diff (reread, connection, NM_SETTING_COMPARE_FLAG_EXACT, &_settings)
+ && !_settings);
+ }));
+ }
+ }
+
+ NM_SET_OUT (out_reread, g_steal_pointer (&reread));
+ NM_SET_OUT (out_reread_same, reread_same);
+ }
/* Only return the filename if this was a newly written ifcfg */
if (out_filename && !filename)
- *out_filename = g_strdup (ifcfg_name);
+ *out_filename = g_steal_pointer (&ifcfg_name);
- success = TRUE;
-
-out:
- if (ifcfg)
- svCloseFile (ifcfg);
- g_free (ifcfg_name);
- return success;
+ return TRUE;
}
gboolean
@@ -2912,15 +2923,19 @@ gboolean
writer_new_connection (NMConnection *connection,
const char *ifcfg_dir,
char **out_filename,
+ NMConnection **out_reread,
+ gboolean *out_reread_same,
GError **error)
{
- return write_connection (connection, ifcfg_dir, NULL, out_filename, error);
+ return write_connection (connection, ifcfg_dir, NULL, out_filename, out_reread, out_reread_same, error);
}
gboolean
writer_update_connection (NMConnection *connection,
const char *ifcfg_dir,
const char *filename,
+ NMConnection **out_reread,
+ gboolean *out_reread_same,
GError **error)
{
if (utils_has_complex_routes (filename)) {
@@ -2929,6 +2944,6 @@ writer_update_connection (NMConnection *connection,
return FALSE;
}
- return write_connection (connection, ifcfg_dir, filename, NULL, error);
+ return write_connection (connection, ifcfg_dir, filename, NULL, out_reread, out_reread_same, error);
}
diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.h b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.h
index 2662f79b06..9cd9513ec2 100644
--- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.h
+++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.h
@@ -29,11 +29,15 @@ gboolean writer_can_write_connection (NMConnection *connection,
gboolean writer_new_connection (NMConnection *connection,
const char *ifcfg_dir,
char **out_filename,
+ NMConnection **out_reread,
+ gboolean *out_reread_same,
GError **error);
gboolean writer_update_connection (NMConnection *connection,
const char *ifcfg_dir,
const char *filename,
+ NMConnection **out_reread,
+ gboolean *out_reread_same,
GError **error);
#endif /* _WRITER_H_ */
diff --git a/src/settings/plugins/ifcfg-rh/shvar.c b/src/settings/plugins/ifcfg-rh/shvar.c
index a058657932..d847ba73f0 100644
--- a/src/settings/plugins/ifcfg-rh/shvar.c
+++ b/src/settings/plugins/ifcfg-rh/shvar.c
@@ -637,15 +637,19 @@ svFileGetName (const shvarFile *s)
}
void
-svFileSetName (shvarFile *s, const char *fileName)
+svFileSetName_test_only (shvarFile *s, const char *fileName)
{
+ /* changing the file name is not supported for regular
+ * operation. Only allowed to use in tests, othewise,
+ * the filename is immutable. */
g_free (s->fileName);
s->fileName = g_strdup (fileName);
}
void
-svFileSetModified (shvarFile *s)
+svFileSetModified_test_only (shvarFile *s)
{
+ /* marking a file as modified is only for testing. */
s->modified = TRUE;
}
diff --git a/src/settings/plugins/ifcfg-rh/shvar.h b/src/settings/plugins/ifcfg-rh/shvar.h
index 5c384bb229..8eaf9b878e 100644
--- a/src/settings/plugins/ifcfg-rh/shvar.h
+++ b/src/settings/plugins/ifcfg-rh/shvar.h
@@ -34,9 +34,9 @@
typedef struct _shvarFile shvarFile;
const char *svFileGetName (const shvarFile *s);
-void svFileSetName (shvarFile *s, const char *fileName);
-void svFileSetModified (shvarFile *s);
+void svFileSetName_test_only (shvarFile *s, const char *fileName);
+void svFileSetModified_test_only (shvarFile *s);
/* Create the file <name>, return a shvarFile (never fails) */
shvarFile *svCreateFile (const char *name);
diff --git a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
index fd4bdfdf7d..bd6068ce15 100644
--- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
+++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
@@ -88,22 +88,72 @@
|| ( _val_string && nm_streq0 (_val, _val_string))); \
} G_STMT_END
-#define _writer_update_connection(connection, ifcfg_dir, filename) \
+static void
+_assert_reread_same (NMConnection *connection, NMConnection *reread)
+{
+ nmtst_assert_connection_verifies_without_normalization (reread);
+ nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
+}
+
+static void
+_assert_reread_same_FIXME (NMConnection *connection, NMConnection *reread)
+{
+ gs_unref_object NMConnection *connection_normalized = NULL;
+ gs_unref_hashtable GHashTable *settings = NULL;
+
+ /* FIXME: these assertion failures should not happen as we expect
+ * that re-reading a connection after write yields the same result.
+ *
+ * Needs investation and fixing. */
+ nmtst_assert_connection_verifies_without_normalization (reread);
+
+ connection_normalized = nmtst_connection_duplicate_and_normalize (connection);
+
+ g_assert (!nm_connection_compare (connection_normalized, reread, NM_SETTING_COMPARE_FLAG_EXACT));
+ g_assert (!nm_connection_diff (connection_normalized, reread, NM_SETTING_COMPARE_FLAG_EXACT, &settings));
+}
+
+#define _writer_update_connection_reread(connection, ifcfg_dir, filename, out_reread, out_reread_same) \
G_STMT_START { \
- NMConnection *_connection = (connection); \
+ gs_unref_object NMConnection *_connection = nmtst_connection_duplicate_and_normalize (connection); \
+ NMConnection **_out_reread = (out_reread); \
+ gboolean *_out_reread_same = (out_reread_same); \
const char *_ifcfg_dir = (ifcfg_dir); \
const char *_filename = (filename); \
GError *_error = NULL; \
gboolean _success; \
\
- g_assert (NM_IS_CONNECTION (connection)); \
g_assert (_ifcfg_dir && _ifcfg_dir[0]); \
g_assert (_filename && _filename[0]); \
\
- _success = writer_update_connection (_connection, _ifcfg_dir, _filename, &_error); \
+ _success = writer_update_connection (_connection, _ifcfg_dir, _filename, _out_reread, _out_reread_same, &_error); \
nmtst_assert_success (_success, _error); \
} G_STMT_END
+#define _writer_update_connection(connection, ifcfg_dir, filename) \
+ G_STMT_START { \
+ gs_unref_object NMConnection *_reread = NULL; \
+ NMConnection *_c = (connection); \
+ gboolean _reread_same = FALSE; \
+ \
+ _writer_update_connection_reread (_c, ifcfg_dir, filename, &_reread, &_reread_same); \
+ _assert_reread_same (_c, _reread); \
+ g_assert (_reread_same); \
+ } G_STMT_END
+
+#define _writer_update_connection_FIXME(connection, ifcfg_dir, filename) \
+ G_STMT_START { \
+ gs_unref_object NMConnection *_reread = NULL; \
+ NMConnection *_c = (connection); \
+ gboolean _reread_same = FALSE; \
+ \
+ /* FIXME: this should not happen. Fix to use _writer_update_connection() */ \
+ \
+ _writer_update_connection_reread (_c, ifcfg_dir, filename, &_reread, &_reread_same); \
+ _assert_reread_same_FIXME (_c, _reread); \
+ g_assert (!_reread_same); \
+ } G_STMT_END
+
static NMConnection *
_connection_from_file (const char *filename,
const char *network_file,
@@ -147,14 +197,18 @@ _connection_from_file_fail (const char *filename,
}
static void
-_writer_new_connection (NMConnection *connection,
- const char *ifcfg_dir,
- char **out_filename)
+_writer_new_connection_reread (NMConnection *connection,
+ const char *ifcfg_dir,
+ char **out_filename,
+ NMConnection **out_reread,
+ gboolean *out_reread_same)
{
gboolean success;
GError *error = NULL;
char *filename = NULL;
gs_unref_object NMConnection *con_verified = NULL;
+ gs_unref_object NMConnection *reread_copy = NULL;
+ NMConnection **reread = out_reread ?: ((nmtst_get_rand_int () % 2) ? &reread_copy : NULL);
g_assert (NM_IS_CONNECTION (connection));
g_assert (ifcfg_dir);
@@ -164,10 +218,15 @@ _writer_new_connection (NMConnection *connection,
success = writer_new_connection (con_verified,
ifcfg_dir,
&filename,
+ reread,
+ out_reread_same,
&error);
nmtst_assert_success (success, error);
g_assert (filename && filename[0]);
+ if (reread)
+ nmtst_assert_connection_verifies_without_normalization (*reread);
+
if (out_filename)
*out_filename = filename;
else
@@ -175,10 +234,40 @@ _writer_new_connection (NMConnection *connection,
}
static void
+_writer_new_connection (NMConnection *connection,
+ const char *ifcfg_dir,
+ char **out_filename)
+{
+ gs_unref_object NMConnection *reread = NULL;
+ gboolean reread_same = FALSE;
+
+ _writer_new_connection_reread (connection, ifcfg_dir, out_filename, &reread, &reread_same);
+ _assert_reread_same (connection, reread);
+ g_assert (reread_same);
+}
+
+static void
+_writer_new_connection_FIXME (NMConnection *connection,
+ const char *ifcfg_dir,
+ char **out_filename)
+{
+ gs_unref_object NMConnection *reread = NULL;
+ gboolean reread_same = FALSE;
+
+ /* FIXME: this should not happen. Fix it to use _writer_new_connection() instead. */
+
+ _writer_new_connection_reread (connection, ifcfg_dir, out_filename, &reread, &reread_same);
+ _assert_reread_same_FIXME (connection, reread);
+ g_assert (!reread_same);
+}
+
+static void
_writer_new_connection_fail (NMConnection *connection,
const char *ifcfg_dir,
GError **error)
{
+ gs_unref_object NMConnection *connection_normalized = NULL;
+ gs_unref_object NMConnection *reread = NULL;
gboolean success;
GError *local = NULL;
char *filename = NULL;
@@ -186,12 +275,17 @@ _writer_new_connection_fail (NMConnection *connection,
g_assert (NM_IS_CONNECTION (connection));
g_assert (ifcfg_dir);
- success = writer_new_connection (connection,
+ connection_normalized = nmtst_connection_duplicate_and_normalize (connection);
+
+ success = writer_new_connection (connection_normalized,
ifcfg_dir,
&filename,
+ &reread,
+ NULL,
&local);
nmtst_assert_no_success (success, local);
g_assert (!filename);
+ g_assert (!reread);
g_propagate_error (error, local);
}
@@ -1567,12 +1661,15 @@ test_read_write_802_1X_subj_matches (void)
g_assert_cmpstr (nm_setting_802_1x_get_phase2_altsubject_match (s_8021x, 0), ==, "x.yourdomain.tld");
g_assert_cmpstr (nm_setting_802_1x_get_phase2_altsubject_match (s_8021x, 1), ==, "y.yourdomain.tld");
+ g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
+ "*missing IEEE_8021X_CA_CERT for EAP method 'peap'; this is insecure!");
_writer_new_connection (connection,
TEST_SCRATCH_DIR "/network-scripts/",
&testfile);
+ g_test_assert_expected_messages ();
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
- "*missing IEEE_8021X_CA_CERT*peap*");
+ "*missing IEEE_8021X_CA_CERT for EAP method 'peap'; this is insecure!");
reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL);
g_test_assert_expected_messages ();
@@ -1831,6 +1928,8 @@ test_clear_master (void)
g_assert_cmpstr (nm_setting_connection_get_master (s_con), ==, NULL);
g_assert_cmpstr (nm_setting_connection_get_slave_type (s_con), ==, NULL);
+ nmtst_assert_connection_verifies_after_normalization (connection, 0, 0);
+
/* 4. update the connection on disk */
_writer_update_connection (connection,
TEST_SCRATCH_DIR "/network-scripts/",
@@ -1917,9 +2016,9 @@ test_write_dns_options (void)
nmtst_assert_connection_verifies (connection);
- _writer_new_connection (connection,
- TEST_SCRATCH_DIR "/network-scripts/",
- &testfile);
+ _writer_new_connection_FIXME (connection,
+ TEST_SCRATCH_DIR "/network-scripts/",
+ &testfile);
reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL);
@@ -3781,9 +3880,9 @@ test_write_wired_static (void)
nmtst_assert_connection_verifies (connection);
- _writer_new_connection (connection,
- TEST_SCRATCH_DIR "/network-scripts/",
- &testfile);
+ _writer_new_connection_FIXME (connection,
+ TEST_SCRATCH_DIR "/network-scripts/",
+ &testfile);
route6file = utils_get_route6_path (testfile);
reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL);
@@ -4451,9 +4550,9 @@ test_write_wired_8021x_tls (gconstpointer test_data)
nmtst_assert_connection_verifies (connection);
- _writer_new_connection (connection,
- TEST_SCRATCH_DIR "/network-scripts/",
- &testfile);
+ _writer_new_connection_FIXME (connection,
+ TEST_SCRATCH_DIR "/network-scripts/",
+ &testfile);
reread = _connection_from_file (testfile, NULL, TYPE_WIRELESS, NULL);
@@ -4590,9 +4689,9 @@ test_write_wired_aliases (void)
svCloseFile (ifcfg);
g_assert (g_file_test (TEST_SCRATCH_ALIAS_BASE ":5", G_FILE_TEST_EXISTS));
- _writer_new_connection (connection,
- TEST_SCRATCH_DIR "/network-scripts/",
- &testfile);
+ _writer_new_connection_FIXME (connection,
+ TEST_SCRATCH_DIR "/network-scripts/",
+ &testfile);
/* Re-check the alias files */
g_assert (g_file_test (TEST_SCRATCH_ALIAS_BASE ":2", G_FILE_TEST_EXISTS));
@@ -5444,9 +5543,9 @@ test_write_wifi_leap_secret_flags (gconstpointer data)
nmtst_assert_connection_verifies (connection);
- _writer_new_connection (connection,
- TEST_SCRATCH_DIR "/network-scripts/",
- &testfile);
+ _writer_new_connection_FIXME (connection,
+ TEST_SCRATCH_DIR "/network-scripts/",
+ &testfile);
reread = _connection_from_file (testfile, NULL, TYPE_WIRELESS, NULL);
@@ -6592,9 +6691,9 @@ test_write_wifi_wep_agent_keys (void)
nmtst_assert_connection_verifies (connection);
- _writer_new_connection (connection,
- TEST_SCRATCH_DIR "/network-scripts/",
- &testfile);
+ _writer_new_connection_FIXME (connection,
+ TEST_SCRATCH_DIR "/network-scripts/",
+ &testfile);
reread = _connection_from_file (testfile, NULL, TYPE_WIRELESS, NULL);
@@ -8289,6 +8388,68 @@ test_read_team_port_empty_config (void)
}
static void
+test_team_reread_slave (void)
+{
+ nmtst_auto_unlinkfile char *testfile = NULL;
+ gs_unref_object NMConnection *connection_1 = NULL;
+ gs_unref_object NMConnection *connection_2 = NULL;
+ gs_unref_object NMConnection *reread = NULL;
+ gboolean reread_same = FALSE;
+ NMSettingConnection *s_con;
+
+ connection_1 = nmtst_create_connection_from_keyfile (
+ "[connection]\n"
+ "id=team-slave-enp31s0f1-142\n"
+ "uuid=74f435bb-ede4-415a-9d48-f580b60eba04\n"
+ "type=vlan\n"
+ "autoconnect=false\n"
+ "interface-name=enp31s0f1-142\n"
+ "master=team142\n"
+ "permissions=\n"
+ "slave-type=team\n"
+ "\n"
+ "[vlan]\n"
+ "egress-priority-map=\n"
+ "flags=1\n"
+ "id=142\n"
+ "ingress-priority-map=\n"
+ "parent=enp31s0f1\n"
+ , "/test_team_reread_slave", NULL);
+
+ /* to double-check keyfile syntax, re-create the connection by hand. */
+ connection_2 = nmtst_create_minimal_connection ("team-slave-enp31s0f1-142", "74f435bb-ede4-415a-9d48-f580b60eba04", NM_SETTING_VLAN_SETTING_NAME, &s_con);
+ g_object_set (s_con,
+ NM_SETTING_CONNECTION_AUTOCONNECT, FALSE,
+ NM_SETTING_CONNECTION_INTERFACE_NAME, "enp31s0f1-142",
+ NM_SETTING_CONNECTION_MASTER, "team142",
+ NM_SETTING_CONNECTION_SLAVE_TYPE, "team",
+ NULL);
+ g_object_set (nm_connection_get_setting_vlan (connection_2),
+ NM_SETTING_VLAN_FLAGS, 1,
+ NM_SETTING_VLAN_ID, 142,
+ NM_SETTING_VLAN_PARENT, "enp31s0f1",
+ NULL);
+ nm_connection_add_setting (connection_2, nm_setting_team_port_new ());
+ nmtst_connection_normalize (connection_2);
+
+ nmtst_assert_connection_equals (connection_1, FALSE, connection_2, FALSE);
+
+ _writer_new_connection_reread ((nmtst_get_rand_int () % 2) ? connection_1 : connection_2,
+ TEST_SCRATCH_DIR "/network-scripts/",
+ &testfile,
+ &reread,
+ &reread_same);
+ _assert_reread_same ((nmtst_get_rand_int () % 2) ? connection_1 : connection_2, reread);
+ g_assert (reread_same);
+ g_clear_object (&reread);
+
+ reread = _connection_from_file (testfile, NULL, TYPE_VLAN,
+ NULL);
+ nmtst_assert_connection_equals ((nmtst_get_rand_int () % 2) ? connection_1 : connection_2, FALSE,
+ reread, FALSE);
+}
+
+static void
test_read_proxy_basic (void)
{
NMConnection *connection;
@@ -8702,8 +8863,8 @@ test_write_unknown (gconstpointer test_data)
sv = _svOpenFile (testfile);
- svFileSetName (sv, filename_tmp_1);
- svFileSetModified (sv);
+ svFileSetName_test_only (sv, filename_tmp_1);
+ svFileSetModified_test_only (sv);
if (g_str_has_suffix (testfile, "ifcfg-test-write-unknown-4")) {
_svGetValue_check (sv, "NAME", "l4x");
@@ -9154,6 +9315,7 @@ int main (int argc, char **argv)
g_test_add_data_func (TPATH "team/read-port-2", TEST_IFCFG_DIR"/network-scripts/ifcfg-test-team-port-2", test_read_team_port);
g_test_add_func (TPATH "team/write-port", test_write_team_port);
g_test_add_func (TPATH "team/read-port-empty-config", test_read_team_port_empty_config);
+ g_test_add_func (TPATH "team/reread-slave", test_team_reread_slave);
g_test_add_func (TPATH "proxy/read-proxy-basic", test_read_proxy_basic);
g_test_add_func (TPATH "proxy/write-proxy-basic", test_write_proxy_basic);
diff --git a/src/settings/plugins/keyfile/nms-keyfile-connection.c b/src/settings/plugins/keyfile/nms-keyfile-connection.c
index ff654acf8e..bd07d263c1 100644
--- a/src/settings/plugins/keyfile/nms-keyfile-connection.c
+++ b/src/settings/plugins/keyfile/nms-keyfile-connection.c
@@ -58,12 +58,16 @@ commit_changes (NMSettingsConnection *connection,
{
char *path = NULL;
GError *error = NULL;
+ gs_unref_object NMConnection *reread = NULL;
+ gboolean reread_same = FALSE;
if (!nms_keyfile_writer_connection (NM_CONNECTION (connection),
nm_settings_connection_get_filename (connection),
NM_FLAGS_ALL (commit_reason, NM_SETTINGS_CONNECTION_COMMIT_REASON_USER_ACTION
| NM_SETTINGS_CONNECTION_COMMIT_REASON_ID_CHANGED),
&path,
+ &reread,
+ &reread_same,
&error)) {
callback (connection, error, user_data);
g_clear_error (&error);
@@ -89,6 +93,18 @@ commit_changes (NMSettingsConnection *connection,
NMS_KEYFILE_CONNECTION_LOG_ARG (connection));
}
+ if (reread && !reread_same) {
+ gs_free_error GError *local = NULL;
+
+ if (!nm_settings_connection_replace_settings (connection, reread, FALSE, "update-during-write", &local)) {
+ nm_log_warn (LOGD_SETTINGS, "keyfile: update "NMS_KEYFILE_CONNECTION_LOG_FMT" after persisting connection failed: %s",
+ NMS_KEYFILE_CONNECTION_LOG_ARG (connection), local->message);
+ } else {
+ nm_log_info (LOGD_SETTINGS, "keyfile: update "NMS_KEYFILE_CONNECTION_LOG_FMT" after persisting connection",
+ NMS_KEYFILE_CONNECTION_LOG_ARG (connection));
+ }
+ }
+
g_free (path);
NM_SETTINGS_CONNECTION_CLASS (nms_keyfile_connection_parent_class)->commit_changes (connection,
diff --git a/src/settings/plugins/keyfile/nms-keyfile-plugin.c b/src/settings/plugins/keyfile/nms-keyfile-plugin.c
index 97306d6656..d76b64c726 100644
--- a/src/settings/plugins/keyfile/nms-keyfile-plugin.c
+++ b/src/settings/plugins/keyfile/nms-keyfile-plugin.c
@@ -530,12 +530,19 @@ add_connection (NMSettingsPlugin *config,
{
NMSKeyfilePlugin *self = NMS_KEYFILE_PLUGIN (config);
gs_free char *path = NULL;
+ gs_unref_object NMConnection *reread = NULL;
if (save_to_disk) {
- if (!nms_keyfile_writer_connection (connection, NULL, FALSE, &path, error))
+ if (!nms_keyfile_writer_connection (connection,
+ NULL,
+ FALSE,
+ &path,
+ &reread,
+ NULL,
+ error))
return NULL;
}
- return NM_SETTINGS_CONNECTION (update_connection (self, connection, path, NULL, FALSE, NULL, error));
+ return NM_SETTINGS_CONNECTION (update_connection (self, reread ?: connection, path, NULL, FALSE, NULL, error));
}
static GSList *
diff --git a/src/settings/plugins/keyfile/nms-keyfile-reader.c b/src/settings/plugins/keyfile/nms-keyfile-reader.c
index 39a0148021..05aae855a0 100644
--- a/src/settings/plugins/keyfile/nms-keyfile-reader.c
+++ b/src/settings/plugins/keyfile/nms-keyfile-reader.c
@@ -56,6 +56,10 @@ _fmt_warn (const char *group, NMSetting *setting, const char *property_name, con
return message;
}
+typedef struct {
+ bool verbose;
+} HandlerReadData;
+
static gboolean
_handler_read (GKeyFile *keyfile,
NMConnection *connection,
@@ -64,11 +68,16 @@ _handler_read (GKeyFile *keyfile,
void *user_data,
GError **error)
{
+ const HandlerReadData *handler_data = user_data;
+
if (type == NM_KEYFILE_READ_TYPE_WARN) {
NMKeyfileReadTypeDataWarn *warn_data = type_data;
NMLogLevel level;
char *message_free = NULL;
+ if (!handler_data->verbose)
+ return TRUE;
+
if (warn_data->severity > NM_KEYFILE_WARN_SEVERITY_WARN)
level = LOGL_ERR;
else if (warn_data->severity >= NM_KEYFILE_WARN_SEVERITY_WARN)
@@ -89,6 +98,19 @@ _handler_read (GKeyFile *keyfile,
}
NMConnection *
+nms_keyfile_reader_from_keyfile (GKeyFile *key_file,
+ const char *filename,
+ gboolean verbose,
+ GError **error)
+{
+ HandlerReadData data = {
+ .verbose = verbose,
+ };
+
+ return nm_keyfile_read (key_file, filename, NULL, _handler_read, &data, error);
+}
+
+NMConnection *
nms_keyfile_reader_from_file (const char *filename, GError **error)
{
GKeyFile *key_file;
@@ -122,7 +144,7 @@ nms_keyfile_reader_from_file (const char *filename, GError **error)
if (!g_key_file_load_from_file (key_file, filename, G_KEY_FILE_NONE, error))
goto out;
- connection = nm_keyfile_read (key_file, filename, NULL, _handler_read, NULL, error);
+ connection = nms_keyfile_reader_from_keyfile (key_file, filename, TRUE, error);
if (!connection)
goto out;
diff --git a/src/settings/plugins/keyfile/nms-keyfile-reader.h b/src/settings/plugins/keyfile/nms-keyfile-reader.h
index c52fea31d2..f8b3fac8f4 100644
--- a/src/settings/plugins/keyfile/nms-keyfile-reader.h
+++ b/src/settings/plugins/keyfile/nms-keyfile-reader.h
@@ -24,6 +24,11 @@
#include <nm-connection.h>
+NMConnection *nms_keyfile_reader_from_keyfile (GKeyFile *key_file,
+ const char *filename,
+ gboolean verbose,
+ GError **error);
+
NMConnection *nms_keyfile_reader_from_file (const char *filename, GError **error);
#endif /* __NMS_KEYFILE_READER_H__ */
diff --git a/src/settings/plugins/keyfile/nms-keyfile-writer.c b/src/settings/plugins/keyfile/nms-keyfile-writer.c
index a673742050..92ed2849b5 100644
--- a/src/settings/plugins/keyfile/nms-keyfile-writer.c
+++ b/src/settings/plugins/keyfile/nms-keyfile-writer.c
@@ -32,6 +32,7 @@
#include "nm-keyfile-internal.h"
#include "nms-keyfile-utils.h"
+#include "nms-keyfile-reader.h"
/*****************************************************************************/
@@ -174,9 +175,11 @@ _internal_write_connection (NMConnection *connection,
const char *existing_path,
gboolean force_rename,
char **out_path,
+ NMConnection **out_reread,
+ gboolean *out_reread_same,
GError **error)
{
- GKeyFile *key_file;
+ gs_unref_keyfile GKeyFile *key_file = NULL;
gs_free char *data = NULL;
gsize len;
gs_free char *path = NULL;
@@ -188,8 +191,15 @@ _internal_write_connection (NMConnection *connection,
g_return_val_if_fail (!out_path || !*out_path, FALSE);
g_return_val_if_fail (keyfile_dir && keyfile_dir[0] == '/', FALSE);
- if (!nm_connection_verify (connection, error))
+ switch (_nm_connection_verify (connection, error)) {
+ case NM_SETTING_VERIFY_NORMALIZABLE:
+ nm_assert_not_reached ();
+ /* fall-through */
+ case NM_SETTING_VERIFY_SUCCESS:
+ break;
+ default:
g_return_val_if_reached (FALSE);
+ }
id = nm_connection_get_id (connection);
g_assert (id && *id);
@@ -200,7 +210,6 @@ _internal_write_connection (NMConnection *connection,
if (!key_file)
return FALSE;
data = g_key_file_to_data (key_file, &len, error);
- g_key_file_unref (key_file);
if (!data)
return FALSE;
@@ -290,15 +299,48 @@ _internal_write_connection (NMConnection *connection,
path = NULL;
}
+ if (out_reread || out_reread_same)
+ {
+ gs_unref_object NMConnection *reread = NULL;
+ gboolean reread_same = FALSE;
+
+ reread = nms_keyfile_reader_from_keyfile (key_file, path, FALSE, NULL);
+
+ nm_assert (NM_IS_CONNECTION (reread));
+
+ if ( reread
+ && !nm_connection_normalize (reread, NULL, NULL, NULL)) {
+ nm_assert_not_reached ();
+ g_clear_object (&reread);
+ }
+
+ if (reread && out_reread_same) {
+ reread_same = !!nm_connection_compare (reread, connection, NM_SETTING_COMPARE_FLAG_EXACT);
+
+ nm_assert (reread_same == nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT));
+ nm_assert (reread_same == ({
+ gs_unref_hashtable GHashTable *_settings = NULL;
+
+ ( nm_connection_diff (reread, connection, NM_SETTING_COMPARE_FLAG_EXACT, &_settings)
+ && !_settings);
+ }));
+ }
+
+ NM_SET_OUT (out_reread, g_steal_pointer (&reread));
+ NM_SET_OUT (out_reread_same, reread_same);
+ }
+
return TRUE;
}
gboolean
nms_keyfile_writer_connection (NMConnection *connection,
- const char *existing_path,
- gboolean force_rename,
- char **out_path,
- GError **error)
+ const char *existing_path,
+ gboolean force_rename,
+ char **out_path,
+ NMConnection **out_reread,
+ gboolean *out_reread_same,
+ GError **error)
{
return _internal_write_connection (connection,
nms_keyfile_utils_get_path (),
@@ -306,16 +348,20 @@ nms_keyfile_writer_connection (NMConnection *connection,
existing_path,
force_rename,
out_path,
+ out_reread,
+ out_reread_same,
error);
}
gboolean
nms_keyfile_writer_test_connection (NMConnection *connection,
- const char *keyfile_dir,
- uid_t owner_uid,
- pid_t owner_grp,
- char **out_path,
- GError **error)
+ const char *keyfile_dir,
+ uid_t owner_uid,
+ pid_t owner_grp,
+ char **out_path,
+ NMConnection **out_reread,
+ gboolean *out_reread_same,
+ GError **error)
{
return _internal_write_connection (connection,
keyfile_dir,
@@ -323,6 +369,8 @@ nms_keyfile_writer_test_connection (NMConnection *connection,
NULL,
FALSE,
out_path,
+ out_reread,
+ out_reread_same,
error);
}
diff --git a/src/settings/plugins/keyfile/nms-keyfile-writer.h b/src/settings/plugins/keyfile/nms-keyfile-writer.h
index 4f43455d07..ca2e2a461f 100644
--- a/src/settings/plugins/keyfile/nms-keyfile-writer.h
+++ b/src/settings/plugins/keyfile/nms-keyfile-writer.h
@@ -28,6 +28,8 @@ gboolean nms_keyfile_writer_connection (NMConnection *connection,
const char *existing_path,
gboolean force_rename,
char **out_path,
+ NMConnection **out_reread,
+ gboolean *out_reread_same,
GError **error);
gboolean nms_keyfile_writer_test_connection (NMConnection *connection,
@@ -35,6 +37,8 @@ gboolean nms_keyfile_writer_test_connection (NMConnection *connection,
uid_t owner_uid,
pid_t owner_grp,
char **out_path,
+ NMConnection **out_reread,
+ gboolean *out_reread_same,
GError **error);
#endif /* __NMS_KEYFILE_WRITER_H__ */
diff --git a/src/settings/plugins/keyfile/tests/test-keyfile.c b/src/settings/plugins/keyfile/tests/test-keyfile.c
index f1102bd32b..1d1f5d8ccb 100644
--- a/src/settings/plugins/keyfile/tests/test-keyfile.c
+++ b/src/settings/plugins/keyfile/tests/test-keyfile.c
@@ -113,13 +113,25 @@ assert_reread_and_unlink (NMConnection *connection, gboolean normalize_connectio
}
static void
-write_test_connection (NMConnection *connection, char **testfile)
+assert_reread_same (NMConnection *connection,
+ NMConnection *reread)
+{
+ nmtst_assert_connection_verifies_without_normalization (reread);
+ nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
+}
+
+static void
+write_test_connection_reread (NMConnection *connection,
+ char **testfile,
+ NMConnection **out_reread,
+ gboolean *out_reread_same)
{
uid_t owner_uid;
gid_t owner_grp;
gboolean success;
GError *error = NULL;
GError **p_error = (nmtst_get_rand_int () % 2) ? &error : NULL;
+ gs_unref_object NMConnection *connection_normalized = NULL;
g_assert (NM_IS_CONNECTION (connection));
g_assert (testfile && !*testfile);
@@ -127,13 +139,33 @@ write_test_connection (NMConnection *connection, char **testfile)
owner_uid = geteuid ();
owner_grp = getegid ();
- success = nms_keyfile_writer_test_connection (connection, TEST_SCRATCH_DIR, owner_uid, owner_grp, testfile, p_error);
+ connection_normalized = nmtst_connection_duplicate_and_normalize (connection);
+
+ success = nms_keyfile_writer_test_connection (connection_normalized,
+ TEST_SCRATCH_DIR,
+ owner_uid,
+ owner_grp,
+ testfile,
+ out_reread,
+ out_reread_same,
+ p_error);
g_assert_no_error (error);
g_assert (success);
g_assert (*testfile && (*testfile)[0]);
}
static void
+write_test_connection (NMConnection *connection, char **testfile)
+{
+ gs_unref_object NMConnection *reread = NULL;
+ gboolean reread_same = FALSE;
+
+ write_test_connection_reread (connection, testfile, &reread, &reread_same);
+ assert_reread_same (connection, reread);
+ g_assert (reread_same);
+}
+
+static void
write_test_connection_and_reread (NMConnection *connection, gboolean normalize_connection)
{
gs_free char *testfile = NULL;
@@ -161,6 +193,27 @@ keyfile_load_from_file (const char *testfile)
return keyfile;
}
+static void
+_setting_copy_property_gbytes (NMConnection *src, NMConnection *dst, const char *setting_name, const char *property_name)
+{
+ gs_unref_bytes GBytes *blob = NULL;
+ NMSetting *s_src;
+ NMSetting *s_dst;
+
+ g_assert (NM_IS_CONNECTION (src));
+ g_assert (NM_IS_CONNECTION (dst));
+ g_assert (setting_name);
+ g_assert (property_name);
+
+ s_src = nm_connection_get_setting_by_name (src, setting_name);
+ g_assert (NM_IS_SETTING (s_src));
+ s_dst = nm_connection_get_setting_by_name (dst, setting_name);
+ g_assert (NM_IS_SETTING (s_dst));
+
+ g_object_get (s_src, property_name, &blob, NULL);
+ g_object_set (s_dst, property_name, blob, NULL);
+}
+
/*****************************************************************************/
static void
@@ -1639,11 +1692,18 @@ test_write_wired_8021x_tls_connection_path (void)
gs_free_error GError *error = NULL;
gs_unref_keyfile GKeyFile *keyfile = NULL;
gboolean relative = FALSE;
+ gboolean reread_same = FALSE;
connection = create_wired_tls_connection (NM_SETTING_802_1X_CK_SCHEME_PATH);
g_assert (connection != NULL);
- write_test_connection (connection, &testfile);
+ write_test_connection_reread (connection, &testfile, &reread, &reread_same);
+ nmtst_assert_connection_verifies_without_normalization (reread);
+ _setting_copy_property_gbytes (connection, reread, NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_CA_CERT);
+ _setting_copy_property_gbytes (connection, reread, NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_CLIENT_CERT);
+ _setting_copy_property_gbytes (connection, reread, NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_PRIVATE_KEY);
+ assert_reread_same (connection, reread);
+ g_clear_object (&reread);
/* Read the connection back in and compare it to the one we just wrote out */
reread = nms_keyfile_reader_from_file (testfile, &error);
@@ -1716,6 +1776,7 @@ test_write_wired_8021x_tls_connection_blob (void)
char *new_client_cert;
char *new_priv_key;
const char *uuid;
+ gboolean reread_same = FALSE;
gs_free_error GError *error = NULL;
GBytes *password_raw = NULL;
#define PASSWORD_RAW "password-raw\0test"
@@ -1733,7 +1794,13 @@ test_write_wired_8021x_tls_connection_blob (void)
NULL);
g_bytes_unref (password_raw);
- write_test_connection (connection, &testfile);
+ write_test_connection_reread (connection, &testfile, &reread, &reread_same);
+ nmtst_assert_connection_verifies_without_normalization (reread);
+ _setting_copy_property_gbytes (connection, reread, NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_CA_CERT);
+ _setting_copy_property_gbytes (connection, reread, NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_CLIENT_CERT);
+ _setting_copy_property_gbytes (connection, reread, NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_PRIVATE_KEY);
+ assert_reread_same (connection, reread);
+ g_clear_object (&reread);
/* Check that the new certs got written out */
s_con = nm_connection_get_setting_connection (connection);