From c333f062ddcba9b35330647bf6cbd0a07f2d786e Mon Sep 17 00:00:00 2001 From: Michael Biebl Date: Thu, 11 May 2017 14:55:55 +0200 Subject: New upstream version 1.8.0 --- src/settings/plugins/ibft/nms-ibft-reader.h | 2 +- .../plugins/ifcfg-rh/nms-ifcfg-rh-connection.c | 37 +- .../plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c | 4 +- .../plugins/ifcfg-rh/nms-ifcfg-rh-reader.c | 1429 +++++++++++--------- src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c | 134 +- src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h | 6 +- .../plugins/ifcfg-rh/nms-ifcfg-rh-writer.c | 1125 ++++++++------- .../plugins/ifcfg-rh/nms-ifcfg-rh-writer.h | 4 + src/settings/plugins/ifcfg-rh/shvar.c | 158 ++- src/settings/plugins/ifcfg-rh/shvar.h | 27 +- .../ifcfg-System_test-bridge-component-a.cexpected | 8 + .../ifcfg-System_test-bridge-component-b.cexpected | 17 + ...System_test-wired-802-1X-subj-matches.cexpected | 22 + .../network-scripts/ifcfg-Test_User_1.cexpected | 34 + .../ifcfg-Test_Write_Bond_Main.cexpected | 16 + .../ifcfg-Test_Write_Bridge_Component.cexpected | 8 + .../ifcfg-Test_Write_Permissions.cexpected | 11 + .../ifcfg-Test_Write_Proxy_Basic.cexpected | 15 + .../ifcfg-Test_Write_Team_Port.cexpected | 6 + .../ifcfg-Test_Write_VLAN_reorder_hdr.cexpected | 20 + .../ifcfg-Test_Write_WiFi_Band_A.cexpected | 18 + .../ifcfg-Test_Write_WiFi_Hidden.cexpected | 18 + .../ifcfg-Test_Write_WiFi_MAC_always.cexpected | 18 + .../ifcfg-Test_Write_WiFi_MAC_default.cexpected | 17 + .../ifcfg-Test_Write_WiFi_MAC_missing.cexpected | 18 + .../ifcfg-Test_Write_WiFi_MAC_never.cexpected | 18 + .../ifcfg-Test_Write_Wifi_LEAP.cexpected | 16 + .../ifcfg-Test_Write_Wifi_WEP_104_ASCII.cexpected | 15 + ...ifcfg-Test_Write_Wired_Auto-Negotiate.cexpected | 15 + .../ifcfg-Test_Write_Wired_Wake-on-LAN.cexpected | 15 + .../ifcfg-Vlan_test-vlan-interface.cexpected | 22 + .../ifcfg-rh/tests/network-scripts/ifcfg-aliasem3 | 11 + .../tests/network-scripts/ifcfg-aliasem3:1 | 4 + .../tests/network-scripts/ifcfg-dcb-test.cexpected | 41 + .../ifcfg-random_wifi_connection.cexpected | 13 + .../ifcfg-random_wifi_connection_2.cexpected | 15 + .../ifcfg-team-slave-enp31s0f1-142.cexpected | 12 + .../tests/network-scripts/ifcfg-test-bond-eth-type | 7 + .../ifcfg-test-static-routes-legacy.cexpected | 12 + .../network-scripts/route-test-wired-static-routes | 1 + .../route-test-wired-static-routes-legacy | 2 +- .../network-scripts/route6-test-wired-ipv6-manual | 2 + .../plugins/ifcfg-rh/tests/test-ifcfg-rh.c | 572 +++++++- .../plugins/ifnet/nms-ifnet-connection-parser.c | 157 +-- .../plugins/ifnet/nms-ifnet-connection-parser.h | 2 +- src/settings/plugins/ifnet/nms-ifnet-net-utils.h | 4 +- .../plugins/ifupdown/nms-ifupdown-parser.h | 2 +- .../plugins/ifupdown/nms-ifupdown-plugin.c | 90 +- .../plugins/keyfile/nms-keyfile-connection.c | 16 + src/settings/plugins/keyfile/nms-keyfile-plugin.c | 13 +- src/settings/plugins/keyfile/nms-keyfile-reader.c | 28 +- src/settings/plugins/keyfile/nms-keyfile-reader.h | 7 +- src/settings/plugins/keyfile/nms-keyfile-writer.c | 94 +- src/settings/plugins/keyfile/nms-keyfile-writer.h | 6 +- .../keyfile/tests/keyfiles/Test_Wired_Connection | 2 + src/settings/plugins/keyfile/tests/test-keyfile.c | 101 +- 56 files changed, 3030 insertions(+), 1457 deletions(-) create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-bridge-component-a.cexpected create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-bridge-component-b.cexpected create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-wired-802-1X-subj-matches.cexpected create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_User_1.cexpected create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Bond_Main.cexpected create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Bridge_Component.cexpected create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Permissions.cexpected create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Proxy_Basic.cexpected create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Team_Port.cexpected create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_VLAN_reorder_hdr.cexpected create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_Band_A.cexpected create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_Hidden.cexpected create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_MAC_always.cexpected create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_MAC_default.cexpected create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_MAC_missing.cexpected create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_MAC_never.cexpected create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wifi_LEAP.cexpected create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wifi_WEP_104_ASCII.cexpected create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Auto-Negotiate.cexpected create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Wake-on-LAN.cexpected create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Vlan_test-vlan-interface.cexpected create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem3 create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem3:1 create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-dcb-test.cexpected create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-random_wifi_connection.cexpected create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-random_wifi_connection_2.cexpected create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-team-slave-enp31s0f1-142.cexpected create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bond-eth-type create mode 100644 src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-static-routes-legacy.cexpected (limited to 'src/settings/plugins') diff --git a/src/settings/plugins/ibft/nms-ibft-reader.h b/src/settings/plugins/ibft/nms-ibft-reader.h index e2be7b02..27500cc5 100644 --- a/src/settings/plugins/ibft/nms-ibft-reader.h +++ b/src/settings/plugins/ibft/nms-ibft-reader.h @@ -21,7 +21,7 @@ #ifndef __NMS_IBFT_READER_H__ #define __NMS_IBFT_READER_H__ -#include +#include "nm-connection.h" gboolean nms_ibft_reader_load_blocks (const char *iscsiadm_path, GSList **out_blocks, 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 33f4847e..b54f9549 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-connection.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-connection.c @@ -336,43 +336,24 @@ commit_changes (NMSettingsConnection *connection, gpointer user_data) { GError *error = NULL; - NMConnection *reread; - gboolean same = FALSE, success = FALSE; + gboolean success = FALSE; char *ifcfg_path = NULL; const char *filename; - /* To ensure we don't rewrite files that are only changed from other - * processes on-disk, read the existing connection back in and only rewrite - * it if it's really changed. - */ filename = nm_settings_connection_get_filename (connection); if (filename) { - gs_free char *unhandled = NULL; - - reread = connection_from_file (filename, &unhandled, NULL, NULL); - if (reread) { - same = nm_connection_compare (NM_CONNECTION (connection), - reread, - NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS | - NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS); - g_object_unref (reread); - - /* Don't bother writing anything out if in-memory and on-disk data are the same */ - if (same) { - /* But chain up to parent to handle success - emits updated signal */ - NM_SETTINGS_CONNECTION_CLASS (nm_ifcfg_connection_parent_class)->commit_changes (connection, commit_reason, callback, user_data); - return; - } - } - 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); @@ -478,6 +459,11 @@ nm_ifcfg_connection_new (NMConnection *source, if (out_ignore_error) *out_ignore_error = FALSE; + if (full_path) { + /* The connection already is on the disk */ + update_unsaved = FALSE; + } + /* If we're given a connection already, prefer that instead of re-reading */ if (source) tmp = g_object_ref (source); @@ -488,9 +474,6 @@ nm_ifcfg_connection_new (NMConnection *source, out_ignore_error); if (!tmp) return NULL; - - /* If we just read the connection from disk, it's clearly not Unsaved */ - update_unsaved = FALSE; } if (unhandled_spec && g_str_has_prefix (unhandled_spec, "unmanaged:")) 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 414f593b..a3092e71 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c @@ -98,7 +98,7 @@ NM_DEFINE_SINGLETON_GETTER (SettingsPluginIfcfg, settings_plugin_ifcfg_get, SETT #define _NMLOG_DOMAIN LOGD_SETTINGS #define _NMLOG(level, ...) \ G_STMT_START { \ - nm_log ((level), (_NMLOG_DOMAIN), \ + nm_log ((level), (_NMLOG_DOMAIN), NULL, NULL, \ "%s" _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ "ifcfg-rh: " \ _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ @@ -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 46bd2de1..164f6844 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c @@ -48,6 +48,7 @@ #include "nm-setting-bridge.h" #include "nm-setting-bridge-port.h" #include "nm-setting-dcb.h" +#include "nm-setting-user.h" #include "nm-setting-proxy.h" #include "nm-setting-generic.h" #include "nm-core-internal.h" @@ -66,7 +67,7 @@ #define _NMLOG_PREFIX_NAME "ifcfg-rh" #define _NMLOG(level, ...) \ G_STMT_START { \ - nm_log ((level), (_NMLOG_DOMAIN), \ + nm_log ((level), (_NMLOG_DOMAIN), NULL, NULL, \ "%s" _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ _NMLOG_PREFIX_NAME": " \ _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ @@ -97,14 +98,13 @@ make_connection_name (shvarFile *ifcfg, char *full_name = NULL, *name; /* If the ifcfg file already has a NAME, always use that */ - name = svGetValueString (ifcfg, "NAME"); - if (name && strlen (name)) + name = svGetValueStr_cp (ifcfg, "NAME"); + if (name) return name; /* Otherwise construct a new NAME */ - g_free (name); if (!prefix) - prefix = _("System"); + prefix = "System"; /* For cosmetic reasons, if the suggested name is the same as * the ifcfg files name, don't use it. Mainly for wifi so that @@ -142,22 +142,18 @@ make_connection_setting (const char *file, g_free (new_id); /* Try for a UUID key before falling back to hashing the file name */ - uuid = svGetValueString (ifcfg, "UUID"); - if (!uuid || !strlen (uuid)) { - g_free (uuid); + uuid = svGetValueStr_cp (ifcfg, "UUID"); + if (!uuid) uuid = nm_utils_uuid_generate_from_string (svFileGetName (ifcfg), -1, NM_UTILS_UUID_TYPE_LEGACY, NULL); - } - - stable_id = svGetValueString (ifcfg, "STABLE_ID"); g_object_set (s_con, NM_SETTING_CONNECTION_TYPE, type, NM_SETTING_CONNECTION_UUID, uuid, - NM_SETTING_CONNECTION_STABLE_ID, stable_id, + NM_SETTING_CONNECTION_STABLE_ID, svGetValue (ifcfg, "STABLE_ID", &stable_id), NULL); g_free (uuid); - value = svGetValueString (ifcfg, "DEVICE"); + value = svGetValueStr_cp (ifcfg, "DEVICE"); if (value) { GError *error = NULL; @@ -172,7 +168,7 @@ make_connection_setting (const char *file, g_free (value); } - value = svGetValueString (ifcfg, "LLDP"); + value = svGetValueStr_cp (ifcfg, "LLDP"); if (!g_strcmp0 (value, "rx")) lldp = NM_SETTING_CONNECTION_LLDP_ENABLE_RX; else @@ -196,7 +192,7 @@ make_connection_setting (const char *file, NM_SETTING_CONNECTION_LLDP, lldp, NULL); - value = svGetValueString (ifcfg, "USERS"); + value = svGetValueStr_cp (ifcfg, "USERS"); if (value) { char **items, **iter; @@ -212,15 +208,11 @@ make_connection_setting (const char *file, } - zone = svGetValueString (ifcfg, "ZONE"); - if (!zone || !strlen (zone)) { - g_free (zone); - zone = NULL; - } + zone = svGetValueStr_cp (ifcfg, "ZONE"); g_object_set (s_con, NM_SETTING_CONNECTION_ZONE, zone, NULL); g_free (zone); - value = svGetValueString (ifcfg, "SECONDARY_UUIDS"); + value = svGetValueStr_cp (ifcfg, "SECONDARY_UUIDS"); if (value) { char **items, **iter; @@ -235,9 +227,9 @@ make_connection_setting (const char *file, g_strfreev (items); } - value = svGetValueString (ifcfg, "BRIDGE_UUID"); + value = svGetValueStr_cp (ifcfg, "BRIDGE_UUID"); if (!value) - value = svGetValueString (ifcfg, "BRIDGE"); + value = svGetValueStr_cp (ifcfg, "BRIDGE"); if (value) { const char *old_value; @@ -252,7 +244,7 @@ make_connection_setting (const char *file, g_free (value); } - value = svGetValueString (ifcfg, "GATEWAY_PING_TIMEOUT"); + value = svGetValueStr_cp (ifcfg, "GATEWAY_PING_TIMEOUT"); if (value) { gint64 tmp; @@ -280,75 +272,82 @@ make_connection_setting (const char *file, static gboolean read_ip4_address (shvarFile *ifcfg, const char *tag, - char **out_addr, + gboolean *out_has_key, + guint32 *out_addr, GError **error) { - char *value = NULL; - - g_return_val_if_fail (ifcfg != NULL, FALSE); - g_return_val_if_fail (tag != NULL, FALSE); - g_return_val_if_fail (out_addr != NULL, FALSE); - g_return_val_if_fail (!error || !*error, FALSE); + gs_free char *value_to_free = NULL; + const char *value; + guint32 a; - *out_addr = NULL; + nm_assert (ifcfg); + nm_assert (tag); + nm_assert (!error || !*error); - value = svGetValueString (ifcfg, tag); - if (!value) + value = svGetValueStr (ifcfg, tag, &value_to_free); + if (!value) { + NM_SET_OUT (out_has_key, FALSE); + NM_SET_OUT (out_addr, 0); return TRUE; + } - if (nm_utils_ipaddr_valid (AF_INET, value)) { - *out_addr = value; - return TRUE; - } else { + if (inet_pton (AF_INET, value, &a) != 1) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Invalid %s IP4 address '%s'", tag, value); - g_free (value); return FALSE; } + + NM_SET_OUT (out_has_key, TRUE); + NM_SET_OUT (out_addr, a); + return TRUE; } -static char * -get_numbered_tag (char *tag_name, int which) +static void +_numbered_tag (char *buf, gsize buf_len, const char *tag_name, int which) { - if (which == -1) - return g_strdup (tag_name); - return g_strdup_printf ("%s%u", tag_name, which); + gsize l; + + l = g_strlcpy (buf, tag_name, buf_len); + nm_assert (l < buf_len); + if (which != -1) { + buf_len -= l; + l = g_snprintf (&buf[l], buf_len, "%d", which); + nm_assert (l < buf_len); + } } +#define numbered_tag(buf, tag_name, which) \ + ({ \ + _nm_unused char *const _buf = (buf); \ + \ + /* some static assert trying to ensure that the buffer is statically allocated. + * It disallows a buffer size of sizeof(gpointer) to catch that. */ \ + G_STATIC_ASSERT (G_N_ELEMENTS (buf) == sizeof (buf) && sizeof (buf) != sizeof (char *) && sizeof (buf) < G_MAXINT); \ + _numbered_tag (buf, sizeof (buf), ""tag_name"", (which)); \ + buf; \ + }) static gboolean is_any_ip4_address_defined (shvarFile *ifcfg, int *idx) { - int i, ignore, *ret_idx;; + int i, ignore, *ret_idx; ret_idx = idx ? idx : &ignore; for (i = -1; i <= 2; i++) { - char *tag; - char *value; + gs_free char *value = NULL; + char tag[256]; - tag = get_numbered_tag ("IPADDR", i); - value = svGetValueString (ifcfg, tag); - g_free (tag); - if (value) { - g_free (value); + if (svGetValueStr (ifcfg, numbered_tag (tag, "IPADDR", i), &value)) { *ret_idx = i; return TRUE; } - tag = get_numbered_tag ("PREFIX", i); - value = svGetValueString (ifcfg, tag); - g_free(tag); - if (value) { - g_free (value); + if (svGetValueStr (ifcfg, numbered_tag (tag, "PREFIX", i), &value)) { *ret_idx = i; return TRUE; } - tag = get_numbered_tag ("NETMASK", i); - value = svGetValueString (ifcfg, tag); - g_free(tag); - if (value) { - g_free (value); + if (svGetValueStr (ifcfg, numbered_tag (tag, "NETMASK", i), &value)) { *ret_idx = i; return TRUE; } @@ -365,12 +364,14 @@ read_full_ip4_address (shvarFile *ifcfg, char **out_gateway, GError **error) { - char *ip_tag, *prefix_tag, *netmask_tag, *gw_tag; - char *ip = NULL; + char tag[256]; + char prefix_tag[256]; + guint32 ipaddr; + gs_free char *value = NULL; int prefix = 0; - gboolean success = FALSE; - char *value; - guint32 tmp; + gboolean has_key; + guint32 a; + char inet_buf[NM_UTILS_INET_ADDRSTRLEN]; g_return_val_if_fail (which >= -1, FALSE); g_return_val_if_fail (ifcfg != NULL, FALSE); @@ -378,76 +379,186 @@ read_full_ip4_address (shvarFile *ifcfg, g_return_val_if_fail (*out_address == NULL, FALSE); g_return_val_if_fail (!error || !*error, FALSE); - ip_tag = get_numbered_tag ("IPADDR", which); - prefix_tag = get_numbered_tag ("PREFIX", which); - netmask_tag = get_numbered_tag ("NETMASK", which); - gw_tag = get_numbered_tag ("GATEWAY", which); - /* IP address */ - if (!read_ip4_address (ifcfg, ip_tag, &ip, error)) - goto done; - if (!ip) { - if (base_addr) - ip = g_strdup (nm_ip_address_get_address (base_addr)); - else { - success = TRUE; - goto done; - } + if (!read_ip4_address (ifcfg, + numbered_tag (tag, "IPADDR", which), + &has_key, &ipaddr, error)) + return FALSE; + if (!has_key) { + if (!base_addr) + return TRUE; + nm_ip_address_get_address_binary (base_addr, &ipaddr); } /* Gateway */ if (out_gateway && !*out_gateway) { - if (!read_ip4_address (ifcfg, gw_tag, out_gateway, error)) - goto done; + if (!read_ip4_address (ifcfg, + numbered_tag (tag, "GATEWAY", which), + &has_key, &a, error)) + return FALSE; + if (has_key) + *out_gateway = g_strdup (nm_utils_inet4_ntop (a, inet_buf)); } /* Prefix */ - value = svGetValueString (ifcfg, prefix_tag); + numbered_tag (prefix_tag, "PREFIX", which); + value = svGetValueStr_cp (ifcfg, prefix_tag); if (value) { prefix = _nm_utils_ascii_str_to_int64 (value, 10, 0, 32, -1); if (prefix < 0) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Invalid IP4 prefix '%s'", value); - g_free (value); - goto done; + return FALSE; } - g_free (value); } else { /* Fall back to NETMASK if no PREFIX was specified */ - if (!read_ip4_address (ifcfg, netmask_tag, &value, error)) - goto done; - if (value) { - inet_pton (AF_INET, value, &tmp); - prefix = nm_utils_ip4_netmask_to_prefix (tmp); - g_free (value); - } else { + if (!read_ip4_address (ifcfg, + numbered_tag (tag, "NETMASK", which), + &has_key, &a, error)) + return FALSE; + if (has_key) + prefix = nm_utils_ip4_netmask_to_prefix (a); + else { if (base_addr) prefix = nm_ip_address_get_prefix (base_addr); else { /* Try to autodetermine the prefix for the address' class */ - if (inet_pton (AF_INET, ip, &tmp) == 1) { - prefix = nm_utils_ip4_get_default_prefix (tmp); - - PARSE_WARNING ("missing %s, assuming %s/%d", prefix_tag, ip, prefix); - } else { - g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "Missing IP4 prefix"); - goto done; - } + prefix = nm_utils_ip4_get_default_prefix (ipaddr); + PARSE_WARNING ("missing %s, assuming %s/%d", prefix_tag, nm_utils_inet4_ntop (ipaddr, inet_buf), prefix); } } } - *out_address = nm_ip_address_new (AF_INET, ip, prefix, error); + *out_address = nm_ip_address_new_binary (AF_INET, &ipaddr, prefix, error); if (*out_address) - success = TRUE; + return TRUE; -done: - g_free (ip); - g_free (ip_tag); - g_free (prefix_tag); - g_free (netmask_tag); - g_free (gw_tag); + return FALSE; +} + +/* + * Use looser syntax to comprise all the possibilities. + * The validity must be checked after the match. + */ +#define IPV4_ADDR_REGEX "(?:[0-9]{1,3}\\.){3}[0-9]{1,3}" +#define IPV6_ADDR_REGEX "[0-9A-Fa-f:.]+" + +/* + * NOTE: The regexes below don't describe all variants allowed by 'ip route add', + * namely destination IP without 'to' keyword is recognized just at line start. + */ + +static gboolean +parse_route_options (NMIPRoute *route, int family, const char *line, GError **error) +{ + GRegex *regex = NULL; + GMatchInfo *match_info = NULL; + gboolean success = FALSE; + static const char *metrics[] = { NM_IP_ROUTE_ATTRIBUTE_WINDOW, NM_IP_ROUTE_ATTRIBUTE_CWND, + NM_IP_ROUTE_ATTRIBUTE_INITCWND, NM_IP_ROUTE_ATTRIBUTE_INITRWND, + NM_IP_ROUTE_ATTRIBUTE_MTU, NULL }; + char buffer[1024]; + int i; + + g_return_val_if_fail (family == AF_INET || family == AF_INET6, FALSE); + + for (i = 0; metrics[i]; i++) { + nm_sprintf_buf (buffer, "(?:\\s|^)%s\\s+(lock\\s+)?(\\d+)(?:$|\\s)", metrics[i]); + regex = g_regex_new (buffer, 0, 0, NULL); + g_regex_match (regex, line, 0, &match_info); + if (g_match_info_matches (match_info)) { + gs_free char *lock = g_match_info_fetch (match_info, 1); + gs_free char *str = g_match_info_fetch (match_info, 2); + gint64 num = _nm_utils_ascii_str_to_int64 (str, 10, 0, G_MAXUINT32, -1); + + if (num == -1) { + g_match_info_free (match_info); + g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, + "Invalid route %s '%s'", metrics[i], str); + goto out; + } + + nm_ip_route_set_attribute (route, metrics[i], + g_variant_new_uint32 (num)); + if (lock && lock[0]) { + nm_sprintf_buf (buffer, "lock-%s", metrics[i]); + nm_ip_route_set_attribute (route, buffer, + g_variant_new_boolean (TRUE)); + } + } + g_clear_pointer (®ex, g_regex_unref); + g_clear_pointer (&match_info, g_match_info_free); + } + + /* tos */ + regex = g_regex_new ("(?:\\s|^)tos\\s+(\\S+)(?:$|\\s)", 0, 0, NULL); + g_regex_match (regex, line, 0, &match_info); + if (g_match_info_matches (match_info)) { + gs_free char *str = g_match_info_fetch (match_info, 1); + gint64 num = _nm_utils_ascii_str_to_int64 (str, 0, 0, G_MAXUINT8, -1); + + if (num == -1) { + g_match_info_free (match_info); + g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, + "Invalid route %s '%s'", "tos", str); + goto out; + } + nm_ip_route_set_attribute (route, NM_IP_ROUTE_ATTRIBUTE_TOS, + g_variant_new_byte ((guchar) num)); + } + g_clear_pointer (®ex, g_regex_unref); + g_clear_pointer (&match_info, g_match_info_free); + + /* from */ + if (family == AF_INET6) { + regex = g_regex_new ("(?:\\s|^)from\\s+(" IPV6_ADDR_REGEX "(?:/\\d{1,3})?)(?:$|\\s)", 0, 0, NULL); + g_regex_match (regex, line, 0, &match_info); + if (g_match_info_matches (match_info)) { + gs_free char *str = g_match_info_fetch (match_info, 1); + gs_free_error GError *local_error = NULL; + GVariant *variant = g_variant_new_string (str); + + if (!nm_ip_route_attribute_validate (NM_IP_ROUTE_ATTRIBUTE_FROM, variant, family, NULL, &local_error)) { + g_match_info_free (match_info); + g_variant_unref (variant); + g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, + "Invalid route from '%s': %s", str, local_error->message); + goto out; + } + nm_ip_route_set_attribute (route, NM_IP_ROUTE_ATTRIBUTE_FROM, variant); + } + g_clear_pointer (®ex, g_regex_unref); + g_clear_pointer (&match_info, g_match_info_free); + } + + if (family == AF_INET) + regex = g_regex_new ("(?:\\s|^)src\\s+(" IPV4_ADDR_REGEX ")(?:$|\\s)", 0, 0, NULL); + else + regex = g_regex_new ("(?:\\s|^)src\\s+(" IPV6_ADDR_REGEX ")(?:$|\\s)", 0, 0, NULL); + g_regex_match (regex, line, 0, &match_info); + if (g_match_info_matches (match_info)) { + gs_free char *str = g_match_info_fetch (match_info, 1); + gs_free_error GError *local_error = NULL; + GVariant *variant = g_variant_new_string (str); + + if (!nm_ip_route_attribute_validate (NM_IP_ROUTE_ATTRIBUTE_SRC, variant, family, + NULL, &local_error)) { + g_match_info_free (match_info); + g_variant_unref (variant); + g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, + "Invalid route src '%s': %s", str, local_error->message); + goto out; + } + + nm_ip_route_set_attribute (route, NM_IP_ROUTE_ATTRIBUTE_SRC, variant); + } + success = TRUE; + +out: + if (regex) + g_regex_unref (regex); + if (match_info) + g_match_info_free (match_info); return success; } @@ -459,87 +570,85 @@ read_one_ip4_route (shvarFile *ifcfg, NMIPRoute **out_route, GError **error) { - char *ip_tag, *netmask_tag, *gw_tag, *metric_tag, *value; - char *dest = NULL, *next_hop = NULL; + char tag[256]; + char netmask_tag[256]; + guint32 dest; + guint32 next_hop; + guint32 netmask; + gboolean has_key; + gs_free char *value = NULL; gint64 prefix, metric; - gboolean success = FALSE; + char inet_buf[NM_UTILS_INET_ADDRSTRLEN]; g_return_val_if_fail (ifcfg != NULL, FALSE); g_return_val_if_fail (out_route != NULL, FALSE); g_return_val_if_fail (*out_route == NULL, FALSE); g_return_val_if_fail (!error || !*error, FALSE); - ip_tag = g_strdup_printf ("ADDRESS%u", which); - netmask_tag = g_strdup_printf ("NETMASK%u", which); - gw_tag = g_strdup_printf ("GATEWAY%u", which); - metric_tag = g_strdup_printf ("METRIC%u", which); - /* Destination */ - if (!read_ip4_address (ifcfg, ip_tag, &dest, error)) - goto out; - if (!dest) { - /* Check whether IP is missing or 0.0.0.0 */ - char *val; - val = svGetValueString (ifcfg, ip_tag); - if (!val) { - *out_route = NULL; - success = TRUE; /* missing route = success */ - goto out; - } - g_free (val); + if (!read_ip4_address (ifcfg, + numbered_tag (tag, "ADDRESS", which), + &has_key, &dest, error)) + return FALSE; + if (!has_key) { + /* missing route = success */ + *out_route = NULL; + return TRUE; } /* Next hop */ - if (!read_ip4_address (ifcfg, gw_tag, &next_hop, error)) - goto out; + if (!read_ip4_address (ifcfg, + numbered_tag (tag, "GATEWAY", which), + NULL, &next_hop, error)) + return FALSE; /* We don't make distinction between missing GATEWAY IP and 0.0.0.0 */ /* Prefix */ - if (!read_ip4_address (ifcfg, netmask_tag, &value, error)) - goto out; - if (value) { - guint32 netmask; - - inet_pton (AF_INET, value, &netmask); + if (!read_ip4_address (ifcfg, + numbered_tag (netmask_tag, "NETMASK", which), + &has_key, &netmask, error)) + return FALSE; + if (has_key) { prefix = nm_utils_ip4_netmask_to_prefix (netmask); - g_free (value); if (prefix == 0 || netmask != nm_utils_ip4_prefix_to_netmask (prefix)) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "Invalid IP4 netmask '%s' \"%s\"", netmask_tag, nm_utils_inet4_ntop (netmask, NULL)); - goto out; + "Invalid IP4 netmask '%s' \"%s\"", netmask_tag, nm_utils_inet4_ntop (netmask, inet_buf)); + return FALSE; } } else { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Missing IP4 route element '%s'", netmask_tag); - goto out; + return FALSE; } /* Metric */ - value = svGetValueString (ifcfg, metric_tag); + nm_clear_g_free (&value); + value = svGetValueStr_cp (ifcfg, numbered_tag (tag, "METRIC", which)); if (value) { metric = _nm_utils_ascii_str_to_int64 (value, 10, 0, G_MAXUINT32, -1); if (metric < 0) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Invalid IP4 route metric '%s'", value); - g_free (value); - goto out; + return FALSE; } - g_free (value); } else metric = -1; - *out_route = nm_ip_route_new (AF_INET, dest, prefix, next_hop, metric, error); - if (*out_route) - success = TRUE; + *out_route = nm_ip_route_new_binary (AF_INET, &dest, prefix, &next_hop, metric, error); + if (!*out_route) + return FALSE; -out: - g_free (dest); - g_free (next_hop); - g_free (ip_tag); - g_free (netmask_tag); - g_free (gw_tag); - g_free (metric_tag); - return success; + /* Options */ + nm_clear_g_free (&value); + value = svGetValueStr_cp (ifcfg, numbered_tag (tag, "OPTIONS", which)); + if (value) { + if (!parse_route_options (*out_route, AF_INET, value, error)) { + g_clear_pointer (out_route, nm_ip_route_unref); + return FALSE; + } + } + + return TRUE; } static gboolean @@ -665,6 +774,12 @@ read_route_file_legacy (const char *filename, NMSettingIPConfig *s_ip4, GError * route = nm_ip_route_new (AF_INET, dest, prefix_int, next_hop, metric_int, error); if (!route) goto error; + + if (!parse_route_options (route, AF_INET, *iter, error)) { + nm_ip_route_unref (route); + goto error; + } + if (!nm_setting_ip_config_add_route (s_ip4, route)) PARSE_WARNING ("duplicate IP4 route"); nm_ip_route_unref (route); @@ -758,13 +873,6 @@ error: return success; } -/* IPv6 address is very complex to describe completely by a regular expression, - * so don't try to, rather use looser syntax to comprise all possibilities - * NOTE: The regexes below don't describe all variants allowed by 'ip route add', - * namely destination IP without 'to' keyword is recognized just at line start. - */ -#define IPV6_ADDR_REGEX "[0-9A-Fa-f:.]+" - static gboolean read_route6_file (const char *filename, NMSettingIPConfig *s_ip6, GError **error) { @@ -786,6 +894,7 @@ read_route6_file (const char *filename, NMSettingIPConfig *s_ip6, GError **error const char *pattern_via = "via\\s+(" IPV6_ADDR_REGEX ")"; /* IPv6 of gateway */ const char *pattern_metric = "metric\\s+(\\d+)"; /* metric */ + g_return_val_if_fail (filename != NULL, FALSE); g_return_val_if_fail (s_ip6 != NULL, FALSE); g_return_val_if_fail (!error || !*error, FALSE); @@ -891,6 +1000,12 @@ read_route6_file (const char *filename, NMSettingIPConfig *s_ip6, GError **error g_free (next_hop); if (!route) goto error; + + if (!parse_route_options (route, AF_INET6, *iter, error)) { + nm_ip_route_unref (route); + goto error; + } + if (!nm_setting_ip_config_add_route (s_ip6, route)) PARSE_WARNING ("duplicate IP6 route"); nm_ip_route_unref (route); @@ -909,6 +1024,54 @@ error: return success; } +static NMSetting * +make_user_setting (shvarFile *ifcfg, GError **error) +{ + gboolean has_user_data = FALSE; + gs_unref_object NMSettingUser *s_user = NULL; + gs_unref_hashtable GHashTable *keys = NULL; + GHashTableIter iter; + const char *key; + nm_auto_free_gstring GString *str = NULL; + + keys = svGetKeys (ifcfg); + if (!keys) + return NULL; + + g_hash_table_iter_init (&iter, keys); + while (g_hash_table_iter_next (&iter, (gpointer *) &key, NULL)) { + const char *value; + gs_free char *value_to_free = NULL; + + if (!g_str_has_prefix (key, "NM_USER_")) + continue; + + value = svGetValue (ifcfg, key, &value_to_free); + + if (!value) + continue; + + if (!str) + str = g_string_sized_new (100); + else + g_string_set_size (str, 0); + + if (!nms_ifcfg_rh_utils_user_key_decode (key + NM_STRLEN ("NM_USER_"), str)) + continue; + + if (!s_user) + s_user = NM_SETTING_USER (nm_setting_user_new ()); + + if (nm_setting_user_set_data (s_user, str->str, + value, NULL)) + has_user_data = TRUE; + } + + return has_user_data + ? g_steal_pointer (&s_user) + : NULL; +} + static NMSetting * make_proxy_setting (shvarFile *ifcfg, GError **error) { @@ -916,7 +1079,7 @@ make_proxy_setting (shvarFile *ifcfg, GError **error) char *value = NULL; NMSettingProxyMethod method; - value = svGetValueString (ifcfg, "PROXY_METHOD"); + value = svGetValueStr_cp (ifcfg, "PROXY_METHOD"); if (!value) return NULL; @@ -934,14 +1097,14 @@ make_proxy_setting (shvarFile *ifcfg, GError **error) NM_SETTING_PROXY_METHOD, (int) NM_SETTING_PROXY_METHOD_AUTO, NULL); - value = svGetValueString (ifcfg, "PAC_URL"); + value = svGetValueStr_cp (ifcfg, "PAC_URL"); if (value) { value = g_strstrip (value); g_object_set (s_proxy, NM_SETTING_PROXY_PAC_URL, value, NULL); g_free (value); } - value = svGetValueString (ifcfg, "PAC_SCRIPT"); + value = svGetValueStr_cp (ifcfg, "PAC_SCRIPT"); if (value) { value = g_strstrip (value); g_object_set (s_proxy, NM_SETTING_PROXY_PAC_SCRIPT, value, NULL); @@ -956,7 +1119,7 @@ make_proxy_setting (shvarFile *ifcfg, GError **error) break; } - value = svGetValueString (ifcfg, "BROWSER_ONLY"); + value = svGetValueStr_cp (ifcfg, "BROWSER_ONLY"); if (value) { if (!g_ascii_strcasecmp (value, "yes")) g_object_set (s_proxy, NM_SETTING_PROXY_BROWSER_ONLY, TRUE, NULL); @@ -969,21 +1132,27 @@ make_proxy_setting (shvarFile *ifcfg, GError **error) static NMSetting * make_ip4_setting (shvarFile *ifcfg, const char *network_file, + gboolean *out_has_defroute, GError **error) { - NMSettingIPConfig *s_ip4 = NULL; + gs_unref_object NMSettingIPConfig *s_ip4 = NULL; + gs_free char *route_path = NULL; char *value = NULL; - char *route_path = NULL; char *method; gs_free char *dns_options_free = NULL; const char *dns_options = NULL; gs_free char *gateway = NULL; - gint32 i; + int i; + guint32 a; + gboolean has_key; shvarFile *network_ifcfg; shvarFile *route_ifcfg; - gboolean never_default = FALSE; + gboolean never_default; gint64 timeout; gint priority; + char inet_buf[NM_UTILS_INET_ADDRSTRLEN]; + + nm_assert (out_has_defroute && !*out_has_defroute); s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new (); @@ -992,7 +1161,13 @@ make_ip4_setting (shvarFile *ifcfg, * specified is DEFROUTE=yes which means that this connection can be used * as a default route */ - never_default = !svGetValueBoolean (ifcfg, "DEFROUTE", TRUE); + i = svGetValueBoolean (ifcfg, "DEFROUTE", -1); + if (i == -1) + never_default = FALSE; + else { + never_default = !i; + *out_has_defroute = TRUE; + } /* Then check if GATEWAYDEV; it's global and overrides DEFROUTE */ network_ifcfg = svOpenFile (network_file, NULL); @@ -1000,8 +1175,8 @@ make_ip4_setting (shvarFile *ifcfg, char *gatewaydev; /* Get the connection ifcfg device name and the global gateway device */ - value = svGetValueString (ifcfg, "DEVICE"); - gatewaydev = svGetValueString (network_ifcfg, "GATEWAYDEV"); + value = svGetValueStr_cp (ifcfg, "DEVICE"); + gatewaydev = svGetValueStr_cp (network_ifcfg, "GATEWAYDEV"); dns_options = svGetValue (network_ifcfg, "RES_OPTIONS", &dns_options_free); /* If there was a global gateway device specified, then only connections @@ -1015,7 +1190,7 @@ make_ip4_setting (shvarFile *ifcfg, svCloseFile (network_ifcfg); } - value = svGetValueString (ifcfg, "BOOTPROTO"); + value = svGetValueStr_cp (ifcfg, "BOOTPROTO"); if (!value || !*value || !g_ascii_strcasecmp (value, "none")) { if (is_any_ip4_address_defined (ifcfg, NULL)) @@ -1041,24 +1216,26 @@ make_ip4_setting (shvarFile *ifcfg, NULL); /* 1 IP address is allowed for shared connections. Read it. */ if (is_any_ip4_address_defined (ifcfg, &idx)) { + guint32 gw; NMIPAddress *addr = NULL; if (!read_full_ip4_address (ifcfg, idx, NULL, &addr, NULL, error)) - goto done; - if (!read_ip4_address (ifcfg, "GATEWAY", &gateway, error)) - goto done; + return NULL; + if (!read_ip4_address (ifcfg, "GATEWAY", NULL, &gw, error)) + return NULL; (void) nm_setting_ip_config_add_address (s_ip4, addr); nm_ip_address_unref (addr); if (never_default) PARSE_WARNING ("GATEWAY will be ignored when DEFROUTE is disabled"); + gateway = g_strdup (nm_utils_inet4_ntop (gw, inet_buf)); g_object_set (s_ip4, NM_SETTING_IP_CONFIG_GATEWAY, gateway, NULL); } - return NM_SETTING (s_ip4); + return g_steal_pointer (&s_ip4); } else { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Unknown BOOTPROTO '%s'", value); g_free (value); - goto done; + return NULL; } g_free (value); @@ -1073,32 +1250,34 @@ make_ip4_setting (shvarFile *ifcfg, NULL); if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) == 0) - return NM_SETTING (s_ip4); + return g_steal_pointer (&s_ip4); /* Handle DHCP settings */ - value = svGetValueString (ifcfg, "DHCP_HOSTNAME"); - if (value && *value) + value = svGetValueStr_cp (ifcfg, "DHCP_HOSTNAME"); + if (value) { g_object_set (s_ip4, NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, value, NULL); - g_free (value); + g_free (value); + } - value = svGetValueString (ifcfg, "DHCP_FQDN"); - if (value && *value) { + value = svGetValueStr_cp (ifcfg, "DHCP_FQDN"); + if (value) { g_object_set (s_ip4, - NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, NULL, - NM_SETTING_IP4_CONFIG_DHCP_FQDN, value, - NULL); + NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, NULL, + NM_SETTING_IP4_CONFIG_DHCP_FQDN, value, + NULL); + g_free (value); } - g_free (value); g_object_set (s_ip4, NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME, svGetValueBoolean (ifcfg, "DHCP_SEND_HOSTNAME", TRUE), NM_SETTING_IP_CONFIG_DHCP_TIMEOUT, svGetValueInt64 (ifcfg, "IPV4_DHCP_TIMEOUT", 10, 0, G_MAXINT32, 0), NULL); - value = svGetValueString (ifcfg, "DHCP_CLIENT_ID"); - if (value && strlen (value)) + value = svGetValueStr_cp (ifcfg, "DHCP_CLIENT_ID"); + if (value) { g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID, value, NULL); - g_free (value); + g_free (value); + } /* Read static IP addresses. * Read them even for AUTO method - in this case the addresses are @@ -1111,7 +1290,7 @@ make_ip4_setting (shvarFile *ifcfg, /* gateway will only be set if still unset. Hence, we don't leak gateway * here by calling read_full_ip4_address() repeatedly */ if (!read_full_ip4_address (ifcfg, i, NULL, &addr, &gateway, error)) - goto done; + return NULL; if (!addr) { /* The first mandatory variable is 2-indexed (IPADDR2) @@ -1132,16 +1311,17 @@ make_ip4_setting (shvarFile *ifcfg, if (network_ifcfg) { gboolean read_success; - read_success = read_ip4_address (network_ifcfg, "GATEWAY", &gateway, error); + read_success = read_ip4_address (network_ifcfg, "GATEWAY", &has_key, &a, error); svCloseFile (network_ifcfg); if (!read_success) - goto done; - - if (gateway && nm_setting_ip_config_get_num_addresses (s_ip4) == 0) { - gs_free char *f = g_path_get_basename (svFileGetName (ifcfg)); - PARSE_WARNING ("ignoring GATEWAY (/etc/sysconfig/network) for %s " - "because the connection has no static addresses", f); - g_clear_pointer (&gateway, g_free); + return NULL; + if (has_key) { + if (nm_setting_ip_config_get_num_addresses (s_ip4) == 0) { + gs_free char *f = g_path_get_basename (svFileGetName (ifcfg)); + PARSE_WARNING ("ignoring GATEWAY (/etc/sysconfig/network) for %s " + "because the connection has no static addresses", f); + } else + gateway = g_strdup (nm_utils_inet4_ntop (a, inet_buf)); } } } @@ -1154,10 +1334,10 @@ make_ip4_setting (shvarFile *ifcfg, * Pick up just IPv4 addresses (IPv6 addresses are taken by make_ip6_setting()) */ for (i = 1; i <= 10; i++) { - char *tag; + char tag[256]; - tag = g_strdup_printf ("DNS%u", i); - value = svGetValueString (ifcfg, tag); + numbered_tag (tag, "DNS", i); + value = svGetValueStr_cp (ifcfg, tag); if (value) { if (nm_utils_ipaddr_valid (AF_INET, value)) { if (!nm_setting_ip_config_add_dns (s_ip4, value)) @@ -1166,19 +1346,16 @@ make_ip4_setting (shvarFile *ifcfg, /* Ignore IPv6 addresses */ } else { PARSE_WARNING ("invalid DNS server address %s", value); - g_free (tag); g_free (value); - goto done; + return NULL; } g_free (value); } - - g_free (tag); } /* DNS searches */ - value = svGetValueString (ifcfg, "DOMAIN"); + value = svGetValueStr_cp (ifcfg, "DOMAIN"); if (value) { char **searches = NULL; @@ -1222,7 +1399,7 @@ make_ip4_setting (shvarFile *ifcfg, if (!read_one_ip4_route (route_ifcfg, i, &route, error)) { svCloseFile (route_ifcfg); - goto done; + return NULL; } if (!route) @@ -1236,13 +1413,12 @@ make_ip4_setting (shvarFile *ifcfg, } } else { if (!read_route_file_legacy (route_path, s_ip4, error)) - goto done; + return NULL; } - g_free (route_path); /* Legacy value NM used for a while but is incorrect (rh #459370) */ if (!nm_setting_ip_config_get_num_dns_searches (s_ip4)) { - value = svGetValueString (ifcfg, "SEARCH"); + value = svGetValueStr_cp (ifcfg, "SEARCH"); if (value) { char **searches = NULL; @@ -1266,16 +1442,11 @@ make_ip4_setting (shvarFile *ifcfg, g_object_set (s_ip4, NM_SETTING_IP_CONFIG_DAD_TIMEOUT, (gint) (timeout <= 0 ? timeout : timeout * 1000), NULL); - return NM_SETTING (s_ip4); - -done: - g_free (route_path); - g_object_unref (s_ip4); - return NULL; + return g_steal_pointer (&s_ip4); } static void -read_aliases (NMSettingIPConfig *s_ip4, const char *filename) +read_aliases (NMSettingIPConfig *s_ip4, gboolean read_defroute, const char *filename) { GDir *dir; char *dirname, *base; @@ -1301,6 +1472,7 @@ read_aliases (NMSettingIPConfig *s_ip4, const char *filename) gboolean ok; while ((item = g_dir_read_name (dir))) { + gs_free char *gateway = NULL; char *full_path, *device; const char *p; @@ -1329,7 +1501,7 @@ read_aliases (NMSettingIPConfig *s_ip4, const char *filename) continue; } - device = svGetValueString (parsed, "DEVICE"); + device = svGetValueStr_cp (parsed, "DEVICE"); if (!device) { PARSE_WARNING ("alias file '%s' has no DEVICE", full_path); svCloseFile (parsed); @@ -1347,12 +1519,30 @@ read_aliases (NMSettingIPConfig *s_ip4, const char *filename) } addr = NULL; - ok = read_full_ip4_address (parsed, -1, base_addr, &addr, NULL, &err); - svCloseFile (parsed); + ok = read_full_ip4_address (parsed, -1, base_addr, &addr, + read_defroute ? &gateway : NULL, + &err); if (ok) { nm_ip_address_set_attribute (addr, "label", g_variant_new_string (device)); if (!nm_setting_ip_config_add_address (s_ip4, addr)) PARSE_WARNING ("duplicate IP4 address in alias file %s", item); + if (nm_streq0 (nm_setting_ip_config_get_method (s_ip4), NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) + g_object_set (s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, NULL); + if (read_defroute) { + int i; + + if (gateway) { + g_object_set (s_ip4, NM_SETTING_IP_CONFIG_GATEWAY, gateway, NULL); + read_defroute = FALSE; + } + i = svGetValueBoolean (parsed, "DEFROUTE", -1); + if (i != -1) { + g_object_set (s_ip4, + NM_SETTING_IP_CONFIG_NEVER_DEFAULT, (gboolean) !i, + NULL); + read_defroute = FALSE; + } + } } else { PARSE_WARNING ("error reading IP4 address from alias file '%s': %s", full_path, err ? err->message : "no address"); @@ -1360,6 +1550,8 @@ read_aliases (NMSettingIPConfig *s_ip4, const char *filename) } nm_ip_address_unref (addr); + svCloseFile (parsed); + g_free (device); g_free (full_path); } @@ -1416,9 +1608,9 @@ make_ip6_setting (shvarFile *ifcfg, char *default_dev = NULL; /* Get the connection ifcfg device name and the global default route device */ - value = svGetValueString (ifcfg, "DEVICE"); - ipv6_defaultgw = svGetValueString (network_ifcfg, "IPV6_DEFAULTGW"); - ipv6_defaultdev = svGetValueString (network_ifcfg, "IPV6_DEFAULTDEV"); + value = svGetValueStr_cp (ifcfg, "DEVICE"); + ipv6_defaultgw = svGetValueStr_cp (network_ifcfg, "IPV6_DEFAULTGW"); + ipv6_defaultdev = svGetValueStr_cp (network_ifcfg, "IPV6_DEFAULTDEV"); dns_options = svGetValue (network_ifcfg, "RES_OPTIONS", &dns_options_free); if (ipv6_defaultgw) { @@ -1443,7 +1635,7 @@ make_ip6_setting (shvarFile *ifcfg, /* Find out method property */ /* Is IPV6 enabled? Set method to "ignored", when not enabled */ - str_value = svGetValueString (ifcfg, "IPV6INIT"); + str_value = svGetValueStr_cp (ifcfg, "IPV6INIT"); ipv6init = svGetValueBoolean (ifcfg, "IPV6INIT", FALSE); if (!str_value) { network_ifcfg = svOpenFile (network_file, NULL); @@ -1458,7 +1650,7 @@ make_ip6_setting (shvarFile *ifcfg, method = NM_SETTING_IP6_CONFIG_METHOD_IGNORE; /* IPv6 is disabled */ else { ipv6forwarding = svGetValueBoolean (ifcfg, "IPV6FORWARDING", FALSE); - str_value = svGetValueString (ifcfg, "IPV6_AUTOCONF"); + str_value = svGetValueStr_cp (ifcfg, "IPV6_AUTOCONF"); dhcp6 = svGetValueBoolean (ifcfg, "DHCPV6C", FALSE); if (!g_strcmp0 (str_value, "shared")) @@ -1470,9 +1662,9 @@ make_ip6_setting (shvarFile *ifcfg, else { /* IPV6_AUTOCONF=no and no IPv6 address -> method 'link-local' */ g_free (str_value); - str_value = svGetValueString (ifcfg, "IPV6ADDR"); + str_value = svGetValueStr_cp (ifcfg, "IPV6ADDR"); if (!str_value) - str_value = svGetValueString (ifcfg, "IPV6ADDR_SECONDARIES"); + str_value = svGetValueStr_cp (ifcfg, "IPV6ADDR_SECONDARIES"); if (!str_value) method = NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL; @@ -1482,7 +1674,7 @@ make_ip6_setting (shvarFile *ifcfg, /* TODO - handle other methods */ /* Read IPv6 Privacy Extensions configuration */ - str_value = svGetValueString (ifcfg, "IPV6_PRIVACY"); + str_value = svGetValueStr_cp (ifcfg, "IPV6_PRIVACY"); if (str_value) { ip6_privacy = svParseBoolean (str_value, FALSE); if (!ip6_privacy) @@ -1512,13 +1704,13 @@ make_ip6_setting (shvarFile *ifcfg, if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE) == 0) return NM_SETTING (s_ip6); - value = svGetValueString (ifcfg, "DHCPV6_HOSTNAME"); + value = svGetValueStr_cp (ifcfg, "DHCPV6_HOSTNAME"); /* Use DHCP_HOSTNAME as fallback if it is in FQDN format and ipv6.method is * auto or dhcp: this is required to support old ifcfg files */ if (!value && ( !strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) || !strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_DHCP))) { - value = svGetValueString (ifcfg, "DHCP_HOSTNAME"); + value = svGetValueStr_cp (ifcfg, "DHCP_HOSTNAME"); if (value && !strchr (value, '.')) g_clear_pointer (&value, g_free); } @@ -1534,8 +1726,8 @@ make_ip6_setting (shvarFile *ifcfg, * added to the automatic ones. Note that this is not currently supported by * the legacy 'network' service (ifup-eth). */ - ipv6addr = svGetValueString (ifcfg, "IPV6ADDR"); - ipv6addr_secondaries = svGetValueString (ifcfg, "IPV6ADDR_SECONDARIES"); + ipv6addr = svGetValueStr_cp (ifcfg, "IPV6ADDR"); + ipv6addr_secondaries = svGetValueStr_cp (ifcfg, "IPV6ADDR_SECONDARIES"); value = g_strjoin (ipv6addr && ipv6addr_secondaries ? " " : NULL, ipv6addr ? ipv6addr : "", @@ -1562,12 +1754,12 @@ make_ip6_setting (shvarFile *ifcfg, /* Gateway */ if (nm_setting_ip_config_get_num_addresses (s_ip6)) { - value = svGetValueString (ifcfg, "IPV6_DEFAULTGW"); + value = svGetValueStr_cp (ifcfg, "IPV6_DEFAULTGW"); if (!value) { /* If no gateway in the ifcfg, try global /etc/sysconfig/network instead */ network_ifcfg = svOpenFile (network_file, NULL); if (network_ifcfg) { - value = svGetValueString (network_ifcfg, "IPV6_DEFAULTGW"); + value = svGetValueStr_cp (network_ifcfg, "IPV6_DEFAULTGW"); svCloseFile (network_ifcfg); } } @@ -1588,7 +1780,7 @@ make_ip6_setting (shvarFile *ifcfg, } /* IPv6 addressing mode configuration */ - str_value = svGetValueString (ifcfg, "IPV6_ADDR_GEN_MODE"); + str_value = svGetValueStr_cp (ifcfg, "IPV6_ADDR_GEN_MODE"); if (str_value) { if (nm_utils_enum_from_str (nm_setting_ip6_config_addr_gen_mode_get_type (), str_value, (int *) &addr_gen_mode, NULL)) @@ -1604,7 +1796,7 @@ make_ip6_setting (shvarFile *ifcfg, } /* IPv6 tokenized interface identifier */ - str_value = svGetValueString (ifcfg, "IPV6_TOKEN"); + str_value = svGetValueStr_cp (ifcfg, "IPV6_TOKEN"); if (str_value) { g_object_set (s_ip6, NM_SETTING_IP6_CONFIG_TOKEN, str_value, NULL); g_free (str_value); @@ -1614,13 +1806,13 @@ make_ip6_setting (shvarFile *ifcfg, * Pick up just IPv6 addresses (IPv4 addresses are taken by make_ip4_setting()) */ for (i = 1; i <= 10; i++) { - char *tag; + char tag[256]; - tag = g_strdup_printf ("DNS%u", i); - value = svGetValueString (ifcfg, tag); + numbered_tag (tag, "DNS", i); + value = svGetValueStr_cp (ifcfg, tag); if (!value) { - g_free (tag); - break; /* all done */ + /* all done */ + break; } if (nm_utils_ipaddr_valid (AF_INET6, value)) { @@ -1630,12 +1822,10 @@ make_ip6_setting (shvarFile *ifcfg, /* Ignore IPv4 addresses */ } else { PARSE_WARNING ("invalid DNS server address %s", value); - g_free (tag); g_free (value); goto error; } - g_free (tag); g_free (value); } @@ -1676,9 +1866,9 @@ check_if_bond_slave (shvarFile *ifcfg, { char *value; - value = svGetValueString (ifcfg, "MASTER_UUID"); + value = svGetValueStr_cp (ifcfg, "MASTER_UUID"); if (!value) - value = svGetValueString (ifcfg, "MASTER"); + value = svGetValueStr_cp (ifcfg, "MASTER"); if (value) { g_object_set (s_con, NM_SETTING_CONNECTION_MASTER, value, NULL); @@ -1699,9 +1889,9 @@ check_if_team_slave (shvarFile *ifcfg, { gs_free char *value = NULL; - value = svGetValueString (ifcfg, "TEAM_MASTER_UUID"); + value = svGetValueStr_cp (ifcfg, "TEAM_MASTER_UUID"); if (!value) - value = svGetValueString (ifcfg, "TEAM_MASTER"); + value = svGetValueStr_cp (ifcfg, "TEAM_MASTER"); if (!value) return FALSE; @@ -1777,7 +1967,7 @@ read_dcb_app (shvarFile *ifcfg, /* Priority */ tmp = g_strdup_printf ("DCB_APP_%s_PRIORITY", app); - val = svGetValueString (ifcfg, tmp); + val = svGetValueStr_cp (ifcfg, tmp); if (val) { priority = _nm_utils_ascii_str_to_int64 (val, 0, 0, 7, -1); if (priority < 0) { @@ -1814,26 +2004,23 @@ read_dcb_bool_array (shvarFile *ifcfg, DcbSetBoolFunc set_func, GError **error) { - char *val; - gboolean success = FALSE; + gs_free char *val = NULL; guint i; - val = svGetValueString (ifcfg, prop); + val = svGetValueStr_cp (ifcfg, prop); if (!val) return TRUE; if (!(flags & NM_SETTING_DCB_FLAG_ENABLE)) { PARSE_WARNING ("ignoring %s; %s is not enabled", prop, desc); - success = TRUE; - goto out; + return TRUE; } - val = g_strstrip (val); if (strlen (val) != 8) { PARSE_WARNING ("%s value '%s' must be 8 characters long", prop, val); g_set_error_literal (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "boolean array must be 8 characters"); - goto out; + return FALSE; } /* All characters must be either 0 or 1 */ @@ -1842,15 +2029,11 @@ read_dcb_bool_array (shvarFile *ifcfg, PARSE_WARNING ("invalid %s value '%s': not all 0s and 1s", prop, val); g_set_error_literal (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "invalid boolean digit"); - goto out; + return FALSE; } set_func (s_dcb, i, (val[i] == '1')); } - success = TRUE; - -out: - g_free (val); - return success; + return TRUE; } typedef void (*DcbSetUintFunc) (NMSettingDcb *, guint, guint); @@ -1865,26 +2048,23 @@ read_dcb_uint_array (shvarFile *ifcfg, DcbSetUintFunc set_func, GError **error) { - char *val; - gboolean success = FALSE; + gs_free char *val = NULL; guint i; - val = svGetValueString (ifcfg, prop); + val = svGetValueStr_cp (ifcfg, prop); if (!val) return TRUE; if (!(flags & NM_SETTING_DCB_FLAG_ENABLE)) { PARSE_WARNING ("ignoring %s; %s is not enabled", prop, desc); - success = TRUE; - goto out; + return TRUE; } - val = g_strstrip (val); if (strlen (val) != 8) { PARSE_WARNING ("%s value '%s' must be 8 characters long", prop, val); g_set_error_literal (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "uint array must be 8 characters"); - goto out; + return FALSE; } /* All characters must be either 0 - 7 or (optionally) f */ @@ -1898,14 +2078,11 @@ read_dcb_uint_array (shvarFile *ifcfg, prop, val, f_allowed ? " or 'f'" : ""); g_set_error_literal (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "invalid uint digit"); - goto out; + return FALSE; } } - success = TRUE; -out: - g_free (val); - return success; + return TRUE; } static gboolean @@ -1918,28 +2095,26 @@ read_dcb_percent_array (shvarFile *ifcfg, DcbSetUintFunc set_func, GError **error) { - char *val; - gboolean success = FALSE; - char **split = NULL, **iter; + gs_free char *val = NULL; + gs_strfreev char **split = NULL; + char **iter; guint i, sum = 0; - val = svGetValueString (ifcfg, prop); + val = svGetValueStr_cp (ifcfg, prop); if (!val) return TRUE; if (!(flags & NM_SETTING_DCB_FLAG_ENABLE)) { PARSE_WARNING ("ignoring %s; %s is not enabled", prop, desc); - success = TRUE; - goto out; + return TRUE; } - val = g_strstrip (val); split = g_strsplit_set (val, ",", 0); if (!split || (g_strv_length (split) != 8)) { PARSE_WARNING ("invalid %s percentage list value '%s'", prop, val); g_set_error_literal (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "percent array must be 8 elements"); - goto out; + return FALSE; } for (iter = split, i = 0; iter && *iter; iter++, i++) { @@ -1950,7 +2125,7 @@ read_dcb_percent_array (shvarFile *ifcfg, PARSE_WARNING ("invalid %s percentage value '%s'", prop, *iter); g_set_error_literal (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "invalid percent element"); - goto out; + return FALSE; } set_func (s_dcb, i, (guint) tmp); sum += (guint) tmp; @@ -1960,16 +2135,10 @@ read_dcb_percent_array (shvarFile *ifcfg, PARSE_WARNING ("%s percentages do not equal 100%%", prop); g_set_error_literal (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "invalid percentage sum"); - goto out; + return FALSE; } - success = TRUE; - -out: - if (split) - g_strfreev (split); - g_free (val); - return success; + return TRUE; } static gboolean @@ -2001,7 +2170,7 @@ make_dcb_setting (shvarFile *ifcfg, return FALSE; } if (nm_setting_dcb_get_app_fcoe_flags (s_dcb) & NM_SETTING_DCB_FLAG_ENABLE) { - val = svGetValueString (ifcfg, KEY_DCB_APP_FCOE_MODE); + val = svGetValueStr_cp (ifcfg, KEY_DCB_APP_FCOE_MODE); if (val) { if (strcmp (val, NM_SETTING_DCB_FCOE_MODE_FABRIC) == 0 || strcmp (val, NM_SETTING_DCB_FCOE_MODE_VN2VN) == 0) @@ -2138,11 +2307,9 @@ add_one_wep_key (shvarFile *ifcfg, g_return_val_if_fail (key_idx <= 3, FALSE); g_return_val_if_fail (s_wsec != NULL, FALSE); - value = svGetValueString (ifcfg, shvar_key); - if (!value || !strlen (value)) { - g_free (value); + value = svGetValueStr_cp (ifcfg, shvar_key); + if (!value) return TRUE; - } /* Validate keys */ if (passphrase) { @@ -2195,9 +2362,10 @@ add_one_wep_key (shvarFile *ifcfg, nm_setting_wireless_security_set_wep_key (s_wsec, key_idx, key); g_free (key); success = TRUE; - } else + } else { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Invalid WEP key length."); + } out: g_free (value); @@ -2245,7 +2413,7 @@ read_secret_flags (shvarFile *ifcfg, const char *flags_key) g_return_val_if_fail (flags_key[0] != '\0', NM_SETTING_SECRET_FLAG_NONE); g_return_val_if_fail (g_str_has_suffix (flags_key, "_FLAGS"), NM_SETTING_SECRET_FLAG_NONE); - val = svGetValueString (ifcfg, flags_key); + val = svGetValueStr_cp (ifcfg, flags_key); if (val) { if (strstr (val, SECRET_FLAG_AGENT)) flags |= NM_SETTING_SECRET_FLAG_AGENT_OWNED; @@ -2264,7 +2432,7 @@ make_wep_setting (shvarFile *ifcfg, const char *file, GError **error) { - NMSettingWirelessSecurity *s_wsec; + gs_unref_object NMSettingWirelessSecurity *s_wsec = NULL; char *value; shvarFile *keys_ifcfg = NULL; int default_key_idx = 0; @@ -2274,14 +2442,14 @@ make_wep_setting (shvarFile *ifcfg, s_wsec = NM_SETTING_WIRELESS_SECURITY (nm_setting_wireless_security_new ()); g_object_set (s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "none", NULL); - value = svGetValueString (ifcfg, "DEFAULTKEY"); + value = svGetValueStr_cp (ifcfg, "DEFAULTKEY"); if (value) { default_key_idx = _nm_utils_ascii_str_to_int64 (value, 0, 1, 4, 0); if (default_key_idx == 0) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Invalid default WEP key '%s'", value); g_free (value); - goto error; + return NULL; } has_default_key = TRUE; default_key_idx--; /* convert to [0...3] */ @@ -2296,21 +2464,21 @@ make_wep_setting (shvarFile *ifcfg, /* Read keys in the ifcfg file if they are system-owned */ if (key_flags == NM_SETTING_SECRET_FLAG_NONE) { if (!read_wep_keys (ifcfg, default_key_idx, s_wsec, error)) - goto error; + return NULL; /* Try to get keys from the "shadow" key file */ keys_ifcfg = utils_get_keys_ifcfg (file, FALSE); if (keys_ifcfg) { if (!read_wep_keys (keys_ifcfg, default_key_idx, s_wsec, error)) { svCloseFile (keys_ifcfg); - goto error; + return NULL; } svCloseFile (keys_ifcfg); g_assert (error == NULL || *error == NULL); } } - value = svGetValueString (ifcfg, "SECURITYMODE"); + value = svGetValueStr_cp (ifcfg, "SECURITYMODE"); if (value) { char *lcase; @@ -2326,7 +2494,7 @@ make_wep_setting (shvarFile *ifcfg, "Invalid WEP authentication algorithm '%s'", lcase); g_free (lcase); - goto error; + return NULL; } g_free (lcase); } @@ -2347,20 +2515,14 @@ make_wep_setting (shvarFile *ifcfg, g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "WEP Shared Key authentication is invalid for " "unencrypted connections."); - goto error; + return NULL; } /* Unencrypted */ - g_object_unref (s_wsec); - s_wsec = NULL; + return NULL; } - return (NMSetting *) s_wsec; - -error: - if (s_wsec) - g_object_unref (s_wsec); - return NULL; + return g_steal_pointer (&s_wsec); } static gboolean @@ -2373,7 +2535,7 @@ fill_wpa_ciphers (shvarFile *ifcfg, char **list = NULL, **iter; int i = 0; - p = value = svGetValueString (ifcfg, group ? "CIPHER_GROUP" : "CIPHER_PAIRWISE"); + p = value = svGetValueStr_cp (ifcfg, group ? "CIPHER_GROUP" : "CIPHER_PAIRWISE"); if (!value) return TRUE; @@ -2443,13 +2605,13 @@ parse_wpa_psk (shvarFile *ifcfg, /* Try to get keys from the "shadow" key file */ keys_ifcfg = utils_get_keys_ifcfg (file, FALSE); if (keys_ifcfg) { - psk = svGetValueString (keys_ifcfg, "WPA_PSK"); + psk = svGetValueStr_cp (keys_ifcfg, "WPA_PSK"); svCloseFile (keys_ifcfg); } /* Fall back to the original ifcfg */ if (!psk) - psk = svGetValueString (ifcfg, "WPA_PSK"); + psk = svGetValueStr_cp (ifcfg, "WPA_PSK"); if (!psk) return NULL; @@ -2486,7 +2648,7 @@ eap_simple_reader (const char *eap_method, NMSettingSecretFlags flags; char *value; - value = svGetValueString (ifcfg, "IEEE_8021X_IDENTITY"); + value = svGetValueStr_cp (ifcfg, "IEEE_8021X_IDENTITY"); if (!value) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Missing IEEE_8021X_IDENTITY for EAP method '%s'.", @@ -2501,10 +2663,10 @@ eap_simple_reader (const char *eap_method, /* Only read the password if it's system-owned */ if (flags == NM_SETTING_SECRET_FLAG_NONE) { - value = svGetValueString (ifcfg, "IEEE_8021X_PASSWORD"); + value = svGetValueStr_cp (ifcfg, "IEEE_8021X_PASSWORD"); if (!value && keys) { /* Try the lookaside keys file */ - value = svGetValueString (keys, "IEEE_8021X_PASSWORD"); + value = svGetValueStr_cp (keys, "IEEE_8021X_PASSWORD"); } if (!value) { @@ -2543,6 +2705,19 @@ get_full_file_path (const char *ifcfg_path, const char *file_path) return ret; } +static char * +get_cert_value (const char *ifcfg_path, const char *value, + NMSetting8021xCKScheme *out_scheme) +{ + if (strncmp (value, "pkcs11:", 7) == 0) { + *out_scheme = NM_SETTING_802_1X_CK_SCHEME_PKCS11; + return g_strdup (value); + } + + *out_scheme = NM_SETTING_802_1X_CK_SCHEME_PATH; + return get_full_file_path (ifcfg_path, value); +} + static gboolean eap_tls_reader (const char *eap_method, shvarFile *ifcfg, @@ -2551,48 +2726,58 @@ eap_tls_reader (const char *eap_method, gboolean phase2, GError **error) { + gs_free char *ca_cert = NULL; + gs_free char *privkey = NULL; + gs_free char *privkey_password = NULL; char *value; - char *ca_cert = NULL; - char *real_path = NULL; - char *client_cert = NULL; - char *privkey = NULL; - char *privkey_password = NULL; - gboolean success = FALSE; + char *ca_cert_password = NULL; + char *client_cert_password = NULL; NMSetting8021xCKFormat privkey_format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN; const char *ca_cert_key = phase2 ? "IEEE_8021X_INNER_CA_CERT" : "IEEE_8021X_CA_CERT"; - const char *pk_pw_key = phase2 ? "IEEE_8021X_INNER_PRIVATE_KEY_PASSWORD": "IEEE_8021X_PRIVATE_KEY_PASSWORD"; - const char *pk_key = phase2 ? "IEEE_8021X_INNER_PRIVATE_KEY" : "IEEE_8021X_PRIVATE_KEY"; + const char *ca_cert_pw_key = phase2 ? "IEEE_8021X_INNER_CA_CERT_PASSWORD" : "IEEE_8021X_CA_CERT_PASSWORD"; + const char *ca_cert_pw_prop = phase2 ? NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD : NM_SETTING_802_1X_CA_CERT_PASSWORD; + const char *ca_cert_pw_flags_key = phase2 ? "IEEE_8021X_INNER_CA_CERT_PASSWORD_FLAGS" : "IEEE_8021X_CA_CERT_PASSWORD_FLAGS"; + const char *ca_cert_pw_flags_prop = phase2 ? NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD_FLAGS : NM_SETTING_802_1X_CA_CERT_PASSWORD_FLAGS; const char *cli_cert_key = phase2 ? "IEEE_8021X_INNER_CLIENT_CERT" : "IEEE_8021X_CLIENT_CERT"; - const char *pk_pw_flags_key = phase2 ? "IEEE_8021X_INNER_PRIVATE_KEY_PASSWORD_FLAGS": "IEEE_8021X_PRIVATE_KEY_PASSWORD_FLAGS"; + const char *cli_cert_pw_key = phase2 ? "IEEE_8021X_INNER_CLIENT_CERT_PASSWORD" : "IEEE_8021X_CLIENT_CERT_PASSWORD"; + const char *cli_cert_pw_prop = phase2 ? NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD : NM_SETTING_802_1X_CLIENT_CERT_PASSWORD; + const char *cli_cert_pw_flags_key = phase2 ? "IEEE_8021X_INNER_CLIENT_CERT_PASSWORD_FLAGS" : "IEEE_8021X_CLIENT_CERT_PASSWORD_FLAGS"; + const char *cli_cert_pw_flags_prop = phase2 ? NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD_FLAGS : NM_SETTING_802_1X_CLIENT_CERT_PASSWORD_FLAGS; + const char *pk_key = phase2 ? "IEEE_8021X_INNER_PRIVATE_KEY" : "IEEE_8021X_PRIVATE_KEY"; + const char *pk_pw_key = phase2 ? "IEEE_8021X_INNER_PRIVATE_KEY_PASSWORD": "IEEE_8021X_PRIVATE_KEY_PASSWORD"; + const char *pk_pw_flags_key = phase2 ? "IEEE_8021X_INNER_PRIVATE_KEY_PASSWORD_FLAGS" : "IEEE_8021X_PRIVATE_KEY_PASSWORD_FLAGS"; const char *pk_pw_flags_prop = phase2 ? NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS : NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD_FLAGS; NMSettingSecretFlags flags; + NMSetting8021xCKScheme scheme; - value = svGetValueString (ifcfg, "IEEE_8021X_IDENTITY"); + value = svGetValueStr_cp (ifcfg, "IEEE_8021X_IDENTITY"); if (value) { g_object_set (s_8021x, NM_SETTING_802_1X_IDENTITY, value, NULL); g_free (value); } - ca_cert = svGetValueString (ifcfg, ca_cert_key); + ca_cert = svGetValueStr_cp (ifcfg, ca_cert_key); if (ca_cert) { - real_path = get_full_file_path (svFileGetName (ifcfg), ca_cert); + gs_free char *real_cert_value = NULL; + + real_cert_value = get_cert_value (svFileGetName (ifcfg), ca_cert, &scheme); if (phase2) { - if (!nm_setting_802_1x_set_phase2_ca_cert (s_8021x, - real_path, - NM_SETTING_802_1X_CK_SCHEME_PATH, - NULL, - error)) - goto done; + if (!nm_setting_802_1x_set_phase2_ca_cert (s_8021x, real_cert_value, scheme, NULL, error)) + return FALSE; } else { - if (!nm_setting_802_1x_set_ca_cert (s_8021x, - real_path, - NM_SETTING_802_1X_CK_SCHEME_PATH, - NULL, - error)) - goto done; + if (!nm_setting_802_1x_set_ca_cert (s_8021x, real_cert_value, scheme, NULL, error)) + return FALSE; + } + + if (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11) { + flags = read_secret_flags (ifcfg, ca_cert_pw_flags_key); + g_object_set (s_8021x, ca_cert_pw_flags_prop, flags, NULL); + + if (flags == NM_SETTING_SECRET_FLAG_NONE) { + ca_cert_password = svGetValueStr_cp (ifcfg, ca_cert_pw_key); + g_object_set (s_8021x, ca_cert_pw_prop, ca_cert_password, NULL); + } } - g_free (real_path); - real_path = NULL; } else { PARSE_WARNING ("missing %s for EAP method '%s'; this is insecure!", ca_cert_key, eap_method); @@ -2605,10 +2790,10 @@ eap_tls_reader (const char *eap_method, /* Read the private key password if it's system-owned */ if (flags == NM_SETTING_SECRET_FLAG_NONE) { /* Private key password */ - privkey_password = svGetValueString (ifcfg, pk_pw_key); + privkey_password = svGetValueStr_cp (ifcfg, pk_pw_key); if (!privkey_password && keys) { /* Try the lookaside keys file */ - privkey_password = svGetValueString (keys, pk_pw_key); + privkey_password = svGetValueStr_cp (keys, pk_pw_key); } if (!privkey_password) { @@ -2616,40 +2801,42 @@ eap_tls_reader (const char *eap_method, "Missing %s for EAP method '%s'.", pk_pw_key, eap_method); - goto done; + return FALSE; } } /* The private key itself */ - privkey = svGetValueString (ifcfg, pk_key); + privkey = svGetValueStr_cp (ifcfg, pk_key); if (!privkey) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Missing %s for EAP method '%s'.", pk_key, eap_method); - goto done; + return FALSE; } - real_path = get_full_file_path (svFileGetName (ifcfg), privkey); - if (phase2) { - if (!nm_setting_802_1x_set_phase2_private_key (s_8021x, - real_path, - privkey_password, - NM_SETTING_802_1X_CK_SCHEME_PATH, - &privkey_format, - error)) - goto done; - } else { - if (!nm_setting_802_1x_set_private_key (s_8021x, - real_path, - privkey_password, - NM_SETTING_802_1X_CK_SCHEME_PATH, - &privkey_format, - error)) - goto done; + { + gs_free char *real_cert_value = NULL; + + real_cert_value = get_cert_value (svFileGetName (ifcfg), privkey, &scheme); + if (phase2) { + if (!nm_setting_802_1x_set_phase2_private_key (s_8021x, + real_cert_value, + privkey_password, + scheme, + &privkey_format, + error)) + return FALSE; + } else { + if (!nm_setting_802_1x_set_private_key (s_8021x, + real_cert_value, + privkey_password, + scheme, + &privkey_format, + error)) + return FALSE; + } } - g_free (real_path); - real_path = NULL; /* Only set the client certificate if the private key is not PKCS#12 format, * as NM (due to supplicant restrictions) requires. If the key was PKCS#12, @@ -2658,44 +2845,39 @@ eap_tls_reader (const char *eap_method, */ if ( privkey_format == NM_SETTING_802_1X_CK_FORMAT_RAW_KEY || privkey_format == NM_SETTING_802_1X_CK_FORMAT_X509) { - client_cert = svGetValueString (ifcfg, cli_cert_key); + gs_free char *real_cert_value = NULL; + gs_free char *client_cert = NULL; + + client_cert = svGetValueStr_cp (ifcfg, cli_cert_key); if (!client_cert) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Missing %s for EAP method '%s'.", cli_cert_key, eap_method); - goto done; + return FALSE; } - real_path = get_full_file_path (svFileGetName (ifcfg), client_cert); + real_cert_value = get_cert_value (svFileGetName (ifcfg), client_cert, &scheme); if (phase2) { - if (!nm_setting_802_1x_set_phase2_client_cert (s_8021x, - real_path, - NM_SETTING_802_1X_CK_SCHEME_PATH, - NULL, - error)) - goto done; + if (!nm_setting_802_1x_set_phase2_client_cert (s_8021x, real_cert_value, scheme, NULL, error)) + return FALSE; } else { - if (!nm_setting_802_1x_set_client_cert (s_8021x, - real_path, - NM_SETTING_802_1X_CK_SCHEME_PATH, - NULL, - error)) - goto done; + if (!nm_setting_802_1x_set_client_cert (s_8021x, real_cert_value, scheme, NULL, error)) + return FALSE; } - g_free (real_path); - real_path = NULL; - } - success = TRUE; + if (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11) { + flags = read_secret_flags (ifcfg, cli_cert_pw_flags_key); + g_object_set (s_8021x, cli_cert_pw_flags_prop, flags, NULL); -done: - g_free (real_path); - g_free (ca_cert); - g_free (client_cert); - g_free (privkey); - g_free (privkey_password); - return success; + if (flags == NM_SETTING_SECRET_FLAG_NONE) { + client_cert_password = svGetValueStr_cp (ifcfg, cli_cert_pw_key); + g_object_set (s_8021x, cli_cert_pw_prop, client_cert_password, NULL); + } + } + } + + return TRUE; } static gboolean @@ -2708,28 +2890,25 @@ eap_peap_reader (const char *eap_method, { char *anon_ident = NULL; char *ca_cert = NULL; - char *real_cert_path = NULL; + char *real_cert_value = NULL; char *inner_auth = NULL; char *peapver = NULL; char *lower; char **list = NULL, **iter; gboolean success = FALSE; + NMSetting8021xCKScheme scheme; - ca_cert = svGetValueString (ifcfg, "IEEE_8021X_CA_CERT"); + ca_cert = svGetValueStr_cp (ifcfg, "IEEE_8021X_CA_CERT"); if (ca_cert) { - real_cert_path = get_full_file_path (svFileGetName (ifcfg), ca_cert); - if (!nm_setting_802_1x_set_ca_cert (s_8021x, - real_cert_path, - NM_SETTING_802_1X_CK_SCHEME_PATH, - NULL, - error)) + real_cert_value = get_cert_value (svFileGetName (ifcfg), ca_cert, &scheme); + if (!nm_setting_802_1x_set_ca_cert (s_8021x, real_cert_value, scheme, NULL, error)) goto done; } else { PARSE_WARNING ("missing IEEE_8021X_CA_CERT for EAP method '%s'; this is insecure!", eap_method); } - peapver = svGetValueString (ifcfg, "IEEE_8021X_PEAP_VERSION"); + peapver = svGetValueStr_cp (ifcfg, "IEEE_8021X_PEAP_VERSION"); if (peapver) { if (!strcmp (peapver, "0")) g_object_set (s_8021x, NM_SETTING_802_1X_PHASE1_PEAPVER, "0", NULL); @@ -2746,11 +2925,11 @@ eap_peap_reader (const char *eap_method, if (svGetValueBoolean (ifcfg, "IEEE_8021X_PEAP_FORCE_NEW_LABEL", FALSE)) g_object_set (s_8021x, NM_SETTING_802_1X_PHASE1_PEAPLABEL, "1", NULL); - anon_ident = svGetValueString (ifcfg, "IEEE_8021X_ANON_IDENTITY"); - if (anon_ident && strlen (anon_ident)) + anon_ident = svGetValueStr_cp (ifcfg, "IEEE_8021X_ANON_IDENTITY"); + if (anon_ident) g_object_set (s_8021x, NM_SETTING_802_1X_ANONYMOUS_IDENTITY, anon_ident, NULL); - inner_auth = svGetValueString (ifcfg, "IEEE_8021X_INNER_AUTH_METHODS"); + inner_auth = svGetValueStr_cp (ifcfg, "IEEE_8021X_INNER_AUTH_METHODS"); if (!inner_auth) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Missing IEEE_8021X_INNER_AUTH_METHODS."); @@ -2797,7 +2976,7 @@ done: g_strfreev (list); g_free (inner_auth); g_free (peapver); - g_free (real_cert_path); + g_free (real_cert_value); g_free (ca_cert); g_free (anon_ident); return success; @@ -2814,30 +2993,27 @@ eap_ttls_reader (const char *eap_method, gboolean success = FALSE; char *anon_ident = NULL; char *ca_cert = NULL; - char *real_cert_path = NULL; + char *real_cert_value = NULL; char *inner_auth = NULL; char *tmp; char **list = NULL, **iter; + NMSetting8021xCKScheme scheme; - ca_cert = svGetValueString (ifcfg, "IEEE_8021X_CA_CERT"); + ca_cert = svGetValueStr_cp (ifcfg, "IEEE_8021X_CA_CERT"); if (ca_cert) { - real_cert_path = get_full_file_path (svFileGetName (ifcfg), ca_cert); - if (!nm_setting_802_1x_set_ca_cert (s_8021x, - real_cert_path, - NM_SETTING_802_1X_CK_SCHEME_PATH, - NULL, - error)) + real_cert_value = get_cert_value (svFileGetName (ifcfg), ca_cert, &scheme); + if (!nm_setting_802_1x_set_ca_cert (s_8021x, real_cert_value, scheme, NULL, error)) goto done; } else { PARSE_WARNING ("missing IEEE_8021X_CA_CERT for EAP method '%s'; this is insecure!", eap_method); } - anon_ident = svGetValueString (ifcfg, "IEEE_8021X_ANON_IDENTITY"); - if (anon_ident && strlen (anon_ident)) + anon_ident = svGetValueStr_cp (ifcfg, "IEEE_8021X_ANON_IDENTITY"); + if (anon_ident) g_object_set (s_8021x, NM_SETTING_802_1X_ANONYMOUS_IDENTITY, anon_ident, NULL); - tmp = svGetValueString (ifcfg, "IEEE_8021X_INNER_AUTH_METHODS"); + tmp = svGetValueStr_cp (ifcfg, "IEEE_8021X_INNER_AUTH_METHODS"); if (!tmp) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Missing IEEE_8021X_INNER_AUTH_METHODS."); @@ -2885,7 +3061,7 @@ done: if (list) g_strfreev (list); g_free (inner_auth); - g_free (real_cert_path); + g_free (real_cert_value); g_free (ca_cert); g_free (anon_ident); return success; @@ -2906,17 +3082,17 @@ eap_fast_reader (const char *eap_method, char *fast_provisioning = NULL; char *lower; char **list = NULL, **iter; - const char* pac_prov_str; + const char *pac_prov_str; gboolean allow_unauth = FALSE, allow_auth = FALSE; gboolean success = FALSE; - pac_file = svGetValueString (ifcfg, "IEEE_8021X_PAC_FILE"); + pac_file = svGetValueStr_cp (ifcfg, "IEEE_8021X_PAC_FILE"); if (pac_file) { real_pac_path = get_full_file_path (svFileGetName (ifcfg), pac_file); g_object_set (s_8021x, NM_SETTING_802_1X_PAC_FILE, real_pac_path, NULL); } - fast_provisioning = svGetValueString (ifcfg, "IEEE_8021X_FAST_PROVISIONING"); + fast_provisioning = svGetValueStr_cp (ifcfg, "IEEE_8021X_FAST_PROVISIONING"); if (fast_provisioning) { list = g_strsplit_set (fast_provisioning, " \t", 0); for (iter = list; iter && *iter; iter++) { @@ -2944,11 +3120,11 @@ eap_fast_reader (const char *eap_method, goto done; } - anon_ident = svGetValueString (ifcfg, "IEEE_8021X_ANON_IDENTITY"); - if (anon_ident && strlen (anon_ident)) + anon_ident = svGetValueStr_cp (ifcfg, "IEEE_8021X_ANON_IDENTITY"); + if (anon_ident) g_object_set (s_8021x, NM_SETTING_802_1X_ANONYMOUS_IDENTITY, anon_ident, NULL); - inner_auth = svGetValueString (ifcfg, "IEEE_8021X_INNER_AUTH_METHODS"); + inner_auth = svGetValueStr_cp (ifcfg, "IEEE_8021X_INNER_AUTH_METHODS"); if (!inner_auth) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Missing IEEE_8021X_INNER_AUTH_METHODS."); @@ -2998,12 +3174,12 @@ done: typedef struct { const char *method; - gboolean (*reader)(const char *eap_method, - shvarFile *ifcfg, - shvarFile *keys, - NMSetting8021x *s_8021x, - gboolean phase2, - GError **error); + gboolean (*reader) (const char *eap_method, + shvarFile *ifcfg, + shvarFile *keys, + NMSetting8021x *s_8021x, + gboolean phase2, + GError **error); gboolean wifi_phase2_only; } EAPReader; @@ -3035,7 +3211,7 @@ read_8021x_list_value (shvarFile *ifcfg, g_return_if_fail (ifcfg_var_name != NULL); g_return_if_fail (prop_name != NULL); - value = svGetValueString (ifcfg, ifcfg_var_name); + value = svGetValueStr_cp (ifcfg, ifcfg_var_name); if (!value) return; @@ -3053,12 +3229,13 @@ fill_8021x (shvarFile *ifcfg, gboolean wifi, GError **error) { + nm_auto_shvar_file_close shvarFile *keys = NULL; NMSetting8021x *s_8021x; - shvarFile *keys = NULL; char *value; char **list = NULL, **iter; + gint64 timeout; - value = svGetValueString (ifcfg, "IEEE_8021X_EAP_METHODS"); + value = svGetValueStr_cp (ifcfg, "IEEE_8021X_EAP_METHODS"); if (!value) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Missing IEEE_8021X_EAP_METHODS for key management '%s'", @@ -3104,7 +3281,7 @@ fill_8021x (shvarFile *ifcfg, found = TRUE; break; - next: +next: eap++; } @@ -3119,37 +3296,54 @@ fill_8021x (shvarFile *ifcfg, goto error; } - value = svGetValueString (ifcfg, "IEEE_8021X_SUBJECT_MATCH"); + value = svGetValueStr_cp (ifcfg, "IEEE_8021X_SUBJECT_MATCH"); g_object_set (s_8021x, NM_SETTING_802_1X_SUBJECT_MATCH, value, NULL); g_free (value); - value = svGetValueString (ifcfg, "IEEE_8021X_PHASE2_SUBJECT_MATCH"); + value = svGetValueStr_cp (ifcfg, "IEEE_8021X_PHASE2_SUBJECT_MATCH"); g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_SUBJECT_MATCH, value, NULL); g_free (value); + value = svGetValueStr_cp (ifcfg, "IEEE_8021X_PHASE1_AUTH_FLAGS"); + if (value) { + NMSetting8021xAuthFlags flags; + char *token; + + if (nm_utils_enum_from_str (nm_setting_802_1x_auth_flags_get_type (), value, + (int *) &flags, &token)) { + g_object_set (s_8021x, NM_SETTING_802_1X_PHASE1_AUTH_FLAGS, flags, NULL); + } else { + g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, + "Invalid IEEE_8021X_PHASE1_AUTH_FLAGS flag '%s'", token); + g_free (token); + g_free (value); + goto error; + } + g_free (value); + } + read_8021x_list_value (ifcfg, "IEEE_8021X_ALTSUBJECT_MATCHES", s_8021x, NM_SETTING_802_1X_ALTSUBJECT_MATCHES); read_8021x_list_value (ifcfg, "IEEE_8021X_PHASE2_ALTSUBJECT_MATCHES", s_8021x, NM_SETTING_802_1X_PHASE2_ALTSUBJECT_MATCHES); - value = svGetValueString (ifcfg, "IEEE_8021X_DOMAIN_SUFFIX_MATCH"); + value = svGetValueStr_cp (ifcfg, "IEEE_8021X_DOMAIN_SUFFIX_MATCH"); g_object_set (s_8021x, NM_SETTING_802_1X_DOMAIN_SUFFIX_MATCH, value, NULL); g_free (value); - value = svGetValueString (ifcfg, "IEEE_8021X_PHASE2_DOMAIN_SUFFIX_MATCH"); + value = svGetValueStr_cp (ifcfg, "IEEE_8021X_PHASE2_DOMAIN_SUFFIX_MATCH"); g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_DOMAIN_SUFFIX_MATCH, value, NULL); g_free (value); + timeout = svGetValueInt64 (ifcfg, "IEEE_8021X_AUTH_TIMEOUT", 10, 0, G_MAXINT32, 0); + g_object_set (s_8021x, NM_SETTING_802_1X_AUTH_TIMEOUT, (gint32) timeout, NULL); + if (list) g_strfreev (list); - if (keys) - svCloseFile (keys); return s_8021x; error: if (list) g_strfreev (list); - if (keys) - svCloseFile (keys); g_object_unref (s_8021x); return NULL; } @@ -3168,7 +3362,7 @@ make_wpa_setting (shvarFile *ifcfg, wsec = NM_SETTING_WIRELESS_SECURITY (nm_setting_wireless_security_new ()); - value = svGetValueString (ifcfg, "KEY_MGMT"); + value = svGetValueStr_cp (ifcfg, "KEY_MGMT"); wpa_psk = !g_strcmp0 (value, "WPA-PSK"); wpa_eap = !g_strcmp0 (value, "WPA-EAP"); ieee8021x = !g_strcmp0 (value, "IEEE8021X"); @@ -3188,8 +3382,8 @@ make_wpa_setting (shvarFile *ifcfg, } else { char *allow_wpa, *allow_rsn; - allow_wpa = svGetValueString (ifcfg, "WPA_ALLOW_WPA"); - allow_rsn = svGetValueString (ifcfg, "WPA_ALLOW_WPA2"); + allow_wpa = svGetValueStr_cp (ifcfg, "WPA_ALLOW_WPA"); + allow_rsn = svGetValueStr_cp (ifcfg, "WPA_ALLOW_WPA2"); if (allow_wpa && svGetValueBoolean (ifcfg, "WPA_ALLOW_WPA", TRUE)) nm_setting_wireless_security_add_proto (wsec, "wpa"); @@ -3243,7 +3437,7 @@ make_wpa_setting (shvarFile *ifcfg, g_free (value); - value = svGetValueString (ifcfg, "SECURITYMODE"); + value = svGetValueStr_cp (ifcfg, "SECURITYMODE"); if (NM_IN_STRSET (value, NULL, "open")) g_object_set (wsec, NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, value, NULL); @@ -3269,12 +3463,12 @@ make_leap_setting (shvarFile *ifcfg, wsec = NM_SETTING_WIRELESS_SECURITY (nm_setting_wireless_security_new ()); - value = svGetValueString (ifcfg, "KEY_MGMT"); + value = svGetValueStr_cp (ifcfg, "KEY_MGMT"); if (!value || strcmp (value, "IEEE8021X")) goto error; /* Not LEAP */ g_free (value); - value = svGetValueString (ifcfg, "SECURITYMODE"); + value = svGetValueStr_cp (ifcfg, "SECURITYMODE"); if (!value || strcasecmp (value, "leap")) goto error; /* Not LEAP */ @@ -3285,12 +3479,12 @@ make_leap_setting (shvarFile *ifcfg, /* Read LEAP password if it's system-owned */ if (flags == NM_SETTING_SECRET_FLAG_NONE) { - value = svGetValueString (ifcfg, "IEEE_8021X_PASSWORD"); + value = svGetValueStr_cp (ifcfg, "IEEE_8021X_PASSWORD"); if (!value) { /* Try to get keys from the "shadow" key file */ keys_ifcfg = utils_get_keys_ifcfg (file, FALSE); if (keys_ifcfg) { - value = svGetValueString (keys_ifcfg, "IEEE_8021X_PASSWORD"); + value = svGetValueStr_cp (keys_ifcfg, "IEEE_8021X_PASSWORD"); svCloseFile (keys_ifcfg); } } @@ -3299,8 +3493,8 @@ make_leap_setting (shvarFile *ifcfg, g_free (value); } - value = svGetValueString (ifcfg, "IEEE_8021X_IDENTITY"); - if (!value || !strlen (value)) { + value = svGetValueStr_cp (ifcfg, "IEEE_8021X_IDENTITY"); + if (!value) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Missing LEAP identity"); goto error; @@ -3392,25 +3586,25 @@ make_wireless_setting (shvarFile *ifcfg, s_wireless = NM_SETTING_WIRELESS (nm_setting_wireless_new ()); - value = svGetValueString (ifcfg, "HWADDR"); + value = svGetValueStr_cp (ifcfg, "HWADDR"); if (value) { value = g_strstrip (value); g_object_set (s_wireless, NM_SETTING_WIRELESS_MAC_ADDRESS, value, NULL); g_free (value); } - value = svGetValueString (ifcfg, "MACADDR"); + value = svGetValueStr_cp (ifcfg, "MACADDR"); if (value) { value = g_strstrip (value); g_object_set (s_wireless, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, value, NULL); g_free (value); } - value = svGetValueString (ifcfg, "GENERATE_MAC_ADDRESS_MASK"); + value = svGetValueStr_cp (ifcfg, "GENERATE_MAC_ADDRESS_MASK"); g_object_set (s_wireless, NM_SETTING_WIRELESS_GENERATE_MAC_ADDRESS_MASK, value, NULL); g_free (value); - value = svGetValueString (ifcfg, "HWADDR_BLACKLIST"); + value = svGetValueStr_cp (ifcfg, "HWADDR_BLACKLIST"); if (value) { char **strv; @@ -3420,7 +3614,7 @@ make_wireless_setting (shvarFile *ifcfg, g_free (value); } - value = svGetValueString (ifcfg, "ESSID"); + value = svGetValueStr_cp (ifcfg, "ESSID"); if (value) { gs_unref_bytes GBytes *bytes = NULL; gsize ssid_len = 0; @@ -3449,7 +3643,7 @@ make_wireless_setting (shvarFile *ifcfg, g_free (value); } - value = svGetValueString (ifcfg, "MODE"); + value = svGetValueStr_cp (ifcfg, "MODE"); if (value) { char *lcase; const char *mode = NULL; @@ -3475,14 +3669,14 @@ make_wireless_setting (shvarFile *ifcfg, g_object_set (s_wireless, NM_SETTING_WIRELESS_MODE, mode, NULL); } - value = svGetValueString (ifcfg, "BSSID"); + value = svGetValueStr_cp (ifcfg, "BSSID"); if (value) { value = g_strstrip (value); g_object_set (s_wireless, NM_SETTING_WIRELESS_BSSID, value, NULL); g_free (value); } - value = svGetValueString (ifcfg, "CHANNEL"); + value = svGetValueStr_cp (ifcfg, "CHANNEL"); if (value) { errno = 0; chan = _nm_utils_ascii_str_to_int64 (value, 10, 1, 196, 0); @@ -3496,7 +3690,7 @@ make_wireless_setting (shvarFile *ifcfg, g_free (value); } - value = svGetValueString (ifcfg, "BAND"); + value = svGetValueStr_cp (ifcfg, "BAND"); if (value) { if (!strcmp (value, "a")) { if (chan && chan <= 14) { @@ -3527,7 +3721,7 @@ make_wireless_setting (shvarFile *ifcfg, g_object_set (s_wireless, NM_SETTING_WIRELESS_BAND, "bg", NULL); } - value = svGetValueString (ifcfg, "MTU"); + value = svGetValueStr_cp (ifcfg, "MTU"); if (value) { int mtu; @@ -3637,7 +3831,7 @@ wireless_connection_from_ifcfg (const char *file, printable_ssid = nm_utils_ssid_to_utf8 (g_bytes_get_data (ssid, NULL), g_bytes_get_size (ssid)); } else - printable_ssid = g_strdup_printf ("unmanaged"); + printable_ssid = g_strdup ("unmanaged"); mode = nm_setting_wireless_get_mode (NM_SETTING_WIRELESS (wireless_setting)); if (mode && !strcmp (mode, "adhoc")) @@ -3856,7 +4050,7 @@ parse_ethtool_options (shvarFile *ifcfg, NMSettingWired *s_wired, const char *va } /* ETHTOOL_WAKE_ON_LAN = ignore overrides WoL settings in ETHTOOL_OPTS */ - wol_value = svGetValueString (ifcfg, "ETHTOOL_WAKE_ON_LAN"); + wol_value = svGetValueStr_cp (ifcfg, "ETHTOOL_WAKE_ON_LAN"); if (wol_value) { if (strcmp (wol_value, "ignore") == 0) wol_flags = NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE; @@ -3891,7 +4085,7 @@ make_wired_setting (shvarFile *ifcfg, s_wired = NM_SETTING_WIRED (nm_setting_wired_new ()); - value = svGetValueString (ifcfg, "MTU"); + value = svGetValueStr_cp (ifcfg, "MTU"); if (value) { int mtu; @@ -3903,14 +4097,14 @@ make_wired_setting (shvarFile *ifcfg, g_free (value); } - value = svGetValueString (ifcfg, "HWADDR"); + value = svGetValueStr_cp (ifcfg, "HWADDR"); if (value) { value = g_strstrip (value); g_object_set (s_wired, NM_SETTING_WIRED_MAC_ADDRESS, value, NULL); g_free (value); } - value = svGetValueString (ifcfg, "SUBCHANNELS"); + value = svGetValueStr_cp (ifcfg, "SUBCHANNELS"); if (value) { const char *p = value; gboolean success = TRUE; @@ -3941,28 +4135,29 @@ make_wired_setting (shvarFile *ifcfg, g_free (value); } - value = svGetValueString (ifcfg, "PORTNAME"); - if (value && strlen (value)) { + value = svGetValueStr_cp (ifcfg, "PORTNAME"); + if (value) { nm_setting_wired_add_s390_option (s_wired, "portname", value); + g_free (value); } - g_free (value); - value = svGetValueString (ifcfg, "CTCPROT"); - if (value && strlen (value)) + value = svGetValueStr_cp (ifcfg, "CTCPROT"); + if (value) { nm_setting_wired_add_s390_option (s_wired, "ctcprot", value); - g_free (value); + g_free (value); + } - nettype = svGetValueString (ifcfg, "NETTYPE"); - if (nettype && strlen (nettype)) { + nettype = svGetValueStr_cp (ifcfg, "NETTYPE"); + if (nettype) { if (!strcmp (nettype, "qeth") || !strcmp (nettype, "lcs") || !strcmp (nettype, "ctc")) g_object_set (s_wired, NM_SETTING_WIRED_S390_NETTYPE, nettype, NULL); else PARSE_WARNING ("unknown s390 NETTYPE '%s'", nettype); + g_free (nettype); } - g_free (nettype); - value = svGetValueString (ifcfg, "OPTIONS"); - if (value && strlen (value)) { + value = svGetValueStr_cp (ifcfg, "OPTIONS"); + if (value) { char **options, **iter; iter = options = g_strsplit_set (value, " ", 0); @@ -3979,21 +4174,21 @@ make_wired_setting (shvarFile *ifcfg, iter++; } g_strfreev (options); + g_free (value); } - g_free (value); - value = svGetValueString (ifcfg, "MACADDR"); + value = svGetValueStr_cp (ifcfg, "MACADDR"); if (value) { value = g_strstrip (value); g_object_set (s_wired, NM_SETTING_WIRED_CLONED_MAC_ADDRESS, value, NULL); g_free (value); } - value = svGetValueString (ifcfg, "GENERATE_MAC_ADDRESS_MASK"); + value = svGetValueStr_cp (ifcfg, "GENERATE_MAC_ADDRESS_MASK"); g_object_set (s_wired, NM_SETTING_WIRED_GENERATE_MAC_ADDRESS_MASK, value, NULL); g_free (value); - value = svGetValueString (ifcfg, "HWADDR_BLACKLIST"); + value = svGetValueStr_cp (ifcfg, "HWADDR_BLACKLIST"); if (value) { char **strv; @@ -4003,7 +4198,7 @@ make_wired_setting (shvarFile *ifcfg, g_free (value); } - value = svGetValueString (ifcfg, "KEY_MGMT"); + value = svGetValueStr_cp (ifcfg, "KEY_MGMT"); if (value) { if (!strcmp (value, "IEEE8021X")) { *s_8021x = fill_8021x (ifcfg, file, value, FALSE, error); @@ -4078,19 +4273,19 @@ parse_infiniband_p_key (shvarFile *ifcfg, int id; gboolean ret = FALSE; - device = svGetValueString (ifcfg, "DEVICE"); + device = svGetValueStr_cp (ifcfg, "DEVICE"); if (!device) { PARSE_WARNING ("InfiniBand connection specified PKEY but not DEVICE"); goto done; } - physdev = svGetValueString (ifcfg, "PHYSDEV"); + physdev = svGetValueStr_cp (ifcfg, "PHYSDEV"); if (!physdev) { PARSE_WARNING ("InfiniBand connection specified PKEY but not PHYSDEV"); goto done; } - pkey_id = svGetValueString (ifcfg, "PKEY_ID"); + pkey_id = svGetValueStr_cp (ifcfg, "PKEY_ID"); if (!pkey_id) { PARSE_WARNING ("InfiniBand connection specified PKEY but not PKEY_ID"); goto done; @@ -4138,7 +4333,7 @@ make_infiniband_setting (shvarFile *ifcfg, s_infiniband = NM_SETTING_INFINIBAND (nm_setting_infiniband_new ()); - value = svGetValueString (ifcfg, "MTU"); + value = svGetValueStr_cp (ifcfg, "MTU"); if (value) { int mtu; @@ -4150,7 +4345,7 @@ make_infiniband_setting (shvarFile *ifcfg, g_free (value); } - value = svGetValueString (ifcfg, "HWADDR"); + value = svGetValueStr_cp (ifcfg, "HWADDR"); if (value) { value = g_strstrip (value); g_object_set (s_infiniband, NM_SETTING_INFINIBAND_MAC_ADDRESS, value, NULL); @@ -4248,17 +4443,17 @@ make_bond_setting (shvarFile *ifcfg, NMSettingBond *s_bond; char *value; - s_bond = NM_SETTING_BOND (nm_setting_bond_new ()); - - value = svGetValueString (ifcfg, "DEVICE"); - if (!value || !strlen (value)) { + value = svGetValueStr_cp (ifcfg, "DEVICE"); + if (!value) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "mandatory DEVICE keyword missing"); - goto error; + return NULL; } g_free (value); - value = svGetValueString (ifcfg, "BONDING_OPTS"); + s_bond = NM_SETTING_BOND (nm_setting_bond_new ()); + + value = svGetValueStr_cp (ifcfg, "BONDING_OPTS"); if (value) { char **items, **iter; @@ -4271,7 +4466,7 @@ make_bond_setting (shvarFile *ifcfg, if (keys && *keys) { key = *keys; val = *(keys + 1); - if (val && strlen(key) && strlen(val)) + if (val && key[0] && val[0]) handle_bond_option (s_bond, key, val); } @@ -4283,10 +4478,6 @@ make_bond_setting (shvarFile *ifcfg, } return (NMSetting *) s_bond; - -error: - g_object_unref (s_bond); - return NULL; } static NMConnection * @@ -4342,7 +4533,7 @@ read_team_config (shvarFile *ifcfg, const char *key, GError **error) gs_free char *value = NULL; size_t l; - value = svGetValueString (ifcfg, key); + value = svGetValueStr_cp (ifcfg, key); if (!value) return NULL; @@ -4370,29 +4561,26 @@ make_team_setting (shvarFile *ifcfg, char *value; GError *local_err = NULL; - s_team = NM_SETTING_TEAM (nm_setting_team_new ()); - - value = svGetValueString (ifcfg, "DEVICE"); - if (!value || !strlen (value)) { + value = svGetValueStr_cp (ifcfg, "DEVICE"); + if (!value) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "mandatory DEVICE keyword missing"); - goto error; + return NULL; } g_free (value); value = read_team_config (ifcfg, "TEAM_CONFIG", &local_err); if (local_err) { g_propagate_error (error, local_err); - goto error; + return NULL; } + + s_team = NM_SETTING_TEAM (nm_setting_team_new ()); + g_object_set (s_team, NM_SETTING_TEAM_CONFIG, value, NULL); g_free (value); return (NMSetting *) s_team; - -error: - g_object_unref (s_team); - return NULL; } static NMConnection * @@ -4454,23 +4642,23 @@ handle_bridge_option (NMSetting *setting, guint32 u = 0; if (!strcmp (key, "priority")) { - if (stp == FALSE) { + if (stp == FALSE) PARSE_WARNING ("'priority' invalid when STP is disabled"); - } else if (get_uint (value, &u)) + else if (get_uint (value, &u)) g_object_set (setting, NM_SETTING_BRIDGE_PRIORITY, u, NULL); else PARSE_WARNING ("invalid priority value '%s'", value); } else if (!strcmp (key, "hello_time")) { - if (stp == FALSE) { + if (stp == FALSE) PARSE_WARNING ("'hello_time' invalid when STP is disabled"); - } else if (get_uint (value, &u)) + else if (get_uint (value, &u)) g_object_set (setting, NM_SETTING_BRIDGE_HELLO_TIME, u, NULL); else PARSE_WARNING ("invalid hello_time value '%s'", value); } else if (!strcmp (key, "max_age")) { - if (stp == FALSE) { + if (stp == FALSE) PARSE_WARNING ("'max_age' invalid when STP is disabled"); - } else if (get_uint (value, &u)) + else if (get_uint (value, &u)) g_object_set (setting, NM_SETTING_BRIDGE_MAX_AGE, u, NULL); else PARSE_WARNING ("invalid max_age value '%s'", value); @@ -4506,7 +4694,7 @@ handle_bridging_opts (NMSetting *setting, if (keys && *keys) { key = *keys; val = *(keys + 1); - if (val && strlen(key) && strlen(val)) + if (val && strlen (key) && strlen (val)) func (setting, stp, key, val); } @@ -4527,24 +4715,24 @@ make_bridge_setting (shvarFile *ifcfg, gboolean stp = FALSE; gboolean stp_set = FALSE; - s_bridge = NM_SETTING_BRIDGE (nm_setting_bridge_new ()); - - value = svGetValueString (ifcfg, "DEVICE"); - if (!value || !strlen (value)) { + value = svGetValueStr_cp (ifcfg, "DEVICE"); + if (!value) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "mandatory DEVICE keyword missing"); - goto error; + return NULL; } g_free (value); - value = svGetValueString (ifcfg, "MACADDR"); + s_bridge = NM_SETTING_BRIDGE (nm_setting_bridge_new ()); + + value = svGetValueStr_cp (ifcfg, "MACADDR"); if (value) { value = g_strstrip (value); g_object_set (s_bridge, NM_SETTING_BRIDGE_MAC_ADDRESS, value, NULL); g_free (value); } - value = svGetValueString (ifcfg, "STP"); + value = svGetValueStr_cp (ifcfg, "STP"); if (value) { if (!strcasecmp (value, "on") || !strcasecmp (value, "yes")) { g_object_set (s_bridge, NM_SETTING_BRIDGE_STP, TRUE, NULL); @@ -4563,7 +4751,7 @@ make_bridge_setting (shvarFile *ifcfg, g_object_set (s_bridge, NM_SETTING_BRIDGE_STP, FALSE, NULL); } - value = svGetValueString (ifcfg, "DELAY"); + value = svGetValueStr_cp (ifcfg, "DELAY"); if (value) { if (stp) { if (get_uint (value, &u)) @@ -4575,17 +4763,13 @@ make_bridge_setting (shvarFile *ifcfg, g_free (value); } - value = svGetValueString (ifcfg, "BRIDGING_OPTS"); + value = svGetValueStr_cp (ifcfg, "BRIDGING_OPTS"); if (value) { handle_bridging_opts (NM_SETTING (s_bridge), stp, value, handle_bridge_option); g_free (value); } return (NMSetting *) s_bridge; - -error: - g_object_unref (s_bridge); - return NULL; } static NMConnection * @@ -4616,7 +4800,7 @@ bridge_connection_from_ifcfg (const char *file, g_object_unref (connection); return NULL; } - nm_connection_add_setting (connection, bridge_setting); + nm_connection_add_setting (connection, bridge_setting); return connection; } @@ -4658,14 +4842,14 @@ make_bridge_port_setting (shvarFile *ifcfg) g_return_val_if_fail (ifcfg != NULL, FALSE); - value = svGetValueString (ifcfg, "BRIDGE_UUID"); + value = svGetValueStr_cp (ifcfg, "BRIDGE_UUID"); if (!value) - value = svGetValueString (ifcfg, "BRIDGE"); + value = svGetValueStr_cp (ifcfg, "BRIDGE"); if (value) { g_free (value); s_port = nm_setting_bridge_port_new (); - value = svGetValueString (ifcfg, "BRIDGING_OPTS"); + value = svGetValueStr_cp (ifcfg, "BRIDGING_OPTS"); if (value) handle_bridging_opts (s_port, FALSE, value, handle_bridge_port_option); g_free (value); @@ -4742,7 +4926,7 @@ parse_prio_map_list (NMSettingVlan *s_vlan, char *value; gchar **list = NULL, **iter; - value = svGetValueString (ifcfg, key); + value = svGetValueStr_cp (ifcfg, key); if (!value) return; @@ -4764,16 +4948,16 @@ make_vlan_setting (shvarFile *ifcfg, const char *file, GError **error) { - NMSettingVlan *s_vlan = NULL; + gs_unref_object NMSettingVlan *s_vlan = NULL; + gs_free char *parent = NULL; + gs_free char *iface_name = NULL; char *value = NULL; - char *iface_name = NULL; - char *parent = NULL; const char *p = NULL; int vlan_id = -1; guint32 vlan_flags = 0; gint gvrp, reorder_hdr; - value = svGetValueString (ifcfg, "VLAN_ID"); + value = svGetValueStr_cp (ifcfg, "VLAN_ID"); if (value) { vlan_id = _nm_utils_ascii_str_to_int64 (value, 10, 0, 4095, -1); if (vlan_id == -1) { @@ -4786,7 +4970,7 @@ make_vlan_setting (shvarFile *ifcfg, } /* Need DEVICE if we don't have a separate VLAN_ID property */ - iface_name = svGetValueString (ifcfg, "DEVICE"); + iface_name = svGetValueStr_cp (ifcfg, "DEVICE"); if (!iface_name && vlan_id < 0) { g_set_error_literal (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Missing DEVICE property; cannot determine VLAN ID."); @@ -4796,7 +4980,7 @@ make_vlan_setting (shvarFile *ifcfg, s_vlan = NM_SETTING_VLAN (nm_setting_vlan_new ()); /* Parent interface from PHYSDEV takes precedence if it exists */ - parent = svGetValueString (ifcfg, "PHYSDEV"); + parent = svGetValueStr_cp (ifcfg, "PHYSDEV"); if (iface_name) { p = strchr (iface_name, '.'); @@ -4808,8 +4992,7 @@ make_vlan_setting (shvarFile *ifcfg, /* Like initscripts, if no PHYSDEV and we get an obviously * invalid parent interface from DEVICE, fail. */ - g_free (parent); - parent = NULL; + nm_clear_g_free (&parent); } } p++; @@ -4834,17 +5017,16 @@ make_vlan_setting (shvarFile *ifcfg, if (vlan_id < 0) { g_set_error_literal (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Failed to determine VLAN ID from DEVICE or VLAN_ID."); - goto error; + return NULL; } g_object_set (s_vlan, NM_SETTING_VLAN_ID, vlan_id, NULL); if (parent == NULL) { g_set_error_literal (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Failed to determine VLAN parent from DEVICE or PHYSDEV"); - goto error; + return NULL; } g_object_set (s_vlan, NM_SETTING_VLAN_PARENT, parent, NULL); - g_clear_pointer (&parent, g_free); vlan_flags |= NM_VLAN_FLAG_REORDER_HEADERS; @@ -4852,7 +5034,7 @@ make_vlan_setting (shvarFile *ifcfg, if (gvrp > 0) vlan_flags |= NM_VLAN_FLAG_GVRP; - value = svGetValueString (ifcfg, "VLAN_FLAGS"); + value = svGetValueStr_cp (ifcfg, "VLAN_FLAGS"); if (value) { gs_strfreev char **strv = NULL; char **ptr; @@ -4883,15 +5065,7 @@ make_vlan_setting (shvarFile *ifcfg, parse_prio_map_list (s_vlan, ifcfg, "VLAN_INGRESS_PRIORITY_MAP", NM_VLAN_INGRESS_MAP); parse_prio_map_list (s_vlan, ifcfg, "VLAN_EGRESS_PRIORITY_MAP", NM_VLAN_EGRESS_MAP); - g_free (iface_name); - - return (NMSetting *) s_vlan; - -error: - g_free (parent); - g_free (iface_name); - g_object_unref (s_vlan); - return NULL; + return g_steal_pointer (&s_vlan); } static NMConnection * @@ -4963,7 +5137,7 @@ create_unhandled_connection (const char *filename, shvarFile *ifcfg, nm_connection_add_setting (connection, nm_setting_generic_new ()); /* Get a spec */ - value = svGetValueString (ifcfg, "HWADDR"); + value = svGetValueStr_cp (ifcfg, "HWADDR"); if (value) { char *lower = g_ascii_strdown (value, -1); *out_spec = g_strdup_printf ("%s:mac:%s", type, lower); @@ -4972,14 +5146,14 @@ create_unhandled_connection (const char *filename, shvarFile *ifcfg, return connection; } - value = svGetValueString (ifcfg, "SUBCHANNELS"); + value = svGetValueStr_cp (ifcfg, "SUBCHANNELS"); if (value) { *out_spec = g_strdup_printf ("%s:s390-subchannels:%s", type, value); g_free (value); return connection; } - value = svGetValueString (ifcfg, "DEVICE"); + value = svGetValueStr_cp (ifcfg, "DEVICE"); if (value) { *out_spec = g_strdup_printf ("%s:interface-name:%s", type, value); g_free (value); @@ -5008,11 +5182,9 @@ uuid_from_file (const char *filename) return NULL; /* Try for a UUID key before falling back to hashing the file name */ - uuid = svGetValueString (ifcfg, "UUID"); - if (!uuid || !strlen (uuid)) { - g_free (uuid); + uuid = svGetValueStr_cp (ifcfg, "UUID"); + if (!uuid) uuid = nm_utils_uuid_generate_from_string (svFileGetName (ifcfg), -1, NM_UTILS_UUID_TYPE_LEGACY, NULL); - } svCloseFile (ifcfg); return uuid; @@ -5029,7 +5201,8 @@ check_dns_search_domains (shvarFile *ifcfg, NMSetting *s_ip4, NMSetting *s_ip6) */ if (!s_ip4 || nm_setting_ip_config_get_num_dns_searches (NM_SETTING_IP_CONFIG (s_ip4)) == 0) { /* DNS searches */ - char *value = svGetValueString (ifcfg, "DOMAIN"); + char *value = svGetValueStr_cp (ifcfg, "DOMAIN"); + if (value) { char **searches = g_strsplit (value, " ", 0); if (searches) { @@ -5055,12 +5228,13 @@ connection_from_file_full (const char *filename, GError **error, gboolean *out_ignore_error) { - NMConnection *connection = NULL; - shvarFile *parsed; + nm_auto_shvar_file_close shvarFile *parsed = NULL; + gs_unref_object NMConnection *connection = NULL; gs_free char *type = NULL; char *devtype, *bootproto; - NMSetting *s_ip4, *s_ip6, *s_proxy, *s_port, *s_dcb = NULL; + NMSetting *s_ip4, *s_ip6, *s_proxy, *s_port, *s_dcb = NULL, *s_user; const char *ifcfg_name = NULL; + gboolean has_ip4_defroute = FALSE; g_return_val_if_fail (filename != NULL, NULL); g_return_val_if_fail (out_unhandled && !*out_unhandled, NULL); @@ -5082,30 +5256,38 @@ connection_from_file_full (const char *filename, if (!svGetValueBoolean (parsed, "NM_CONTROLLED", TRUE)) { connection = create_unhandled_connection (filename, parsed, "unmanaged", out_unhandled); - if (!connection) + if (!connection) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED, "NM_CONTROLLED was false but device was not uniquely identified; device will be managed"); - goto done; + } + return g_steal_pointer (&connection); } /* iBFT is handled by the iBFT settings plugin */ - bootproto = svGetValueString (parsed, "BOOTPROTO"); + bootproto = svGetValueStr_cp (parsed, "BOOTPROTO"); if (bootproto && !g_ascii_strcasecmp (bootproto, "ibft")) { if (out_ignore_error) *out_ignore_error = TRUE; g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Ignoring iBFT configuration"); g_free (bootproto); - goto done; + return NULL; } g_free (bootproto); - devtype = svGetValueString (parsed, "DEVICETYPE"); + devtype = svGetValueStr_cp (parsed, "DEVICETYPE"); 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) { @@ -5114,33 +5296,32 @@ connection_from_file_full (const char *filename, /* Team and TeamPort types are also accepted by the mere * presense of TEAM_CONFIG/TEAM_MASTER. They don't require * DEVICETYPE. */ - t = svGetValueString (parsed, "TEAM_CONFIG"); + t = svGetValueStr_cp (parsed, "TEAM_CONFIG"); if (t) type = g_strdup (TYPE_TEAM); } if (!type) - type = svGetValueString (parsed, "TYPE"); + type = svGetValueStr_cp (parsed, "TYPE"); if (!type) { gs_free char *tmp = NULL; char *device; - if ((tmp = svGetValueString (parsed, "IPV6TUNNELIPV4"))) { + if ((tmp = svGetValueStr_cp (parsed, "IPV6TUNNELIPV4"))) { if (out_ignore_error) *out_ignore_error = TRUE; g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Ignoring unsupported connection due to IPV6TUNNELIPV4"); - goto done; + return NULL; } - device = svGetValueString (parsed, "DEVICE"); + device = svGetValueStr_cp (parsed, "DEVICE"); if (!device) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "File '%s' had neither TYPE nor DEVICE keys.", filename); - goto done; + return NULL; } - g_assert (device[0]); if (!strcmp (device, "lo")) { if (out_ignore_error) @@ -5148,7 +5329,7 @@ connection_from_file_full (const char *filename, g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Ignoring loopback device config."); g_free (device); - goto done; + return NULL; } if (!test_type) { @@ -5196,7 +5377,7 @@ connection_from_file_full (const char *filename, g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Ignore script for unknown device type which has a matching %s script", p_path); - goto done; + return NULL; } } @@ -5220,11 +5401,21 @@ connection_from_file_full (const char *filename, } } + if (nm_streq0 (type, TYPE_ETHERNET)) { + gs_free char *bond_options = NULL; + + if (svGetValueStr (parsed, "BONDING_OPTS", &bond_options)) { + /* initscripts consider these as bond masters */ + g_free (type); + type = g_strdup (TYPE_BOND); + } + } + if (svGetValueBoolean (parsed, "BONDING_MASTER", FALSE) && strcasecmp (type, TYPE_BOND)) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "BONDING_MASTER=yes key only allowed in TYPE=bond connections"); - goto done; + return NULL; } /* Construct the connection */ @@ -5244,29 +5435,30 @@ connection_from_file_full (const char *filename, connection = bridge_connection_from_ifcfg (filename, parsed, error); else { connection = create_unhandled_connection (filename, parsed, "unrecognized", out_unhandled); - if (!connection) + if (!connection) { PARSE_WARNING ("connection type was unrecognized but device was not uniquely identified; device may be managed"); - goto done; + g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, + "Failed to read unrecognized connection"); + } + return g_steal_pointer (&connection); } if (!connection) - goto done; + return NULL; s_ip6 = make_ip6_setting (parsed, network_file, error); - if (!s_ip6) { - g_object_unref (connection); - connection = NULL; - goto done; - } else + if (!s_ip6) + return NULL; + else nm_connection_add_setting (connection, s_ip6); - s_ip4 = make_ip4_setting (parsed, network_file, error); - if (!s_ip4) { - g_object_unref (connection); - connection = NULL; - goto done; - } else { - read_aliases (NM_SETTING_IP_CONFIG (s_ip4), filename); + s_ip4 = make_ip4_setting (parsed, network_file, &has_ip4_defroute, error); + if (!s_ip4) + return NULL; + else { + read_aliases (NM_SETTING_IP_CONFIG (s_ip4), + !has_ip4_defroute && !nm_setting_ip_config_get_gateway (NM_SETTING_IP_CONFIG (s_ip4)), + filename); nm_connection_add_setting (connection, s_ip4); } @@ -5280,6 +5472,10 @@ connection_from_file_full (const char *filename, if (s_proxy) nm_connection_add_setting (connection, s_proxy); + s_user = make_user_setting (parsed, error); + if (s_user) + nm_connection_add_setting (connection, s_user); + /* Bridge port? */ s_port = make_bridge_port_setting (parsed); if (s_port) @@ -5290,22 +5486,15 @@ connection_from_file_full (const char *filename, if (s_port) nm_connection_add_setting (connection, s_port); - if (!make_dcb_setting (parsed, network_file, &s_dcb, error)) { - g_object_unref (connection); - connection = NULL; - goto done; - } + if (!make_dcb_setting (parsed, network_file, &s_dcb, error)) + return NULL; if (s_dcb) nm_connection_add_setting (connection, s_dcb); - if (!nm_connection_normalize (connection, NULL, NULL, error)) { - g_object_unref (connection); - connection = NULL; - } + if (!nm_connection_normalize (connection, NULL, NULL, error)) + return NULL; -done: - svCloseFile (parsed); - return connection; + return g_steal_pointer (&connection); } NMConnection * @@ -5348,7 +5537,7 @@ devtimeout_from_file (const char *filename) if (!ifcfg) return 0; - devtimeout_str = svGetValueString (ifcfg, "DEVTIMEOUT"); + devtimeout_str = svGetValueStr_cp (ifcfg, "DEVTIMEOUT"); if (devtimeout_str) { devtimeout = _nm_utils_ascii_str_to_int64 (devtimeout_str, 10, 0, G_MAXUINT, 0); g_free (devtimeout_str); diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c index d1c00976..e82ef60c 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c @@ -45,8 +45,9 @@ check_rpm_temp_suffix (const char *path) /* Matches *;[a-fA-F0-9]{8}; used by rpm */ ptr = strrchr (path, ';'); - if (ptr && (strspn (ptr + 1, "abcdefABCDEF0123456789") == 8) - && (! ptr[9])) + if ( ptr + && strspn (ptr + 1, "abcdefABCDEF0123456789") == 8 + && !ptr[9]) return TRUE; return FALSE; } @@ -100,19 +101,20 @@ utils_should_ignore_file (const char *filename, gboolean only_ifcfg) } char * -utils_cert_path (const char *parent, const char *suffix) +utils_cert_path (const char *parent, const char *suffix, const char *extension) { + gs_free char *dir = NULL; const char *name; - char *dir, *path; - g_return_val_if_fail (parent != NULL, NULL); - g_return_val_if_fail (suffix != NULL, NULL); + g_return_val_if_fail (parent, NULL); + g_return_val_if_fail (suffix, NULL); + g_return_val_if_fail (extension, NULL); name = utils_get_ifcfg_name (parent, FALSE); + g_return_val_if_fail (name, NULL); + dir = g_path_get_dirname (parent); - path = g_strdup_printf ("%s/%s-%s", dir, name, suffix); - g_free (dir); - return path; + return g_strdup_printf ("%s/%s-%s.%s", dir, name, suffix, extension); } const char * @@ -363,3 +365,117 @@ utils_detect_ifcfg_path (const char *path, gboolean only_ifcfg) return NULL; return utils_get_ifcfg_path (path); } + +void +nms_ifcfg_rh_utils_user_key_encode (const char *key, GString *str_buffer) +{ + gsize i; + + nm_assert (key); + nm_assert (str_buffer); + + for (i = 0; key[i]; i++) { + char ch = key[i]; + + /* we encode the key in only upper case letters, digits, and underscore. + * As we expect lower-case letters to be more common, we encode lower-case + * letters as upper case, and upper-case letters with a leading underscore. */ + + if (ch >= '0' && ch <= '9') { + g_string_append_c (str_buffer, ch); + continue; + } + if (ch >= 'a' && ch <= 'z') { + g_string_append_c (str_buffer, ch - 'a' + 'A'); + continue; + } + if (ch == '.') { + g_string_append (str_buffer, "__"); + continue; + } + if (ch >= 'A' && ch <= 'Z') { + g_string_append_c (str_buffer, '_'); + g_string_append_c (str_buffer, ch); + continue; + } + g_string_append_printf (str_buffer, "_%03o", (unsigned) ch); + } +} + +gboolean +nms_ifcfg_rh_utils_user_key_decode (const char *name, GString *str_buffer) +{ + gsize i; + + nm_assert (name); + nm_assert (str_buffer); + + if (!name[0]) + return FALSE; + + for (i = 0; name[i]; ) { + char ch = name[i]; + + if (ch >= '0' && ch <= '9') { + g_string_append_c (str_buffer, ch); + i++; + continue; + } + if (ch >= 'A' && ch <= 'Z') { + g_string_append_c (str_buffer, ch - 'A' + 'a'); + i++; + continue; + } + + if (ch == '_') { + ch = name[i + 1]; + if (ch == '_') { + g_string_append_c (str_buffer, '.'); + i += 2; + continue; + } + if (ch >= 'A' && ch <= 'Z') { + g_string_append_c (str_buffer, ch); + i += 2; + continue; + } + if (ch >= '0' && ch <= '7') { + char ch2, ch3; + unsigned v; + + ch2 = name[i + 2]; + if (!(ch2 >= '0' && ch2 <= '7')) + return FALSE; + + ch3 = name[i + 3]; + if (!(ch3 >= '0' && ch3 <= '7')) + return FALSE; + +#define OCTAL_VALUE(ch) ((unsigned) ((ch) - '0')) + v = (OCTAL_VALUE (ch) << 6) + + (OCTAL_VALUE (ch2) << 3) + + OCTAL_VALUE (ch3); + if ( v > 0xFF + || v == 0) + return FALSE; + ch = (char) v; + if ( (ch >= 'A' && ch <= 'Z') + || (ch >= '0' && ch <= '9') + || (ch == '.') + || (ch >= 'a' && ch <= 'z')) { + /* such characters are not expected to be encoded via + * octal representation. The encoding is invalid. */ + return FALSE; + } + g_string_append_c (str_buffer, ch); + i += 4; + continue; + } + return FALSE; + } + + return FALSE; + } + + return TRUE; +} diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h index af0469e6..2b2c2755 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h @@ -31,7 +31,7 @@ #define NM_IFCFG_CONNECTION_LOG_FMTD "%s (%s,\"%s\",%p)" #define NM_IFCFG_CONNECTION_LOG_ARGD(con) NM_IFCFG_CONNECTION_LOG_PATH (nm_settings_connection_get_filename ((NMSettingsConnection *) (con))), nm_connection_get_uuid ((NMConnection *) (con)), nm_connection_get_id ((NMConnection *) (con)), (con) -char *utils_cert_path (const char *parent, const char *suffix); +char *utils_cert_path (const char *parent, const char *suffix, const char *extension); const char *utils_get_ifcfg_name (const char *file, gboolean only_ifcfg); @@ -54,5 +54,7 @@ gboolean utils_is_ifcfg_alias_file (const char *alias, const char *ifcfg); char *utils_detect_ifcfg_path (const char *path, gboolean only_ifcfg); -#endif /* _UTILS_H_ */ +void nms_ifcfg_rh_utils_user_key_encode (const char *key, GString *str_buffer); +gboolean nms_ifcfg_rh_utils_user_key_decode (const char *name, GString *str_buffer); +#endif /* _UTILS_H_ */ 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 fa8013b0..d6f33c49 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c @@ -42,11 +42,13 @@ #include "nm-setting-ip6-config.h" #include "nm-setting-pppoe.h" #include "nm-setting-vlan.h" +#include "nm-setting-user.h" #include "nm-setting-team.h" #include "nm-setting-team-port.h" #include "nm-utils.h" #include "nm-core-internal.h" #include "NetworkManagerUtils.h" +#include "nm-setting-metadata.h" #include "nms-ifcfg-rh-common.h" #include "nms-ifcfg-rh-reader.h" @@ -59,7 +61,7 @@ #define _NMLOG_PREFIX_NAME "ifcfg-rh" #define _NMLOG(level, ...) \ G_STMT_START { \ - nm_log ((level), (_NMLOG_DOMAIN), \ + nm_log ((level), (_NMLOG_DOMAIN), NULL, NULL, \ "%s" _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ _NMLOG_PREFIX_NAME": " \ _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ @@ -99,7 +101,7 @@ save_secret_flags (shvarFile *ifcfg, g_string_append (str, SECRET_FLAG_NOT_REQUIRED); } - svSetValueString (ifcfg, key, str->len ? str->str : NULL); + svSetValueStr (ifcfg, key, str->len ? str->str : NULL); g_string_free (str, TRUE); } @@ -127,7 +129,7 @@ set_secret (shvarFile *ifcfg, /* Only write the secret if it's system owned and supposed to be saved */ if (flags == NM_SETTING_SECRET_FLAG_NONE) - svSetValueString (keyfile, key, value); + svSetValueStr (keyfile, key, value); else svUnsetValue (keyfile, key); @@ -143,112 +145,70 @@ set_secret (shvarFile *ifcfg, error: /* Try setting the secret in the actual ifcfg */ - svSetValueString (ifcfg, key, value); + svSetValueStr (ifcfg, key, value); } -typedef struct ObjectType { - const char *setting_key; - NMSetting8021xCKScheme (*scheme_func)(NMSetting8021x *setting); - const char * (*path_func) (NMSetting8021x *setting); - GBytes * (*blob_func) (NMSetting8021x *setting); - const char *ifcfg_key; - const char *suffix; -} ObjectType; - -static const ObjectType ca_type = { - NM_SETTING_802_1X_CA_CERT, - nm_setting_802_1x_get_ca_cert_scheme, - nm_setting_802_1x_get_ca_cert_path, - nm_setting_802_1x_get_ca_cert_blob, - "IEEE_8021X_CA_CERT", - "ca-cert.der" -}; - -static const ObjectType phase2_ca_type = { - NM_SETTING_802_1X_PHASE2_CA_CERT, - nm_setting_802_1x_get_phase2_ca_cert_scheme, - nm_setting_802_1x_get_phase2_ca_cert_path, - nm_setting_802_1x_get_phase2_ca_cert_blob, - "IEEE_8021X_INNER_CA_CERT", - "inner-ca-cert.der" -}; - -static const ObjectType client_type = { - NM_SETTING_802_1X_CLIENT_CERT, - nm_setting_802_1x_get_client_cert_scheme, - nm_setting_802_1x_get_client_cert_path, - nm_setting_802_1x_get_client_cert_blob, - "IEEE_8021X_CLIENT_CERT", - "client-cert.der" -}; - -static const ObjectType phase2_client_type = { - NM_SETTING_802_1X_PHASE2_CLIENT_CERT, - nm_setting_802_1x_get_phase2_client_cert_scheme, - nm_setting_802_1x_get_phase2_client_cert_path, - nm_setting_802_1x_get_phase2_client_cert_blob, - "IEEE_8021X_INNER_CLIENT_CERT", - "inner-client-cert.der" -}; - -static const ObjectType pk_type = { - NM_SETTING_802_1X_PRIVATE_KEY, - nm_setting_802_1x_get_private_key_scheme, - nm_setting_802_1x_get_private_key_path, - nm_setting_802_1x_get_private_key_blob, - "IEEE_8021X_PRIVATE_KEY", - "private-key.pem" -}; - -static const ObjectType phase2_pk_type = { - NM_SETTING_802_1X_PHASE2_PRIVATE_KEY, - nm_setting_802_1x_get_phase2_private_key_scheme, - nm_setting_802_1x_get_phase2_private_key_path, - nm_setting_802_1x_get_phase2_private_key_blob, - "IEEE_8021X_INNER_PRIVATE_KEY", - "inner-private-key.pem" -}; - -static const ObjectType p12_type = { - NM_SETTING_802_1X_PRIVATE_KEY, - nm_setting_802_1x_get_private_key_scheme, - nm_setting_802_1x_get_private_key_path, - nm_setting_802_1x_get_private_key_blob, - "IEEE_8021X_PRIVATE_KEY", - "private-key.p12" -}; - -static const ObjectType phase2_p12_type = { - NM_SETTING_802_1X_PHASE2_PRIVATE_KEY, - nm_setting_802_1x_get_phase2_private_key_scheme, - nm_setting_802_1x_get_phase2_private_key_path, - nm_setting_802_1x_get_phase2_private_key_blob, - "IEEE_8021X_INNER_PRIVATE_KEY", - "inner-private-key.p12" +typedef struct { + const NMSetting8021xSchemeVtable *vtable; + const char *ifcfg_rh_key; +} Setting8021xSchemeVtable; + +static const Setting8021xSchemeVtable setting_8021x_scheme_vtable[] = { + [NM_SETTING_802_1X_SCHEME_TYPE_CA_CERT] = { + .vtable = &nm_setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_CA_CERT], + .ifcfg_rh_key = "IEEE_8021X_CA_CERT", + }, + [NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_CA_CERT] = { + .vtable = &nm_setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_CA_CERT], + .ifcfg_rh_key = "IEEE_8021X_INNER_CA_CERT", + }, + [NM_SETTING_802_1X_SCHEME_TYPE_CLIENT_CERT] = { + .vtable = &nm_setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_CLIENT_CERT], + .ifcfg_rh_key = "IEEE_8021X_CLIENT_CERT", + }, + [NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_CLIENT_CERT] = { + .vtable = &nm_setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_CLIENT_CERT], + .ifcfg_rh_key = "IEEE_8021X_INNER_CLIENT_CERT", + }, + [NM_SETTING_802_1X_SCHEME_TYPE_PRIVATE_KEY] = { + .vtable = &nm_setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_PRIVATE_KEY], + .ifcfg_rh_key = "IEEE_8021X_PRIVATE_KEY", + }, + [NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_PRIVATE_KEY] = { + .vtable = &nm_setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_PRIVATE_KEY], + .ifcfg_rh_key = "IEEE_8021X_INNER_PRIVATE_KEY", + }, }; static gboolean write_object (NMSetting8021x *s_8021x, shvarFile *ifcfg, - const ObjectType *objtype, + const Setting8021xSchemeVtable *objtype, GError **error) { NMSetting8021xCKScheme scheme; - const char *path = NULL; + const char *value = NULL; GBytes *blob = NULL; + const char *password = NULL; + NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE; + char *secret_name, *secret_flags; + const char *extension; g_return_val_if_fail (ifcfg != NULL, FALSE); g_return_val_if_fail (objtype != NULL, FALSE); - scheme = (*(objtype->scheme_func))(s_8021x); + scheme = (*(objtype->vtable->scheme_func))(s_8021x); switch (scheme) { case NM_SETTING_802_1X_CK_SCHEME_UNKNOWN: break; case NM_SETTING_802_1X_CK_SCHEME_BLOB: - blob = (*(objtype->blob_func))(s_8021x); + blob = (*(objtype->vtable->blob_func))(s_8021x); break; case NM_SETTING_802_1X_CK_SCHEME_PATH: - path = (*(objtype->path_func))(s_8021x); + value = (*(objtype->vtable->path_func))(s_8021x); + break; + case NM_SETTING_802_1X_CK_SCHEME_PKCS11: + value = (*(objtype->vtable->uri_func))(s_8021x); break; default: g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED, @@ -256,10 +216,26 @@ write_object (NMSetting8021x *s_8021x, return FALSE; } + /* Set the password for certificate/private key. */ + secret_name = g_strdup_printf ("%s_PASSWORD", objtype->ifcfg_rh_key); + secret_flags = g_strdup_printf ("%s_PASSWORD_FLAGS", objtype->ifcfg_rh_key); + password = (*(objtype->vtable->passwd_func))(s_8021x); + flags = (*(objtype->vtable->pwflag_func))(s_8021x); + set_secret (ifcfg, secret_name, password, secret_flags, flags); + g_free (secret_name); + g_free (secret_flags); + + if (!objtype->vtable->format_func) + extension = "der"; + else if (objtype->vtable->format_func (s_8021x) == NM_SETTING_802_1X_CK_FORMAT_PKCS12) + extension = "p12"; + else + extension = "pem"; + /* If certificate/private key wasn't sent, the connection may no longer be * 802.1x and thus we clear out the paths and certs. */ - if (!path && !blob) { + if (!value && !blob) { char *standard_file; int ignored; @@ -269,20 +245,20 @@ write_object (NMSetting8021x *s_8021x, * /etc/sysconfig/network-scripts/ca-cert-Test_Write_Wifi_WPA_EAP-TLS.der * will be deleted, but /etc/pki/tls/cert.pem will not. */ - standard_file = utils_cert_path (svFileGetName (ifcfg), objtype->suffix); + standard_file = utils_cert_path (svFileGetName (ifcfg), objtype->vtable->file_suffix, extension); if (g_file_test (standard_file, G_FILE_TEST_EXISTS)) ignored = unlink (standard_file); g_free (standard_file); - svUnsetValue (ifcfg, objtype->ifcfg_key); + svUnsetValue (ifcfg, objtype->ifcfg_rh_key); return TRUE; } /* If the object path was specified, prefer that over any raw cert data that * may have been sent. */ - if (path) { - svSetValueString (ifcfg, objtype->ifcfg_key, path); + if (value) { + svSetValueStr (ifcfg, objtype->ifcfg_rh_key, value); return TRUE; } @@ -292,11 +268,11 @@ write_object (NMSetting8021x *s_8021x, char *new_file; GError *write_error = NULL; - new_file = utils_cert_path (svFileGetName (ifcfg), objtype->suffix); + new_file = utils_cert_path (svFileGetName (ifcfg), objtype->vtable->file_suffix, extension); if (!new_file) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED, "Could not create file path for %s / %s", - NM_SETTING_802_1X_SETTING_NAME, objtype->setting_key); + NM_SETTING_802_1X_SETTING_NAME, objtype->vtable->setting_key); return FALSE; } @@ -310,13 +286,13 @@ write_object (NMSetting8021x *s_8021x, 0600, &write_error); if (success) { - svSetValueString (ifcfg, objtype->ifcfg_key, new_file); + svSetValueStr (ifcfg, objtype->ifcfg_rh_key, new_file); g_free (new_file); return TRUE; } else { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED, "Could not write certificate/key for %s / %s: %s", - NM_SETTING_802_1X_SETTING_NAME, objtype->setting_key, + NM_SETTING_802_1X_SETTING_NAME, objtype->vtable->setting_key, (write_error && write_error->message) ? write_error->message : "(unknown)"); g_clear_error (&write_error); } @@ -332,71 +308,45 @@ write_8021x_certs (NMSetting8021x *s_8021x, shvarFile *ifcfg, GError **error) { - const char *password = NULL; - gboolean success = FALSE, is_pkcs12 = FALSE; - const ObjectType *otype = NULL; - NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE; + const Setting8021xSchemeVtable *otype = NULL; /* CA certificate */ - if (!write_object (s_8021x, ifcfg, phase2 ? &phase2_ca_type : &ca_type, error)) + if (!write_object (s_8021x, ifcfg, + phase2 + ? &setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_CA_CERT] + : &setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_CA_CERT], + error)) return FALSE; /* Private key */ - if (phase2) { - otype = &phase2_pk_type; - if (nm_setting_802_1x_get_phase2_private_key_format (s_8021x) == NM_SETTING_802_1X_CK_FORMAT_PKCS12) { - otype = &phase2_p12_type; - is_pkcs12 = TRUE; - } - password = nm_setting_802_1x_get_phase2_private_key_password (s_8021x); - flags = nm_setting_802_1x_get_phase2_private_key_password_flags (s_8021x); - } else { - otype = &pk_type; - if (nm_setting_802_1x_get_private_key_format (s_8021x) == NM_SETTING_802_1X_CK_FORMAT_PKCS12) { - otype = &p12_type; - is_pkcs12 = TRUE; - } - password = nm_setting_802_1x_get_private_key_password (s_8021x); - flags = nm_setting_802_1x_get_private_key_password_flags (s_8021x); - } + if (phase2) + otype = &setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_PRIVATE_KEY]; + else + otype = &setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_PRIVATE_KEY]; /* Save the private key */ if (!write_object (s_8021x, ifcfg, otype, error)) - goto out; - - /* Private key password */ - if (phase2) { - set_secret (ifcfg, - "IEEE_8021X_INNER_PRIVATE_KEY_PASSWORD", - password, - "IEEE_8021X_INNER_PRIVATE_KEY_PASSWORD_FLAGS", - flags); - } else { - set_secret (ifcfg, - "IEEE_8021X_PRIVATE_KEY_PASSWORD", - password, - "IEEE_8021X_PRIVATE_KEY_PASSWORD_FLAGS", - flags); - } + return FALSE; /* Client certificate */ - if (is_pkcs12) { + if (otype->vtable->format_func (s_8021x) == NM_SETTING_802_1X_CK_FORMAT_PKCS12) { /* Don't need a client certificate with PKCS#12 since the file is both * the client certificate and the private key in one file. */ - svSetValueString (ifcfg, - phase2 ? "IEEE_8021X_INNER_CLIENT_CERT" : "IEEE_8021X_CLIENT_CERT", - NULL); + svSetValueStr (ifcfg, + phase2 ? "IEEE_8021X_INNER_CLIENT_CERT" : "IEEE_8021X_CLIENT_CERT", + NULL); } else { /* Save the client certificate */ - if (!write_object (s_8021x, ifcfg, phase2 ? &phase2_client_type : &client_type, error)) - goto out; + if (!write_object (s_8021x, ifcfg, + phase2 + ? &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)) + return FALSE; } - success = TRUE; - -out: - return success; + return TRUE; } static gboolean @@ -406,12 +356,13 @@ write_8021x_setting (NMConnection *connection, GError **error) { NMSetting8021x *s_8021x; + NMSetting8021xAuthFlags auth_flags; const char *value, *match; char *tmp = NULL; - gboolean success = FALSE; GString *phase2_auth; GString *str; guint32 i, num; + gint timeout; s_8021x = nm_connection_get_setting_802_1x (connection); if (!s_8021x) { @@ -423,7 +374,7 @@ write_8021x_setting (NMConnection *connection, /* If wired, write KEY_MGMT */ if (wired) - svSetValueString (ifcfg, "KEY_MGMT", "IEEE8021X"); + svSetValueStr (ifcfg, "KEY_MGMT", "IEEE8021X"); /* EAP method */ if (nm_setting_802_1x_get_num_eap_methods (s_8021x)) { @@ -431,14 +382,14 @@ write_8021x_setting (NMConnection *connection, if (value) tmp = g_ascii_strup (value, -1); } - svSetValueString (ifcfg, "IEEE_8021X_EAP_METHODS", tmp); + svSetValueStr (ifcfg, "IEEE_8021X_EAP_METHODS", tmp); g_free (tmp); - svSetValueString (ifcfg, "IEEE_8021X_IDENTITY", - nm_setting_802_1x_get_identity (s_8021x)); + svSetValueStr (ifcfg, "IEEE_8021X_IDENTITY", + nm_setting_802_1x_get_identity (s_8021x)); - svSetValueString (ifcfg, "IEEE_8021X_ANON_IDENTITY", - nm_setting_802_1x_get_anonymous_identity (s_8021x)); + svSetValueStr (ifcfg, "IEEE_8021X_ANON_IDENTITY", + nm_setting_802_1x_get_anonymous_identity (s_8021x)); set_secret (ifcfg, "IEEE_8021X_PASSWORD", @@ -450,30 +401,30 @@ write_8021x_setting (NMConnection *connection, value = nm_setting_802_1x_get_phase1_peapver (s_8021x); svUnsetValue (ifcfg, "IEEE_8021X_PEAP_VERSION"); if (value && (!strcmp (value, "0") || !strcmp (value, "1"))) - svSetValueString (ifcfg, "IEEE_8021X_PEAP_VERSION", value); + svSetValueStr (ifcfg, "IEEE_8021X_PEAP_VERSION", value); /* Force new PEAP label */ value = nm_setting_802_1x_get_phase1_peaplabel (s_8021x); svUnsetValue (ifcfg, "IEEE_8021X_PEAP_FORCE_NEW_LABEL"); if (value && !strcmp (value, "1")) - svSetValueString (ifcfg, "IEEE_8021X_PEAP_FORCE_NEW_LABEL", "yes"); + svSetValueStr (ifcfg, "IEEE_8021X_PEAP_FORCE_NEW_LABEL", "yes"); /* PAC file */ value = nm_setting_802_1x_get_pac_file (s_8021x); svUnsetValue (ifcfg, "IEEE_8021X_PAC_FILE"); if (value) - svSetValueString (ifcfg, "IEEE_8021X_PAC_FILE", value); + svSetValueStr (ifcfg, "IEEE_8021X_PAC_FILE", value); /* FAST PAC provisioning */ value = nm_setting_802_1x_get_phase1_fast_provisioning (s_8021x); svUnsetValue (ifcfg, "IEEE_8021X_FAST_PROVISIONING"); if (value) { if (strcmp (value, "1") == 0) - svSetValueString (ifcfg, "IEEE_8021X_FAST_PROVISIONING", "allow-unauth"); + svSetValueStr (ifcfg, "IEEE_8021X_FAST_PROVISIONING", "allow-unauth"); else if (strcmp (value, "2") == 0) - svSetValueString (ifcfg, "IEEE_8021X_FAST_PROVISIONING", "allow-auth"); + svSetValueStr (ifcfg, "IEEE_8021X_FAST_PROVISIONING", "allow-auth"); else if (strcmp (value, "3") == 0) - svSetValueString (ifcfg, "IEEE_8021X_FAST_PROVISIONING", "allow-unauth allow-auth"); + svSetValueStr (ifcfg, "IEEE_8021X_FAST_PROVISIONING", "allow-unauth allow-auth"); } /* Phase2 auth methods */ @@ -497,16 +448,27 @@ write_8021x_setting (NMConnection *connection, g_free (tmp); } - svSetValueString (ifcfg, "IEEE_8021X_INNER_AUTH_METHODS", - phase2_auth->len ? phase2_auth->str : NULL); + auth_flags = nm_setting_802_1x_get_phase1_auth_flags (s_8021x); + if (auth_flags == NM_SETTING_802_1X_AUTH_FLAGS_NONE) { + svUnsetValue (ifcfg, "IEEE_8021X_PHASE1_AUTH_FLAGS"); + } else { + gs_free char *flags_str = NULL; + + flags_str = _nm_utils_enum_to_str_full (nm_setting_802_1x_auth_flags_get_type (), + auth_flags, " "); + svSetValueStr (ifcfg, "IEEE_8021X_PHASE1_AUTH_FLAGS", flags_str); + } + + svSetValueStr (ifcfg, "IEEE_8021X_INNER_AUTH_METHODS", + phase2_auth->len ? phase2_auth->str : NULL); g_string_free (phase2_auth, TRUE); - svSetValueString (ifcfg, "IEEE_8021X_SUBJECT_MATCH", - nm_setting_802_1x_get_subject_match (s_8021x)); + svSetValueStr (ifcfg, "IEEE_8021X_SUBJECT_MATCH", + nm_setting_802_1x_get_subject_match (s_8021x)); - svSetValueString (ifcfg, "IEEE_8021X_PHASE2_SUBJECT_MATCH", - nm_setting_802_1x_get_phase2_subject_match (s_8021x)); + svSetValueStr (ifcfg, "IEEE_8021X_PHASE2_SUBJECT_MATCH", + nm_setting_802_1x_get_phase2_subject_match (s_8021x)); svUnsetValue (ifcfg, "IEEE_8021X_ALTSUBJECT_MATCHES"); str = g_string_new (NULL); @@ -518,7 +480,7 @@ write_8021x_setting (NMConnection *connection, g_string_append (str, match); } if (str->len > 0) - svSetValueString (ifcfg, "IEEE_8021X_ALTSUBJECT_MATCHES", str->str); + svSetValueStr (ifcfg, "IEEE_8021X_ALTSUBJECT_MATCHES", str->str); g_string_free (str, TRUE); svUnsetValue (ifcfg, "IEEE_8021X_PHASE2_ALTSUBJECT_MATCHES"); @@ -531,21 +493,28 @@ write_8021x_setting (NMConnection *connection, g_string_append (str, match); } if (str->len > 0) - svSetValueString (ifcfg, "IEEE_8021X_PHASE2_ALTSUBJECT_MATCHES", str->str); + svSetValueStr (ifcfg, "IEEE_8021X_PHASE2_ALTSUBJECT_MATCHES", str->str); g_string_free (str, TRUE); - svSetValueString (ifcfg, "IEEE_8021X_DOMAIN_SUFFIX_MATCH", - nm_setting_802_1x_get_domain_suffix_match (s_8021x)); - svSetValueString (ifcfg, "IEEE_8021X_PHASE2_DOMAIN_SUFFIX_MATCH", - nm_setting_802_1x_get_phase2_domain_suffix_match (s_8021x)); + svSetValueStr (ifcfg, "IEEE_8021X_DOMAIN_SUFFIX_MATCH", + nm_setting_802_1x_get_domain_suffix_match (s_8021x)); + svSetValueStr (ifcfg, "IEEE_8021X_PHASE2_DOMAIN_SUFFIX_MATCH", + nm_setting_802_1x_get_phase2_domain_suffix_match (s_8021x)); - success = write_8021x_certs (s_8021x, FALSE, ifcfg, error); - if (success) { - /* phase2/inner certs */ - success = write_8021x_certs (s_8021x, TRUE, ifcfg, error); - } + timeout = nm_setting_802_1x_get_auth_timeout (s_8021x); + if (timeout > 0) + svSetValueInt64 (ifcfg, "IEEE_8021X_AUTH_TIMEOUT", timeout); + else + svUnsetValue (ifcfg, "IEEE_8021X_AUTH_TIMEOUT"); + + if (!write_8021x_certs (s_8021x, FALSE, ifcfg, error)) + return FALSE; - return success; + /* phase2/inner certs */ + if (!write_8021x_certs (s_8021x, TRUE, ifcfg, error)) + return FALSE; + + return TRUE; } static gboolean @@ -582,27 +551,27 @@ write_wireless_security_setting (NMConnection *connection, wep = TRUE; *no_8021x = TRUE; } else if (!strcmp (key_mgmt, "wpa-none") || !strcmp (key_mgmt, "wpa-psk")) { - svSetValueString (ifcfg, "KEY_MGMT", "WPA-PSK"); + svSetValueStr (ifcfg, "KEY_MGMT", "WPA-PSK"); wpa = TRUE; *no_8021x = TRUE; } else if (!strcmp (key_mgmt, "ieee8021x")) { - svSetValueString (ifcfg, "KEY_MGMT", "IEEE8021X"); + svSetValueStr (ifcfg, "KEY_MGMT", "IEEE8021X"); dynamic_wep = TRUE; } else if (!strcmp (key_mgmt, "wpa-eap")) { - svSetValueString (ifcfg, "KEY_MGMT", "WPA-EAP"); + svSetValueStr (ifcfg, "KEY_MGMT", "WPA-EAP"); wpa = TRUE; } svUnsetValue (ifcfg, "SECURITYMODE"); if (auth_alg) { if (!strcmp (auth_alg, "shared")) - svSetValueString (ifcfg, "SECURITYMODE", "restricted"); + svSetValueStr (ifcfg, "SECURITYMODE", "restricted"); else if (!strcmp (auth_alg, "open")) - svSetValueString (ifcfg, "SECURITYMODE", "open"); + svSetValueStr (ifcfg, "SECURITYMODE", "open"); else if (!strcmp (auth_alg, "leap")) { - svSetValueString (ifcfg, "SECURITYMODE", "leap"); - svSetValueString (ifcfg, "IEEE_8021X_IDENTITY", - nm_setting_wireless_security_get_leap_username (s_wsec)); + svSetValueStr (ifcfg, "SECURITYMODE", "leap"); + svSetValueStr (ifcfg, "IEEE_8021X_IDENTITY", + nm_setting_wireless_security_get_leap_username (s_wsec)); set_secret (ifcfg, "IEEE_8021X_PASSWORD", nm_setting_wireless_security_get_leap_password (s_wsec), @@ -632,7 +601,7 @@ write_wireless_security_setting (NMConnection *connection, if (wep) { /* Default WEP TX key index */ tmp = g_strdup_printf ("%d", nm_setting_wireless_security_get_wep_tx_keyidx (s_wsec) + 1); - svSetValueString (ifcfg, "DEFAULTKEY", tmp); + svSetValueStr (ifcfg, "DEFAULTKEY", tmp); g_free (tmp); for (i = 0; i < 4; i++) { @@ -688,9 +657,9 @@ write_wireless_security_setting (NMConnection *connection, for (i = 0; i < num; i++) { proto = nm_setting_wireless_security_get_proto (s_wsec, i); if (proto && !strcmp (proto, "wpa")) - svSetValueString (ifcfg, "WPA_ALLOW_WPA", "yes"); + svSetValueStr (ifcfg, "WPA_ALLOW_WPA", "yes"); else if (proto && !strcmp (proto, "rsn")) - svSetValueString (ifcfg, "WPA_ALLOW_WPA2", "yes"); + svSetValueStr (ifcfg, "WPA_ALLOW_WPA2", "yes"); } /* WPA Pairwise ciphers */ @@ -712,7 +681,7 @@ write_wireless_security_setting (NMConnection *connection, } } if (strlen (str->str) && (dynamic_wep == FALSE)) - svSetValueString (ifcfg, "CIPHER_PAIRWISE", str->str); + svSetValueStr (ifcfg, "CIPHER_PAIRWISE", str->str); g_string_free (str, TRUE); /* WPA Group ciphers */ @@ -728,7 +697,7 @@ write_wireless_security_setting (NMConnection *connection, g_free (tmp); } if (strlen (str->str) && (dynamic_wep == FALSE)) - svSetValueString (ifcfg, "CIPHER_GROUP", str->str); + svSetValueStr (ifcfg, "CIPHER_GROUP", str->str); g_string_free (str, TRUE); if (wpa) @@ -768,13 +737,13 @@ write_wireless_setting (NMConnection *connection, } device_mac = nm_setting_wireless_get_mac_address (s_wireless); - svSetValueString (ifcfg, "HWADDR", device_mac); + svSetValueStr (ifcfg, "HWADDR", device_mac); cloned_mac = nm_setting_wireless_get_cloned_mac_address (s_wireless); - svSetValueString (ifcfg, "MACADDR", cloned_mac); + svSetValueStr (ifcfg, "MACADDR", cloned_mac); - svSetValueString (ifcfg, "GENERATE_MAC_ADDRESS_MASK", - nm_setting_wireless_get_generate_mac_address_mask (s_wireless)); + svSetValueStr (ifcfg, "GENERATE_MAC_ADDRESS_MASK", + nm_setting_wireless_get_generate_mac_address_mask (s_wireless)); svUnsetValue (ifcfg, "HWADDR_BLACKLIST"); macaddr_blacklist = nm_setting_wireless_get_mac_address_blacklist (s_wireless); @@ -782,7 +751,7 @@ write_wireless_setting (NMConnection *connection, char *blacklist_str; blacklist_str = g_strjoinv (" ", (char **) macaddr_blacklist); - svSetValueString (ifcfg, "HWADDR_BLACKLIST", blacklist_str); + svSetValueStr (ifcfg, "HWADDR_BLACKLIST", blacklist_str); g_free (blacklist_str); } @@ -790,7 +759,7 @@ write_wireless_setting (NMConnection *connection, mtu = nm_setting_wireless_get_mtu (s_wireless); if (mtu) { tmp = g_strdup_printf ("%u", mtu); - svSetValueString (ifcfg, "MTU", tmp); + svSetValueStr (ifcfg, "MTU", tmp); g_free (tmp); } @@ -838,7 +807,7 @@ write_wireless_setting (NMConnection *connection, g_string_append (str, "0x"); for (i = 0; i < ssid_len; i++) g_string_append_printf (str, "%02X", ssid_data[i]); - svSetValueString (ifcfg, "ESSID", str->str); + svSetValueStr (ifcfg, "ESSID", str->str); g_string_free (str, TRUE); } else { char buf[33]; @@ -846,17 +815,17 @@ write_wireless_setting (NMConnection *connection, nm_assert (ssid_len <= 32); memcpy (buf, ssid_data, ssid_len); buf[ssid_len] = '\0'; - svSetValueString (ifcfg, "ESSID", buf); + svSetValueStr (ifcfg, "ESSID", buf); } mode = nm_setting_wireless_get_mode (s_wireless); if (!mode || !strcmp (mode, "infrastructure")) { - svSetValueString (ifcfg, "MODE", "Managed"); + svSetValueStr (ifcfg, "MODE", "Managed"); } else if (!strcmp (mode, "adhoc")) { - svSetValueString (ifcfg, "MODE", "Ad-Hoc"); + svSetValueStr (ifcfg, "MODE", "Ad-Hoc"); adhoc = TRUE; } else if (!strcmp (mode, "ap")) { - svSetValueString (ifcfg, "MODE", "Ap"); + svSetValueStr (ifcfg, "MODE", "Ap"); } else { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED, "Invalid mode '%s' in '%s' setting", @@ -869,15 +838,15 @@ write_wireless_setting (NMConnection *connection, chan = nm_setting_wireless_get_channel (s_wireless); if (chan) { tmp = g_strdup_printf ("%u", chan); - svSetValueString (ifcfg, "CHANNEL", tmp); + svSetValueStr (ifcfg, "CHANNEL", tmp); g_free (tmp); } else { /* Band only set if channel is not, since channel implies band */ - svSetValueString (ifcfg, "BAND", nm_setting_wireless_get_band (s_wireless)); + svSetValueStr (ifcfg, "BAND", nm_setting_wireless_get_band (s_wireless)); } bssid = nm_setting_wireless_get_bssid (s_wireless); - svSetValueString (ifcfg, "BSSID", bssid); + svSetValueStr (ifcfg, "BSSID", bssid); /* Ensure DEFAULTKEY and SECURITYMODE are cleared unless there's security; * otherwise there's no way to detect WEP vs. open when WEP keys aren't @@ -923,17 +892,17 @@ write_wireless_setting (NMConnection *connection, g_free (keys_path); } - svSetValueString (ifcfg, "SSID_HIDDEN", nm_setting_wireless_get_hidden (s_wireless) ? "yes" : NULL); + svSetValueStr (ifcfg, "SSID_HIDDEN", nm_setting_wireless_get_hidden (s_wireless) ? "yes" : NULL); switch (nm_setting_wireless_get_powersave (s_wireless)) { case NM_SETTING_WIRELESS_POWERSAVE_IGNORE: - svSetValueString (ifcfg, "POWERSAVE", "ignore"); + svSetValueStr (ifcfg, "POWERSAVE", "ignore"); break; case NM_SETTING_WIRELESS_POWERSAVE_DISABLE: - svSetValueString (ifcfg, "POWERSAVE", "disable"); + svSetValueStr (ifcfg, "POWERSAVE", "disable"); break; case NM_SETTING_WIRELESS_POWERSAVE_ENABLE: - svSetValueString (ifcfg, "POWERSAVE", "enable"); + svSetValueStr (ifcfg, "POWERSAVE", "enable"); break; default: case NM_SETTING_WIRELESS_POWERSAVE_DEFAULT: @@ -943,18 +912,18 @@ write_wireless_setting (NMConnection *connection, switch (nm_setting_wireless_get_mac_address_randomization (s_wireless)) { case NM_SETTING_MAC_RANDOMIZATION_NEVER: - svSetValueString (ifcfg, "MAC_ADDRESS_RANDOMIZATION", "never"); + svSetValueStr (ifcfg, "MAC_ADDRESS_RANDOMIZATION", "never"); break; case NM_SETTING_MAC_RANDOMIZATION_ALWAYS: - svSetValueString (ifcfg, "MAC_ADDRESS_RANDOMIZATION", "always"); + svSetValueStr (ifcfg, "MAC_ADDRESS_RANDOMIZATION", "always"); break; case NM_SETTING_MAC_RANDOMIZATION_DEFAULT: default: - svSetValueString (ifcfg, "MAC_ADDRESS_RANDOMIZATION", "default"); + svSetValueStr (ifcfg, "MAC_ADDRESS_RANDOMIZATION", "default"); break; } - svSetValueString (ifcfg, "TYPE", TYPE_WIRELESS); + svSetValueStr (ifcfg, "TYPE", TYPE_WIRELESS); return TRUE; } @@ -976,13 +945,13 @@ write_infiniband_setting (NMConnection *connection, shvarFile *ifcfg, GError **e } mac = nm_setting_infiniband_get_mac_address (s_infiniband); - svSetValueString (ifcfg, "HWADDR", mac); + svSetValueStr (ifcfg, "HWADDR", mac); svUnsetValue (ifcfg, "MTU"); mtu = nm_setting_infiniband_get_mtu (s_infiniband); if (mtu) { tmp = g_strdup_printf ("%u", mtu); - svSetValueString (ifcfg, "MTU", tmp); + svSetValueStr (ifcfg, "MTU", tmp); g_free (tmp); } @@ -991,17 +960,17 @@ write_infiniband_setting (NMConnection *connection, shvarFile *ifcfg, GError **e p_key = nm_setting_infiniband_get_p_key (s_infiniband); if (p_key != -1) { - svSetValueString (ifcfg, "PKEY", "yes"); + svSetValueStr (ifcfg, "PKEY", "yes"); tmp = g_strdup_printf ("%u", p_key); - svSetValueString (ifcfg, "PKEY_ID", tmp); + svSetValueStr (ifcfg, "PKEY_ID", tmp); g_free (tmp); parent = nm_setting_infiniband_get_parent (s_infiniband); if (parent) - svSetValueString (ifcfg, "PHYSDEV", parent); + svSetValueStr (ifcfg, "PHYSDEV", parent); } - svSetValueString (ifcfg, "TYPE", TYPE_INFINIBAND); + svSetValueStr (ifcfg, "TYPE", TYPE_INFINIBAND); return TRUE; } @@ -1029,13 +998,13 @@ write_wired_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) } device_mac = nm_setting_wired_get_mac_address (s_wired); - svSetValueString (ifcfg, "HWADDR", device_mac); + svSetValueStr (ifcfg, "HWADDR", device_mac); cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired); - svSetValueString (ifcfg, "MACADDR", cloned_mac); + svSetValueStr (ifcfg, "MACADDR", cloned_mac); - svSetValueString (ifcfg, "GENERATE_MAC_ADDRESS_MASK", - nm_setting_wired_get_generate_mac_address_mask (s_wired)); + svSetValueStr (ifcfg, "GENERATE_MAC_ADDRESS_MASK", + nm_setting_wired_get_generate_mac_address_mask (s_wired)); svUnsetValue (ifcfg, "HWADDR_BLACKLIST"); macaddr_blacklist = nm_setting_wired_get_mac_address_blacklist (s_wired); @@ -1043,7 +1012,7 @@ write_wired_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) char *blacklist_str; blacklist_str = g_strjoinv (" ", (char **) macaddr_blacklist); - svSetValueString (ifcfg, "HWADDR_BLACKLIST", blacklist_str); + svSetValueStr (ifcfg, "HWADDR_BLACKLIST", blacklist_str); g_free (blacklist_str); } @@ -1051,7 +1020,7 @@ write_wired_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) mtu = nm_setting_wired_get_mtu (s_wired); if (mtu) { tmp = g_strdup_printf ("%u", mtu); - svSetValueString (ifcfg, "MTU", tmp); + svSetValueStr (ifcfg, "MTU", tmp); g_free (tmp); } @@ -1061,30 +1030,30 @@ write_wired_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) int len = g_strv_length ((char **)s390_subchannels); tmp = NULL; - if (len == 2) { - tmp = g_strdup_printf ("%s,%s", s390_subchannels[0], s390_subchannels[1]); - } else if (len == 3) { - tmp = g_strdup_printf ("%s,%s,%s", s390_subchannels[0], s390_subchannels[1], - s390_subchannels[2]); + if (len == 2) { + tmp = g_strdup_printf ("%s,%s", s390_subchannels[0], s390_subchannels[1]); + } else if (len == 3) { + tmp = g_strdup_printf ("%s,%s,%s", s390_subchannels[0], s390_subchannels[1], + s390_subchannels[2]); } - svSetValueString (ifcfg, "SUBCHANNELS", tmp); + svSetValueStr (ifcfg, "SUBCHANNELS", tmp); g_free (tmp); } svUnsetValue (ifcfg, "NETTYPE"); nettype = nm_setting_wired_get_s390_nettype (s_wired); if (nettype) - svSetValueString (ifcfg, "NETTYPE", nettype); + svSetValueStr (ifcfg, "NETTYPE", nettype); svUnsetValue (ifcfg, "PORTNAME"); portname = nm_setting_wired_get_s390_option_by_key (s_wired, "portname"); if (portname) - svSetValueString (ifcfg, "PORTNAME", portname); + svSetValueStr (ifcfg, "PORTNAME", portname); svUnsetValue (ifcfg, "CTCPROT"); ctcprot = nm_setting_wired_get_s390_option_by_key (s_wired, "ctcprot"); if (ctcprot) - svSetValueString (ifcfg, "CTCPROT", ctcprot); + svSetValueStr (ifcfg, "CTCPROT", ctcprot); svUnsetValue (ifcfg, "OPTIONS"); num_opts = nm_setting_wired_get_num_s390_options (s_wired); @@ -1102,7 +1071,7 @@ write_wired_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) g_string_append_printf (str, "%s=%s", s390_key, s390_val); } if (str->len) - svSetValueString (ifcfg, "OPTIONS", str->str); + svSetValueStr (ifcfg, "OPTIONS", str->str); g_string_free (str, TRUE); } @@ -1166,12 +1135,12 @@ write_wired_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) g_string_append_printf (str, "s sopass %s", wol_password); } if (str) { - svSetValueString (ifcfg, "ETHTOOL_OPTS", str->str); + svSetValueStr (ifcfg, "ETHTOOL_OPTS", str->str); g_string_free (str, TRUE); } /* End ETHTOOL_OPT stuffing */ - svSetValueString (ifcfg, "TYPE", TYPE_ETHERNET); + svSetValueStr (ifcfg, "TYPE", TYPE_ETHERNET); return TRUE; } @@ -1213,18 +1182,18 @@ write_wired_for_virtual (NMConnection *connection, shvarFile *ifcfg) has_wired = TRUE; device_mac = nm_setting_wired_get_mac_address (s_wired); - svSetValueString (ifcfg, "HWADDR", device_mac); + svSetValueStr (ifcfg, "HWADDR", device_mac); cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired); - svSetValueString (ifcfg, "MACADDR", cloned_mac); + svSetValueStr (ifcfg, "MACADDR", cloned_mac); - svSetValueString (ifcfg, "GENERATE_MAC_ADDRESS_MASK", - nm_setting_wired_get_generate_mac_address_mask (s_wired)); + svSetValueStr (ifcfg, "GENERATE_MAC_ADDRESS_MASK", + nm_setting_wired_get_generate_mac_address_mask (s_wired)); mtu = nm_setting_wired_get_mtu (s_wired); if (mtu) { tmp = g_strdup_printf ("%u", mtu); - svSetValueString (ifcfg, "MTU", tmp); + svSetValueStr (ifcfg, "MTU", tmp); g_free (tmp); } else svUnsetValue (ifcfg, "MTU"); @@ -1256,13 +1225,13 @@ write_vlan_setting (NMConnection *connection, shvarFile *ifcfg, gboolean *wired, return FALSE; } - svSetValueString (ifcfg, "VLAN", "yes"); - svSetValueString (ifcfg, "TYPE", TYPE_VLAN); - svSetValueString (ifcfg, "DEVICE", nm_setting_connection_get_interface_name (s_con)); - svSetValueString (ifcfg, "PHYSDEV", nm_setting_vlan_get_parent (s_vlan)); + svSetValueStr (ifcfg, "VLAN", "yes"); + svSetValueStr (ifcfg, "TYPE", TYPE_VLAN); + svSetValueStr (ifcfg, "DEVICE", nm_setting_connection_get_interface_name (s_con)); + svSetValueStr (ifcfg, "PHYSDEV", nm_setting_vlan_get_parent (s_vlan)); tmp = g_strdup_printf ("%d", nm_setting_vlan_get_id (s_vlan)); - svSetValueString (ifcfg, "VLAN_ID", tmp); + svSetValueStr (ifcfg, "VLAN_ID", tmp); g_free (tmp); vlan_flags = nm_setting_vlan_get_flags (s_vlan); @@ -1276,16 +1245,16 @@ write_vlan_setting (NMConnection *connection, shvarFile *ifcfg, gboolean *wired, if (!NM_FLAGS_HAS (vlan_flags, NM_VLAN_FLAG_REORDER_HEADERS)) nm_utils_strbuf_append (&s_buf_ptr, &s_buf_len, "%sNO_REORDER_HDR", s_buf[0] ? "," : ""); - svSetValueString (ifcfg, "VLAN_FLAGS", s_buf); + svSetValueStr (ifcfg, "VLAN_FLAGS", s_buf); svSetValueBoolean (ifcfg, "MVRP", NM_FLAGS_HAS (vlan_flags, NM_VLAN_FLAG_MVRP)); tmp = vlan_priority_maplist_to_stringlist (s_vlan, NM_VLAN_INGRESS_MAP); - svSetValueString (ifcfg, "VLAN_INGRESS_PRIORITY_MAP", tmp); + svSetValueStr (ifcfg, "VLAN_INGRESS_PRIORITY_MAP", tmp); g_free (tmp); tmp = vlan_priority_maplist_to_stringlist (s_vlan, NM_VLAN_EGRESS_MAP); - svSetValueString (ifcfg, "VLAN_EGRESS_PRIORITY_MAP", tmp); + svSetValueStr (ifcfg, "VLAN_EGRESS_PRIORITY_MAP", tmp); g_free (tmp); svUnsetValue (ifcfg, "HWADDR"); @@ -1318,7 +1287,7 @@ write_bonding_setting (NMConnection *connection, shvarFile *ifcfg, gboolean *wir return FALSE; } - svSetValueString (ifcfg, "DEVICE", iface); + svSetValueStr (ifcfg, "DEVICE", iface); svUnsetValue (ifcfg, "BONDING_OPTS"); num_opts = nm_setting_bond_get_num_options (s_bond); @@ -1338,13 +1307,13 @@ write_bonding_setting (NMConnection *connection, shvarFile *ifcfg, gboolean *wir } if (str->len) - svSetValueString (ifcfg, "BONDING_OPTS", str->str); + svSetValueStr (ifcfg, "BONDING_OPTS", str->str); g_string_free (str, TRUE); } - svSetValueString (ifcfg, "TYPE", TYPE_BOND); - svSetValueString (ifcfg, "BONDING_MASTER", "yes"); + svSetValueStr (ifcfg, "TYPE", TYPE_BOND); + svSetValueStr (ifcfg, "BONDING_MASTER", "yes"); *wired = write_wired_for_virtual (connection, ifcfg); @@ -1372,9 +1341,9 @@ write_team_setting (NMConnection *connection, shvarFile *ifcfg, gboolean *wired, return FALSE; } - svSetValueString (ifcfg, "DEVICE", iface); + svSetValueStr (ifcfg, "DEVICE", iface); config = nm_setting_team_get_config (s_team); - svSetValueString (ifcfg, "TEAM_CONFIG", config); + svSetValueStr (ifcfg, "TEAM_CONFIG", config); *wired = write_wired_for_virtual (connection, ifcfg); @@ -1440,24 +1409,24 @@ write_bridge_setting (NMConnection *connection, shvarFile *ifcfg, GError **error return FALSE; } - svSetValueString (ifcfg, "DEVICE", iface); + svSetValueStr (ifcfg, "DEVICE", iface); svUnsetValue (ifcfg, "BRIDGING_OPTS"); svSetValueBoolean (ifcfg, "STP", FALSE); svUnsetValue (ifcfg, "DELAY"); mac = nm_setting_bridge_get_mac_address (s_bridge); - svSetValueString (ifcfg, "MACADDR", mac); + svSetValueStr (ifcfg, "MACADDR", mac); /* Bridge options */ opts = g_string_sized_new (32); if (nm_setting_bridge_get_stp (s_bridge)) { - svSetValueString (ifcfg, "STP", "yes"); + svSetValueStr (ifcfg, "STP", "yes"); i = nm_setting_bridge_get_forward_delay (s_bridge); if (i != get_setting_default_uint (NM_SETTING (s_bridge), NM_SETTING_BRIDGE_FORWARD_DELAY)) { s = g_strdup_printf ("%u", i); - svSetValueString (ifcfg, "DELAY", s); + svSetValueStr (ifcfg, "DELAY", s); g_free (s); } @@ -1493,10 +1462,10 @@ write_bridge_setting (NMConnection *connection, shvarFile *ifcfg, GError **error } if (opts->len) - svSetValueString (ifcfg, "BRIDGING_OPTS", opts->str); + svSetValueStr (ifcfg, "BRIDGING_OPTS", opts->str); g_string_free (opts, TRUE); - svSetValueString (ifcfg, "TYPE", TYPE_BRIDGE); + svSetValueStr (ifcfg, "TYPE", TYPE_BRIDGE); return TRUE; } @@ -1535,7 +1504,7 @@ write_bridge_port_setting (NMConnection *connection, shvarFile *ifcfg, GError ** } if (opts->len) - svSetValueString (ifcfg, "BRIDGING_OPTS", opts->str); + svSetValueStr (ifcfg, "BRIDGING_OPTS", opts->str); g_string_free (opts, TRUE); return TRUE; @@ -1552,7 +1521,7 @@ write_team_port_setting (NMConnection *connection, shvarFile *ifcfg, GError **er return TRUE; config = nm_setting_team_port_get_config (s_port); - svSetValueString (ifcfg, "TEAM_PORT_CONFIG", config); + svSetValueStr (ifcfg, "TEAM_PORT_CONFIG", config); return TRUE; } @@ -1563,13 +1532,13 @@ write_dcb_flags (shvarFile *ifcfg, const char *tag, NMSettingDcbFlags flags) char prop[NM_STRLEN ("DCB_xxxxxxxxxxxxxxxxxxxxxxx_yyyyyyyyyyyyyyyyyyyy")]; nm_sprintf_buf (prop, "DCB_%s_ENABLE", tag); - svSetValueString (ifcfg, prop, (flags & NM_SETTING_DCB_FLAG_ENABLE) ? "yes" : NULL); + svSetValueStr (ifcfg, prop, (flags & NM_SETTING_DCB_FLAG_ENABLE) ? "yes" : NULL); nm_sprintf_buf (prop, "DCB_%s_ADVERTISE", tag); - svSetValueString (ifcfg, prop, (flags & NM_SETTING_DCB_FLAG_ADVERTISE) ? "yes" : NULL); + svSetValueStr (ifcfg, prop, (flags & NM_SETTING_DCB_FLAG_ADVERTISE) ? "yes" : NULL); nm_sprintf_buf (prop, "DCB_%s_WILLING", tag); - svSetValueString (ifcfg, prop, (flags & NM_SETTING_DCB_FLAG_WILLING) ? "yes" : NULL); + svSetValueStr (ifcfg, prop, (flags & NM_SETTING_DCB_FLAG_WILLING) ? "yes" : NULL); } static void @@ -1609,7 +1578,7 @@ write_dcb_bool_array (shvarFile *ifcfg, str[8] = 0; for (i = 0; i < 8; i++) str[i] = get_func (s_dcb, i) ? '1' : '0'; - svSetValueString (ifcfg, key, str); + svSetValueStr (ifcfg, key, str); } typedef guint (*DcbGetUintFunc) (NMSettingDcb *, guint); @@ -1639,7 +1608,7 @@ write_dcb_uint_array (shvarFile *ifcfg, else g_assert_not_reached (); } - svSetValueString (ifcfg, key, str); + svSetValueStr (ifcfg, key, str); } static void @@ -1663,7 +1632,7 @@ write_dcb_percent_array (shvarFile *ifcfg, g_string_append_c (str, ','); g_string_append_printf (str, "%d", get_func (s_dcb, i)); } - svSetValueString (ifcfg, key, str->str); + svSetValueStr (ifcfg, key, str->str); g_string_free (str, TRUE); } @@ -1707,13 +1676,13 @@ write_dcb_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) return TRUE; } - svSetValueString (ifcfg, "DCB", "yes"); + svSetValueStr (ifcfg, "DCB", "yes"); write_dcb_app (ifcfg, "APP_FCOE", nm_setting_dcb_get_app_fcoe_flags (s_dcb), nm_setting_dcb_get_app_fcoe_priority (s_dcb)); if (nm_setting_dcb_get_app_fcoe_flags (s_dcb) & NM_SETTING_DCB_FLAG_ENABLE) - svSetValueString (ifcfg, KEY_DCB_APP_FCOE_MODE, nm_setting_dcb_get_app_fcoe_mode (s_dcb)); + svSetValueStr (ifcfg, KEY_DCB_APP_FCOE_MODE, nm_setting_dcb_get_app_fcoe_mode (s_dcb)); else svUnsetValue (ifcfg, KEY_DCB_APP_FCOE_MODE); @@ -1749,21 +1718,21 @@ write_connection_setting (NMSettingConnection *s_con, shvarFile *ifcfg) char *tmp; gint i_int; - svSetValueString (ifcfg, "NAME", nm_setting_connection_get_id (s_con)); - svSetValueString (ifcfg, "UUID", nm_setting_connection_get_uuid (s_con)); - svSetValueString (ifcfg, "STABLE_ID", nm_setting_connection_get_stable_id (s_con)); - svSetValueString (ifcfg, "DEVICE", nm_setting_connection_get_interface_name (s_con)); + svSetValueStr (ifcfg, "NAME", nm_setting_connection_get_id (s_con)); + svSetValueStr (ifcfg, "UUID", nm_setting_connection_get_uuid (s_con)); + svSetValueStr (ifcfg, "STABLE_ID", nm_setting_connection_get_stable_id (s_con)); + svSetValueStr (ifcfg, "DEVICE", nm_setting_connection_get_interface_name (s_con)); svSetValueBoolean (ifcfg, "ONBOOT", nm_setting_connection_get_autoconnect (s_con)); i_int = nm_setting_connection_get_autoconnect_priority (s_con); tmp = i_int != NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_DEFAULT ? g_strdup_printf ("%d", i_int) : NULL; - svSetValueString (ifcfg, "AUTOCONNECT_PRIORITY", tmp); + svSetValueStr (ifcfg, "AUTOCONNECT_PRIORITY", tmp); g_free (tmp); i_int = nm_setting_connection_get_autoconnect_retries (s_con); tmp = i_int != -1 ? g_strdup_printf ("%d", i_int) : NULL; - svSetValueString (ifcfg, "AUTOCONNECT_RETRIES", tmp); + svSetValueStr (ifcfg, "AUTOCONNECT_RETRIES", tmp); g_free (tmp); /* Only save the value for master connections */ @@ -1773,9 +1742,9 @@ write_connection_setting (NMSettingConnection *s_con, shvarFile *ifcfg) || !g_strcmp0 (type, NM_SETTING_BRIDGE_SETTING_NAME)) { NMSettingConnectionAutoconnectSlaves autoconnect_slaves; autoconnect_slaves = nm_setting_connection_get_autoconnect_slaves (s_con); - svSetValueString (ifcfg, "AUTOCONNECT_SLAVES", - autoconnect_slaves == NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_YES ? "yes" : - autoconnect_slaves == NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_NO ? "no" : NULL); + svSetValueStr (ifcfg, "AUTOCONNECT_SLAVES", + autoconnect_slaves == NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_YES ? "yes" : + autoconnect_slaves == NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_NO ? "no" : NULL); } else svUnsetValue (ifcfg, "AUTOCONNECT_SLAVES"); @@ -1789,7 +1758,7 @@ write_connection_setting (NMSettingConnection *s_con, shvarFile *ifcfg) default: tmp = NULL; } - svSetValueString (ifcfg, "LLDP", tmp); + svSetValueStr (ifcfg, "LLDP", tmp); /* Permissions */ svUnsetValue (ifcfg, "USERS"); @@ -1809,19 +1778,19 @@ write_connection_setting (NMSettingConnection *s_con, shvarFile *ifcfg) if (nm_setting_connection_get_permission (s_con, i, NULL, &puser, NULL)) g_string_append (str, puser); } - svSetValueString (ifcfg, "USERS", str->str); + svSetValueStr (ifcfg, "USERS", str->str); g_string_free (str, TRUE); } - svSetValueString (ifcfg, "ZONE", nm_setting_connection_get_zone(s_con)); + svSetValueStr (ifcfg, "ZONE", nm_setting_connection_get_zone (s_con)); - svSetValueString (ifcfg, "MASTER_UUID", NULL); - svSetValueString (ifcfg, "MASTER", NULL); - svSetValueString (ifcfg, "SLAVE", NULL); - svSetValueString (ifcfg, "BRIDGE_UUID", NULL); - svSetValueString (ifcfg, "BRIDGE", NULL); - svSetValueString (ifcfg, "TEAM_MASTER_UUID", NULL); - svSetValueString (ifcfg, "TEAM_MASTER", NULL); + svSetValueStr (ifcfg, "MASTER_UUID", NULL); + svSetValueStr (ifcfg, "MASTER", NULL); + svSetValueStr (ifcfg, "SLAVE", NULL); + svSetValueStr (ifcfg, "BRIDGE_UUID", NULL); + svSetValueStr (ifcfg, "BRIDGE", NULL); + svSetValueStr (ifcfg, "TEAM_MASTER_UUID", NULL); + svSetValueStr (ifcfg, "TEAM_MASTER", NULL); master = nm_setting_connection_get_master (s_con); if (master) { @@ -1838,23 +1807,23 @@ write_connection_setting (NMSettingConnection *s_con, shvarFile *ifcfg) } if (nm_setting_connection_is_slave_type (s_con, NM_SETTING_BOND_SETTING_NAME)) { - svSetValueString (ifcfg, "MASTER_UUID", master); - svSetValueString (ifcfg, "MASTER", master_iface); - svSetValueString (ifcfg, "SLAVE", "yes"); + svSetValueStr (ifcfg, "MASTER_UUID", master); + svSetValueStr (ifcfg, "MASTER", master_iface); + svSetValueStr (ifcfg, "SLAVE", "yes"); } else if (nm_setting_connection_is_slave_type (s_con, NM_SETTING_BRIDGE_SETTING_NAME)) { - svSetValueString (ifcfg, "BRIDGE_UUID", master); - svSetValueString (ifcfg, "BRIDGE", master_iface); + svSetValueStr (ifcfg, "BRIDGE_UUID", master); + svSetValueStr (ifcfg, "BRIDGE", master_iface); } else if (nm_setting_connection_is_slave_type (s_con, NM_SETTING_TEAM_SETTING_NAME)) { - svSetValueString (ifcfg, "TEAM_MASTER_UUID", master); - svSetValueString (ifcfg, "TEAM_MASTER", master_iface); + svSetValueStr (ifcfg, "TEAM_MASTER_UUID", master); + svSetValueStr (ifcfg, "TEAM_MASTER", master_iface); svUnsetValue (ifcfg, "TYPE"); } } if (nm_streq0 (type, NM_SETTING_TEAM_SETTING_NAME)) - svSetValueString (ifcfg, "DEVICETYPE", TYPE_TEAM); + svSetValueStr (ifcfg, "DEVICETYPE", TYPE_TEAM); else if (master_iface && nm_setting_connection_is_slave_type (s_con, NM_SETTING_TEAM_SETTING_NAME)) - svSetValueString (ifcfg, "DEVICETYPE", TYPE_TEAM_PORT); + svSetValueStr (ifcfg, "DEVICETYPE", TYPE_TEAM_PORT); else svUnsetValue (ifcfg, "DEVICETYPE"); @@ -1876,40 +1845,94 @@ write_connection_setting (NMSettingConnection *s_con, shvarFile *ifcfg) if ((uuid = nm_setting_connection_get_secondary (s_con, i)) != NULL) g_string_append (str, uuid); } - svSetValueString (ifcfg, "SECONDARY_UUIDS", str->str); + svSetValueStr (ifcfg, "SECONDARY_UUIDS", str->str); g_string_free (str, TRUE); } svUnsetValue (ifcfg, "GATEWAY_PING_TIMEOUT"); if (nm_setting_connection_get_gateway_ping_timeout (s_con)) { tmp = g_strdup_printf ("%" G_GUINT32_FORMAT, nm_setting_connection_get_gateway_ping_timeout (s_con)); - svSetValueString (ifcfg, "GATEWAY_PING_TIMEOUT", tmp); + svSetValueStr (ifcfg, "GATEWAY_PING_TIMEOUT", tmp); g_free (tmp); } switch (nm_setting_connection_get_metered (s_con)) { case NM_METERED_YES: - svSetValueString (ifcfg, "CONNECTION_METERED", "yes"); + svSetValueStr (ifcfg, "CONNECTION_METERED", "yes"); break; case NM_METERED_NO: - svSetValueString (ifcfg, "CONNECTION_METERED", "no"); + svSetValueStr (ifcfg, "CONNECTION_METERED", "no"); break; default: svUnsetValue (ifcfg, "CONNECTION_METERED"); } } +static char * +get_route_attributes_string (NMIPRoute *route, int family) +{ + gs_strfreev char **names = NULL; + GVariant *attr, *lock; + GString *str; + int i; + + names = nm_ip_route_get_attribute_names (route); + if (!names || !names[0]) + return NULL; + + str = g_string_new (""); + + for (i = 0; names[i]; i++) { + attr = nm_ip_route_get_attribute (route, names[i]); + + if (!nm_ip_route_attribute_validate (names[i], attr, family, NULL, NULL)) + continue; + + if (NM_IN_STRSET (names[i], NM_IP_ROUTE_ATTRIBUTE_WINDOW, + NM_IP_ROUTE_ATTRIBUTE_CWND, + NM_IP_ROUTE_ATTRIBUTE_INITCWND, + NM_IP_ROUTE_ATTRIBUTE_INITRWND, + NM_IP_ROUTE_ATTRIBUTE_MTU)) { + char lock_name[256]; + + nm_sprintf_buf (lock_name, "lock-%s", names[i]); + lock = nm_ip_route_get_attribute (route, lock_name); + + g_string_append_printf (str, + "%s %s%u", + names[i], + (lock && g_variant_get_boolean (lock)) ? "lock " : "", + g_variant_get_uint32 (attr)); + } else if (strstr (names[i], "lock-")) { + /* handled above */ + } else if (nm_streq (names[i], NM_IP_ROUTE_ATTRIBUTE_TOS)) { + g_string_append_printf (str, "%s %u", names[i], (unsigned) g_variant_get_byte (attr)); + } else if ( nm_streq (names[i], NM_IP_ROUTE_ATTRIBUTE_SRC) + || nm_streq (names[i], NM_IP_ROUTE_ATTRIBUTE_FROM)) { + char *arg = nm_streq (names[i], NM_IP_ROUTE_ATTRIBUTE_SRC) ? "src" : "from"; + + g_string_append_printf (str, "%s %s", arg, g_variant_get_string (attr, NULL)); + } else { + _LOGW ("unknown route option '%s'", names[i]); + continue; + } + if (names[i + 1]) + g_string_append_c (str, ' '); + } + + return g_string_free (str, FALSE); +} + static gboolean write_route_file_legacy (const char *filename, NMSettingIPConfig *s_ip4, GError **error) { 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); @@ -1922,8 +1945,10 @@ write_route_file_legacy (const char *filename, NMSettingIPConfig *s_ip4, GError return TRUE; } - route_items = g_malloc0 (sizeof (char*) * (num + 1)); + route_items = g_malloc0 (sizeof (char *) * (num + 1)); for (i = 0; i < num; i++) { + gs_free char *options = NULL; + route = nm_setting_ip_config_get_route (s_ip4, i); dest = nm_ip_route_get_dest (route); @@ -1931,10 +1956,19 @@ write_route_file_legacy (const char *filename, NMSettingIPConfig *s_ip4, GError next_hop = nm_ip_route_get_next_hop (route); metric = nm_ip_route_get_metric (route); - if (metric == -1) - route_items[i] = g_strdup_printf ("%s/%u via %s\n", dest, prefix, next_hop); - else - route_items[i] = g_strdup_printf ("%s/%u via %s metric %u\n", dest, prefix, next_hop, (guint32) metric); + options = get_route_attributes_string (route, AF_INET); + + if (metric == -1) { + route_items[i] = g_strdup_printf ("%s/%u via %s%s%s\n", + dest, prefix, next_hop, + options ? " " : "", + options ?: ""); + } else { + route_items[i] = g_strdup_printf ("%s/%u via %s metric %u%s%s\n", + dest, prefix, next_hop, (guint32) metric, + options ? " " : "", + options ?: ""); + } } route_items[num] = NULL; route_contents = g_strjoinv (NULL, route_items); @@ -1943,15 +1977,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 @@ -1972,19 +2001,19 @@ write_proxy_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) method = nm_setting_proxy_get_method (s_proxy); switch (method) { case NM_SETTING_PROXY_METHOD_AUTO: - svSetValueString (ifcfg, "PROXY_METHOD", "auto"); + svSetValueStr (ifcfg, "PROXY_METHOD", "auto"); pac_url = nm_setting_proxy_get_pac_url (s_proxy); if (pac_url) - svSetValueString (ifcfg, "PAC_URL", pac_url); + svSetValueStr (ifcfg, "PAC_URL", pac_url); pac_script = nm_setting_proxy_get_pac_script (s_proxy); if (pac_script) - svSetValueString (ifcfg, "PAC_SCRIPT", pac_script); + svSetValueStr (ifcfg, "PAC_SCRIPT", pac_script); break; case NM_SETTING_PROXY_METHOD_NONE: - svSetValueString (ifcfg, "PROXY_METHOD", "none"); + svSetValueStr (ifcfg, "PROXY_METHOD", "none"); break; } @@ -1993,15 +2022,52 @@ write_proxy_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) return TRUE; } +static gboolean +write_user_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) +{ + NMSettingUser *s_user; + guint i, len; + const char *const*keys; + + s_user = NM_SETTING_USER (nm_connection_get_setting (connection, NM_TYPE_SETTING_USER)); + + svUnsetValuesWithPrefix (ifcfg, "NM_USER_"); + + if (!s_user) + return TRUE; + + keys = nm_setting_user_get_keys (s_user, &len); + if (len) { + nm_auto_free_gstring GString *str = g_string_sized_new (100); + + for (i = 0; i < len; i++) { + const char *key = keys[i]; + + g_string_set_size (str, 0); + g_string_append (str, "NM_USER_"); + nms_ifcfg_rh_utils_user_key_encode (key, str); + svSetValue (ifcfg, + str->str, + nm_setting_user_get_data (s_user, key)); + } + } + + return TRUE; +} + static gboolean write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) { NMSettingIPConfig *s_ip4; const char *value; - char *addr_key, *prefix_key, *netmask_key, *gw_key, *metric_key, *tmp; + char *tmp; + char addr_key[64]; + char prefix_key[64]; + char netmask_key[64]; + char gw_key[64]; char *route_path = NULL; - gint32 j; - guint32 i, n, num; + gint j; + guint i, num, n; gint64 route_metric; gint priority; int timeout; @@ -2041,26 +2107,21 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) svUnsetValue (ifcfg, "BOOTPROTO"); for (j = -1; j < 256; j++) { if (j == -1) { - addr_key = g_strdup ("IPADDR"); - prefix_key = g_strdup ("PREFIX"); - netmask_key = g_strdup ("NETMASK"); - gw_key = g_strdup ("GATEWAY"); + nm_sprintf_buf (addr_key, "IPADDR"); + nm_sprintf_buf (prefix_key, "PREFIX"); + nm_sprintf_buf (netmask_key, "NETMASK"); + nm_sprintf_buf (gw_key, "GATEWAY"); } else { - addr_key = g_strdup_printf ("IPADDR%d", j); - prefix_key = g_strdup_printf ("PREFIX%d", j); - netmask_key = g_strdup_printf ("NETMASK%d", j); - gw_key = g_strdup_printf ("GATEWAY%d", j); + nm_sprintf_buf (addr_key, "IPADDR%d", (guint) j); + nm_sprintf_buf (prefix_key, "PREFIX%u", (guint) j); + nm_sprintf_buf (netmask_key, "NETMASK%u", (guint) j); + nm_sprintf_buf (gw_key, "GATEWAY%u", (guint) j); } svUnsetValue (ifcfg, addr_key); svUnsetValue (ifcfg, prefix_key); svUnsetValue (ifcfg, netmask_key); svUnsetValue (ifcfg, gw_key); - - g_free (addr_key); - g_free (prefix_key); - g_free (netmask_key); - g_free (gw_key); } route_path = utils_get_route_path (svFileGetName (ifcfg)); @@ -2069,14 +2130,20 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) return TRUE; } + num = nm_setting_ip_config_get_num_addresses (s_ip4); + if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) - svSetValueString (ifcfg, "BOOTPROTO", "dhcp"); - else if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL)) - svSetValueString (ifcfg, "BOOTPROTO", "none"); - else if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL)) - svSetValueString (ifcfg, "BOOTPROTO", "autoip"); + svSetValueStr (ifcfg, "BOOTPROTO", "dhcp"); + else if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL)) { + /* Preserve the archaic form of "static" if there actually + * is static configuration. */ + if (g_strcmp0 (svGetValue (ifcfg, "BOOTPROTO", &tmp), "static") || !num) + svSetValueStr (ifcfg, "BOOTPROTO", "none"); + g_free (tmp); + } else if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL)) + svSetValueStr (ifcfg, "BOOTPROTO", "autoip"); else if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED)) - svSetValueString (ifcfg, "BOOTPROTO", "shared"); + svSetValueStr (ifcfg, "BOOTPROTO", "shared"); /* Clear out un-numbered IP address fields */ svUnsetValue (ifcfg, "IPADDR"); @@ -2092,9 +2159,9 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) /* Write out IPADDR, PREFIX, GATEWAY for current IP addresses * without labels. Unset obsolete NETMASK. */ - num = nm_setting_ip_config_get_num_addresses (s_ip4); for (i = n = 0; i < num; i++) { NMIPAddress *addr; + guint prefix; addr = nm_setting_ip_config_get_address (s_ip4, i); @@ -2112,66 +2179,62 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) * See https://bugzilla.redhat.com/show_bug.cgi?id=771673 * and https://bugzilla.redhat.com/show_bug.cgi?id=1105770 */ - addr_key = g_strdup ("IPADDR"); - prefix_key = g_strdup ("PREFIX"); - netmask_key = g_strdup ("NETMASK"); - gw_key = g_strdup ("GATEWAY"); + nm_sprintf_buf (addr_key, "IPADDR"); + nm_sprintf_buf (prefix_key, "PREFIX"); + nm_sprintf_buf (netmask_key, "NETMASK"); + nm_sprintf_buf (gw_key, "GATEWAY"); } else { - addr_key = g_strdup_printf ("IPADDR%d", n); - prefix_key = g_strdup_printf ("PREFIX%d", n); - netmask_key = g_strdup_printf ("NETMASK%d", n); - gw_key = g_strdup_printf ("GATEWAY%d", n); + nm_sprintf_buf (addr_key, "IPADDR%u", n); + nm_sprintf_buf (prefix_key, "PREFIX%u", n); + nm_sprintf_buf (netmask_key, "NETMASK%u", n); + nm_sprintf_buf (gw_key, "GATEWAY%u", n); } - svSetValueString (ifcfg, addr_key, nm_ip_address_get_address (addr)); + svSetValueStr (ifcfg, addr_key, nm_ip_address_get_address (addr)); - tmp = g_strdup_printf ("%u", nm_ip_address_get_prefix (addr)); - svSetValueString (ifcfg, prefix_key, tmp); + prefix = nm_ip_address_get_prefix (addr); + tmp = g_strdup_printf ("%u", prefix); + svSetValueStr (ifcfg, prefix_key, tmp); g_free (tmp); - svUnsetValue (ifcfg, netmask_key); - svUnsetValue (ifcfg, gw_key); + /* If the legacy "NETMASK" is present, keep it. */ + if (svGetValue (ifcfg, netmask_key, &tmp)) { + char buf[INET_ADDRSTRLEN]; - g_free (addr_key); - g_free (prefix_key); - g_free (netmask_key); - g_free (gw_key); + g_free (tmp); + svSetValueStr (ifcfg, netmask_key, nm_utils_inet4_ntop (prefix, buf)); + } + + svUnsetValue (ifcfg, gw_key); n++; } /* Clear remaining IPADDR, etc */ - for (; n < 256; n++) { - addr_key = g_strdup_printf ("IPADDR%d", n); - prefix_key = g_strdup_printf ("PREFIX%d", n); - netmask_key = g_strdup_printf ("NETMASK%d", n); - gw_key = g_strdup_printf ("GATEWAY%d", n); + for (i = n; i < 256; i++) { + nm_sprintf_buf (addr_key, "IPADDR%u", i); + nm_sprintf_buf (prefix_key, "PREFIX%u", i); + nm_sprintf_buf (netmask_key, "NETMASK%u", i); + nm_sprintf_buf (gw_key, "GATEWAY%u", i); svUnsetValue (ifcfg, addr_key); svUnsetValue (ifcfg, prefix_key); svUnsetValue (ifcfg, netmask_key); svUnsetValue (ifcfg, gw_key); - - g_free (addr_key); - g_free (prefix_key); - g_free (netmask_key); - g_free (gw_key); } - svSetValueString (ifcfg, "GATEWAY", nm_setting_ip_config_get_gateway (s_ip4)); + svSetValueStr (ifcfg, "GATEWAY", nm_setting_ip_config_get_gateway (s_ip4)); num = nm_setting_ip_config_get_num_dns (s_ip4); for (i = 0; i < 254; i++) { const char *dns; - addr_key = g_strdup_printf ("DNS%d", i + 1); - + nm_sprintf_buf (addr_key, "DNS%u", i + 1); if (i >= num) svUnsetValue (ifcfg, addr_key); else { dns = nm_setting_ip_config_get_dns (s_ip4, i); - svSetValueString (ifcfg, addr_key, dns); + svSetValueStr (ifcfg, addr_key, dns); } - g_free (addr_key); } num = nm_setting_ip_config_get_num_dns_searches (s_ip4); @@ -2182,7 +2245,7 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) g_string_append_c (searches, ' '); g_string_append (searches, nm_setting_ip_config_get_dns_search (s_ip4, i)); } - svSetValueString (ifcfg, "DOMAIN", searches->str); + svSetValueStr (ifcfg, "DOMAIN", searches->str); g_string_free (searches, TRUE); } else svUnsetValue (ifcfg, "DOMAIN"); @@ -2191,37 +2254,37 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) svSetValueBoolean (ifcfg, "DEFROUTE", !nm_setting_ip_config_get_never_default (s_ip4)); /* Missing PEERDNS means TRUE, so write it only when is FALSE */ - svSetValueString (ifcfg, "PEERDNS", - nm_setting_ip_config_get_ignore_auto_dns (s_ip4) ? "no" : NULL); + svSetValueStr (ifcfg, "PEERDNS", + nm_setting_ip_config_get_ignore_auto_dns (s_ip4) ? "no" : NULL); /* Missing PEERROUTES means TRUE, so write it only when is FALSE */ - svSetValueString (ifcfg, "PEERROUTES", - nm_setting_ip_config_get_ignore_auto_routes (s_ip4) ? "no" : NULL); + svSetValueStr (ifcfg, "PEERROUTES", + nm_setting_ip_config_get_ignore_auto_routes (s_ip4) ? "no" : NULL); value = nm_setting_ip_config_get_dhcp_hostname (s_ip4); - svSetValueString (ifcfg, "DHCP_HOSTNAME", value); + svSetValueStr (ifcfg, "DHCP_HOSTNAME", value); value = nm_setting_ip4_config_get_dhcp_fqdn (NM_SETTING_IP4_CONFIG (s_ip4)); - svSetValueString (ifcfg, "DHCP_FQDN", value); + svSetValueStr (ifcfg, "DHCP_FQDN", value); /* Missing DHCP_SEND_HOSTNAME means TRUE, and we prefer not write it explicitly * in that case, because it is NM-specific variable */ - svSetValueString (ifcfg, "DHCP_SEND_HOSTNAME", - nm_setting_ip_config_get_dhcp_send_hostname (s_ip4) ? NULL : "no"); + svSetValueStr (ifcfg, "DHCP_SEND_HOSTNAME", + nm_setting_ip_config_get_dhcp_send_hostname (s_ip4) ? NULL : "no"); value = nm_setting_ip4_config_get_dhcp_client_id (NM_SETTING_IP4_CONFIG (s_ip4)); - svSetValueString (ifcfg, "DHCP_CLIENT_ID", value); + svSetValueStr (ifcfg, "DHCP_CLIENT_ID", value); timeout = nm_setting_ip_config_get_dhcp_timeout (s_ip4); tmp = timeout ? g_strdup_printf ("%d", timeout) : NULL; - svSetValueString (ifcfg, "IPV4_DHCP_TIMEOUT", tmp); + svSetValueStr (ifcfg, "IPV4_DHCP_TIMEOUT", tmp); g_free (tmp); svSetValueBoolean (ifcfg, "IPV4_FAILURE_FATAL", !nm_setting_ip_config_get_may_fail (s_ip4)); route_metric = nm_setting_ip_config_get_route_metric (s_ip4); tmp = route_metric != -1 ? g_strdup_printf ("%"G_GINT64_FORMAT, route_metric) : NULL; - svSetValueString (ifcfg, "IPV4_ROUTE_METRIC", tmp); + svSetValueStr (ifcfg, "IPV4_ROUTE_METRIC", tmp); g_free (tmp); /* Static routes - route- file */ @@ -2250,28 +2313,34 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) NMIPRoute *route; guint32 netmask; gint64 metric; + char metric_key[64]; + char options_key[64]; - addr_key = g_strdup_printf ("ADDRESS%d", i); - netmask_key = g_strdup_printf ("NETMASK%d", i); - gw_key = g_strdup_printf ("GATEWAY%d", i); - metric_key = g_strdup_printf ("METRIC%d", i); + nm_sprintf_buf (addr_key, "ADDRESS%u", i); + nm_sprintf_buf (netmask_key, "NETMASK%u", i); + nm_sprintf_buf (gw_key, "GATEWAY%u", i); + nm_sprintf_buf (metric_key, "METRIC%u", i); + nm_sprintf_buf (options_key, "OPTIONS%u", i); if (i >= num) { svUnsetValue (routefile, addr_key); svUnsetValue (routefile, netmask_key); svUnsetValue (routefile, gw_key); svUnsetValue (routefile, metric_key); + svUnsetValue (routefile, options_key); } else { + gs_free char *options = NULL; + route = nm_setting_ip_config_get_route (s_ip4, i); - svSetValueString (routefile, addr_key, nm_ip_route_get_dest (route)); + svSetValueStr (routefile, addr_key, nm_ip_route_get_dest (route)); memset (buf, 0, sizeof (buf)); netmask = nm_utils_ip4_prefix_to_netmask (nm_ip_route_get_prefix (route)); inet_ntop (AF_INET, (const void *) &netmask, &buf[0], sizeof (buf)); - svSetValueString (routefile, netmask_key, &buf[0]); + svSetValueStr (routefile, netmask_key, &buf[0]); - svSetValueString (routefile, gw_key, nm_ip_route_get_next_hop (route)); + svSetValueStr (routefile, gw_key, nm_ip_route_get_next_hop (route)); memset (buf, 0, sizeof (buf)); metric = nm_ip_route_get_metric (route); @@ -2279,15 +2348,14 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) svUnsetValue (routefile, metric_key); else { tmp = g_strdup_printf ("%u", (guint32) metric); - svSetValueString (routefile, metric_key, tmp); + svSetValueStr (routefile, metric_key, tmp); g_free (tmp); } - } - g_free (addr_key); - g_free (netmask_key); - g_free (gw_key); - g_free (metric_key); + options = get_route_attributes_string (route, AF_INET); + if (options) + svSetValueStr (routefile, options_key, options); + } } if (!svWriteFile (routefile, 0644, error)) { svCloseFile (routefile); @@ -2305,7 +2373,7 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) if (timeout < 0) svUnsetValue (ifcfg, "ARPING_WAIT"); else if (timeout == 0) - svSetValueString (ifcfg, "ARPING_WAIT", "0"); + svSetValueStr (ifcfg, "ARPING_WAIT", "0"); else { /* Round the value up to next integer */ svSetValueInt64 (ifcfg, "ARPING_WAIT", (timeout - 1) / 1000 + 1); @@ -2325,7 +2393,7 @@ write_ip4_aliases (NMConnection *connection, char *base_ifcfg_path) { NMSettingIPConfig *s_ip4; gs_free char *base_ifcfg_dir = NULL, *base_ifcfg_name = NULL; - const char*base_name; + const char *base_name; int i, num, base_ifcfg_name_len, base_name_len; GDir *dir; @@ -2392,13 +2460,13 @@ write_ip4_aliases (NMConnection *connection, char *base_ifcfg_path) ifcfg = svCreateFile (path); g_free (path); - svSetValueString (ifcfg, "DEVICE", label); + svSetValueStr (ifcfg, "DEVICE", label); addr = nm_setting_ip_config_get_address (s_ip4, i); - svSetValueString (ifcfg, "IPADDR", nm_ip_address_get_address (addr)); + svSetValueStr (ifcfg, "IPADDR", nm_ip_address_get_address (addr)); tmp = g_strdup_printf ("%u", nm_ip_address_get_prefix (addr)); - svSetValueString (ifcfg, "PREFIX", tmp); + svSetValueStr (ifcfg, "PREFIX", tmp); g_free (tmp); svWriteFile (ifcfg, 0644, NULL); @@ -2409,16 +2477,13 @@ write_ip4_aliases (NMConnection *connection, char *base_ifcfg_path) static gboolean write_route6_file (const char *filename, NMSettingIPConfig *s_ip6, GError **error) { - char **route_items; - char *route_contents; + nm_auto_free_gstring GString *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); - g_return_val_if_fail (error != NULL, FALSE); - g_return_val_if_fail (*error == NULL, FALSE); + g_return_val_if_fail (filename, FALSE); + g_return_val_if_fail (s_ip6, FALSE); + g_return_val_if_fail (!error || !*error, FALSE); num = nm_setting_ip_config_get_num_routes (s_ip6); if (num == 0) { @@ -2426,38 +2491,39 @@ write_route6_file (const char *filename, NMSettingIPConfig *s_ip6, GError **erro return TRUE; } - route_items = g_malloc0 (sizeof (char*) * (num + 1)); + contents = g_string_new (""); for (i = 0; i < num; i++) { + gs_free char *options = NULL; + route = nm_setting_ip_config_get_route (s_ip6, i); + options = get_route_attributes_string (route, AF_INET6); if (nm_ip_route_get_metric (route) == -1) { - route_items[i] = g_strdup_printf ("%s/%u via %s\n", + g_string_append_printf (contents, "%s/%u via %s%s%s", nm_ip_route_get_dest (route), nm_ip_route_get_prefix (route), - nm_ip_route_get_next_hop (route)); + nm_ip_route_get_next_hop (route), + options ? " " : "", + options ?: ""); } else { - route_items[i] = g_strdup_printf ("%s/%u via %s metric %u\n", + g_string_append_printf (contents, "%s/%u via %s metric %u%s%s", nm_ip_route_get_dest (route), nm_ip_route_get_prefix (route), nm_ip_route_get_next_hop (route), - (guint32) nm_ip_route_get_metric (route)); + (unsigned) nm_ip_route_get_metric (route), + options ? " " : "", + options ?: ""); } + g_string_append (contents, "\n"); } - route_items[num] = NULL; - route_contents = g_strjoinv (NULL, route_items); - g_strfreev (route_items); - if (!g_file_set_contents (filename, route_contents, -1, NULL)) { + if (!g_file_set_contents (filename, contents->str, -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 @@ -2466,7 +2532,7 @@ write_ip6_setting_dhcp_hostname (NMSettingIPConfig *s_ip6, shvarFile *ifcfg) const char *hostname; hostname = nm_setting_ip_config_get_dhcp_hostname (s_ip6); - svSetValueString (ifcfg, "DHCPV6_HOSTNAME", hostname); + svSetValueStr (ifcfg, "DHCPV6_HOSTNAME", hostname); /* Missing DHCPV6_SEND_HOSTNAME means TRUE, and we prefer not write it * explicitly in that case, because it is NM-specific variable @@ -2474,7 +2540,7 @@ write_ip6_setting_dhcp_hostname (NMSettingIPConfig *s_ip6, shvarFile *ifcfg) if (nm_setting_ip_config_get_dhcp_send_hostname (s_ip6)) svUnsetValue (ifcfg, "DHCPV6_SEND_HOSTNAME"); else - svSetValueString (ifcfg, "DHCPV6_SEND_HOSTNAME", "no"); + svSetValueStr (ifcfg, "DHCPV6_SEND_HOSTNAME", "no"); } static gboolean @@ -2483,11 +2549,9 @@ write_ip6_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) NMSettingIPConfig *s_ip6; NMSettingIPConfig *s_ip4; const char *value; - char *addr_key; char *tmp; - guint32 i, num, num4; + guint i, num, num4; gint priority; - GString *searches; NMIPAddress *addr; const char *dns; gint64 route_metric; @@ -2518,28 +2582,28 @@ write_ip6_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) value = nm_setting_ip_config_get_method (s_ip6); g_assert (value); if (!strcmp (value, NM_SETTING_IP6_CONFIG_METHOD_IGNORE)) { - svSetValueString (ifcfg, "IPV6INIT", "no"); + svSetValueStr (ifcfg, "IPV6INIT", "no"); svUnsetValue (ifcfg, "DHCPV6C"); return TRUE; } else if (!strcmp (value, NM_SETTING_IP6_CONFIG_METHOD_AUTO)) { - svSetValueString (ifcfg, "IPV6INIT", "yes"); - svSetValueString (ifcfg, "IPV6_AUTOCONF", "yes"); + svSetValueStr (ifcfg, "IPV6INIT", "yes"); + svSetValueStr (ifcfg, "IPV6_AUTOCONF", "yes"); svUnsetValue (ifcfg, "DHCPV6C"); } else if (!strcmp (value, NM_SETTING_IP6_CONFIG_METHOD_DHCP)) { - svSetValueString (ifcfg, "IPV6INIT", "yes"); - svSetValueString (ifcfg, "IPV6_AUTOCONF", "no"); - svSetValueString (ifcfg, "DHCPV6C", "yes"); + svSetValueStr (ifcfg, "IPV6INIT", "yes"); + svSetValueStr (ifcfg, "IPV6_AUTOCONF", "no"); + svSetValueStr (ifcfg, "DHCPV6C", "yes"); } else if (!strcmp (value, NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) { - svSetValueString (ifcfg, "IPV6INIT", "yes"); - svSetValueString (ifcfg, "IPV6_AUTOCONF", "no"); + svSetValueStr (ifcfg, "IPV6INIT", "yes"); + svSetValueStr (ifcfg, "IPV6_AUTOCONF", "no"); svUnsetValue (ifcfg, "DHCPV6C"); } else if (!strcmp (value, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL)) { - svSetValueString (ifcfg, "IPV6INIT", "yes"); - svSetValueString (ifcfg, "IPV6_AUTOCONF", "no"); + svSetValueStr (ifcfg, "IPV6INIT", "yes"); + svSetValueStr (ifcfg, "IPV6_AUTOCONF", "no"); svUnsetValue (ifcfg, "DHCPV6C"); } else if (!strcmp (value, NM_SETTING_IP6_CONFIG_METHOD_SHARED)) { - svSetValueString (ifcfg, "IPV6INIT", "yes"); - svSetValueString (ifcfg, "IPV6_AUTOCONF", "shared"); + svSetValueStr (ifcfg, "IPV6INIT", "yes"); + svSetValueStr (ifcfg, "IPV6_AUTOCONF", "shared"); svUnsetValue (ifcfg, "DHCPV6C"); } @@ -2563,9 +2627,9 @@ write_ip6_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) nm_ip_address_get_address (addr), nm_ip_address_get_prefix (addr)); } - svSetValueString (ifcfg, "IPV6ADDR", ip_str1->str); - svSetValueString (ifcfg, "IPV6ADDR_SECONDARIES", ip_str2->str); - svSetValueString (ifcfg, "IPV6_DEFAULTGW", nm_setting_ip_config_get_gateway (s_ip6)); + svSetValueStr (ifcfg, "IPV6ADDR", ip_str1->str); + svSetValueStr (ifcfg, "IPV6ADDR_SECONDARIES", ip_str2->str); + svSetValueStr (ifcfg, "IPV6_DEFAULTGW", nm_setting_ip_config_get_gateway (s_ip6)); g_string_free (ip_str1, TRUE); g_string_free (ip_str2, TRUE); @@ -2574,68 +2638,68 @@ write_ip6_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) num4 = s_ip4 ? nm_setting_ip_config_get_num_dns (s_ip4) : 0; /* from where to start with IPv6 entries */ num = nm_setting_ip_config_get_num_dns (s_ip6); for (i = 0; i < 254; i++) { - addr_key = g_strdup_printf ("DNS%d", i + num4 + 1); + char addr_key[64]; + + nm_sprintf_buf (addr_key, "DNS%u", i + num4 + 1); if (i >= num) svUnsetValue (ifcfg, addr_key); else { dns = nm_setting_ip_config_get_dns (s_ip6, i); - svSetValueString (ifcfg, addr_key, dns); + svSetValueStr (ifcfg, addr_key, dns); } - g_free (addr_key); } /* Write out DNS domains - 'DOMAIN' key is shared for both IPv4 and IPv6 domains */ num = nm_setting_ip_config_get_num_dns_searches (s_ip6); if (num > 0) { - char *ip4_domains; - ip4_domains = svGetValueString (ifcfg, "DOMAIN"); - searches = g_string_new (ip4_domains); + gs_free char *ip4_domains = NULL; + nm_auto_free_gstring GString *searches = NULL; + + searches = g_string_new (svGetValueStr (ifcfg, "DOMAIN", &ip4_domains)); for (i = 0; i < num; i++) { if (searches->len > 0) g_string_append_c (searches, ' '); g_string_append (searches, nm_setting_ip_config_get_dns_search (s_ip6, i)); } - svSetValueString (ifcfg, "DOMAIN", searches->str); - g_string_free (searches, TRUE); - g_free (ip4_domains); + svSetValueStr (ifcfg, "DOMAIN", searches->str); } /* handle IPV6_DEFROUTE */ /* IPV6_DEFROUTE has the opposite meaning from 'never-default' */ - if (nm_setting_ip_config_get_never_default(s_ip6)) - svSetValueString (ifcfg, "IPV6_DEFROUTE", "no"); + if (nm_setting_ip_config_get_never_default (s_ip6)) + svSetValueStr (ifcfg, "IPV6_DEFROUTE", "no"); else - svSetValueString (ifcfg, "IPV6_DEFROUTE", "yes"); + svSetValueStr (ifcfg, "IPV6_DEFROUTE", "yes"); - svSetValueString (ifcfg, "IPV6_PEERDNS", - nm_setting_ip_config_get_ignore_auto_dns (s_ip6) ? "no" : NULL); + svSetValueStr (ifcfg, "IPV6_PEERDNS", + nm_setting_ip_config_get_ignore_auto_dns (s_ip6) ? "no" : NULL); - svSetValueString (ifcfg, "IPV6_PEERROUTES", - nm_setting_ip_config_get_ignore_auto_routes (s_ip6) ? "no" : NULL); + svSetValueStr (ifcfg, "IPV6_PEERROUTES", + nm_setting_ip_config_get_ignore_auto_routes (s_ip6) ? "no" : NULL); - svSetValueString (ifcfg, "IPV6_FAILURE_FATAL", - nm_setting_ip_config_get_may_fail (s_ip6) ? "no" : "yes"); + svSetValueStr (ifcfg, "IPV6_FAILURE_FATAL", + nm_setting_ip_config_get_may_fail (s_ip6) ? "no" : "yes"); route_metric = nm_setting_ip_config_get_route_metric (s_ip6); tmp = route_metric != -1 ? g_strdup_printf ("%"G_GINT64_FORMAT, route_metric) : NULL; - svSetValueString (ifcfg, "IPV6_ROUTE_METRIC", tmp); + svSetValueStr (ifcfg, "IPV6_ROUTE_METRIC", tmp); g_free (tmp); /* IPv6 Privacy Extensions */ svUnsetValue (ifcfg, "IPV6_PRIVACY"); svUnsetValue (ifcfg, "IPV6_PRIVACY_PREFER_PUBLIC_IP"); - switch (nm_setting_ip6_config_get_ip6_privacy (NM_SETTING_IP6_CONFIG (s_ip6))){ + switch (nm_setting_ip6_config_get_ip6_privacy (NM_SETTING_IP6_CONFIG (s_ip6))) { case NM_SETTING_IP6_CONFIG_PRIVACY_DISABLED: - svSetValueString (ifcfg, "IPV6_PRIVACY", "no"); + svSetValueStr (ifcfg, "IPV6_PRIVACY", "no"); break; case NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR: - svSetValueString (ifcfg, "IPV6_PRIVACY", "rfc3041"); - svSetValueString (ifcfg, "IPV6_PRIVACY_PREFER_PUBLIC_IP", "yes"); + svSetValueStr (ifcfg, "IPV6_PRIVACY", "rfc3041"); + svSetValueStr (ifcfg, "IPV6_PRIVACY_PREFER_PUBLIC_IP", "yes"); break; case NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR: - svSetValueString (ifcfg, "IPV6_PRIVACY", "rfc3041"); + svSetValueStr (ifcfg, "IPV6_PRIVACY", "rfc3041"); break; default: break; @@ -2646,7 +2710,7 @@ write_ip6_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) if (addr_gen_mode != NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64) { tmp = nm_utils_enum_to_str (nm_setting_ip6_config_addr_gen_mode_get_type (), addr_gen_mode); - svSetValueString (ifcfg, "IPV6_ADDR_GEN_MODE", tmp); + svSetValueStr (ifcfg, "IPV6_ADDR_GEN_MODE", tmp); g_free (tmp); } else { svUnsetValue (ifcfg, "IPV6_ADDR_GEN_MODE"); @@ -2654,7 +2718,7 @@ write_ip6_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) /* IPv6 tokenized interface identifier */ value = nm_setting_ip6_config_get_token (NM_SETTING_IP6_CONFIG (s_ip6)); - svSetValueString (ifcfg, "IPV6_TOKEN", value); + svSetValueStr (ifcfg, "IPV6_TOKEN", value); priority = nm_setting_ip_config_get_dns_priority (s_ip6); if (priority) @@ -2667,17 +2731,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 @@ -2762,18 +2823,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; @@ -2802,13 +2865,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); @@ -2826,7 +2888,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)) { @@ -2835,82 +2897,113 @@ 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; + + if (!write_user_setting (connection, ifcfg, error)) + 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 : ""); + } 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); - - success = TRUE; + *out_filename = g_steal_pointer (&ifcfg_name); -out: - if (ifcfg) - svCloseFile (ifcfg); - g_free (ifcfg_name); - return success; + return TRUE; } gboolean @@ -2942,15 +3035,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)) { @@ -2959,6 +3056,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 2662f79b..9cd9513e 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 65bcc0d9..9fce5aa1 100644 --- a/src/settings/plugins/ifcfg-rh/shvar.c +++ b/src/settings/plugins/ifcfg-rh/shvar.c @@ -41,7 +41,7 @@ /*****************************************************************************/ -typedef struct { +struct _shvarLine { /* There are three cases: * * 1) the line is not a valid variable assignment (that is, it doesn't @@ -61,7 +61,9 @@ typedef struct { char *line; const char *key; char *key_with_prefix; -} shvarLine; +}; + +typedef struct _shvarLine shvarLine; struct _shvarFile { char *fileName; @@ -220,14 +222,12 @@ svEscape (const char *s, char **to_free) int newlen; size_t i, j, slen; - slen = strlen (s); - - for (i = 0; i < slen; i++) { - if (_char_req_escape (s[i])) + for (slen = 0; s[slen]; slen++) { + if (_char_req_escape (s[slen])) mangle++; - else if (_char_req_quotes (s[i])) + else if (_char_req_quotes (s[slen])) requires_quotes = TRUE; - else if (s[i] < ' ') { + else if (s[slen] < ' ') { /* if the string contains newline we can only express it using ANSI C quotation * (as we don't support line continuation). * Additionally, ANSI control characters look odd with regular quotation, so handle @@ -639,15 +639,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; } @@ -877,6 +881,30 @@ shlist_find (const GList *current, const char *key) /*****************************************************************************/ +GHashTable * +svGetKeys (shvarFile *s) +{ + GHashTable *keys = NULL; + const GList *current; + const shvarLine *line; + + nm_assert (s); + + for (current = s->lineList; current; current = current->next) { + line = current->data; + if (line->key && line->line) { + /* we don't clone the keys. The keys are only valid + * until @s gets modified. */ + if (!keys) + keys = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL); + g_hash_table_add (keys, (gpointer) line->key); + } + } + return keys; +} + +/*****************************************************************************/ + static const char * _svGetValue (shvarFile *s, const char *key, char **to_free) { @@ -895,39 +923,104 @@ _svGetValue (shvarFile *s, const char *key, char **to_free) } if (last) { line = last->data; - if (line->line) - return svUnescape (line->line, to_free); + if (line->line) { + const char *v; + + v = svUnescape (line->line, to_free); + if (!v) { + /* a wrongly quoted value is treated like the empty string. + * See also svWriteFile(), which handles unparsable values + * that way. */ + nm_assert (!*to_free); + return ""; + } + return v; + } } *to_free = NULL; return NULL; } +/* Returns the value for key. The value is either owned by @s + * or returned as to_free. This aims to avoid cloning the string. + * + * - like svGetValue_cp(), but avoids cloning the value if possible. + * - like svGetValueStr(), but does not ignore empty string values. + */ const char * svGetValue (shvarFile *s, const char *key, char **to_free) { - g_return_val_if_fail (s != NULL, NULL); - g_return_val_if_fail (key != NULL, NULL); + g_return_val_if_fail (s, NULL); + g_return_val_if_fail (key, NULL); g_return_val_if_fail (to_free, NULL); return _svGetValue (s, key, to_free); } -/* Get the value associated with the key, and leave the current pointer - * pointing at the line containing the value. The char* returned MUST - * be freed by the caller. +/* Returns the value for key. The value is either owned by @s + * or returned as to_free. This aims to avoid cloning the string. + * + * - like svGetValue(), but does not return an empty string. + * - like svGetValueStr_cp(), but avoids cloning the value if possible. + */ +const char * +svGetValueStr (shvarFile *s, const char *key, char **to_free) +{ + const char *value; + + g_return_val_if_fail (s, NULL); + g_return_val_if_fail (key, NULL); + g_return_val_if_fail (to_free, NULL); + + value = _svGetValue (s, key, to_free); + if (!value || !value[0]) { + nm_assert (!*to_free); + return NULL; + } + return value; +} + +/* Returns the value for key. The returned value must be freed + * by the caller. + * + * - like svGetValue(), but always returns a copy of the value. + * - like svGetValueStr_cp(), but does not ignore an empty string. */ char * -svGetValueString (shvarFile *s, const char *key) +svGetValue_cp (shvarFile *s, const char *key) { char *to_free; const char *value; + g_return_val_if_fail (s, NULL); + g_return_val_if_fail (key, NULL); + value = _svGetValue (s, key, &to_free); if (!value) { nm_assert (!to_free); return NULL; } - if (!value[0]) { + return to_free ?: g_strdup (value); +} + +/* Returns the value for key. The returned value must be freed + * by the caller. + * If the key is unset or the value an empty string, NULL is returned. + * + * - like svGetValueStr(), but always returns a copy of the value. + * - like svGetValue_cp(), but returns NULL instead of an empty string. + */ +char * +svGetValueStr_cp (shvarFile *s, const char *key) +{ + char *to_free; + const char *value; + + g_return_val_if_fail (s, NULL); + g_return_val_if_fail (key, NULL); + + value = _svGetValue (s, key, &to_free); + if (!value || !value[0]) { nm_assert (!to_free); return NULL; } @@ -991,8 +1084,8 @@ svGetValueInt64 (shvarFile *s, const char *key, guint base, gint64 min, gint64 m /*****************************************************************************/ -/* Same as svSetValueString() but it preserves empty @value -- contrary to - * svSetValueString() for which "" effectively means to remove the value. */ +/* Same as svSetValueStr() but it preserves empty @value -- contrary to + * svSetValueStr() for which "" effectively means to remove the value. */ void svSetValue (shvarFile *s, const char *key, const char *value) { @@ -1041,7 +1134,7 @@ svSetValue (shvarFile *s, const char *key, const char *value) * to the bottom of the file. */ void -svSetValueString (shvarFile *s, const char *key, const char *value) +svSetValueStr (shvarFile *s, const char *key, const char *value) { svSetValue (s, key, value && value[0] ? value : NULL); } @@ -1066,6 +1159,27 @@ svUnsetValue (shvarFile *s, const char *key) svSetValue (s, key, NULL); } +void +svUnsetValuesWithPrefix (shvarFile *s, const char *prefix) +{ + GList *current; + + g_return_if_fail (s); + g_return_if_fail (prefix); + + for (current = s->lineList; current; current = current->next) { + shvarLine *line = current->data; + + ASSERT_shvarLine (line); + if ( line->key + && g_str_has_prefix (line->key, prefix)) { + if (nm_clear_g_free (&line->line)) + s->modified = TRUE; + } + ASSERT_shvarLine (line); + } +} + /*****************************************************************************/ /* Write the current contents iff modified. Returns FALSE on error diff --git a/src/settings/plugins/ifcfg-rh/shvar.h b/src/settings/plugins/ifcfg-rh/shvar.h index a6498fce..9d8c2364 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 , return a shvarFile (never fails) */ shvarFile *svCreateFile (const char *name); @@ -49,10 +49,15 @@ shvarFile *svOpenFile (const char *name, GError **error); * be freed by the caller. */ const char *svGetValue (shvarFile *s, const char *key, char **to_free); -char *svGetValueString (shvarFile *s, const char *key); +char *svGetValue_cp (shvarFile *s, const char *key); + +const char *svGetValueStr (shvarFile *s, const char *key, char **to_free); +char *svGetValueStr_cp (shvarFile *s, const char *key); gint svParseBoolean (const char *value, gint def); +GHashTable *svGetKeys (shvarFile *s); + /* return TRUE if resolves to any truth value (e.g. "yes", "y", "true") * return FALSE if resolves to any non-truth value (e.g. "no", "n", "false") * return otherwise @@ -66,13 +71,15 @@ gint64 svGetValueInt64 (shvarFile *s, const char *key, guint base, gint64 min, g * the key=value pair after that line. Otherwise, prepend the pair * to the top of the file. */ -void svSetValueString (shvarFile *s, const char *key, const char *value); void svSetValue (shvarFile *s, const char *key, const char *value); +void svSetValueStr (shvarFile *s, const char *key, const char *value); void svSetValueBoolean (shvarFile *s, const char *key, gboolean value); void svSetValueInt64 (shvarFile *s, const char *key, gint64 value); void svUnsetValue (shvarFile *s, const char *key); +void svUnsetValuesWithPrefix (shvarFile *s, const char *prefix); + /* Write the current contents iff modified. Returns FALSE on error * and TRUE on success. Do not write if no values have been modified. * The mode argument is only used if creating the file, not if @@ -87,4 +94,16 @@ void svCloseFile (shvarFile *s); const char *svEscape (const char *s, char **to_free); const char *svUnescape (const char *s, char **to_free); +static inline void +_nm_auto_shvar_file_close (shvarFile **p_s) +{ + if (*p_s) { + int errsv = errno; + + svCloseFile (*p_s); + errno = errsv; + } +} +#define nm_auto_shvar_file_close nm_auto(_nm_auto_shvar_file_close) + #endif /* _SHVAR_H */ diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-bridge-component-a.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-bridge-component-a.cexpected new file mode 100644 index 00000000..d81d9187 --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-bridge-component-a.cexpected @@ -0,0 +1,8 @@ +HWADDR=00:22:15:59:62:97 +TYPE=Ethernet +BRIDGING_OPTS="priority=28 hairpin_mode=1" +NAME="System test-bridge-component" +UUID=${UUID} +DEVICE=eth0 +ONBOOT=no +BRIDGE=br0 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-bridge-component-b.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-bridge-component-b.cexpected new file mode 100644 index 00000000..d4785ff5 --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-bridge-component-b.cexpected @@ -0,0 +1,17 @@ +HWADDR=00:22:15:59:62:97 +TYPE=Ethernet +BRIDGING_OPTS="priority=28 hairpin_mode=1" +NAME="System test-bridge-component" +UUID=${UUID} +DEVICE=eth0 +ONBOOT=no +PROXY_METHOD=none +BROWSER_ONLY=no +BOOTPROTO=dhcp +DEFROUTE=yes +IPV4_FAILURE_FATAL=no +IPV6INIT=yes +IPV6_AUTOCONF=yes +IPV6_DEFROUTE=yes +IPV6_FAILURE_FATAL=no +IPV6_ADDR_GEN_MODE=stable-privacy diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-wired-802-1X-subj-matches.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-wired-802-1X-subj-matches.cexpected new file mode 100644 index 00000000..59a6f79b --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-wired-802-1X-subj-matches.cexpected @@ -0,0 +1,22 @@ +HWADDR=00:11:22:33:44:EE +TYPE=Ethernet +KEY_MGMT=IEEE8021X +IEEE_8021X_EAP_METHODS=PEAP +IEEE_8021X_IDENTITY="Jara Cimrman" +IEEE_8021X_PASSWORD_FLAGS="user ask" +IEEE_8021X_PEAP_VERSION=1 +IEEE_8021X_INNER_AUTH_METHODS=GTC +IEEE_8021X_SUBJECT_MATCH=server1.yourdomain.tld +IEEE_8021X_PHASE2_SUBJECT_MATCH=server2.yourdomain.tld +IEEE_8021X_ALTSUBJECT_MATCHES="a.yourdomain.tld b.yourdomain.tld c.yourdomain.tld" +IEEE_8021X_PHASE2_ALTSUBJECT_MATCHES="x.yourdomain.tld y.yourdomain.tld" +PROXY_METHOD=none +BROWSER_ONLY=no +BOOTPROTO=dhcp +DEFROUTE=yes +IPV4_FAILURE_FATAL=no +IPV6INIT=no +NAME="System test-wired-802-1X-subj-matches" +UUID=${UUID} +DEVICE=eth0 +ONBOOT=yes diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_User_1.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_User_1.cexpected new file mode 100644 index 00000000..a48be78a --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_User_1.cexpected @@ -0,0 +1,34 @@ +TYPE=Ethernet +PROXY_METHOD=none +BROWSER_ONLY=no +NM_USER__M_Y___053=val=MY.+ +NM_USER__M_Y___055=val=MY.- +NM_USER__M_Y___057=val=MY./ +NM_USER__M_Y__8_053_V=val=MY.8+V +NM_USER__M_Y__8_055_V=val=MY.8-V +NM_USER__M_Y__8_057_V=val=MY.8/V +NM_USER__M_Y__8_075_V=val=MY.8=V +NM_USER__M_Y__8_V=val=MY.8V +NM_USER__M_Y__8_137_V=val=MY.8_V +NM_USER__M_Y___075=val=MY.= +NM_USER__M_Y___A_V=val=MY.AV +NM_USER__M_Y___137=val=MY._ +NM_USER_MY___AV=val=my.Av +NM_USER_MY___137V=val=my._v +NM_USER_MY__KEYS__1=val=my.keys.1 +NM_USER_MY__OTHER___K_E_Y__42=val=my.other.KEY.42 +NM_USER_MY__V_053=val=my.v+ +NM_USER_MY__V_137_137AL3=val=my.v__al3 +NM_USER_MY__VAL1= +NM_USER_MY__VAL2=val=my.val2 +BOOTPROTO=dhcp +DEFROUTE=yes +IPV4_FAILURE_FATAL=no +IPV6INIT=yes +IPV6_AUTOCONF=yes +IPV6_DEFROUTE=yes +IPV6_FAILURE_FATAL=no +IPV6_ADDR_GEN_MODE=stable-privacy +NAME="Test User 1" +UUID=${UUID} +ONBOOT=yes diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Bond_Main.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Bond_Main.cexpected new file mode 100644 index 00000000..3956003d --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Bond_Main.cexpected @@ -0,0 +1,16 @@ +DEVICE=bond0 +BONDING_OPTS=mode=balance-rr +TYPE=Bond +BONDING_MASTER=yes +PROXY_METHOD=none +BROWSER_ONLY=no +BOOTPROTO=none +IPADDR=1.1.1.3 +PREFIX=24 +GATEWAY=1.1.1.1 +DEFROUTE=yes +IPV4_FAILURE_FATAL=no +IPV6INIT=no +NAME="Test Write Bond Main" +UUID=${UUID} +ONBOOT=yes diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Bridge_Component.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Bridge_Component.cexpected new file mode 100644 index 00000000..c478db38 --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Bridge_Component.cexpected @@ -0,0 +1,8 @@ +HWADDR=31:33:33:37:BE:CD +MTU=1492 +TYPE=Ethernet +BRIDGING_OPTS="priority=50 path_cost=33" +NAME="Test Write Bridge Component" +UUID=${UUID} +ONBOOT=yes +BRIDGE=br0 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Permissions.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Permissions.cexpected new file mode 100644 index 00000000..80e96921 --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Permissions.cexpected @@ -0,0 +1,11 @@ +TYPE=Ethernet +PROXY_METHOD=none +BROWSER_ONLY=no +BOOTPROTO=dhcp +DEFROUTE=yes +IPV4_FAILURE_FATAL=no +IPV6INIT=no +NAME="Test Write Permissions" +UUID=${UUID} +ONBOOT=yes +USERS="blahblah foobar asdfasdf" diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Proxy_Basic.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Proxy_Basic.cexpected new file mode 100644 index 00000000..716eedc2 --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Proxy_Basic.cexpected @@ -0,0 +1,15 @@ +TYPE=Ethernet +PROXY_METHOD=auto +PAC_URL=https://wpad.neverland.org/wpad.dat +BROWSER_ONLY=no +BOOTPROTO=dhcp +DEFROUTE=yes +IPV4_FAILURE_FATAL=no +IPV6INIT=yes +IPV6_AUTOCONF=yes +IPV6_DEFROUTE=yes +IPV6_FAILURE_FATAL=no +IPV6_ADDR_GEN_MODE=stable-privacy +NAME="Test Write Proxy Basic" +UUID=${UUID} +ONBOOT=yes diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Team_Port.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Team_Port.cexpected new file mode 100644 index 00000000..0b1deb80 --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Team_Port.cexpected @@ -0,0 +1,6 @@ +TEAM_PORT_CONFIG="{ \"p4p1\": { \"prio\": -10, \"sticky\": true } }" +NAME="Test Write Team Port" +UUID=${UUID} +ONBOOT=yes +TEAM_MASTER=team0 +DEVICETYPE=TeamPort diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_VLAN_reorder_hdr.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_VLAN_reorder_hdr.cexpected new file mode 100644 index 00000000..339f8107 --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_VLAN_reorder_hdr.cexpected @@ -0,0 +1,20 @@ +VLAN=yes +TYPE=Vlan +PHYSDEV=eth0 +VLAN_ID=444 +REORDER_HDR=yes +GVRP=no +MVRP=no +PROXY_METHOD=none +BROWSER_ONLY=no +BOOTPROTO=dhcp +DEFROUTE=yes +IPV4_FAILURE_FATAL=no +IPV6INIT=yes +IPV6_AUTOCONF=yes +IPV6_DEFROUTE=yes +IPV6_FAILURE_FATAL=no +IPV6_ADDR_GEN_MODE=stable-privacy +NAME="Test Write VLAN reorder_hdr" +UUID=${UUID} +ONBOOT=no diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_Band_A.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_Band_A.cexpected new file mode 100644 index 00000000..a95a58db --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_Band_A.cexpected @@ -0,0 +1,18 @@ +ESSID="Test SSID" +MODE=Managed +BAND=a +MAC_ADDRESS_RANDOMIZATION=default +TYPE=Wireless +PROXY_METHOD=none +BROWSER_ONLY=no +BOOTPROTO=dhcp +DEFROUTE=yes +IPV4_FAILURE_FATAL=no +IPV6INIT=yes +IPV6_AUTOCONF=yes +IPV6_DEFROUTE=yes +IPV6_FAILURE_FATAL=no +IPV6_ADDR_GEN_MODE=stable-privacy +NAME="Test Write WiFi Band A" +UUID=${UUID} +ONBOOT=yes diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_Hidden.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_Hidden.cexpected new file mode 100644 index 00000000..026993b8 --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_Hidden.cexpected @@ -0,0 +1,18 @@ +ESSID="Test SSID" +MODE=Managed +SSID_HIDDEN=yes +MAC_ADDRESS_RANDOMIZATION=default +TYPE=Wireless +PROXY_METHOD=none +BROWSER_ONLY=no +BOOTPROTO=dhcp +DEFROUTE=yes +IPV4_FAILURE_FATAL=no +IPV6INIT=yes +IPV6_AUTOCONF=yes +IPV6_DEFROUTE=yes +IPV6_FAILURE_FATAL=no +IPV6_ADDR_GEN_MODE=stable-privacy +NAME="Test Write WiFi Hidden" +UUID=${UUID} +ONBOOT=yes diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_MAC_always.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_MAC_always.cexpected new file mode 100644 index 00000000..f3704f10 --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_MAC_always.cexpected @@ -0,0 +1,18 @@ +MACADDR=random +ESSID="Test SSID" +MODE=Managed +MAC_ADDRESS_RANDOMIZATION=always +TYPE=Wireless +PROXY_METHOD=none +BROWSER_ONLY=no +BOOTPROTO=dhcp +DEFROUTE=yes +IPV4_FAILURE_FATAL=no +IPV6INIT=yes +IPV6_AUTOCONF=yes +IPV6_DEFROUTE=yes +IPV6_FAILURE_FATAL=no +IPV6_ADDR_GEN_MODE=stable-privacy +NAME="Test Write WiFi MAC always" +UUID=${UUID} +ONBOOT=yes diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_MAC_default.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_MAC_default.cexpected new file mode 100644 index 00000000..005c6179 --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_MAC_default.cexpected @@ -0,0 +1,17 @@ +ESSID="Test SSID" +MODE=Managed +MAC_ADDRESS_RANDOMIZATION=default +TYPE=Wireless +PROXY_METHOD=none +BROWSER_ONLY=no +BOOTPROTO=dhcp +DEFROUTE=yes +IPV4_FAILURE_FATAL=no +IPV6INIT=yes +IPV6_AUTOCONF=yes +IPV6_DEFROUTE=yes +IPV6_FAILURE_FATAL=no +IPV6_ADDR_GEN_MODE=stable-privacy +NAME="Test Write WiFi MAC default" +UUID=${UUID} +ONBOOT=yes diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_MAC_missing.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_MAC_missing.cexpected new file mode 100644 index 00000000..dff17ef2 --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_MAC_missing.cexpected @@ -0,0 +1,18 @@ +MACADDR=permanent +ESSID="Test SSID" +MODE=Managed +MAC_ADDRESS_RANDOMIZATION=never +TYPE=Wireless +PROXY_METHOD=none +BROWSER_ONLY=no +BOOTPROTO=dhcp +DEFROUTE=yes +IPV4_FAILURE_FATAL=no +IPV6INIT=yes +IPV6_AUTOCONF=yes +IPV6_DEFROUTE=yes +IPV6_FAILURE_FATAL=no +IPV6_ADDR_GEN_MODE=stable-privacy +NAME="Test Write WiFi MAC missing" +UUID=${UUID} +ONBOOT=yes diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_MAC_never.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_MAC_never.cexpected new file mode 100644 index 00000000..94274cf9 --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_MAC_never.cexpected @@ -0,0 +1,18 @@ +MACADDR=permanent +ESSID="Test SSID" +MODE=Managed +MAC_ADDRESS_RANDOMIZATION=never +TYPE=Wireless +PROXY_METHOD=none +BROWSER_ONLY=no +BOOTPROTO=dhcp +DEFROUTE=yes +IPV4_FAILURE_FATAL=no +IPV6INIT=yes +IPV6_AUTOCONF=yes +IPV6_DEFROUTE=yes +IPV6_FAILURE_FATAL=no +IPV6_ADDR_GEN_MODE=stable-privacy +NAME="Test Write WiFi MAC never" +UUID=${UUID} +ONBOOT=yes diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wifi_LEAP.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wifi_LEAP.cexpected new file mode 100644 index 00000000..d3db19b2 --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wifi_LEAP.cexpected @@ -0,0 +1,16 @@ +ESSID=blahblah +MODE=Managed +KEY_MGMT=IEEE8021X +SECURITYMODE=leap +IEEE_8021X_IDENTITY="Bill Smith" +MAC_ADDRESS_RANDOMIZATION=default +TYPE=Wireless +PROXY_METHOD=none +BROWSER_ONLY=no +BOOTPROTO=dhcp +DEFROUTE=yes +IPV4_FAILURE_FATAL=no +IPV6INIT=no +NAME="Test Write Wifi LEAP" +UUID=${UUID} +ONBOOT=yes diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wifi_WEP_104_ASCII.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wifi_WEP_104_ASCII.cexpected new file mode 100644 index 00000000..32db7262 --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wifi_WEP_104_ASCII.cexpected @@ -0,0 +1,15 @@ +ESSID=blahblah104 +MODE=Managed +SECURITYMODE=open +DEFAULTKEY=1 +MAC_ADDRESS_RANDOMIZATION=default +TYPE=Wireless +PROXY_METHOD=none +BROWSER_ONLY=no +BOOTPROTO=dhcp +DEFROUTE=yes +IPV4_FAILURE_FATAL=no +IPV6INIT=no +NAME="Test Write Wifi WEP 104 ASCII" +UUID=${UUID} +ONBOOT=yes diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Auto-Negotiate.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Auto-Negotiate.cexpected new file mode 100644 index 00000000..8f421cfb --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Auto-Negotiate.cexpected @@ -0,0 +1,15 @@ +ETHTOOL_OPTS="autoneg off speed 10 duplex half" +TYPE=Ethernet +PROXY_METHOD=none +BROWSER_ONLY=no +BOOTPROTO=dhcp +DEFROUTE=yes +IPV4_FAILURE_FATAL=no +IPV6INIT=yes +IPV6_AUTOCONF=yes +IPV6_DEFROUTE=yes +IPV6_FAILURE_FATAL=no +IPV6_ADDR_GEN_MODE=stable-privacy +NAME="Test Write Wired Auto-Negotiate" +UUID=${UUID} +ONBOOT=yes diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Wake-on-LAN.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Wake-on-LAN.cexpected new file mode 100644 index 00000000..398a3017 --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Wake-on-LAN.cexpected @@ -0,0 +1,15 @@ +ETHTOOL_OPTS="wol umgs sopass 00:00:00:11:22:33" +TYPE=Ethernet +PROXY_METHOD=none +BROWSER_ONLY=no +BOOTPROTO=dhcp +DEFROUTE=yes +IPV4_FAILURE_FATAL=no +IPV6INIT=yes +IPV6_AUTOCONF=yes +IPV6_DEFROUTE=yes +IPV6_FAILURE_FATAL=no +IPV6_ADDR_GEN_MODE=stable-privacy +NAME="Test Write Wired Wake-on-LAN" +UUID=${UUID} +ONBOOT=yes diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Vlan_test-vlan-interface.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Vlan_test-vlan-interface.cexpected new file mode 100644 index 00000000..60091b7b --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Vlan_test-vlan-interface.cexpected @@ -0,0 +1,22 @@ +VLAN=yes +TYPE=Vlan +DEVICE=vlan43 +PHYSDEV=eth9 +VLAN_ID=43 +REORDER_HDR=yes +GVRP=yes +VLAN_FLAGS=LOOSE_BINDING +MVRP=no +VLAN_INGRESS_PRIORITY_MAP=0:1,2:5 +VLAN_EGRESS_PRIORITY_MAP=3:1,12:3,14:7 +PROXY_METHOD=none +BROWSER_ONLY=no +BOOTPROTO=none +IPADDR=192.168.43.149 +PREFIX=24 +DEFROUTE=yes +IPV4_FAILURE_FATAL=no +IPV6INIT=no +NAME="Vlan test-vlan-interface" +UUID=${UUID} +ONBOOT=yes diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem3 b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem3 new file mode 100644 index 00000000..b7bdd781 --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem3 @@ -0,0 +1,11 @@ +TYPE=Ethernet +DEVICE=aliasem0 +HWADDR=00:11:22:33:44:55 +BOOTPROTO=none +ONBOOT=yes +DNS1=4.2.2.1 +DNS2=4.2.2.2 +IPADDR=192.168.1.5 +PREFIX=24 +NETMASK=255.255.255.0 +IPV6INIT=no diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem3:1 b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem3:1 new file mode 100644 index 00000000..5e151875 --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem3:1 @@ -0,0 +1,4 @@ +DEVICE=aliasem3:1 +IPADDR=192.168.1.6 +DEFROUTE=yes +GATEWAY=192.168.1.1 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-dcb-test.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-dcb-test.cexpected new file mode 100644 index 00000000..56e233cc --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-dcb-test.cexpected @@ -0,0 +1,41 @@ +TYPE=Ethernet +DCB=yes +DCB_APP_FCOE_ENABLE=yes +DCB_APP_FCOE_ADVERTISE=yes +DCB_APP_FCOE_WILLING=yes +DCB_APP_FCOE_PRIORITY=5 +DCB_APP_FCOE_MODE=fabric +DCB_APP_ISCSI_ENABLE=yes +DCB_APP_ISCSI_ADVERTISE=yes +DCB_APP_ISCSI_WILLING=yes +DCB_APP_ISCSI_PRIORITY=1 +DCB_APP_FIP_ENABLE=yes +DCB_APP_FIP_ADVERTISE=yes +DCB_APP_FIP_WILLING=yes +DCB_APP_FIP_PRIORITY=3 +DCB_PFC_ENABLE=yes +DCB_PFC_ADVERTISE=yes +DCB_PFC_WILLING=yes +DCB_PFC_UP=11010110 +DCB_PG_ENABLE=yes +DCB_PG_ADVERTISE=yes +DCB_PG_WILLING=yes +DCB_PG_ID=4f6f173f +DCB_PG_PCT=10,20,15,10,2,3,35,5 +DCB_PG_UPPCT=10,20,30,40,50,10,0,25 +DCB_PG_STRICT=10110001 +DCB_PG_UP2TC=34721056 +PROXY_METHOD=none +BROWSER_ONLY=no +BOOTPROTO=dhcp +DEFROUTE=yes +IPV4_FAILURE_FATAL=no +IPV6INIT=yes +IPV6_AUTOCONF=yes +IPV6_DEFROUTE=yes +IPV6_FAILURE_FATAL=no +IPV6_ADDR_GEN_MODE=stable-privacy +NAME=dcb-test +UUID=${UUID} +DEVICE=eth0 +ONBOOT=yes diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-random_wifi_connection.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-random_wifi_connection.cexpected new file mode 100644 index 00000000..ead3a047 --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-random_wifi_connection.cexpected @@ -0,0 +1,13 @@ +ESSID=blahblah +MODE=Managed +MAC_ADDRESS_RANDOMIZATION=default +TYPE=Wireless +PROXY_METHOD=none +BROWSER_ONLY=no +BOOTPROTO=dhcp +DEFROUTE=yes +IPV4_FAILURE_FATAL=no +IPV6INIT=no +NAME="random wifi connection" +UUID=${UUID} +ONBOOT=yes diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-random_wifi_connection_2.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-random_wifi_connection_2.cexpected new file mode 100644 index 00000000..7bc1ae6c --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-random_wifi_connection_2.cexpected @@ -0,0 +1,15 @@ +ESSID=SomeSSID +MODE=Managed +MAC_ADDRESS_RANDOMIZATION=default +TYPE=Wireless +PROXY_METHOD=none +BROWSER_ONLY=no +BOOTPROTO=dhcp +DEFROUTE=yes +IPV4_FAILURE_FATAL=no +IPV6INIT=no +NAME="random wifi connection 2" +UUID=${UUID} +ONBOOT=yes +USERS=superman +DEFAULTKEY=1 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-team-slave-enp31s0f1-142.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-team-slave-enp31s0f1-142.cexpected new file mode 100644 index 00000000..367d0ddb --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-team-slave-enp31s0f1-142.cexpected @@ -0,0 +1,12 @@ +VLAN=yes +DEVICE=enp31s0f1-142 +PHYSDEV=enp31s0f1 +VLAN_ID=142 +REORDER_HDR=yes +GVRP=no +MVRP=no +NAME=team-slave-enp31s0f1-142 +UUID=74f435bb-ede4-415a-9d48-f580b60eba04 +ONBOOT=no +TEAM_MASTER=team142 +DEVICETYPE=TeamPort diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bond-eth-type b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bond-eth-type new file mode 100644 index 00000000..8d295c76 --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bond-eth-type @@ -0,0 +1,7 @@ +DEVICE=bond0 +NM_CONTROLLED=yes +TYPE=Ethernet +BONDING_OPTS="miimon=213 mode=4 lacp_rate=1" +BONDING_MASTER=yes +ONBOOT=yes +BOOTPROTO=none diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-static-routes-legacy.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-static-routes-legacy.cexpected new file mode 100644 index 00000000..a28c5c1c --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-static-routes-legacy.cexpected @@ -0,0 +1,12 @@ +HWADDR=00:16:41:11:22:33 +TYPE=Ethernet +PROXY_METHOD=none +BROWSER_ONLY=no +BOOTPROTO=dhcp +DEFROUTE=yes +IPV4_FAILURE_FATAL=no +IPV6INIT=no +NAME=test-static-routes-legacy +UUID=ba60d05a-7898-820d-c2db-427a88f8f2a5 +DEVICE=eth0 +ONBOOT=yes diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes b/src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes index ee2a32d8..10a63b67 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes @@ -6,3 +6,4 @@ ADDRESS1=44.55.66.77 NETMASK1=255.255.255.255 GATEWAY1=192.168.1.7 METRIC1=3 +OPTIONS1="mtu lock 9000 cwnd 12 src 1.1.1.1 tos 0x28 window 30000 initcwnd lock 13 initrwnd 14" diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes-legacy b/src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes-legacy index cb7d42bd..3f02032a 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes-legacy +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes-legacy @@ -3,5 +3,5 @@ 21.31.41.0/24 via 9.9.9.9 metric 1 via 8.8.8.8 to 32.42.52.62 - 43.53.0.0/16 metric 3 via 7.7.7.7 dev eth2 + 43.53.0.0/16 metric 3 via 7.7.7.7 dev eth2 cwnd 14 mtu lock 9000 initrwnd 20 window lock 10000 initcwnd lock 42 src 1.2.3.4 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/route6-test-wired-ipv6-manual b/src/settings/plugins/ifcfg-rh/tests/network-scripts/route6-test-wired-ipv6-manual index b3259ab7..8bdf0acf 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/route6-test-wired-ipv6-manual +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/route6-test-wired-ipv6-manual @@ -5,3 +5,5 @@ default via dead::beaf # routes without "via" are valid abbe::cafe/64 metric 777 + +aaaa::cccc/64 from 1111::2222/48 via 3333::4444 src 5555::6666 mtu lock 1450 cwnd 13 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 f467d864..babb068d 100644 --- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c +++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c @@ -33,6 +33,7 @@ #include "nm-utils.h" #include "nm-setting-connection.h" #include "nm-setting-wired.h" +#include "nm-setting-user.h" #include "nm-setting-wireless.h" #include "nm-setting-wireless-security.h" #include "nm-setting-ip4-config.h" @@ -81,27 +82,170 @@ shvarFile *const _f = (f); \ const char *const _key = (key); \ \ - _val_string = svGetValueString (_f, _key); \ + _val_string = svGetValueStr_cp (_f, _key); \ _val = svGetValue (_f, _key, &_to_free); \ g_assert_cmpstr (_val, ==, (expected_value)); \ g_assert ( (!_val_string && (!_val || !_val[0])) \ || ( _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)); +} + +/* dummy path for an "expected" file, meaning: don't check for expected + * written ifcfg file. */ +static const char const NO_EXPECTED[1]; + +static void +_assert_expected_content (NMConnection *connection, const char *filename, const char *expected) +{ + gs_free char *content_expectd = NULL; + gs_free char *content_written = NULL; + GError *error = NULL; + gsize len_expectd = 0; + gsize len_written = 0; + gboolean success; + const char *uuid = NULL; + + g_assert (NM_IS_CONNECTION (connection)); + g_assert (filename); + g_assert (g_file_test (filename, G_FILE_TEST_EXISTS)); + + g_assert (expected); + if (expected == NO_EXPECTED) + return; + + success = g_file_get_contents (filename, &content_written, &len_written, &error); + nmtst_assert_success (success, error); + + success = g_file_get_contents (expected, &content_expectd, &len_expectd, &error); + nmtst_assert_success (success, error); + + { + gsize i, j; + + for (i = 0; i < len_expectd; ) { + if (content_expectd[i] != '$') { + i++; + continue; + } + if (g_str_has_prefix (&content_expectd[i], "${UUID}")) { + GString *str; + + if (!uuid) { + uuid = nm_connection_get_uuid (connection); + g_assert (uuid); + } + + j = strlen (uuid); + + str = g_string_new_len (content_expectd, len_expectd); + g_string_erase (str, i, NM_STRLEN ("${UUID}")); + g_string_insert_len (str, i, uuid, j); + + g_free (content_expectd); + len_expectd = str->len; + content_expectd = g_string_free (str, FALSE); + i += j; + continue; + } + + /* other '$' is not supported. If need be, support escaping of + * '$' via '$$'. */ + g_assert_not_reached (); + } + } + + if ( len_expectd != len_written + || memcmp (content_expectd, content_written, len_expectd) != 0) { + if (g_getenv ("NMTST_IFCFG_RH_UPDATE_EXPECTED")) { + if (uuid) { + gs_free char *search = g_strdup_printf ("UUID=%s\n", uuid); + const char *s; + gsize i; + GString *str; + + s = content_written; + while (TRUE) { + s = strstr (s, search); + g_assert (s); + if ( s == content_written + || s[-1] == '\n') + break; + s += strlen (search); + } + + i = s - content_written; + + str = g_string_new_len (content_written, len_written); + g_string_erase (str, i, strlen (search)); + g_string_insert (str, i, "UUID=${UUID}\n"); + + len_written = str->len; + content_written = g_string_free (str, FALSE); + } + success = g_file_set_contents (expected, content_written, len_written, &error); + nmtst_assert_success (success, error); + } else { + g_error ("The content of \"%s\" (%zu) differs from \"%s\" (%zu). Set NMTST_IFCFG_RH_UPDATE_EXPECTED=yes to update the files inplace\n\n>>>%s<<<\n\n>>>%s<<<\n", + filename, len_written, + expected, len_expectd, + content_written, + content_expectd); + } + } +} + +#define _writer_update_connection_reread(connection, ifcfg_dir, filename, expected, 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); \ + const char *_expected = (expected); \ 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); \ + _assert_expected_content (_connection, _filename, _expected); \ + } G_STMT_END + +#define _writer_update_connection(connection, ifcfg_dir, filename, expected) \ + G_STMT_START { \ + gs_unref_object NMConnection *_reread = NULL; \ + NMConnection *_c = (connection); \ + gboolean _reread_same = FALSE; \ + \ + _writer_update_connection_reread (_c, ifcfg_dir, filename, expected, &_reread, &_reread_same); \ + _assert_reread_same (_c, _reread); \ + g_assert (_reread_same); \ } G_STMT_END static NMConnection * @@ -147,14 +291,19 @@ _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, + const char *expected, + 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,14 +313,59 @@ _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); + + _assert_expected_content (con_verified, filename, expected); + if (out_filename) *out_filename = filename; else g_free (filename); + +} + +static void +_writer_new_connec_exp (NMConnection *connection, + const char *ifcfg_dir, + const char *expected, + char **out_filename) +{ + gs_unref_object NMConnection *reread = NULL; + gboolean reread_same = FALSE; + + _writer_new_connection_reread (connection, ifcfg_dir, out_filename, expected, &reread, &reread_same); + _assert_reread_same (connection, reread); + g_assert (reread_same); +} + +static void +_writer_new_connection (NMConnection *connection, + const char *ifcfg_dir, + char **out_filename) +{ + _writer_new_connec_exp (connection, ifcfg_dir, NO_EXPECTED, out_filename); +} + +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, NO_EXPECTED, &reread, &reread_same); + _assert_reread_same_FIXME (connection, reread); + g_assert (!reread_same); } static void @@ -179,6 +373,8 @@ _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 +382,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); } @@ -896,6 +1097,62 @@ test_read_wired_obsolete_gateway_n (void) g_object_unref (connection); } +static void +test_user_1 (void) +{ + nmtst_auto_unlinkfile char *testfile = NULL; + gs_unref_object NMConnection *connection = NULL; + gs_unref_object NMConnection *reread = NULL; + NMSettingUser *s_user; + + connection = nmtst_create_minimal_connection ("Test User 1", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL); + s_user = NM_SETTING_USER (nm_setting_user_new ()); + +#define _USER_SET_DATA(s_user, key, val) \ + G_STMT_START { \ + GError *_error = NULL; \ + gboolean _success; \ + \ + _success = nm_setting_user_set_data ((s_user), (key), (val), &_error); \ + nmtst_assert_success (_success, _error); \ + } G_STMT_END + +#define _USER_SET_DATA_X(s_user, key) \ + _USER_SET_DATA (s_user, key, "val="key"") + + _USER_SET_DATA (s_user, "my.val1", ""); + _USER_SET_DATA_X (s_user, "my.val2"); + _USER_SET_DATA_X (s_user, "my.v__al3"); + _USER_SET_DATA_X (s_user, "my._v"); + _USER_SET_DATA_X (s_user, "my.v+"); + _USER_SET_DATA_X (s_user, "my.Av"); + _USER_SET_DATA_X (s_user, "MY.AV"); + _USER_SET_DATA_X (s_user, "MY.8V"); + _USER_SET_DATA_X (s_user, "MY.8-V"); + _USER_SET_DATA_X (s_user, "MY.8_V"); + _USER_SET_DATA_X (s_user, "MY.8+V"); + _USER_SET_DATA_X (s_user, "MY.8/V"); + _USER_SET_DATA_X (s_user, "MY.8=V"); + _USER_SET_DATA_X (s_user, "MY.-"); + _USER_SET_DATA_X (s_user, "MY._"); + _USER_SET_DATA_X (s_user, "MY.+"); + _USER_SET_DATA_X (s_user, "MY./"); + _USER_SET_DATA_X (s_user, "MY.="); + _USER_SET_DATA_X (s_user, "my.keys.1"); + _USER_SET_DATA_X (s_user, "my.other.KEY.42"); + + nm_connection_add_setting (connection, NM_SETTING (s_user)); + + _writer_new_connec_exp (connection, + TEST_SCRATCH_DIR "/network-scripts/", + TEST_IFCFG_DIR "/network-scripts/ifcfg-Test_User_1.cexpected", + &testfile); + + reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL); + + nmtst_assert_connection_equals (connection, TRUE, reread, FALSE); +} + static void test_read_wired_never_default (void) { @@ -1033,6 +1290,15 @@ test_read_wired_static_routes (void) g_assert_cmpint (nm_ip_route_get_prefix (ip4_route), ==, 32); g_assert_cmpstr (nm_ip_route_get_next_hop (ip4_route), ==, "192.168.1.7"); g_assert_cmpint (nm_ip_route_get_metric (ip4_route), ==, 3); + nmtst_assert_route_attribute_byte (ip4_route, NM_IP_ROUTE_ATTRIBUTE_TOS, 0x28); + nmtst_assert_route_attribute_uint32 (ip4_route, NM_IP_ROUTE_ATTRIBUTE_WINDOW, 30000); + nmtst_assert_route_attribute_uint32 (ip4_route, NM_IP_ROUTE_ATTRIBUTE_CWND, 12); + nmtst_assert_route_attribute_uint32 (ip4_route, NM_IP_ROUTE_ATTRIBUTE_INITCWND, 13); + nmtst_assert_route_attribute_uint32 (ip4_route, NM_IP_ROUTE_ATTRIBUTE_INITRWND, 14); + nmtst_assert_route_attribute_uint32 (ip4_route, NM_IP_ROUTE_ATTRIBUTE_MTU, 9000); + nmtst_assert_route_attribute_boolean (ip4_route, NM_IP_ROUTE_ATTRIBUTE_LOCK_MTU, TRUE); + nmtst_assert_route_attribute_boolean (ip4_route, NM_IP_ROUTE_ATTRIBUTE_LOCK_INITCWND, TRUE); + nmtst_assert_route_attribute_string (ip4_route, NM_IP_ROUTE_ATTRIBUTE_SRC, "1.1.1.1"); g_object_unref (connection); } @@ -1094,6 +1360,14 @@ test_read_wired_static_routes_legacy (void) g_assert_cmpint (nm_ip_route_get_prefix (ip4_route), ==, 16); g_assert_cmpstr (nm_ip_route_get_next_hop (ip4_route), ==, "7.7.7.7"); g_assert_cmpint (nm_ip_route_get_metric (ip4_route), ==, 3); + nmtst_assert_route_attribute_uint32 (ip4_route, NM_IP_ROUTE_ATTRIBUTE_WINDOW, 10000); + nmtst_assert_route_attribute_uint32 (ip4_route, NM_IP_ROUTE_ATTRIBUTE_CWND, 14); + nmtst_assert_route_attribute_uint32 (ip4_route, NM_IP_ROUTE_ATTRIBUTE_INITCWND, 42); + nmtst_assert_route_attribute_uint32 (ip4_route, NM_IP_ROUTE_ATTRIBUTE_INITRWND, 20); + nmtst_assert_route_attribute_uint32 (ip4_route, NM_IP_ROUTE_ATTRIBUTE_MTU, 9000); + nmtst_assert_route_attribute_boolean (ip4_route, NM_IP_ROUTE_ATTRIBUTE_LOCK_WINDOW, TRUE); + nmtst_assert_route_attribute_boolean (ip4_route, NM_IP_ROUTE_ATTRIBUTE_LOCK_MTU, TRUE); + nmtst_assert_route_attribute_string (ip4_route, NM_IP_ROUTE_ATTRIBUTE_SRC, "1.2.3.4"); g_object_unref (connection); } @@ -1234,7 +1508,7 @@ test_read_wired_ipv6_manual (void) g_assert_cmpint (nm_ip_address_get_prefix (ip6_addr), ==, 96); /* Routes */ - g_assert_cmpint (nm_setting_ip_config_get_num_routes (s_ip6), ==, 2); + g_assert_cmpint (nm_setting_ip_config_get_num_routes (s_ip6), ==, 3); /* Route #1 */ ip6_route = nm_setting_ip_config_get_route (s_ip6, 0); g_assert (ip6_route); @@ -1249,6 +1523,17 @@ test_read_wired_ipv6_manual (void) g_assert_cmpint (nm_ip_route_get_prefix (ip6_route), ==, 64); g_assert_cmpstr (nm_ip_route_get_next_hop (ip6_route), ==, NULL); g_assert_cmpint (nm_ip_route_get_metric (ip6_route), ==, 777); + /* Route #3 */ + ip6_route = nm_setting_ip_config_get_route (s_ip6, 2); + g_assert (ip6_route); + g_assert_cmpstr (nm_ip_route_get_dest (ip6_route), ==, "aaaa::cccc"); + g_assert_cmpint (nm_ip_route_get_prefix (ip6_route), ==, 64); + g_assert_cmpstr (nm_ip_route_get_next_hop (ip6_route), ==, "3333::4444"); + nmtst_assert_route_attribute_uint32 (ip6_route, NM_IP_ROUTE_ATTRIBUTE_CWND, 13); + nmtst_assert_route_attribute_uint32 (ip6_route, NM_IP_ROUTE_ATTRIBUTE_MTU, 1450); + nmtst_assert_route_attribute_boolean (ip6_route, NM_IP_ROUTE_ATTRIBUTE_LOCK_MTU, TRUE); + nmtst_assert_route_attribute_string (ip6_route, NM_IP_ROUTE_ATTRIBUTE_FROM, "1111::2222/48"); + nmtst_assert_route_attribute_string (ip6_route, NM_IP_ROUTE_ATTRIBUTE_SRC, "5555::6666"); /* DNS Addresses */ g_assert_cmpint (nm_setting_ip_config_get_num_dns (s_ip6), ==, 2); @@ -1567,12 +1852,16 @@ 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"); - _writer_new_connection (connection, + g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE, + "*missing IEEE_8021X_CA_CERT for EAP method 'peap'; this is insecure!"); + _writer_new_connec_exp (connection, TEST_SCRATCH_DIR "/network-scripts/", + TEST_IFCFG_DIR "/network-scripts/ifcfg-System_test-wired-802-1X-subj-matches.cexpected", &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 (); @@ -1624,24 +1913,38 @@ test_read_802_1x_ttls_eapgtc (void) } static void -test_read_wired_aliases_good (void) +test_read_wired_aliases_good (gconstpointer test_data) { + const int N = GPOINTER_TO_INT (test_data); NMConnection *connection; NMSettingConnection *s_con; NMSettingIPConfig *s_ip4; - int expected_num_addresses = 4; - const char *expected_address[4] = { "192.168.1.5", "192.168.1.6", "192.168.1.9", "192.168.1.99" }; - const char *expected_label[4] = { NULL, "aliasem0:1", "aliasem0:2", "aliasem0:99" }; + int expected_num_addresses; + const char *expected_address_0[] = { "192.168.1.5", "192.168.1.6", "192.168.1.9", "192.168.1.99", NULL }; + const char *expected_address_3[] = { "192.168.1.5", "192.168.1.6", NULL }; + const char *expected_label_0[] = { NULL, "aliasem0:1", "aliasem0:2", "aliasem0:99", NULL, }; + const char *expected_label_3[] = { NULL, "aliasem3:1", NULL, }; + const char **expected_address; + const char **expected_label; int i, j; + char path[256]; - connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-aliasem0", - NULL, TYPE_ETHERNET, NULL); + expected_address = N == 0 ? expected_address_0 : expected_address_3; + expected_label = N == 0 ? expected_label_0 : expected_label_3; + expected_num_addresses = g_strv_length ((char **) expected_address); + + nm_sprintf_buf (path, TEST_IFCFG_DIR "/network-scripts/ifcfg-aliasem%d", N); + + connection = _connection_from_file (path, NULL, TYPE_ETHERNET, NULL); /* ===== CONNECTION SETTING ===== */ s_con = nm_connection_get_setting_connection (connection); g_assert (s_con); - g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "System aliasem0"); + if (N == 0) + g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "System aliasem0"); + else + g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "System aliasem3"); /* ===== IPv4 SETTING ===== */ @@ -1680,6 +1983,7 @@ test_read_wired_aliases_good (void) } /* Gateway */ + g_assert (!nm_setting_ip_config_get_never_default (s_ip4)); g_assert_cmpstr (nm_setting_ip_config_get_gateway (s_ip4), ==, "192.168.1.1"); for (i = 0; i < expected_num_addresses; i++) @@ -1803,8 +2107,9 @@ test_clear_master (void) g_assert_cmpstr (nm_setting_connection_get_slave_type (s_con), ==, "bridge"); /* 2. write the connection to a new file */ - _writer_new_connection (connection, + _writer_new_connec_exp (connection, TEST_SCRATCH_DIR "/network-scripts/", + TEST_IFCFG_DIR "/network-scripts/ifcfg-System_test-bridge-component-a.cexpected", &testfile); /* 3. clear master and slave-type */ @@ -1816,10 +2121,13 @@ 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/", - testfile); + testfile, + TEST_IFCFG_DIR "/network-scripts/ifcfg-System_test-bridge-component-b.cexpected"); keyfile = utils_get_keys_path (testfile); g_assert (!g_file_test (keyfile, G_FILE_TEST_EXISTS)); @@ -1902,9 +2210,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); @@ -3120,8 +3428,9 @@ test_write_wifi_hidden (void) nmtst_assert_connection_verifies (connection); - _writer_new_connection (connection, + _writer_new_connec_exp (connection, TEST_SCRATCH_DIR "/network-scripts/", + TEST_IFCFG_DIR "/network-scripts/ifcfg-Test_Write_WiFi_Hidden.cexpected", &testfile); f = _svOpenFile (testfile); @@ -3169,6 +3478,7 @@ test_write_wifi_mac_random (gconstpointer user_data) const char *name, *write_expected; gpointer value_p; NMSettingMacRandomization value; + char cexpected[NM_STRLEN (TEST_IFCFG_DIR) + 100]; nmtst_test_data_unpack (user_data, &name, &value_p, &write_expected); value = GPOINTER_TO_INT (value_p); @@ -3203,8 +3513,9 @@ test_write_wifi_mac_random (gconstpointer user_data) nmtst_assert_connection_verifies (connection); - _writer_new_connection (connection, + _writer_new_connec_exp (connection, TEST_SCRATCH_DIR "/network-scripts/", + nm_sprintf_buf (cexpected, TEST_IFCFG_DIR"/network-scripts/ifcfg-Test_Write_WiFi_MAC_%s.cexpected", name), &testfile); f = _svOpenFile (testfile); @@ -3255,12 +3566,13 @@ test_write_wired_wake_on_lan (void) nmtst_assert_connection_verifies (connection); - _writer_new_connection (connection, + _writer_new_connec_exp (connection, TEST_SCRATCH_DIR "/network-scripts/", + TEST_IFCFG_DIR "/network-scripts/ifcfg-Test_Write_Wired_Wake-on-LAN.cexpected", &testfile); f = _svOpenFile (testfile); - val = svGetValueString (f, "ETHTOOL_OPTS"); + val = svGetValueStr_cp (f, "ETHTOOL_OPTS"); g_assert (val); g_assert (strstr (val, "wol")); g_assert (strstr (val, "sopass 00:00:00:11:22:33")); @@ -3290,12 +3602,13 @@ test_write_wired_auto_negotiate_off (void) NM_SETTING_WIRED_SPEED, 10, NULL); - _writer_new_connection (connection, + _writer_new_connec_exp (connection, TEST_SCRATCH_DIR "/network-scripts/", + TEST_IFCFG_DIR "/network-scripts/ifcfg-Test_Write_Wired_Auto-Negotiate.cexpected", &testfile); f = _svOpenFile (testfile); - val = svGetValueString (f, "ETHTOOL_OPTS"); + val = svGetValueStr_cp (f, "ETHTOOL_OPTS"); g_assert (val); g_assert (strstr (val, "autoneg off")); g_assert (strstr (val, "speed 10")); @@ -3329,7 +3642,7 @@ test_write_wired_auto_negotiate_on (void) &testfile); f = _svOpenFile (testfile); - val = svGetValueString (f, "ETHTOOL_OPTS"); + val = svGetValueStr_cp (f, "ETHTOOL_OPTS"); g_assert (val); g_assert (strstr (val, "autoneg on")); g_assert (!strstr (val, "speed")); @@ -3403,8 +3716,9 @@ test_write_wifi_band_a (void) nmtst_assert_connection_verifies (connection); - _writer_new_connection (connection, + _writer_new_connec_exp (connection, TEST_SCRATCH_DIR "/network-scripts/", + TEST_IFCFG_DIR "/network-scripts/ifcfg-Test_Write_WiFi_Band_A.cexpected", &testfile); f = _svOpenFile (testfile); @@ -3753,6 +4067,12 @@ test_write_wired_static (void) route6 = nm_ip_route_new (AF_INET6, "::", 128, "2222:aaaa::9999", 1, &error); g_assert_no_error (error); + nm_ip_route_set_attribute (route6, NM_IP_ROUTE_ATTRIBUTE_TOS, g_variant_new_byte (0xb8)); + nm_ip_route_set_attribute (route6, NM_IP_ROUTE_ATTRIBUTE_CWND, g_variant_new_uint32 (100)); + nm_ip_route_set_attribute (route6, NM_IP_ROUTE_ATTRIBUTE_MTU, g_variant_new_uint32 (1280)); + nm_ip_route_set_attribute (route6, NM_IP_ROUTE_ATTRIBUTE_LOCK_CWND, g_variant_new_boolean (TRUE)); + nm_ip_route_set_attribute (route6, NM_IP_ROUTE_ATTRIBUTE_FROM, g_variant_new_string ("2222::bbbb/32")); + nm_ip_route_set_attribute (route6, NM_IP_ROUTE_ATTRIBUTE_SRC, g_variant_new_string ("::42")); nm_setting_ip_config_add_route (s_ip6, route6); nm_ip_route_unref (route6); @@ -3766,9 +4086,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); @@ -4082,7 +4402,7 @@ test_write_wired_static_ip6_only_gw (gconstpointer user_data) nmtst_assert_connection_equals (connection, TRUE, reread, FALSE); ifcfg = _svOpenFile (testfile); - written_ifcfg_gateway = svGetValueString (ifcfg, "IPV6_DEFAULTGW"); + written_ifcfg_gateway = svGetValueStr_cp (ifcfg, "IPV6_DEFAULTGW"); svCloseFile (ifcfg); /* access the gateway from the loaded connection. */ @@ -4147,8 +4467,9 @@ test_read_write_static_routes_legacy (void) * we can clean up after the written connection in both the original * source tree and for 'make distcheck'. */ - _writer_new_connection (connection, + _writer_new_connec_exp (connection, TEST_SCRATCH_DIR_TMP, + TEST_IFCFG_DIR "/network-scripts/ifcfg-test-static-routes-legacy.cexpected", &testfile); reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL); @@ -4436,9 +4757,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); @@ -4486,15 +4807,15 @@ test_write_wired_8021x_tls (gconstpointer test_data) } /* Clean up created certs and keys */ - tmp = utils_cert_path (testfile, "ca-cert.der"); + tmp = utils_cert_path (testfile, "ca-cert", "der"); nmtst_file_unlink_if_exists (tmp); g_free (tmp); - tmp = utils_cert_path (testfile, "client-cert.der"); + tmp = utils_cert_path (testfile, "client-cert", "der"); nmtst_file_unlink_if_exists (tmp); g_free (tmp); - tmp = utils_cert_path (testfile, "private-key.pem"); + tmp = utils_cert_path (testfile, "private-key", "pem"); nmtst_file_unlink_if_exists (tmp); g_free (tmp); } @@ -4562,22 +4883,22 @@ test_write_wired_aliases (void) /* Create some pre-existing alias files, to make sure they get overwritten / deleted. */ ifcfg = svCreateFile (TEST_SCRATCH_ALIAS_BASE ":2"); - svSetValueString (ifcfg, "DEVICE", "alias0:2"); - svSetValueString (ifcfg, "IPADDR", "192.168.1.2"); + svSetValueStr (ifcfg, "DEVICE", "alias0:2"); + svSetValueStr (ifcfg, "IPADDR", "192.168.1.2"); svWriteFile (ifcfg, 0644, NULL); svCloseFile (ifcfg); g_assert (g_file_test (TEST_SCRATCH_ALIAS_BASE ":2", G_FILE_TEST_EXISTS)); ifcfg = svCreateFile (TEST_SCRATCH_ALIAS_BASE ":5"); - svSetValueString (ifcfg, "DEVICE", "alias0:5"); - svSetValueString (ifcfg, "IPADDR", "192.168.1.5"); + svSetValueStr (ifcfg, "DEVICE", "alias0:5"); + svSetValueStr (ifcfg, "IPADDR", "192.168.1.5"); svWriteFile (ifcfg, 0644, NULL); 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)); @@ -5263,8 +5584,9 @@ test_write_wifi_wep_104_ascii (void) nmtst_assert_connection_verifies (connection); - _writer_new_connection (connection, + _writer_new_connec_exp (connection, TEST_SCRATCH_DIR "/network-scripts/", + TEST_IFCFG_DIR "/network-scripts/ifcfg-Test_Write_Wifi_WEP_104_ASCII.cexpected", &testfile); reread = _connection_from_file (testfile, NULL, TYPE_WIRELESS, NULL); @@ -5347,8 +5669,9 @@ test_write_wifi_leap (void) nmtst_assert_connection_verifies (connection); - _writer_new_connection (connection, + _writer_new_connec_exp (connection, TEST_SCRATCH_DIR "/network-scripts/", + TEST_IFCFG_DIR "/network-scripts/ifcfg-Test_Write_Wifi_LEAP.cexpected", &testfile); reread = _connection_from_file (testfile, NULL, TYPE_WIRELESS, NULL); @@ -5429,9 +5752,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); @@ -5701,6 +6024,11 @@ test_write_wifi_wpa_eap_tls (void) nm_connection_add_setting (connection, NM_SETTING (s_8021x)); g_object_set (s_8021x, NM_SETTING_802_1X_IDENTITY, "Bill Smith", NULL); + g_object_set (s_8021x, + NM_SETTING_802_1X_PHASE1_AUTH_FLAGS, + (guint) (NM_SETTING_802_1X_AUTH_FLAGS_TLS_1_0_DISABLE | + NM_SETTING_802_1X_AUTH_FLAGS_TLS_1_1_DISABLE), + NULL); nm_setting_802_1x_add_eap_method (s_8021x, "tls"); @@ -6080,7 +6408,8 @@ test_write_wifi_wpa_then_open (void) /* Write it back out */ _writer_update_connection (connection, TEST_SCRATCH_DIR "/network-scripts/", - testfile); + testfile, + TEST_IFCFG_DIR "/network-scripts/ifcfg-random_wifi_connection.cexpected"); keyfile = utils_get_keys_path (testfile); g_assert (!g_file_test (keyfile, G_FILE_TEST_EXISTS)); @@ -6199,7 +6528,8 @@ test_write_wifi_wpa_then_wep_with_perms (void) /* Write it back out */ _writer_update_connection (connection, TEST_SCRATCH_DIR "/network-scripts/", - testfile); + testfile, + TEST_IFCFG_DIR "/network-scripts/ifcfg-random_wifi_connection_2.cexpected"); reread = _connection_from_file (testfile, NULL, TYPE_WIRELESS, NULL); @@ -6498,8 +6828,9 @@ test_write_permissions (void) nmtst_assert_connection_verifies (connection); - _writer_new_connection (connection, + _writer_new_connec_exp (connection, TEST_SCRATCH_DIR "/network-scripts/", + TEST_IFCFG_DIR "/network-scripts/ifcfg-Test_Write_Permissions.cexpected", &testfile); reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL); @@ -6572,9 +6903,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); @@ -6953,8 +7284,9 @@ test_write_bridge_component (void) nmtst_assert_connection_verifies (connection); - _writer_new_connection (connection, + _writer_new_connec_exp (connection, TEST_SCRATCH_DIR "/network-scripts/", + TEST_IFCFG_DIR "/network-scripts/ifcfg-Test_Write_Bridge_Component.cexpected", &testfile); reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL); @@ -7198,8 +7530,9 @@ test_write_vlan (void) connection = _connection_from_file (TEST_IFCFG_VLAN_INTERFACE, NULL, TYPE_VLAN, NULL); - _writer_new_connection (connection, + _writer_new_connec_exp (connection, TEST_SCRATCH_DIR "/network-scripts/", + TEST_IFCFG_DIR "/network-scripts/ifcfg-Vlan_test-vlan-interface.cexpected", &testfile); } @@ -7278,8 +7611,9 @@ test_write_vlan_reorder_hdr (void) NM_SETTING_VLAN_FLAGS, 1, NULL); - _writer_new_connection (connection, + _writer_new_connec_exp (connection, TEST_SCRATCH_DIR "/network-scripts/", + TEST_IFCFG_DIR "/network-scripts/ifcfg-Test_Write_VLAN_reorder_hdr.cexpected", &testfile); reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL); @@ -7373,6 +7707,28 @@ test_read_bond_main (void) g_object_unref (connection); } +static void +test_read_bond_eth_type (void) +{ + NMConnection *connection; + NMSettingBond *s_bond; + + connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-bond-eth-type", + NULL, TYPE_ETHERNET,NULL); + + g_assert_cmpstr (nm_connection_get_interface_name (connection), ==, "bond0"); + + /* ===== Bonding SETTING ===== */ + + s_bond = nm_connection_get_setting_bond (connection); + g_assert (s_bond); + + g_assert_cmpstr (nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_MIIMON), ==, "213"); + g_assert_cmpstr (nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_LACP_RATE), ==, "1"); + + g_object_unref (connection); +} + static void test_write_bond_main (void) { @@ -7436,8 +7792,9 @@ test_write_bond_main (void) nmtst_assert_connection_verifies_without_normalization (connection); - _writer_new_connection (connection, + _writer_new_connec_exp (connection, TEST_SCRATCH_DIR "/network-scripts/", + TEST_IFCFG_DIR "/network-scripts/ifcfg-Test_Write_Bond_Main.cexpected", &testfile); reread = _connection_from_file (testfile, NULL, TYPE_BOND, NULL); @@ -7830,8 +8187,9 @@ test_write_dcb_basic (void) nmtst_assert_connection_verifies (connection); - _writer_new_connection (connection, + _writer_new_connec_exp (connection, TEST_SCRATCH_DIR "/network-scripts/", + TEST_IFCFG_DIR "/network-scripts//ifcfg-dcb-test.cexpected", &testfile); reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL); @@ -8228,8 +8586,9 @@ test_write_team_port (void) nmtst_assert_connection_verifies (connection); - _writer_new_connection (connection, + _writer_new_connec_exp (connection, TEST_SCRATCH_DIR "/network-scripts/", + TEST_IFCFG_DIR "/network-scripts/ifcfg-Test_Write_Team_Port.cexpected", &testfile); f = _svOpenFile (testfile); @@ -8268,6 +8627,69 @@ test_read_team_port_empty_config (void) g_object_unref (connection); } +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, + TEST_IFCFG_DIR "/network-scripts/ifcfg-team-slave-enp31s0f1-142.cexpected", + &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) { @@ -8327,8 +8749,9 @@ test_write_proxy_basic (void) nmtst_assert_connection_verifies (connection); - _writer_new_connection (connection, + _writer_new_connec_exp (connection, TEST_SCRATCH_DIR "/network-scripts/", + TEST_IFCFG_DIR "/network-scripts/ifcfg-Test_Write_Proxy_Basic.cexpected", &testfile); f = _svOpenFile (testfile); @@ -8682,12 +9105,12 @@ 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"); - _svGetValue_check (sv, "NAME2", NULL); + _svGetValue_check (sv, "NAME2", ""); _svGetValue_check (sv, "NAME3", "name3-value"); svSetValue (sv, "NAME", "set-by-test1"); @@ -8944,6 +9367,8 @@ int main (int argc, char **argv) nmtst_add_test_func (TPATH "wired/read/manual/3", test_read_wired_ipv4_manual, TEST_IFCFG_DIR "/network-scripts/ifcfg-test-wired-ipv4-manual-3", "System test-wired-ipv4-manual-3"); nmtst_add_test_func (TPATH "wired/read/manual/4", test_read_wired_ipv4_manual, TEST_IFCFG_DIR "/network-scripts/ifcfg-test-wired-ipv4-manual-4", "System test-wired-ipv4-manual-4"); + g_test_add_func (TPATH "user/1", test_user_1); + g_test_add_func (TPATH "wired/ipv6-manual", test_read_wired_ipv6_manual); nmtst_add_test_func (TPATH "wired-ipv6-only/0", test_read_wired_ipv6_only, TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-ipv6-only", "System test-wired-ipv6-only"); @@ -8960,7 +9385,8 @@ int main (int argc, char **argv) g_test_add_func (TPATH "802-1x/subj-matches", test_read_write_802_1X_subj_matches); g_test_add_func (TPATH "802-1x/ttls-eapgtc", test_read_802_1x_ttls_eapgtc); - g_test_add_func (TPATH "wired/read/aliases", test_read_wired_aliases_good); + g_test_add_data_func (TPATH "wired/read/aliases/good/0", GINT_TO_POINTER (0), test_read_wired_aliases_good); + g_test_add_data_func (TPATH "wired/read/aliases/good/3", GINT_TO_POINTER (3), test_read_wired_aliases_good); g_test_add_func (TPATH "wired/read/aliases/bad1", test_read_wired_aliases_bad_1); g_test_add_func (TPATH "wired/read/aliases/bad2", test_read_wired_aliases_bad_2); g_test_add_func (TPATH "wifi/read/open", test_read_wifi_open); @@ -9112,6 +9538,7 @@ int main (int argc, char **argv) g_test_add_data_func (TPATH "fcoe/write-vn2vn", (gpointer) NM_SETTING_DCB_FCOE_MODE_VN2VN, test_write_fcoe_mode); g_test_add_func (TPATH "bond/read-master", test_read_bond_main); + g_test_add_func (TPATH "bond/read-master-eth-type", test_read_bond_eth_type); g_test_add_func (TPATH "bond/read-slave", test_read_bond_slave); g_test_add_func (TPATH "bond/read-slave-ib", test_read_bond_slave_ib); g_test_add_func (TPATH "bond/write-master", test_write_bond_main); @@ -9133,6 +9560,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/ifnet/nms-ifnet-connection-parser.c b/src/settings/plugins/ifnet/nms-ifnet-connection-parser.c index 84f2d3f4..c5129fea 100644 --- a/src/settings/plugins/ifnet/nms-ifnet-connection-parser.c +++ b/src/settings/plugins/ifnet/nms-ifnet-connection-parser.c @@ -31,6 +31,7 @@ #include "settings/nm-settings-plugin.h" #include "nm-core-internal.h" #include "NetworkManagerUtils.h" +#include "nm-setting-metadata.h" #include "nms-ifnet-net-utils.h" #include "nms-ifnet-wpa-parser.h" @@ -1688,96 +1689,43 @@ error: return NULL; } -typedef NMSetting8021xCKScheme (*SchemeFunc) (NMSetting8021x * setting); -typedef const char *(*PathFunc) (NMSetting8021x * setting); -typedef GBytes *(*BlobFunc) (NMSetting8021x * setting); - -typedef struct ObjectType { - const char *setting_key; - SchemeFunc scheme_func; - PathFunc path_func; - BlobFunc blob_func; - const char *conn_name_key; - const char *suffix; -} ObjectType; - -static const ObjectType ca_type = { - NM_SETTING_802_1X_CA_CERT, - nm_setting_802_1x_get_ca_cert_scheme, - nm_setting_802_1x_get_ca_cert_path, - nm_setting_802_1x_get_ca_cert_blob, - "ca_cert", - "ca-cert.der" -}; - -static const ObjectType phase2_ca_type = { - NM_SETTING_802_1X_PHASE2_CA_CERT, - nm_setting_802_1x_get_phase2_ca_cert_scheme, - nm_setting_802_1x_get_phase2_ca_cert_path, - nm_setting_802_1x_get_phase2_ca_cert_blob, - "ca_cert2", - "inner-ca-cert.der" -}; - -static const ObjectType client_type = { - NM_SETTING_802_1X_CLIENT_CERT, - nm_setting_802_1x_get_client_cert_scheme, - nm_setting_802_1x_get_client_cert_path, - nm_setting_802_1x_get_client_cert_blob, - "client_cert", - "client-cert.der" -}; - -static const ObjectType phase2_client_type = { - NM_SETTING_802_1X_PHASE2_CLIENT_CERT, - nm_setting_802_1x_get_phase2_client_cert_scheme, - nm_setting_802_1x_get_phase2_client_cert_path, - nm_setting_802_1x_get_phase2_client_cert_blob, - "client_cert2", - "inner-client-cert.der" -}; - -static const ObjectType pk_type = { - NM_SETTING_802_1X_PRIVATE_KEY, - nm_setting_802_1x_get_private_key_scheme, - nm_setting_802_1x_get_private_key_path, - nm_setting_802_1x_get_private_key_blob, - "private_key", - "private-key.pem" -}; - -static const ObjectType phase2_pk_type = { - NM_SETTING_802_1X_PHASE2_PRIVATE_KEY, - nm_setting_802_1x_get_phase2_private_key_scheme, - nm_setting_802_1x_get_phase2_private_key_path, - nm_setting_802_1x_get_phase2_private_key_blob, - "private_key2", - "inner-private-key.pem" -}; - -static const ObjectType p12_type = { - NM_SETTING_802_1X_PRIVATE_KEY, - nm_setting_802_1x_get_private_key_scheme, - nm_setting_802_1x_get_private_key_path, - nm_setting_802_1x_get_private_key_blob, - "private_key", - "private-key.p12" -}; - -static const ObjectType phase2_p12_type = { - NM_SETTING_802_1X_PHASE2_PRIVATE_KEY, - nm_setting_802_1x_get_phase2_private_key_scheme, - nm_setting_802_1x_get_phase2_private_key_path, - nm_setting_802_1x_get_phase2_private_key_blob, - "private_key2", - "inner-private-key.p12" +typedef struct Setting8021xSchemeVtable { + const NMSetting8021xSchemeVtable *vtable; + const char *ifnet_key; +} Setting8021xSchemeVtable; + +static const Setting8021xSchemeVtable setting_8021x_scheme_vtable[] = { + [NM_SETTING_802_1X_SCHEME_TYPE_CA_CERT] = { + .vtable = &nm_setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_CA_CERT], + .ifnet_key = "ca_cert", + }, + [NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_CA_CERT] = { + .vtable = &nm_setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_CA_CERT], + .ifnet_key = "ca_cert2", + }, + [NM_SETTING_802_1X_SCHEME_TYPE_CLIENT_CERT] = { + .vtable = &nm_setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_CLIENT_CERT], + .ifnet_key = "client_cert", + }, + [NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_CLIENT_CERT] = { + .vtable = &nm_setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_CLIENT_CERT], + .ifnet_key = "client_cert2", + }, + [NM_SETTING_802_1X_SCHEME_TYPE_PRIVATE_KEY] = { + .vtable = &nm_setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_PRIVATE_KEY], + .ifnet_key = "private_key", + }, + [NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_PRIVATE_KEY] = { + .vtable = &nm_setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_PRIVATE_KEY], + .ifnet_key = "private_key2", + }, }; static gboolean write_object (NMSetting8021x *s_8021x, const char *conn_name, GBytes *override_data, - const ObjectType *objtype, + const Setting8021xSchemeVtable *objtype, GError **error) { NMSetting8021xCKScheme scheme; @@ -1792,13 +1740,13 @@ write_object (NMSetting8021x *s_8021x, */ blob = override_data; else { - scheme = (*(objtype->scheme_func)) (s_8021x); + scheme = (*(objtype->vtable->scheme_func)) (s_8021x); switch (scheme) { case NM_SETTING_802_1X_CK_SCHEME_BLOB: - blob = (*(objtype->blob_func)) (s_8021x); + blob = (*(objtype->vtable->blob_func)) (s_8021x); break; case NM_SETTING_802_1X_CK_SCHEME_PATH: - path = (*(objtype->path_func)) (s_8021x); + path = (*(objtype->vtable->path_func)) (s_8021x); break; default: break; @@ -1809,8 +1757,8 @@ write_object (NMSetting8021x *s_8021x, * may have been sent. */ if (path) { - wpa_set_data (conn_name, (gchar *) objtype->conn_name_key, - (gchar *) path); + wpa_set_data (conn_name, (gchar *) objtype->ifnet_key, + (gchar *) path); return TRUE; } @@ -1828,17 +1776,16 @@ write_8021x_certs (NMSetting8021x *s_8021x, GError **error) { char *password = NULL; - const ObjectType *otype = NULL; + const Setting8021xSchemeVtable *otype = NULL; gboolean is_pkcs12 = FALSE, success = FALSE; GBytes *blob = NULL; GBytes *enc_key = NULL; gchar *generated_pw = NULL; /* CA certificate */ - if (phase2) - otype = &phase2_ca_type; - else - otype = &ca_type; + otype = phase2 + ? &setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_CA_CERT] + : &setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_CA_CERT]; if (!write_object (s_8021x, conn_name, NULL, otype, error)) return FALSE; @@ -1864,14 +1811,13 @@ write_8021x_certs (NMSetting8021x *s_8021x, nm_setting_802_1x_get_private_key_password (s_8021x); } - if (is_pkcs12) - otype = phase2 ? &phase2_p12_type : &p12_type; - else - otype = phase2 ? &phase2_pk_type : &pk_type; + otype = phase2 + ? &setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_PRIVATE_KEY] + : &setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_PRIVATE_KEY]; - if ((*(otype->scheme_func)) (s_8021x) == + if ((*(otype->vtable->scheme_func)) (s_8021x) == NM_SETTING_802_1X_CK_SCHEME_BLOB) - blob = (*(otype->blob_func)) (s_8021x); + blob = (*(otype->vtable->blob_func)) (s_8021x); /* Only do the private key re-encrypt dance if we got the raw key data, which * by definition will be unencrypted. If we're given a direct path to the @@ -1883,7 +1829,7 @@ write_8021x_certs (NMSetting8021x *s_8021x, /* Encrypt the unencrypted private key with the fake password */ tmp_enc_key = nm_utils_rsa_key_encrypt (g_bytes_get_data (blob, NULL), g_bytes_get_size (blob), - password, &generated_pw, error); + password, &generated_pw, error); if (!tmp_enc_key) goto out; @@ -1906,12 +1852,11 @@ write_8021x_certs (NMSetting8021x *s_8021x, /* Client certificate */ if (is_pkcs12) { wpa_set_data (conn_name, - phase2 ? "client_cert2" : "client_cert", NULL); + phase2 ? "client_cert2" : "client_cert", NULL); } else { - if (phase2) - otype = &phase2_client_type; - else - otype = &client_type; + otype = phase2 + ? &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]; /* Save the client certificate */ if (!write_object (s_8021x, conn_name, NULL, otype, error)) diff --git a/src/settings/plugins/ifnet/nms-ifnet-connection-parser.h b/src/settings/plugins/ifnet/nms-ifnet-connection-parser.h index e6c0e88c..51bc34b9 100644 --- a/src/settings/plugins/ifnet/nms-ifnet-connection-parser.h +++ b/src/settings/plugins/ifnet/nms-ifnet-connection-parser.h @@ -22,7 +22,7 @@ #ifndef _CONNECTION_PARSER_H #define _CONNECTION_PARSER_H -#include +#include "nm-connection.h" #include "nms-ifnet-net-parser.h" diff --git a/src/settings/plugins/ifnet/nms-ifnet-net-utils.h b/src/settings/plugins/ifnet/nms-ifnet-net-utils.h index 79d44642..cc273aa7 100644 --- a/src/settings/plugins/ifnet/nms-ifnet-net-utils.h +++ b/src/settings/plugins/ifnet/nms-ifnet-net-utils.h @@ -26,8 +26,8 @@ #include -#include -#include +#include "nm-setting-ip6-config.h" +#include "nm-setting-ip4-config.h" #include "nms-ifnet-net-parser.h" diff --git a/src/settings/plugins/ifupdown/nms-ifupdown-parser.h b/src/settings/plugins/ifupdown/nms-ifupdown-parser.h index 36e52e2c..6a86bf86 100644 --- a/src/settings/plugins/ifupdown/nms-ifupdown-parser.h +++ b/src/settings/plugins/ifupdown/nms-ifupdown-parser.h @@ -24,7 +24,7 @@ #ifndef __PARSER_H__ #define __PARSER_H__ -#include +#include "nm-connection.h" #include "nms-ifupdown-interface-parser.h" diff --git a/src/settings/plugins/ifupdown/nms-ifupdown-plugin.c b/src/settings/plugins/ifupdown/nms-ifupdown-plugin.c index 211e5d57..189b6e69 100644 --- a/src/settings/plugins/ifupdown/nms-ifupdown-plugin.c +++ b/src/settings/plugins/ifupdown/nms-ifupdown-plugin.c @@ -28,8 +28,8 @@ #include #include -#include #include +#include #include "nm-setting-connection.h" #include "nm-dbus-interface.h" @@ -42,6 +42,7 @@ #include "nm-core-internal.h" #include "NetworkManagerUtils.h" #include "nm-config.h" +#include "nm-utils/nm-udev-utils.h" #include "nms-ifupdown-interface-parser.h" #include "nms-ifupdown-connection.h" @@ -62,7 +63,7 @@ /*****************************************************************************/ typedef struct { - GUdevClient *client; + NMUdevClient *udev_client; GHashTable *connections; /* /e/n/i block name :: NMIfupdownConnection */ @@ -103,21 +104,21 @@ NM_DEFINE_SINGLETON_GETTER (SettingsPluginIfupdown, settings_plugin_ifupdown_get static void bind_device_to_connection (SettingsPluginIfupdown *self, - GUdevDevice *device, + struct udev_device *device, NMIfupdownConnection *exported) { NMSettingWired *s_wired; NMSettingWireless *s_wifi; const char *iface, *address; - iface = g_udev_device_get_name (device); + iface = udev_device_get_sysname (device); if (!iface) { nm_log_warn (LOGD_SETTINGS, "failed to get ifname for device."); return; } - address = g_udev_device_get_sysfs_attr (device, "address"); - if (!address || !strlen (address)) { + address = udev_device_get_sysattr_value (device, "address"); + if (!address || !address[0]) { nm_log_warn (LOGD_SETTINGS, "failed to get MAC address for %s", iface); return; } @@ -142,14 +143,14 @@ bind_device_to_connection (SettingsPluginIfupdown *self, } static void -udev_device_added (SettingsPluginIfupdown *self, GUdevDevice *device) +udev_device_added (SettingsPluginIfupdown *self, struct udev_device *device) { SettingsPluginIfupdownPrivate *priv = SETTINGS_PLUGIN_IFUPDOWN_GET_PRIVATE (self); const char *iface, *path; NMIfupdownConnection *exported; - iface = g_udev_device_get_name (device); - path = g_udev_device_get_sysfs_path (device); + iface = udev_device_get_sysname (device); + path = udev_device_get_syspath (device); if (!iface || !path) return; @@ -165,7 +166,7 @@ udev_device_added (SettingsPluginIfupdown *self, GUdevDevice *device) return; } - g_hash_table_insert (priv->kernel_ifaces, g_strdup (iface), g_object_ref (device)); + g_hash_table_insert (priv->kernel_ifaces, g_strdup (iface), udev_device_ref (device)); if (exported) bind_device_to_connection (self, device, exported); @@ -175,13 +176,13 @@ udev_device_added (SettingsPluginIfupdown *self, GUdevDevice *device) } static void -udev_device_removed (SettingsPluginIfupdown *self, GUdevDevice *device) +udev_device_removed (SettingsPluginIfupdown *self, struct udev_device *device) { SettingsPluginIfupdownPrivate *priv = SETTINGS_PLUGIN_IFUPDOWN_GET_PRIVATE (self); const char *iface, *path; - iface = g_udev_device_get_name (device); - path = g_udev_device_get_sysfs_path (device); + iface = udev_device_get_sysname (device); + path = udev_device_get_syspath (device); if (!iface || !path) return; @@ -195,13 +196,13 @@ udev_device_removed (SettingsPluginIfupdown *self, GUdevDevice *device) } static void -udev_device_changed (SettingsPluginIfupdown *self, GUdevDevice *device) +udev_device_changed (SettingsPluginIfupdown *self, struct udev_device *device) { SettingsPluginIfupdownPrivate *priv = SETTINGS_PLUGIN_IFUPDOWN_GET_PRIVATE (self); const char *iface, *path; - iface = g_udev_device_get_name (device); - path = g_udev_device_get_sysfs_path (device); + iface = udev_device_get_sysname (device); + path = udev_device_get_syspath (device); if (!iface || !path) return; @@ -215,20 +216,21 @@ udev_device_changed (SettingsPluginIfupdown *self, GUdevDevice *device) } static void -handle_uevent (GUdevClient *client, - const char *action, - GUdevDevice *device, +handle_uevent (NMUdevClient *client, + struct udev_device *device, gpointer user_data) { SettingsPluginIfupdown *self = SETTINGS_PLUGIN_IFUPDOWN (user_data); const char *subsys; + const char *action; + + action = udev_device_get_action (device); g_return_if_fail (action != NULL); /* A bit paranoid */ - subsys = g_udev_device_get_subsystem (device); - g_return_if_fail (subsys != NULL); - g_return_if_fail (strcmp (subsys, "net") == 0); + subsys = udev_device_get_subsystem (device); + g_return_if_fail (nm_streq0 (subsys, "net")); if (!strcmp (action, "add")) udev_device_added (self, device); @@ -271,7 +273,7 @@ get_unmanaged_specs (NMSettingsPlugin *config) SettingsPluginIfupdownPrivate *priv = SETTINGS_PLUGIN_IFUPDOWN_GET_PRIVATE ((SettingsPluginIfupdown *) config); GSList *specs = NULL; GHashTableIter iter; - GUdevDevice *device; + struct udev_device *device; const char *iface; if (!ALWAYS_UNMANAGE && !priv->unmanage_well_known) @@ -284,7 +286,7 @@ get_unmanaged_specs (NMSettingsPlugin *config) while (g_hash_table_iter_next (&iter, (gpointer) &iface, (gpointer) &device)) { const char *address; - address = g_udev_device_get_sysfs_attr (device, "address"); + address = udev_device_get_sysattr_value (device, "address"); if (address) specs = g_slist_append (specs, g_strdup_printf ("mac:%s", address)); else @@ -317,6 +319,12 @@ get_property (GObject *object, guint prop_id, /*****************************************************************************/ +static void +_udev_device_unref (gpointer ptr) +{ + udev_device_unref (ptr); +} + static void init (NMSettingsPlugin *config) { @@ -324,11 +332,11 @@ init (NMSettingsPlugin *config) SettingsPluginIfupdownPrivate *priv = SETTINGS_PLUGIN_IFUPDOWN_GET_PRIVATE (self); GHashTable *auto_ifaces; if_block *block = NULL; - GList *keys, *iter; + struct udev_enumerate *enumerate; + struct udev_list_entry *keys; GHashTableIter con_iter; const char *block_name; NMIfupdownConnection *connection; - const char *subsys[2] = { "net", NULL }; auto_ifaces = g_hash_table_new (g_str_hash, g_str_equal); @@ -336,18 +344,15 @@ init (NMSettingsPlugin *config) priv->connections = g_hash_table_new (g_str_hash, g_str_equal); if(!priv->kernel_ifaces) - priv->kernel_ifaces = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); + priv->kernel_ifaces = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, _udev_device_unref); if(!priv->eni_ifaces) priv->eni_ifaces = g_hash_table_new (g_str_hash, g_str_equal); nm_log_info (LOGD_SETTINGS, "init!"); - priv->client = g_udev_client_new (subsys); - if (!priv->client) { - nm_log_warn (LOGD_SETTINGS, " error initializing libgudev"); - } else - g_signal_connect (priv->client, "uevent", G_CALLBACK (handle_uevent), self); + priv->udev_client = nm_udev_client_new ((const char *[]) { "net", NULL }, + handle_uevent, self); /* Read in all the interfaces */ ifparser_init (ENI_INTERFACES_FILE, 0); @@ -445,12 +450,20 @@ init (NMSettingsPlugin *config) nm_log_info (LOGD_SETTINGS, "management mode: %s", priv->unmanage_well_known ? "unmanaged" : "managed"); /* Add well-known interfaces */ - keys = g_udev_client_query_by_subsystem (priv->client, "net"); - for (iter = keys; iter; iter = g_list_next (iter)) { - udev_device_added (self, G_UDEV_DEVICE (iter->data)); - g_object_unref (G_UDEV_DEVICE (iter->data)); + enumerate = nm_udev_client_enumerate_new (priv->udev_client); + udev_enumerate_scan_devices (enumerate); + keys = udev_enumerate_get_list_entry (enumerate); + for (; keys; keys = udev_list_entry_get_next (keys)) { + struct udev_device *udevice; + + udevice = udev_device_new_from_syspath (udev_enumerate_get_udev (enumerate), + udev_list_entry_get_name (keys)); + if (udevice) { + udev_device_added (self, udevice); + udev_device_unref (udevice); + } } - g_list_free (keys); + udev_enumerate_unref (enumerate); /* Now if we're running in managed mode, let NM know there are new connections */ if (!priv->unmanage_well_known) { @@ -483,7 +496,8 @@ dispose (GObject *object) g_clear_pointer (&priv->kernel_ifaces, g_hash_table_destroy); g_clear_pointer (&priv->eni_ifaces, g_hash_table_destroy); - g_clear_object (&priv->client); + + priv->udev_client = nm_udev_client_unref (priv->udev_client); G_OBJECT_CLASS (settings_plugin_ifupdown_parent_class)->dispose (object); } diff --git a/src/settings/plugins/keyfile/nms-keyfile-connection.c b/src/settings/plugins/keyfile/nms-keyfile-connection.c index ff654acf..bd07d263 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 97306d66..4af80142 100644 --- a/src/settings/plugins/keyfile/nms-keyfile-plugin.c +++ b/src/settings/plugins/keyfile/nms-keyfile-plugin.c @@ -77,7 +77,7 @@ G_DEFINE_TYPE_EXTENDED (NMSKeyfilePlugin, nms_keyfile_plugin, G_TYPE_OBJECT, 0, #define _NMLOG_PREFIX_NAME "keyfile" #define _NMLOG_DOMAIN LOGD_SETTINGS #define _NMLOG(level, ...) \ - nm_log ((level), _NMLOG_DOMAIN, \ + nm_log ((level), _NMLOG_DOMAIN, NULL, NULL, \ "%s" _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ _NMLOG_PREFIX_NAME": " \ _NM_UTILS_MACRO_REST (__VA_ARGS__)) @@ -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 39a01480..cb4b8379 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) @@ -78,7 +87,9 @@ _handler_read (GKeyFile *keyfile, else level = LOGL_INFO; - nm_log (level, LOGD_SETTINGS, "keyfile: %s", + nm_log (level, LOGD_SETTINGS, NULL, + nm_connection_get_uuid (connection), + "keyfile: %s", _fmt_warn (warn_data->group, warn_data->setting, warn_data->property_name, warn_data->message, &message_free)); @@ -88,6 +99,19 @@ _handler_read (GKeyFile *keyfile, return FALSE; } +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) { @@ -122,7 +146,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 c52fea31..b60c1e69 100644 --- a/src/settings/plugins/keyfile/nms-keyfile-reader.h +++ b/src/settings/plugins/keyfile/nms-keyfile-reader.h @@ -22,7 +22,12 @@ #ifndef __NMS_KEYFILE_READER_H__ #define __NMS_KEYFILE_READER_H__ -#include +#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); diff --git a/src/settings/plugins/keyfile/nms-keyfile-writer.c b/src/settings/plugins/keyfile/nms-keyfile-writer.c index 95897db3..92ed2849 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" /*****************************************************************************/ @@ -51,12 +52,12 @@ cert_writer (NMConnection *connection, NMSetting8021xCKFormat format; const char *path = NULL, *ext = "pem"; - scheme = cert_data->scheme_func (cert_data->setting); + scheme = cert_data->vtable->scheme_func (cert_data->setting); if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) { char *tmp = NULL; const char *accepted_path = NULL; - path = cert_data->path_func (cert_data->setting); + path = cert_data->vtable->path_func (cert_data->setting); g_assert (path); if (g_str_has_prefix (path, info->keyfile_dir)) { @@ -92,11 +93,11 @@ cert_writer (NMConnection *connection, if (!accepted_path) accepted_path = tmp = g_strconcat (NM_KEYFILE_CERT_SCHEME_PREFIX_PATH, path, NULL); - nm_keyfile_plugin_kf_set_string (file, setting_name, cert_data->property_name, accepted_path); + nm_keyfile_plugin_kf_set_string (file, setting_name, cert_data->vtable->setting_key, accepted_path); g_free (tmp); } else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11) { - nm_keyfile_plugin_kf_set_string (file, setting_name, cert_data->property_name, - cert_data->uri_func (cert_data->setting)); + nm_keyfile_plugin_kf_set_string (file, setting_name, cert_data->vtable->setting_key, + cert_data->vtable->uri_func (cert_data->setting)); } else if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) { GBytes *blob; const guint8 *blob_data; @@ -105,13 +106,13 @@ cert_writer (NMConnection *connection, GError *local = NULL; char *new_path; - blob = cert_data->blob_func (cert_data->setting); + blob = cert_data->vtable->blob_func (cert_data->setting); g_assert (blob); blob_data = g_bytes_get_data (blob, &blob_len); - if (cert_data->format_func) { + if (cert_data->vtable->format_func) { /* Get the extension for a private key */ - format = cert_data->format_func (cert_data->setting); + format = cert_data->vtable->format_func (cert_data->setting); if (format == NM_SETTING_802_1X_CK_FORMAT_PKCS12) ext = "p12"; } else { @@ -124,17 +125,17 @@ cert_writer (NMConnection *connection, * from now on instead of pushing around the certificate data. */ new_path = g_strdup_printf ("%s/%s-%s.%s", info->keyfile_dir, nm_connection_get_uuid (connection), - cert_data->suffix, ext); + cert_data->vtable->file_suffix, ext); success = nm_utils_file_set_contents (new_path, (const gchar *) blob_data, blob_len, 0600, &local); if (success) { /* Write the path value to the keyfile. * We know, that basename(new_path) starts with a UUID, hence no conflict with "data:;base64," */ - nm_keyfile_plugin_kf_set_string (file, setting_name, cert_data->property_name, strrchr (new_path, '/') + 1); + nm_keyfile_plugin_kf_set_string (file, setting_name, cert_data->vtable->setting_key, strrchr (new_path, '/') + 1); } else { nm_log_warn (LOGD_SETTINGS, "keyfile: %s.%s: failed to write certificate to file %s: %s", - setting_name, cert_data->property_name, new_path, local->message); + setting_name, cert_data->vtable->setting_key, new_path, local->message); g_error_free (local); } g_free (new_path); @@ -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 4f43455d..ac41dfa2 100644 --- a/src/settings/plugins/keyfile/nms-keyfile-writer.h +++ b/src/settings/plugins/keyfile/nms-keyfile-writer.h @@ -22,12 +22,14 @@ #ifndef __NMS_KEYFILE_WRITER_H__ #define __NMS_KEYFILE_WRITER_H__ -#include +#include "nm-connection.h" 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/keyfiles/Test_Wired_Connection b/src/settings/plugins/keyfile/tests/keyfiles/Test_Wired_Connection index de8373be..5cb4d726 100644 --- a/src/settings/plugins/keyfile/tests/keyfiles/Test_Wired_Connection +++ b/src/settings/plugins/keyfile/tests/keyfiles/Test_Wired_Connection @@ -34,6 +34,7 @@ routes8=1.1.1.8/18,0.0.0.0, routes9=1.1.1.9/19,0.0.0.0,0 routes10=1.1.1.10/20,,0 routes11=1.1.1.11/21,,21 +routes11_options=cwnd=10,lock-cwnd=true,mtu=1430,src=7.7.7.7 ignore-auto-routes=false ignore-auto-dns=false @@ -58,5 +59,6 @@ route3=6:7:8:9:0:1:2:3/126,,1 route4=7:8:9:0:1:2:3:4/125/::,5 route5=8:9:0:1:2:3:4:5/124,6 route6=8:9:0:1:2:3:4:6/123,, +route6_options=from=abce::/63 ignore-auto-routes=false ignore-auto-dns=false diff --git a/src/settings/plugins/keyfile/tests/test-keyfile.c b/src/settings/plugins/keyfile/tests/test-keyfile.c index f1102bd3..d9da5317 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,12 +139,32 @@ 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) { @@ -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 @@ -171,6 +224,7 @@ test_read_valid_wired_connection (void) NMSettingWired *s_wired; NMSettingIPConfig *s_ip4; NMSettingIPConfig *s_ip6; + NMIPRoute *route; gs_free_error GError *error = NULL; const char *mac; char expected_mac_address[ETH_ALEN] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 }; @@ -265,6 +319,15 @@ test_read_valid_wired_connection (void) check_ip_route (s_ip4, 10, "1.1.1.10", 20, NULL, -1); check_ip_route (s_ip4, 11, "1.1.1.11", 21, NULL, 21); + /* Route attributes */ + route = nm_setting_ip_config_get_route (s_ip4, 11); + g_assert (route); + + nmtst_assert_route_attribute_uint32 (route, NM_IP_ROUTE_ATTRIBUTE_CWND, 10); + nmtst_assert_route_attribute_uint32 (route, NM_IP_ROUTE_ATTRIBUTE_MTU, 1430); + nmtst_assert_route_attribute_boolean (route, NM_IP_ROUTE_ATTRIBUTE_LOCK_CWND, TRUE); + nmtst_assert_route_attribute_string (route, NM_IP_ROUTE_ATTRIBUTE_SRC, "7.7.7.7"); + /* ===== IPv6 SETTING ===== */ s_ip6 = nm_connection_get_setting_ip6_config (connection); g_assert (s_ip6); @@ -304,6 +367,11 @@ test_read_valid_wired_connection (void) check_ip_route (s_ip6, 4, "7:8:9:0:1:2:3:4", 125, NULL, 5); check_ip_route (s_ip6, 5, "8:9:0:1:2:3:4:5", 124, NULL, 6); check_ip_route (s_ip6, 6, "8:9:0:1:2:3:4:6", 123, NULL, -1); + + /* Route attributes */ + route = nm_setting_ip_config_get_route (s_ip6, 6); + g_assert (route); + nmtst_assert_route_attribute_string (route, NM_IP_ROUTE_ATTRIBUTE_FROM, "abce::/63"); } static void @@ -349,6 +417,7 @@ test_write_wired_connection (void) NMSettingWired *s_wired; NMSettingIPConfig *s_ip4; NMSettingIPConfig *s_ip6; + NMIPRoute *rt; const char *mac = "99:88:77:66:55:44"; const char *dns1 = "4.2.2.1"; const char *dns2 = "4.2.2.2"; @@ -376,6 +445,7 @@ test_write_wired_connection (void) const char *route6_4 = "5:6:7:8:9:0:1:2"; const char *route6_4_nh = "::"; guint64 timestamp = 0x12345678L; + GError *error = NULL; connection = nm_simple_connection_new (); @@ -420,7 +490,14 @@ test_write_wired_connection (void) add_one_ip_route (s_ip4, route1, route1_nh, 24, 3); add_one_ip_route (s_ip4, route2, route2_nh, 8, 1); add_one_ip_route (s_ip4, route3, route3_nh, 7, -1); - add_one_ip_route (s_ip4, route4, route4_nh, 6, 4); + + rt = nm_ip_route_new (AF_INET, route4, 6, route4_nh, 4, &error); + g_assert_no_error (error); + nm_ip_route_set_attribute (rt, NM_IP_ROUTE_ATTRIBUTE_CWND, g_variant_new_uint32 (10)); + nm_ip_route_set_attribute (rt, NM_IP_ROUTE_ATTRIBUTE_MTU, g_variant_new_uint32 (1492)); + nm_ip_route_set_attribute (rt, NM_IP_ROUTE_ATTRIBUTE_SRC, g_variant_new_string ("1.2.3.4")); + g_assert (nm_setting_ip_config_add_route (s_ip4, rt)); + nm_ip_route_unref (rt); /* DNS servers */ nm_setting_ip_config_add_dns (s_ip4, dns1); @@ -1639,11 +1716,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 +1800,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 +1818,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); -- cgit 1.3.0-6-gf8a5