From a265892385333878339c81b0489af9fb7d22d7e6 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Sun, 25 Aug 2019 14:36:21 +0200 Subject: [PATCH 1/6] shared/tests: add nmtst_keyfile_get_num_keys() helper --- shared/nm-utils/nm-test-utils.h | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/shared/nm-utils/nm-test-utils.h b/shared/nm-utils/nm-test-utils.h index b2d103f18a..d7a8788dfb 100644 --- a/shared/nm-utils/nm-test-utils.h +++ b/shared/nm-utils/nm-test-utils.h @@ -2272,6 +2272,29 @@ nmtst_keyfile_assert_data (GKeyFile *kf, const char *data, gssize data_len) g_assert_cmpmem (d2, d2_len, d1, d1_len); } +static inline gssize +nmtst_keyfile_get_num_keys (GKeyFile *keyfile, + const char *group_name) +{ + gs_strfreev char **keys = NULL; + gs_free_error GError *error = NULL; + gsize l; + + g_assert (keyfile); + g_assert (group_name); + + if (!g_key_file_has_group (keyfile, group_name)) + return -1; + + keys = g_key_file_get_keys (keyfile, group_name, &l, &error); + + nmtst_assert_success (keys, error); + + g_assert_cmpint (NM_PTRARRAY_LEN (keys), ==, l); + + return l; +} + /*****************************************************************************/ #endif /* __NM_TEST_UTILS_H__ */ From 1c2c7d3cb740fa9f68612698b7d9e3a5a7e68a2d Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Sun, 25 Aug 2019 13:25:12 +0200 Subject: [PATCH 2/6] settings/keyfile: log reason why re-read connection cannot be normalized It's a bug either way, but let's log what exactly went wrong. --- src/settings/plugins/keyfile/nms-keyfile-writer.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/settings/plugins/keyfile/nms-keyfile-writer.c b/src/settings/plugins/keyfile/nms-keyfile-writer.c index ef42928fb1..464832d103 100644 --- a/src/settings/plugins/keyfile/nms-keyfile-writer.c +++ b/src/settings/plugins/keyfile/nms-keyfile-writer.c @@ -346,6 +346,7 @@ _internal_write_connection (NMConnection *connection, if (out_reread || out_reread_same) { gs_unref_object NMConnection *reread = NULL; + gs_free_error GError *reread_error = NULL; gboolean reread_same = FALSE; reread = nms_keyfile_reader_from_keyfile (kf_file, path, NULL, profile_dir, FALSE, NULL); @@ -353,7 +354,8 @@ _internal_write_connection (NMConnection *connection, nm_assert (NM_IS_CONNECTION (reread)); if ( reread - && !nm_connection_normalize (reread, NULL, NULL, NULL)) { + && !nm_connection_normalize (reread, NULL, NULL, &reread_error)) { + nm_log_err (LOGD_SETTINGS, "BUG: failure to normalize profile that we just wrote to disk: %s", reread_error->message); nm_assert_not_reached (); g_clear_object (&reread); } @@ -448,4 +450,3 @@ nms_keyfile_writer_test_connection (NMConnection *connection, out_reread_same, error); } - From 3b8aab2999454d748f6d47911d4f8a7af40a3fcd Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 27 Aug 2019 11:06:45 +0200 Subject: [PATCH 3/6] settings/keyfile: check whether profile can be re-read before writing to disk and fail First of all, keyfile writer (and reader) are supposed to be able to store every profile to disk and re-read a valid profile back. Note that the profile might be modified in the process, for example, blob certificates are written to a file. So, the result might no be exactly the same, but it must still be valid (and should only diverge in expected ways from the original, like mangled certificates). Previously, we would re-read the profile after writing to disk. If that failed, we would only fail an assertion but otherwise proceeed. It is a bug after all. However, it's bad to check only after writing to file, because it results in a unreadable profile on disk, and in the first moment it appears that noting went wrong. Instead, we should fail early. Note that nms_keyfile_reader_from_keyfile() must entirely operate on the in-memory representation of the keyfile. It must not actually access any files on disk. Hence, moving this check before writing the profile must work. Otherwise, that would be a separate bug. Actually, keyfile reader and writer violate this. I added FIXME comments for that. But it doesn't interfere with this patch. --- libnm-core/nm-keyfile.c | 7 ++ .../plugins/keyfile/nms-keyfile-writer.c | 72 ++++++++++--------- 2 files changed, 45 insertions(+), 34 deletions(-) diff --git a/libnm-core/nm-keyfile.c b/libnm-core/nm-keyfile.c index 9b032c4cd8..dbffe65e18 100644 --- a/libnm-core/nm-keyfile.c +++ b/libnm-core/nm-keyfile.c @@ -1369,6 +1369,9 @@ nm_keyfile_detect_unqualified_path_scheme (const char *base_dir, */ path = get_cert_path (base_dir, (const guint8 *) data, data_len); + + /* FIXME(keyfile-parse-in-memory): it is wrong that keyfile reader makes decisions based on + * the file systems content. The serialization/parsing should be entirely in-memory. */ if ( !memchr (data, '/', data_len) && !has_cert_ext (path)) { if (!consider_exists) @@ -1449,6 +1452,10 @@ cert_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key) path2 = path2_free; } + /* FIXME(keyfile-parse-in-memory): keyfile reader must not access the file system and + * (in a first step) only operate in memory-only. If the presence of files should be checked, + * then by invoking a callback (and possibly keyfile settings plugin would + * collect the file names to be checked and check them later). */ if (!g_file_test (path2, G_FILE_TEST_EXISTS)) { handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_INFO_MISSING_FILE, _("certificate or key file '%s' does not exist"), diff --git a/src/settings/plugins/keyfile/nms-keyfile-writer.c b/src/settings/plugins/keyfile/nms-keyfile-writer.c index 464832d103..515376f8df 100644 --- a/src/settings/plugins/keyfile/nms-keyfile-writer.c +++ b/src/settings/plugins/keyfile/nms-keyfile-writer.c @@ -126,6 +126,10 @@ cert_writer (NMConnection *connection, new_path = g_strdup_printf ("%s/%s-%s.%s", info->keyfile_dir, nm_connection_get_uuid (connection), cert_data->vtable->file_suffix, ext); + /* FIXME(keyfile-parse-in-memory): writer must not access/write to the file system before + * being sure that the entire profile can be written and all circumstances are good to + * proceed. That means, while writing we must only collect the blogs in-memory, and write + * them all in the end together (or not at all). */ success = nm_utils_file_set_contents (new_path, (const char *) blob_data, blob_len, @@ -197,10 +201,12 @@ _internal_write_connection (NMConnection *connection, gs_free char *path = NULL; const char *id; WriteInfo info = { 0 }; - GError *local_err = NULL; + gs_free_error GError *local_err = NULL; int errsv; gboolean rename; int i_path; + gs_unref_object NMConnection *reread = NULL; + gboolean reread_same = FALSE; g_return_val_if_fail (!out_path || !*out_path, FALSE); g_return_val_if_fail (keyfile_dir && keyfile_dir[0] == '/', FALSE); @@ -313,6 +319,35 @@ _internal_write_connection (NMConnection *connection, return FALSE; } + if ( out_reread + || out_reread_same) { + gs_free_error GError *reread_error = NULL; + + reread = nms_keyfile_reader_from_keyfile (kf_file, path, NULL, profile_dir, FALSE, &reread_error); + + if ( !reread + || !nm_connection_normalize (reread, NULL, NULL, &reread_error)) { + nm_log_err (LOGD_SETTINGS, "BUG: the profile cannot be stored in keyfile format without becoming unusable: %s", reread_error->message); + g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED, + "keyfile writer produces an invalid connection: %s", + reread_error->message); + nm_assert_not_reached (); + return FALSE; + } + + if (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_utils_file_set_contents (path, kf_content_buf, kf_content_len, @@ -323,7 +358,6 @@ _internal_write_connection (NMConnection *connection, g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED, "error writing to file '%s': %s", path, local_err->message); - g_error_free (local_err); return FALSE; } @@ -344,38 +378,8 @@ _internal_write_connection (NMConnection *connection, && !nm_streq (path, existing_path)) unlink (existing_path); - if (out_reread || out_reread_same) { - gs_unref_object NMConnection *reread = NULL; - gs_free_error GError *reread_error = NULL; - gboolean reread_same = FALSE; - - reread = nms_keyfile_reader_from_keyfile (kf_file, path, NULL, profile_dir, FALSE, NULL); - - nm_assert (NM_IS_CONNECTION (reread)); - - if ( reread - && !nm_connection_normalize (reread, NULL, NULL, &reread_error)) { - nm_log_err (LOGD_SETTINGS, "BUG: failure to normalize profile that we just wrote to disk: %s", reread_error->message); - 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); - } - + NM_SET_OUT (out_reread, g_steal_pointer (&reread)); + NM_SET_OUT (out_reread_same, reread_same); NM_SET_OUT (out_path, g_steal_pointer (&path)); return TRUE; From f8abb05ebab92243f530768fcff01df6129b8369 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Sun, 25 Aug 2019 14:29:13 +0200 Subject: [PATCH 4/6] keyfile/tests: add unit test showing bug where keyfile writer looses settings that are all-default --- libnm-core/tests/test-setting.c | 49 +++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/libnm-core/tests/test-setting.c b/libnm-core/tests/test-setting.c index 3438aea99d..0a314562c3 100644 --- a/libnm-core/tests/test-setting.c +++ b/libnm-core/tests/test-setting.c @@ -3281,6 +3281,53 @@ test_parse_tc_handle (void) /*****************************************************************************/ +static void +test_empty_setting (void) +{ + gs_unref_object NMConnection *con = NULL; + gs_unref_object NMConnection *con2 = NULL; + NMSettingBluetooth *s_bt; + NMSettingGsm *s_gsm; + gs_unref_keyfile GKeyFile *kf = NULL; + gs_free_error GError *error = NULL; + + con = nmtst_create_minimal_connection ("bt-empty-gsm", "dca3192a-f2dc-48eb-b806-d0ff788f122c", NM_SETTING_BLUETOOTH_SETTING_NAME, NULL); + + s_bt = _nm_connection_get_setting (con, NM_TYPE_SETTING_BLUETOOTH); + g_object_set (s_bt, + NM_SETTING_BLUETOOTH_TYPE, "dun", + NM_SETTING_BLUETOOTH_BDADDR, "aa:bb:cc:dd:ee:ff", + NULL); + + s_gsm = NM_SETTING_GSM (nm_setting_gsm_new ()); + nm_connection_add_setting (con, NM_SETTING (s_gsm)); + + nmtst_connection_normalize (con); + + nmtst_assert_connection_verifies_without_normalization (con); + + kf = nm_keyfile_write (con, NULL, NULL, &error); + nmtst_assert_success (kf, error); + + /* the [gsm] setting was lost because it only has default values. + * As a result, the connection also became invalid. */ + + g_assert (!g_key_file_has_group (kf, "gsm")); + + con2 = nm_keyfile_read (kf, + "/ignored/current/working/directory/for/loading/relative/paths", + NULL, + NULL, + &error); + nmtst_assert_success (con2, error); + + g_assert (!nm_connection_get_setting (con2, NM_TYPE_SETTING_GSM)); + + nmtst_assert_connection_unnormalizable (con2, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_SETTING); +} + +/*****************************************************************************/ + NMTST_DEFINE (); int @@ -3368,5 +3415,7 @@ main (int argc, char **argv) g_test_add_func ("/libnm/test_team_setting", test_team_setting); + g_test_add_func ("/libnm/test_empty_setting", test_empty_setting); + return g_test_run (); } From e6eb01c18fe49ab99cc3b3f82c351d71eae10169 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Sun, 25 Aug 2019 13:54:42 +0200 Subject: [PATCH 5/6] keyfile: refactor _parse_info_find() to get ParseInfoSetting I thought I would need this, but ended up not using it. Anyway, it makes sense in general that the function can lookup all relevant information, so merge it. --- libnm-core/nm-keyfile.c | 73 +++++++++++++++++++++++++---------------- 1 file changed, 45 insertions(+), 28 deletions(-) diff --git a/libnm-core/nm-keyfile.c b/libnm-core/nm-keyfile.c index dbffe65e18..a6499d70f1 100644 --- a/libnm-core/nm-keyfile.c +++ b/libnm-core/nm-keyfile.c @@ -2913,41 +2913,47 @@ static const ParseInfoSetting *const parse_infos[_NM_META_SETTING_TYPE_NUM] = { ), }; -static const ParseInfoProperty * +static void _parse_info_find (NMSetting *setting, const char *property_name, - const NMMetaSettingInfo **out_setting_info) + const NMMetaSettingInfo **out_setting_info, + const ParseInfoSetting **out_parse_info_setting, + const ParseInfoProperty **out_parse_info_property) { const NMMetaSettingInfo *setting_info; const ParseInfoSetting *pis; - gssize idx; + const ParseInfoProperty *pip; #if NM_MORE_ASSERTS > 10 { guint i, j; + static int asserted = FALSE; - for (i = 0; i < G_N_ELEMENTS (parse_infos); i++) { - pis = parse_infos[i]; + if (!asserted) { + for (i = 0; i < G_N_ELEMENTS (parse_infos); i++) { + pis = parse_infos[i]; - if (!pis) - continue; + if (!pis) + continue; - g_assert (pis->properties); - g_assert (pis->properties[0]); - for (j = 0; pis->properties[j]; j++) { - const ParseInfoProperty *pip0; - const ParseInfoProperty *pip = pis->properties[j]; + g_assert (pis->properties); + g_assert (pis->properties[0]); + for (j = 0; pis->properties[j]; j++) { + const ParseInfoProperty *pip0; + const ParseInfoProperty *pipj = pis->properties[j]; - g_assert (pip->property_name); - if ( j > 0 - && (pip0 = pis->properties[j - 1]) - && strcmp (pip0->property_name, pip->property_name) >= 0) { - g_error ("Wrong order at index #%d.%d: \"%s.%s\" before \"%s.%s\"", - i, j - 1, - nm_meta_setting_infos[i].setting_name, pip0->property_name, - nm_meta_setting_infos[i].setting_name, pip->property_name); + g_assert (pipj->property_name); + if ( j > 0 + && (pip0 = pis->properties[j - 1]) + && strcmp (pip0->property_name, pipj->property_name) >= 0) { + g_error ("Wrong order at index #%d.%d: \"%s.%s\" before \"%s.%s\"", + i, j - 1, + nm_meta_setting_infos[i].setting_name, pip0->property_name, + nm_meta_setting_infos[i].setting_name, pipj->property_name); + } } } + asserted = TRUE; } } #endif @@ -2955,16 +2961,25 @@ _parse_info_find (NMSetting *setting, if ( !NM_IS_SETTING (setting) || !(setting_info = NM_SETTING_GET_CLASS (setting)->setting_info)) { /* handle invalid setting objects gracefully. */ - *out_setting_info = NULL; - return NULL; + NM_SET_OUT (out_setting_info, NULL); + NM_SET_OUT (out_parse_info_setting, NULL); + NM_SET_OUT (out_parse_info_property, NULL); + return; } nm_assert (setting_info->setting_name); + nm_assert (_NM_INT_NOT_NEGATIVE (setting_info->meta_type)); + nm_assert (setting_info->meta_type < G_N_ELEMENTS (parse_infos)); - *out_setting_info = setting_info; + pis = parse_infos[setting_info->meta_type]; + + pip = NULL; + if ( pis + && property_name) { + gssize idx; - if ((pis = parse_infos[setting_info->meta_type])) { G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (ParseInfoProperty, property_name) == 0); + idx = nm_utils_ptrarray_find_binary_search ((gconstpointer *) pis->properties, NM_PTRARRAY_LEN (pis->properties), &property_name, @@ -2973,10 +2988,12 @@ _parse_info_find (NMSetting *setting, NULL, NULL); if (idx >= 0) - return pis->properties[idx]; + pip = pis->properties[idx]; } - return NULL; + NM_SET_OUT (out_setting_info, setting_info); + NM_SET_OUT (out_parse_info_setting, pis); + NM_SET_OUT (out_parse_info_property, pip); } /*****************************************************************************/ @@ -3002,7 +3019,7 @@ read_one_setting_value (KeyfileReaderInfo *info, key = property_info->name; - pip = _parse_info_find (setting, key, &setting_info); + _parse_info_find (setting, key, &setting_info, NULL, &pip); nm_assert (setting_info); @@ -3620,7 +3637,7 @@ write_setting_value (KeyfileWriterInfo *info, key = property_info->name; - pip = _parse_info_find (setting, key, &setting_info); + _parse_info_find (setting, key, &setting_info, NULL, &pip); if (!pip) { if (!setting_info) { From ddd148e02b6b1ee85abadb9558275dc5a159b451 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Sun, 25 Aug 2019 13:29:41 +0200 Subject: [PATCH 6/6] keyfile: let keyfile writer serialize setting with all default values It's important whether a setting is present or not. Keyfile writer omits properties that have a default value, that means, if the setting has all-default values, it would be dropped. For [proxy] that doesn't really matter, because we tend to normalize it back. For some settings it matters: $ nmcli connection add type bluetooth con-name bt autoconnect no bluetooth.type dun bluetooth.bdaddr aa:bb:cc:dd:ee:ff gsm.apn a Connection 'bt' (652cabd8-d350-4246-a6f3-3dc17eeb028f) successfully added. $ nmcli connection modify bt gsm.apn '' When storing this to keyfile, the [gsm] section was dropped (server-side) and we fail an nm_assert() (omitted from the example output below). [1566732645.9845] BUG: failure to normalized profile that we just wrote to disk: bluetooth: 'dun' connection requires 'gsm' or 'cdma' setting [1566732645.9846] keyfile: commit: "/etc/NetworkManager/system-connections/bt.nmconnection": profile 652cabd8-d350-4246-a6f3-3dc17eeb028f (bt) written [1566732645.9846] settings: update[652cabd8-d350-4246-a6f3-3dc17eeb028f]: update-from-dbus: update profile "bt" [1566732645.9849] settings: storage[652cabd8-d350-4246-a6f3-3dc17eeb028f,3e504752a4a78fb3/keyfile]: change event with connection "bt" (file "/etc/NetworkManager/system-connections/> [1566732645.9849] settings: update[652cabd8-d350-4246-a6f3-3dc17eeb028f]: updating connection "bt" (3e504752a4a78fb3/keyfile) [1566732645.9857] ++ connection 'update connection' (0x7f7918003340/NMSimpleConnection/"bluetooth" < 0x55e1c52480e0/NMSimpleConnection/"bluetooth") [/org/freedesktop/NetworkManager> [1566732645.9857] ++ gsm [ 0x55e1c5276f80 < 0x55e1c53205f0 ] [1566732645.9858] ++ gsm.apn < 'a' Of course, after reload the connection on disk is no loner valid. Keyfile writer wrote an invalid setting. # nmcli connection reload Logfile: [1566732775.4920] keyfile: load: "/etc/NetworkManager/system-connections/bt.nmconnection": failed to load connection: invalid connection: bluetooth: 'dun' connection requires 'gsm' or 'cdma' setting ... [1566732775.5432] settings: update[652cabd8-d350-4246-a6f3-3dc17eeb028f]: delete connection "bt" (3e504752a4a78fb3/keyfile) [1566732775.5434] Deleting secrets for connection /org/freedesktop/NetworkManager/Settings (bt) [1566732775.5436] dbus-object[9a402fbe14c8d975]: unexport: "/org/freedesktop/NetworkManager/Settings/55" --- libnm-core/nm-keyfile.c | 20 ++++++++++++++++++-- libnm-core/tests/test-setting.c | 32 +++++++++++++++++--------------- 2 files changed, 35 insertions(+), 17 deletions(-) diff --git a/libnm-core/nm-keyfile.c b/libnm-core/nm-keyfile.c index a6499d70f1..d2360f8c2a 100644 --- a/libnm-core/nm-keyfile.c +++ b/libnm-core/nm-keyfile.c @@ -2935,8 +2935,9 @@ _parse_info_find (NMSetting *setting, if (!pis) continue; + if (!pis->properties) + continue; - g_assert (pis->properties); g_assert (pis->properties[0]); for (j = 0; pis->properties[j]; j++) { const ParseInfoProperty *pip0; @@ -3874,9 +3875,13 @@ nm_keyfile_write (NMConnection *connection, for (i = 0; i < n_settings; i++) { const NMSettInfoSetting *sett_info; NMSetting *setting = settings[i]; + const char *setting_name; + const char *setting_alias; sett_info = _nm_setting_class_get_sett_info (NM_SETTING_GET_CLASS (setting)); + setting_name = sett_info->setting_class->setting_info->setting_name; + if (sett_info->detail.gendata_info) { guint k, n_keys; const char *const*keys; @@ -3886,7 +3891,6 @@ nm_keyfile_write (NMConnection *connection, n_keys = _nm_setting_gendata_get_all (setting, &keys, NULL); if (n_keys > 0) { - const char *setting_name = sett_info->setting_class->setting_info->setting_name; GHashTable *h = _nm_setting_gendata_hash (setting, FALSE); for (k = 0; k < n_keys; k++) { @@ -3926,6 +3930,18 @@ nm_keyfile_write (NMConnection *connection, goto out_with_info_error; } + setting_alias = nm_keyfile_plugin_get_alias_for_setting_name (setting_name); + if ( ( setting_alias + && g_key_file_has_group (info.keyfile, setting_alias)) + || g_key_file_has_group (info.keyfile, setting_name)) { + /* we have a section for the setting. Nothing to do. */ + } else { + /* ensure the group is present. There is no API for that, so add and remove + * a dummy key. */ + g_key_file_set_value (info.keyfile, setting_alias ?: setting_name, ".X", "1"); + g_key_file_remove_key (info.keyfile, setting_alias ?: setting_name, ".X", NULL); + } + nm_assert (!info.error); } diff --git a/libnm-core/tests/test-setting.c b/libnm-core/tests/test-setting.c index 0a314562c3..b24bb1e37f 100644 --- a/libnm-core/tests/test-setting.c +++ b/libnm-core/tests/test-setting.c @@ -2581,7 +2581,7 @@ static void test_roundtrip_conversion (gconstpointer test_data) { const int MODE = GPOINTER_TO_INT (test_data); - const char *ID= nm_sprintf_bufa (100, "roundtip-conversion-%d", MODE); + const char *ID= nm_sprintf_bufa (100, "roundtrip-conversion-%d", MODE); const char *UUID= "63376701-b61e-4318-bf7e-664a1c1eeaab"; const char *INTERFACE_NAME = nm_sprintf_bufa (100, "ifname%d", MODE); guint32 ETH_MTU = nmtst_rand_select ((guint32) 0u, @@ -2663,6 +2663,8 @@ test_roundtrip_conversion (gconstpointer test_data) "addr-gen-mode=stable-privacy\n" "dns-search=\n" "method=auto\n" + "\n" + "[proxy]\n" "", ID, UUID, @@ -2722,6 +2724,8 @@ test_roundtrip_conversion (gconstpointer test_data) "interface-name=%s\n" "permissions=\n" "\n" + "[wireguard]\n" + "\n" "[ipv4]\n" "dns-search=\n" "method=disabled\n" @@ -2730,6 +2734,8 @@ test_roundtrip_conversion (gconstpointer test_data) "addr-gen-mode=stable-privacy\n" "dns-search=\n" "method=ignore\n" + "\n" + "[proxy]\n" "", ID, UUID, @@ -2770,7 +2776,8 @@ test_roundtrip_conversion (gconstpointer test_data) "type=wireguard\n" "interface-name=%s\n" "permissions=\n" - "%s" /* [wireguard] */ + "\n" + "[wireguard]\n" "%s" /* fwmark */ "%s" /* listen-port */ "%s" /* private-key-flags */ @@ -2785,17 +2792,12 @@ test_roundtrip_conversion (gconstpointer test_data) "addr-gen-mode=stable-privacy\n" "dns-search=\n" "method=ignore\n" + "\n" + "[proxy]\n" "", ID, UUID, INTERFACE_NAME, - ( ( (WG_FWMARK != 0) - || (WG_LISTEN_PORT != 0) - || (WG_PRIVATE_KEY_FLAGS != NM_SETTING_SECRET_FLAG_NONE) - || ( WG_PRIVATE_KEY - && WG_PRIVATE_KEY_FLAGS == NM_SETTING_SECRET_FLAG_NONE)) - ? "\n[wireguard]\n" - : ""), ( (WG_FWMARK != 0) ? nm_sprintf_bufa (100, "fwmark=%u\n", WG_FWMARK) : ""), @@ -2887,6 +2889,8 @@ test_roundtrip_conversion (gconstpointer test_data) "routing-rule1=priority 1 from ::/0 table 1000\n" "routing-rule2=priority 2 from 1:2:3:b::/65 table 1001\n" "routing-rule3=priority 3 from 1:2:3:c::/66 table 1002\n" + "\n" + "[proxy]\n" "", ID, UUID, @@ -3309,10 +3313,8 @@ test_empty_setting (void) kf = nm_keyfile_write (con, NULL, NULL, &error); nmtst_assert_success (kf, error); - /* the [gsm] setting was lost because it only has default values. - * As a result, the connection also became invalid. */ - - g_assert (!g_key_file_has_group (kf, "gsm")); + g_assert (g_key_file_has_group (kf, "gsm")); + g_assert_cmpint (nmtst_keyfile_get_num_keys (kf, "gsm"), ==, 0); con2 = nm_keyfile_read (kf, "/ignored/current/working/directory/for/loading/relative/paths", @@ -3321,9 +3323,9 @@ test_empty_setting (void) &error); nmtst_assert_success (con2, error); - g_assert (!nm_connection_get_setting (con2, NM_TYPE_SETTING_GSM)); + g_assert (nm_connection_get_setting (con2, NM_TYPE_SETTING_GSM)); - nmtst_assert_connection_unnormalizable (con2, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_SETTING); + nmtst_assert_connection_verifies_without_normalization (con2); } /*****************************************************************************/