diff options
Diffstat (limited to 'src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c')
| -rw-r--r-- | src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c | 1233 |
1 files changed, 717 insertions, 516 deletions
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 c1960846..09a37991 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c @@ -33,6 +33,7 @@ #include <sys/ioctl.h> #include <unistd.h> +#include "nm-utils/nm-secret-utils.h" #include "nm-connection.h" #include "nm-dbus-interface.h" #include "nm-setting-connection.h" @@ -41,6 +42,7 @@ #include "nm-setting-ip6-config.h" #include "nm-setting-wired.h" #include "nm-setting-wireless.h" +#include "nm-setting-ethtool.h" #include "nm-setting-8021x.h" #include "nm-setting-bond.h" #include "nm-setting-team.h" @@ -53,6 +55,7 @@ #include "nm-setting-generic.h" #include "nm-core-internal.h" #include "nm-utils.h" +#include "nm-ethtool-utils.h" #include "platform/nm-platform.h" #include "NetworkManagerUtils.h" @@ -77,6 +80,210 @@ /*****************************************************************************/ +static char * +get_full_file_path (const char *ifcfg_path, const char *file_path) +{ + const char *base = file_path; + char *p, *ret, *dirname; + + g_return_val_if_fail (ifcfg_path != NULL, NULL); + g_return_val_if_fail (file_path != NULL, NULL); + + if (file_path[0] == '/') + return g_strdup (file_path); + + p = strrchr (file_path, '/'); + if (p) + base = p + 1; + + dirname = g_path_get_dirname (ifcfg_path); + ret = g_build_path ("/", dirname, base, NULL); + g_free (dirname); + return ret; +} + +/*****************************************************************************/ + +static NMSettingSecretFlags +_secret_read_ifcfg_flags (shvarFile *ifcfg, const char *flags_key) +{ + NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE; + gs_free char *val_free = NULL; + const char *val; + + nm_assert (flags_key); + nm_assert (g_str_has_suffix (flags_key, "_FLAGS")); + + val = svGetValueStr (ifcfg, flags_key, &val_free); + if (val) { + if (strstr (val, SECRET_FLAG_AGENT)) + flags |= NM_SETTING_SECRET_FLAG_AGENT_OWNED; + if (strstr (val, SECRET_FLAG_NOT_SAVED)) + flags |= NM_SETTING_SECRET_FLAG_NOT_SAVED; + if (strstr (val, SECRET_FLAG_NOT_REQUIRED)) + flags |= NM_SETTING_SECRET_FLAG_NOT_REQUIRED; + } + return flags; +} + +static void +_secret_read_ifcfg (shvarFile *ifcfg, + shvarFile *keys_ifcfg, + const char *name, + char **value, + NMSettingSecretFlags *flags) +{ + char flags_key[250]; + + nm_sprintf_buf (flags_key, "%s_FLAGS", name); + + *flags = _secret_read_ifcfg_flags (ifcfg, flags_key); + + if (*flags != NM_SETTING_SECRET_FLAG_NONE) + *value = NULL; + else { + *value = svGetValue_cp (ifcfg, name); + if (!*value && keys_ifcfg) + *value = svGetValue_cp (keys_ifcfg, name); + } +} + +static void +_secret_set_from_ifcfg (gpointer setting, + shvarFile *ifcfg, + shvarFile *keys_ifcfg, + const char *ifcfg_key, + const char *property_name) +{ + nm_auto_free_secret char *secret = NULL; + NMSettingSecretFlags flags; + char flags_key[250]; + + nm_assert (NM_IS_SETTING (setting)); + + _secret_read_ifcfg (ifcfg, keys_ifcfg, ifcfg_key, &secret, &flags); + + g_object_set (setting, + property_name, + secret, + nm_sprintf_buf (flags_key, "%s-flags", property_name), + flags, + NULL); +} + +static gboolean +_secret_password_raw_to_bytes (const char *ifcfg_key, + const char *password_raw, + GBytes **out_bytes, + GError **error) +{ + nm_auto_free_secret_buf NMSecretBuf *secret = NULL; + gsize len; + + if (!password_raw) { + NM_SET_OUT (out_bytes, NULL); + return TRUE; + } + + if (password_raw[0] == '0' && password_raw[1] == 'x') + password_raw += 2; + + secret = nm_secret_buf_new (strlen (password_raw) / 2 + 3); + if (!_nm_utils_str2bin_full (password_raw, FALSE, ":", secret->bin, secret->len, &len)) { + g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, + "Invalid hex password in %s", + ifcfg_key); + return FALSE; + } + + NM_SET_OUT (out_bytes, nm_secret_buf_to_gbytes_take (g_steal_pointer (&secret), len)); + return TRUE; +} + +/*****************************************************************************/ + +static GBytes * +_cert_get_cert_bytes (const char *ifcfg_path, + const char *value, + GError **error) +{ + gs_free char *path = NULL; + + if (g_str_has_prefix (value, "pkcs11:")) + return _nm_setting_802_1x_cert_value_to_bytes (NM_SETTING_802_1X_CK_SCHEME_PKCS11, (guint8 *) value, -1, error); + + path = get_full_file_path (ifcfg_path, value); + return _nm_setting_802_1x_cert_value_to_bytes (NM_SETTING_802_1X_CK_SCHEME_PATH, (guint8 *) path, -1, error); +} + +static gboolean +_cert_get_cert (shvarFile *ifcfg, + const char *ifcfg_key, + GBytes **out_cert, + NMSetting8021xCKScheme *out_scheme, + GError **error) +{ + nm_auto_free_secret char *val_free = NULL; + const char *val; + gs_unref_bytes GBytes *cert = NULL; + GError *local = NULL; + NMSetting8021xCKScheme scheme; + + val = svGetValueStr (ifcfg, ifcfg_key, &val_free); + if (!val) { + NM_SET_OUT (out_cert, NULL); + NM_SET_OUT (out_scheme, NM_SETTING_802_1X_CK_SCHEME_UNKNOWN); + return TRUE; + } + + cert = _cert_get_cert_bytes (svFileGetName (ifcfg), val, &local); + if (!cert) + goto err; + + scheme = _nm_setting_802_1x_cert_get_scheme (cert, &local); + if (scheme == NM_SETTING_802_1X_CK_SCHEME_UNKNOWN) + goto err; + + NM_SET_OUT (out_cert, g_steal_pointer (&cert)); + NM_SET_OUT (out_scheme, scheme); + return TRUE; + +err: + g_set_error (error, + NM_SETTINGS_ERROR, + NM_SETTINGS_ERROR_INVALID_CONNECTION, + "invalid certificate %s: %s", + ifcfg_key, + local->message); + g_error_free (local); + return FALSE; +} + +static gboolean +_cert_set_from_ifcfg (gpointer setting, + shvarFile *ifcfg, + const char *ifcfg_key, + const char *property_name, + GBytes **out_cert, + GError **error) +{ + gs_unref_bytes GBytes *cert = NULL; + + if (!_cert_get_cert (ifcfg, + ifcfg_key, + &cert, + NULL, + error)) + return FALSE; + + g_object_set (setting, property_name, cert, NULL); + + NM_SET_OUT (out_cert, g_steal_pointer (&cert)); + return TRUE; +} + +/*****************************************************************************/ + static void check_if_bond_slave (shvarFile *ifcfg, NMSettingConnection *s_con) @@ -232,13 +439,16 @@ make_connection_setting (const char *file, NM_SETTING_CONNECTION_AUTOCONNECT, svGetValueBoolean (ifcfg, "ONBOOT", TRUE), NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY, - (gint) svGetValueInt64 (ifcfg, "AUTOCONNECT_PRIORITY", 10, + (int) svGetValueInt64 (ifcfg, "AUTOCONNECT_PRIORITY", 10, NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_MIN, NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_MAX, NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_DEFAULT), NM_SETTING_CONNECTION_AUTOCONNECT_RETRIES, - (gint) svGetValueInt64 (ifcfg, "AUTOCONNECT_RETRIES", 10, + (int) svGetValueInt64 (ifcfg, "AUTOCONNECT_RETRIES", 10, -1, G_MAXINT32, -1), + NM_SETTING_CONNECTION_MULTI_CONNECT, + (gint) svGetValueInt64 (ifcfg, "MULTI_CONNECT", 10, + G_MININT32, G_MAXINT32, NM_CONNECTION_MULTI_CONNECT_DEFAULT), NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES, svGetValueBoolean (ifcfg, "AUTOCONNECT_SLAVES", NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_DEFAULT), NM_SETTING_CONNECTION_LLDP, lldp, @@ -249,7 +459,7 @@ make_connection_setting (const char *file, if (v) { gs_free const char **items = NULL; - items = nm_utils_strsplit_set (v, " "); + items = nm_utils_strsplit_set (v, " ", FALSE); for (iter = items; iter && *iter; iter++) { if (!nm_setting_connection_add_permission (s_con, "user", *iter, NULL)) PARSE_WARNING ("invalid USERS item '%s'", *iter); @@ -265,7 +475,7 @@ make_connection_setting (const char *file, if (v) { gs_free const char **items = NULL; - items = nm_utils_strsplit_set (v, " \t"); + items = nm_utils_strsplit_set (v, " \t", FALSE); for (iter = items; iter && *iter; iter++) { if (!nm_setting_connection_add_secondary (s_con, *iter)) PARSE_WARNING ("secondary connection UUID '%s' already added", *iter); @@ -335,7 +545,7 @@ make_connection_setting (const char *file, } vint64 = svGetValueInt64 (ifcfg, "AUTH_RETRIES", 10, -1, G_MAXINT32, -1); - g_object_set (s_con, NM_SETTING_CONNECTION_AUTH_RETRIES, (gint) vint64, NULL); + g_object_set (s_con, NM_SETTING_CONNECTION_AUTH_RETRIES, (int) vint64, NULL); i_val = NM_SETTING_CONNECTION_MDNS_DEFAULT; if (!svGetValueEnum (ifcfg, "MDNS", @@ -344,6 +554,13 @@ make_connection_setting (const char *file, PARSE_WARNING ("invalid MDNS setting"); g_object_set (s_con, NM_SETTING_CONNECTION_MDNS, i_val, NULL); + i_val = NM_SETTING_CONNECTION_LLMNR_DEFAULT; + if (!svGetValueEnum (ifcfg, "LLMNR", + nm_setting_connection_llmnr_get_type (), + &i_val, NULL)) + PARSE_WARNING ("invalid LLMNR setting"); + g_object_set (s_con, NM_SETTING_CONNECTION_LLMNR, i_val, NULL); + return NM_SETTING (s_con); } @@ -674,7 +891,7 @@ parse_route_line (const char *line, * Maybe later we want to support some form of quotation here. * Which of course, would be incompatible with initscripts. */ - words_free = nm_utils_strsplit_set (line, " \t\n"); + words_free = nm_utils_strsplit_set (line, " \t\n", FALSE); words = words_free ?: NM_PTRARRAY_EMPTY (const char *); @@ -1110,7 +1327,7 @@ parse_dns_options (NMSettingIPConfig *ip_config, const char *value) if (!nm_setting_ip_config_has_dns_options (ip_config)) nm_setting_ip_config_clear_dns_options (ip_config, TRUE); - options = nm_utils_strsplit_set (value, " "); + options = nm_utils_strsplit_set (value, " ", FALSE); if (options) { for (item = options; *item; item++) { if (!nm_setting_ip_config_add_dns_option (ip_config, *item)) @@ -1178,7 +1395,7 @@ make_user_setting (shvarFile *ifcfg) const char *key; nm_auto_free_gstring GString *str = NULL; - keys = svGetKeys (ifcfg); + keys = svGetKeys (ifcfg, SV_KEY_TYPE_USER); if (!keys) return NULL; @@ -1187,9 +1404,6 @@ make_user_setting (shvarFile *ifcfg) 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) @@ -1217,6 +1431,32 @@ make_user_setting (shvarFile *ifcfg) } static NMSetting * +make_match_setting (shvarFile *ifcfg) +{ + NMSettingMatch *s_match = NULL; + gs_free const char **strv = NULL; + gs_free char *value = NULL; + const char *v; + gsize i; + + v = svGetValueStr (ifcfg, "MATCH_INTERFACE_NAME", &value); + if (!v) + return NULL; + + strv = nm_utils_strsplit_set (v, " \t", TRUE); + if (strv) { + for (i = 0; strv[i]; i++) { + if (!s_match) + s_match = (NMSettingMatch *) nm_setting_match_new (); + nm_setting_match_add_interface_name (s_match, + _nm_utils_unescape_spaces ((char *) strv[i])); + } + } + + return (NMSetting *) s_match; +} + +static NMSetting * make_proxy_setting (shvarFile *ifcfg) { NMSettingProxy *s_proxy = NULL; @@ -1286,7 +1526,7 @@ make_ip4_setting (shvarFile *ifcfg, shvarFile *route_ifcfg; gboolean never_default; gint64 timeout; - gint priority; + int priority; char inet_buf[NM_UTILS_INET_ADDRSTRLEN]; const char *const *item; guint32 route_table; @@ -1483,7 +1723,7 @@ make_ip4_setting (shvarFile *ifcfg, if (v) { gs_free const char **searches = NULL; - searches = nm_utils_strsplit_set (v, " "); + searches = nm_utils_strsplit_set (v, " ", FALSE); if (searches) { for (item = searches; *item; item++) { if (!nm_setting_ip_config_add_dns_search (s_ip4, *item)) @@ -1544,7 +1784,7 @@ make_ip4_setting (shvarFile *ifcfg, if (v) { gs_free const char **searches = NULL; - searches = nm_utils_strsplit_set (v, " "); + searches = nm_utils_strsplit_set (v, " ", FALSE); if (searches) { for (item = searches; *item; item++) { if (!nm_setting_ip_config_add_dns_search (s_ip4, *item)) @@ -1561,7 +1801,7 @@ make_ip4_setting (shvarFile *ifcfg, if (timeout > 0) timeout *= 1000; } - g_object_set (s_ip4, NM_SETTING_IP_CONFIG_DAD_TIMEOUT, (gint) timeout, NULL); + g_object_set (s_ip4, NM_SETTING_IP_CONFIG_DAD_TIMEOUT, (int) timeout, NULL); return g_steal_pointer (&s_ip4); } @@ -1697,7 +1937,7 @@ make_ip6_setting (shvarFile *ifcfg, guint32 i; int i_val; GError *local = NULL; - gint priority; + int priority; gboolean never_default = FALSE; gboolean ip6_privacy = FALSE, ip6_privacy_prefer_public_ip; NMSettingIP6ConfigPrivacy ip6_privacy_val; @@ -1860,7 +2100,7 @@ make_ip6_setting (shvarFile *ifcfg, ipv6addr_secondaries ?: "", NULL); - list = nm_utils_strsplit_set (value, " "); + list = nm_utils_strsplit_set (value, " ", FALSE); for (iter = list, i = 0; iter && *iter; iter++, i++) { NMIPAddress *addr = NULL; @@ -1953,7 +2193,7 @@ make_ip6_setting (shvarFile *ifcfg, if (v) { gs_free const char **searches = NULL; - searches = nm_utils_strsplit_set (v, " "); + searches = nm_utils_strsplit_set (v, " ", FALSE); if (searches) { for (iter = searches; *iter; iter++) { if (!nm_setting_ip_config_add_dns_search (s_ip6, *iter)) @@ -1982,6 +2222,68 @@ error: } static NMSetting * +make_sriov_setting (shvarFile *ifcfg) +{ + gs_unref_hashtable GHashTable *keys = NULL; + gs_unref_ptrarray GPtrArray *vfs = NULL; + NMTernary autoprobe_drivers; + NMSettingSriov *s_sriov; + int total_vfs; + + total_vfs = svGetValueInt64 (ifcfg, "SRIOV_TOTAL_VFS", 10, 0, G_MAXINT32, 0); + if (!total_vfs) + return NULL; + + autoprobe_drivers = svGetValueInt64 (ifcfg, + "SRIOV_AUTOPROBE_DRIVERS", + 10, + NM_TERNARY_FALSE, + NM_TERNARY_TRUE, + NM_TERNARY_DEFAULT); + + keys = svGetKeys (ifcfg, SV_KEY_TYPE_SRIOV_VF); + if (keys) { + GHashTableIter iter; + const char *key; + + g_hash_table_iter_init (&iter, keys); + while (g_hash_table_iter_next (&iter, (gpointer *) &key, NULL)) { + gs_free_error GError *error = NULL; + gs_free char *value_to_free = NULL; + const char *value; + NMSriovVF *vf; + + nm_assert (g_str_has_prefix (key, "SRIOV_VF")); + + value = svGetValue (ifcfg, key, &value_to_free); + if (!value) + continue; + + key += NM_STRLEN ("SRIOV_VF"); + + vf = _nm_utils_sriov_vf_from_strparts (key, value, &error); + if (!vf) { + PARSE_WARNING ("ignoring invalid SR-IOV VF '%s %s': %s", + key, value, error->message); + continue; + } + if (!vfs) + vfs = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_sriov_vf_unref); + g_ptr_array_add (vfs, vf); + } + } + + s_sriov = (NMSettingSriov *) nm_setting_sriov_new (); + g_object_set (s_sriov, + NM_SETTING_SRIOV_TOTAL_VFS, total_vfs, + NM_SETTING_SRIOV_VFS, vfs, + NM_SETTING_SRIOV_AUTOPROBE_DRIVERS, (int) autoprobe_drivers, + NULL); + + return (NMSetting *) s_sriov; +} + +static NMSetting * make_tc_setting (shvarFile *ifcfg) { NMSettingTCConfig *s_tc = NULL; @@ -2241,7 +2543,7 @@ read_dcb_percent_array (shvarFile *ifcfg, return TRUE; } - split = nm_utils_strsplit_set (val, ","); + split = nm_utils_strsplit_set (val, ",", FALSE); if (NM_PTRARRAY_LEN (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, @@ -2518,30 +2820,6 @@ read_wep_keys (shvarFile *ifcfg, return TRUE; } -static NMSettingSecretFlags -read_secret_flags (shvarFile *ifcfg, const char *flags_key) -{ - NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE; - char *val; - - g_return_val_if_fail (flags_key != NULL, NM_SETTING_SECRET_FLAG_NONE); - 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 = svGetValueStr_cp (ifcfg, flags_key); - if (val) { - if (strstr (val, SECRET_FLAG_AGENT)) - flags |= NM_SETTING_SECRET_FLAG_AGENT_OWNED; - if (strstr (val, SECRET_FLAG_NOT_SAVED)) - flags |= NM_SETTING_SECRET_FLAG_NOT_SAVED; - if (strstr (val, SECRET_FLAG_NOT_REQUIRED)) - flags |= NM_SETTING_SECRET_FLAG_NOT_REQUIRED; - - g_free (val); - } - return flags; -} - static NMSetting * make_wep_setting (shvarFile *ifcfg, const char *file, @@ -2573,7 +2851,7 @@ make_wep_setting (shvarFile *ifcfg, } /* Read WEP key flags */ - key_flags = read_secret_flags (ifcfg, "WEP_KEY_FLAGS"); + key_flags = _secret_read_ifcfg_flags (ifcfg, "WEP_KEY_FLAGS"); g_object_set (s_wsec, NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS, key_flags, NULL); /* Read keys in the ifcfg file if they are system-owned */ @@ -2677,7 +2955,7 @@ fill_wpa_ciphers (shvarFile *ifcfg, if (!p) return TRUE; - list = nm_utils_strsplit_set (p, " "); + list = nm_utils_strsplit_set (p, " ", FALSE); for (iter = list; iter && *iter; iter++, i++) { /* Ad-Hoc configurations cannot have pairwise ciphers, and can only * have one group cipher. Ignore any additional group ciphers and @@ -2772,254 +3050,118 @@ parse_wpa_psk (shvarFile *ifcfg, return g_steal_pointer (&psk); } -static void -read_8021x_password (shvarFile *ifcfg, shvarFile *keys_ifcfg, const char *name, - char **value, NMSettingSecretFlags *flags) -{ - gs_free char *flags_key = NULL; - - *value = NULL; - flags_key = g_strdup_printf ("%s_FLAGS", name); - *flags = read_secret_flags (ifcfg, flags_key); - - if (*flags == NM_SETTING_SECRET_FLAG_NONE) { - *value = svGetValueStr_cp (ifcfg, name); - if (!*value && keys_ifcfg) - *value = svGetValueStr_cp (keys_ifcfg, name); - } -} - static gboolean eap_simple_reader (const char *eap_method, shvarFile *ifcfg, - shvarFile *keys, + shvarFile *keys_ifcfg, NMSetting8021x *s_8021x, gboolean phase2, GError **error) { NMSettingSecretFlags flags; - GBytes *bytes; - char *value; + gs_free char *identity_free = NULL; + nm_auto_free_secret char *password_raw_str = NULL; + gs_unref_bytes GBytes *password_raw_bytes = NULL; - 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'.", - eap_method); - return FALSE; - } - g_object_set (s_8021x, NM_SETTING_802_1X_IDENTITY, value, NULL); - nm_clear_g_free (&value); + g_object_set (s_8021x, + NM_SETTING_802_1X_IDENTITY, + svGetValueStr (ifcfg, "IEEE_8021X_IDENTITY", &identity_free), + NULL); - read_8021x_password (ifcfg, keys, "IEEE_8021X_PASSWORD", &value, &flags); - g_object_set (s_8021x, NM_SETTING_802_1X_PASSWORD_FLAGS, flags, NULL); - if (value) { - g_object_set (s_8021x, NM_SETTING_802_1X_PASSWORD, value, NULL); - nm_clear_g_free (&value); - } + _secret_set_from_ifcfg (s_8021x, + ifcfg, + keys_ifcfg, + "IEEE_8021X_PASSWORD", + NM_SETTING_802_1X_PASSWORD); + + _secret_read_ifcfg (ifcfg, keys_ifcfg, "IEEE_8021X_PASSWORD_RAW", &password_raw_str, &flags); + if (!_secret_password_raw_to_bytes ("IEEE_8021X_PASSWORD_RAW", + password_raw_str, + &password_raw_bytes, + error)) + return FALSE; - read_8021x_password (ifcfg, keys, "IEEE_8021X_PASSWORD_RAW", &value, &flags); - g_object_set (s_8021x, NM_SETTING_802_1X_PASSWORD_RAW_FLAGS, flags, NULL); - if (value) { - bytes = nm_utils_hexstr2bin (value); - if (!bytes) { - g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "Invalid hex string '%s' in IEEE_8021X_PASSWORD_RAW.", - value); - g_free (value); - return FALSE; - } - g_object_set (s_8021x, NM_SETTING_802_1X_PASSWORD_RAW, bytes, NULL); - g_bytes_unref (bytes); - nm_clear_g_free (&value); - } + g_object_set (s_8021x, + NM_SETTING_802_1X_PASSWORD_RAW_FLAGS, + flags, + NM_SETTING_802_1X_PASSWORD_RAW, + password_raw_bytes, + NULL); return TRUE; } -static char * -get_full_file_path (const char *ifcfg_path, const char *file_path) -{ - const char *base = file_path; - char *p, *ret, *dirname; - - g_return_val_if_fail (ifcfg_path != NULL, NULL); - g_return_val_if_fail (file_path != NULL, NULL); - - if (file_path[0] == '/') - return g_strdup (file_path); - - p = strrchr (file_path, '/'); - if (p) - base = p + 1; - - dirname = g_path_get_dirname (ifcfg_path); - ret = g_build_path ("/", dirname, base, NULL); - g_free (dirname); - 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, - shvarFile *keys, + shvarFile *keys_ifcfg, NMSetting8021x *s_8021x, 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_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 *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 *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; + gs_unref_bytes GBytes *privkey = NULL; + gs_unref_bytes GBytes *client_cert = NULL; + gs_free char *identity_free = NULL; - 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 = svGetValueStr_cp (ifcfg, ca_cert_key); - if (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_cert_value, scheme, NULL, error)) - return FALSE; - } else { - 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); - } - } - } else { - PARSE_WARNING ("missing %s for EAP method '%s'; this is insecure!", - ca_cert_key, eap_method); - } - - /* Read and set private key password flags */ - flags = read_secret_flags (ifcfg, pk_pw_flags_key); - g_object_set (s_8021x, pk_pw_flags_prop, flags, NULL); - - /* Read the private key password if it's system-owned */ - if (flags == NM_SETTING_SECRET_FLAG_NONE) { - /* Private key password */ - privkey_password = svGetValueStr_cp (ifcfg, pk_pw_key); - if (!privkey_password && keys) { - /* Try the lookaside keys file */ - privkey_password = svGetValueStr_cp (keys, pk_pw_key); - } - } + g_object_set (s_8021x, + NM_SETTING_802_1X_IDENTITY, + svGetValueStr (ifcfg, "IEEE_8021X_IDENTITY", &identity_free), + NULL); - /* The private key itself */ - privkey = svGetValueStr_cp (ifcfg, pk_key); + if (!_cert_set_from_ifcfg (s_8021x, + ifcfg, + phase2 ? "IEEE_8021X_INNER_CA_CERT" : "IEEE_8021X_CA_CERT", + phase2 ? NM_SETTING_802_1X_PHASE2_CA_CERT : NM_SETTING_802_1X_CA_CERT, + NULL, + error)) + return FALSE; + _secret_set_from_ifcfg (s_8021x, + ifcfg, + keys_ifcfg, + phase2 ? "IEEE_8021X_INNER_CA_CERT_PASSWORD" : "IEEE_8021X_CA_CERT_PASSWORD", + phase2 ? NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD : NM_SETTING_802_1X_CA_CERT_PASSWORD); + + if (!_cert_set_from_ifcfg (s_8021x, + ifcfg, + phase2 ? "IEEE_8021X_INNER_PRIVATE_KEY" : "IEEE_8021X_PRIVATE_KEY", + phase2 ? NM_SETTING_802_1X_PHASE2_PRIVATE_KEY : NM_SETTING_802_1X_PRIVATE_KEY, + &privkey, + error)) + return FALSE; + _secret_set_from_ifcfg (s_8021x, + ifcfg, + keys_ifcfg, + phase2 ? "IEEE_8021X_INNER_PRIVATE_KEY_PASSWORD" : "IEEE_8021X_PRIVATE_KEY_PASSWORD", + phase2 ? NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD : NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD); if (!privkey) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Missing %s for EAP method '%s'.", - pk_key, + phase2 ? "IEEE_8021X_INNER_PRIVATE_KEY" : "IEEE_8021X_PRIVATE_KEY", eap_method); return FALSE; } - { - 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; - } - } - - /* 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, - * then nm_setting_802_1x_set_private_key() already set the client certificate - * to the same value as the private key. - */ - if (privkey_format != NM_SETTING_802_1X_CK_FORMAT_PKCS12) { - 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); - return FALSE; - } - - 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_cert_value, scheme, NULL, error)) - return FALSE; - } else { - if (!nm_setting_802_1x_set_client_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, cli_cert_pw_flags_key); - g_object_set (s_8021x, cli_cert_pw_flags_prop, flags, NULL); - - 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); - } - } + if (!_cert_set_from_ifcfg (s_8021x, + ifcfg, + phase2 ? "IEEE_8021X_INNER_CLIENT_CERT" : "IEEE_8021X_CLIENT_CERT", + phase2 ? NM_SETTING_802_1X_PHASE2_CLIENT_CERT : NM_SETTING_802_1X_CLIENT_CERT, + &client_cert, + error)) + return FALSE; + /* FIXME: writer does not actually write IEEE_8021X_CLIENT_CERT_PASSWORD and other + * certificate related passwords. It should, because otherwise persisting such profiles + * to ifcfg looses information. As this currently only matters for PKCS11 URIs, it seems + * a seldomly used feature so that it is not fixed yet. */ + _secret_set_from_ifcfg (s_8021x, + ifcfg, + keys_ifcfg, + phase2 ? "IEEE_8021X_INNER_CLIENT_CERT_PASSWORD" : "IEEE_8021X_CLIENT_CERT_PASSWORD", + phase2 ? NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD : NM_SETTING_802_1X_CLIENT_CERT_PASSWORD); + if (!client_cert) { + g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, + "Missing certificate for EAP method '%s'.", + eap_method); + return FALSE; } return TRUE; @@ -3028,7 +3170,7 @@ eap_tls_reader (const char *eap_method, static gboolean eap_peap_reader (const char *eap_method, shvarFile *ifcfg, - shvarFile *keys, + shvarFile *keys_ifcfg, NMSetting8021x *s_8021x, gboolean phase2, GError **error) @@ -3037,19 +3179,19 @@ eap_peap_reader (const char *eap_method, const char *v; gs_free const char **list = NULL; const char *const *iter; - NMSetting8021xCKScheme scheme; - - v = svGetValueStr (ifcfg, "IEEE_8021X_CA_CERT", &value); - if (v) { - gs_free char *real_cert_value = NULL; - real_cert_value = get_cert_value (svFileGetName (ifcfg), v, &scheme); - if (!nm_setting_802_1x_set_ca_cert (s_8021x, real_cert_value, scheme, NULL, error)) - return FALSE; - } else { - PARSE_WARNING ("missing IEEE_8021X_CA_CERT for EAP method '%s'; this is insecure!", - eap_method); - } + if (!_cert_set_from_ifcfg (s_8021x, + ifcfg, + "IEEE_8021X_CA_CERT", + NM_SETTING_802_1X_CA_CERT, + NULL, + error)) + return FALSE; + _secret_set_from_ifcfg (s_8021x, + ifcfg, + keys_ifcfg, + "IEEE_8021X_CA_CERT_PASSWORD", + NM_SETTING_802_1X_CA_CERT_PASSWORD); nm_clear_g_free (&value); v = svGetValueStr (ifcfg, "IEEE_8021X_PEAP_VERSION", &value); @@ -3083,16 +3225,16 @@ eap_peap_reader (const char *eap_method, } /* Handle options for the inner auth method */ - list = nm_utils_strsplit_set (v, " "); + list = nm_utils_strsplit_set (v, " ", FALSE); iter = list; if (iter) { if (NM_IN_STRSET (*iter, "MSCHAPV2", "MD5", "GTC")) { - if (!eap_simple_reader (*iter, ifcfg, keys, s_8021x, TRUE, error)) + if (!eap_simple_reader (*iter, ifcfg, keys_ifcfg, s_8021x, TRUE, error)) return FALSE; } else if (nm_streq (*iter, "TLS")) { - if (!eap_tls_reader (*iter, ifcfg, keys, s_8021x, TRUE, error)) + if (!eap_tls_reader (*iter, ifcfg, keys_ifcfg, s_8021x, TRUE, error)) return FALSE; } else { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, @@ -3121,7 +3263,7 @@ eap_peap_reader (const char *eap_method, static gboolean eap_ttls_reader (const char *eap_method, shvarFile *ifcfg, - shvarFile *keys, + shvarFile *keys_ifcfg, NMSetting8021x *s_8021x, gboolean phase2, GError **error) @@ -3131,19 +3273,19 @@ eap_ttls_reader (const char *eap_method, const char *v; gs_free const char **list = NULL; const char *const *iter; - NMSetting8021xCKScheme scheme; - - v = svGetValueStr (ifcfg, "IEEE_8021X_CA_CERT", &value); - if (v) { - gs_free char *real_cert_value = NULL; - real_cert_value = get_cert_value (svFileGetName (ifcfg), v, &scheme); - if (!nm_setting_802_1x_set_ca_cert (s_8021x, real_cert_value, scheme, NULL, error)) - return FALSE; - } else { - PARSE_WARNING ("missing IEEE_8021X_CA_CERT for EAP method '%s'; this is insecure!", - eap_method); - } + if (!_cert_set_from_ifcfg (s_8021x, + ifcfg, + "IEEE_8021X_CA_CERT", + NM_SETTING_802_1X_CA_CERT, + NULL, + error)) + return FALSE; + _secret_set_from_ifcfg (s_8021x, + ifcfg, + keys_ifcfg, + "IEEE_8021X_CA_CERT_PASSWORD", + NM_SETTING_802_1X_CA_CERT_PASSWORD); nm_clear_g_free (&value); v = svGetValueStr (ifcfg, "IEEE_8021X_ANON_IDENTITY", &value); @@ -3161,24 +3303,24 @@ eap_ttls_reader (const char *eap_method, inner_auth = g_ascii_strdown (v, -1); /* Handle options for the inner auth method */ - list = nm_utils_strsplit_set (inner_auth, " "); + list = nm_utils_strsplit_set (inner_auth, " ", FALSE); iter = list; if (iter) { if (NM_IN_STRSET (*iter, "mschapv2", "mschap", "pap", "chap")) { - if (!eap_simple_reader (*iter, ifcfg, keys, s_8021x, TRUE, error)) + if (!eap_simple_reader (*iter, ifcfg, keys_ifcfg, s_8021x, TRUE, error)) return FALSE; g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTH, *iter, NULL); } else if (nm_streq (*iter, "eap-tls")) { - if (!eap_tls_reader (*iter, ifcfg, keys, s_8021x, TRUE, error)) + if (!eap_tls_reader (*iter, ifcfg, keys_ifcfg, s_8021x, TRUE, error)) return FALSE; g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTHEAP, "tls", NULL); } else if (NM_IN_STRSET (*iter, "eap-mschapv2", "eap-md5", "eap-gtc")) { - if (!eap_simple_reader (*iter, ifcfg, keys, s_8021x, TRUE, error)) + if (!eap_simple_reader (*iter, ifcfg, keys_ifcfg, s_8021x, TRUE, error)) return FALSE; g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTHEAP, (*iter + NM_STRLEN ("eap-")), NULL); } else { @@ -3195,7 +3337,7 @@ eap_ttls_reader (const char *eap_method, static gboolean eap_fast_reader (const char *eap_method, shvarFile *ifcfg, - shvarFile *keys, + shvarFile *keys_ifcfg, NMSetting8021x *s_8021x, gboolean phase2, GError **error) @@ -3222,7 +3364,7 @@ eap_fast_reader (const char *eap_method, if (fast_provisioning) { gs_free const char **list1 = NULL; - list1 = nm_utils_strsplit_set (fast_provisioning, " \t"); + list1 = nm_utils_strsplit_set (fast_provisioning, " \t", FALSE); for (iter = list1; iter && *iter; iter++) { if (strcmp (*iter, "allow-unauth") == 0) allow_unauth = TRUE; @@ -3256,12 +3398,12 @@ eap_fast_reader (const char *eap_method, } /* Handle options for the inner auth method */ - list = nm_utils_strsplit_set (inner_auth, " "); + list = nm_utils_strsplit_set (inner_auth, " ", FALSE); iter = list; if (iter) { if ( !strcmp (*iter, "MSCHAPV2") || !strcmp (*iter, "GTC")) { - if (!eap_simple_reader (*iter, ifcfg, keys, s_8021x, TRUE, error)) + if (!eap_simple_reader (*iter, ifcfg, keys_ifcfg, s_8021x, TRUE, error)) goto done; } else { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, @@ -3296,7 +3438,7 @@ typedef struct { const char *method; gboolean (*reader) (const char *eap_method, shvarFile *ifcfg, - shvarFile *keys, + shvarFile *keys_ifcfg, NMSetting8021x *s_8021x, gboolean phase2, GError **error); @@ -3336,7 +3478,7 @@ read_8021x_list_value (shvarFile *ifcfg, if (!v) return; - strv = nm_utils_strsplit_set (v, " \t"); + strv = nm_utils_strsplit_set (v, " \t", FALSE); if (strv) g_object_set (setting, prop_name, strv, NULL); } @@ -3348,7 +3490,7 @@ fill_8021x (shvarFile *ifcfg, gboolean wifi, GError **error) { - nm_auto_shvar_file_close shvarFile *keys = NULL; + nm_auto_shvar_file_close shvarFile *keys_ifcfg = NULL; gs_unref_object NMSetting8021x *s_8021x = NULL; gs_free char *value = NULL; const char *v; @@ -3365,12 +3507,12 @@ fill_8021x (shvarFile *ifcfg, return NULL; } - list = nm_utils_strsplit_set (v, " "); + list = nm_utils_strsplit_set (v, " ", FALSE); s_8021x = (NMSetting8021x *) nm_setting_802_1x_new (); - /* Read in the lookaside keys file, if present */ - keys = utils_get_keys_ifcfg (file, FALSE); + /* Read in the lookaside keys_ifcfg file, if present */ + keys_ifcfg = utils_get_keys_ifcfg (file, FALSE); /* Validate and handle each EAP method */ for (iter = list; iter && *iter; iter++) { @@ -3394,7 +3536,7 @@ fill_8021x (shvarFile *ifcfg, } /* Parse EAP method specific options */ - if (!(*eap->reader)(lower, ifcfg, keys, s_8021x, FALSE, error)) + if (!(*eap->reader)(lower, ifcfg, keys_ifcfg, s_8021x, FALSE, error)) return NULL; nm_setting_802_1x_add_eap_method (s_8021x, lower); @@ -3444,7 +3586,7 @@ next: g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_DOMAIN_SUFFIX_MATCH, v, NULL); timeout = svGetValueInt64 (ifcfg, "IEEE_8021X_AUTH_TIMEOUT", 10, 0, G_MAXINT32, 0); - g_object_set (s_8021x, NM_SETTING_802_1X_AUTH_TIMEOUT, (gint) timeout, NULL); + g_object_set (s_8021x, NM_SETTING_802_1X_AUTH_TIMEOUT, (int) timeout, NULL); return g_steal_pointer (&s_8021x); } @@ -3510,7 +3652,7 @@ make_wpa_setting (shvarFile *ifcfg, if (wpa_psk) { NMSettingSecretFlags psk_flags; - psk_flags = read_secret_flags (ifcfg, "WPA_PSK_FLAGS"); + psk_flags = _secret_read_ifcfg_flags (ifcfg, "WPA_PSK_FLAGS"); g_object_set (wsec, NM_SETTING_WIRELESS_SECURITY_PSK_FLAGS, psk_flags, NULL); /* Read PSK if it's system-owned */ @@ -3597,7 +3739,7 @@ make_leap_setting (shvarFile *ifcfg, return NULL; /* Not LEAP */ nm_clear_g_free (&value); - flags = read_secret_flags (ifcfg, "IEEE_8021X_PASSWORD_FLAGS"); + flags = _secret_read_ifcfg_flags (ifcfg, "IEEE_8021X_PASSWORD_FLAGS"); g_object_set (wsec, NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD_FLAGS, flags, NULL); /* Read LEAP password if it's system-owned */ @@ -3674,7 +3816,7 @@ transform_hwaddr_blacklist (const char *blacklist) const char **strv; gsize i, j; - strv = nm_utils_strsplit_set (blacklist, " \t"); + strv = nm_utils_strsplit_set (blacklist, " \t", FALSE); if (!strv) return NULL; for (i = 0, j = 0; strv[j]; j++) { @@ -3923,7 +4065,7 @@ wireless_connection_from_ifcfg (const char *file, NMSetting8021x *s_8021x = NULL; GBytes *ssid; NMSetting *security_setting = NULL; - char *printable_ssid = NULL; + gs_free char *ssid_utf8 = NULL; const char *mode; gboolean adhoc = FALSE; GError *local = NULL; @@ -3943,12 +4085,6 @@ wireless_connection_from_ifcfg (const char *file, nm_connection_add_setting (connection, wireless_setting); ssid = nm_setting_wireless_get_ssid (NM_SETTING_WIRELESS (wireless_setting)); - if (ssid) { - printable_ssid = nm_utils_ssid_to_utf8 (g_bytes_get_data (ssid, NULL), - g_bytes_get_size (ssid)); - } else - printable_ssid = g_strdup ("unmanaged"); - mode = nm_setting_wireless_get_mode (NM_SETTING_WIRELESS (wireless_setting)); if (mode && !strcmp (mode, "adhoc")) adhoc = TRUE; @@ -3956,7 +4092,6 @@ wireless_connection_from_ifcfg (const char *file, /* Wireless security */ security_setting = make_wireless_security_setting (ifcfg, file, ssid, adhoc, &s_8021x, &local); if (local) { - g_free (printable_ssid); g_object_unref (connection); g_propagate_error (error, local); return NULL; @@ -3967,11 +4102,16 @@ wireless_connection_from_ifcfg (const char *file, nm_connection_add_setting (connection, NM_SETTING (s_8021x)); } + if (ssid) + ssid_utf8 = _nm_utils_ssid_to_utf8 (ssid); + /* Connection */ - con_setting = make_connection_setting (file, ifcfg, + con_setting = make_connection_setting (file, + ifcfg, NM_SETTING_WIRELESS_SETTING_NAME, - printable_ssid, NULL); - g_free (printable_ssid); + nm_str_not_empty (ssid_utf8) ?: "unmanaged", + NULL); + if (!con_setting) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Failed to create connection setting."); @@ -3984,199 +4124,253 @@ wireless_connection_from_ifcfg (const char *file, } static void -parse_ethtool_option_autoneg (const char *value, gboolean *out_autoneg) +parse_ethtool_option (const char *value, + NMSettingWiredWakeOnLan *out_flags, + char **out_password, + gboolean *out_autoneg, + guint32 *out_speed, + const char **out_duplex, + NMSettingEthtool **out_s_ethtool) { - if (!value) { - PARSE_WARNING ("Auto-negotiation option missing"); + gs_free const char **words = NULL; + guint i; + + words = nm_utils_strsplit_set (value, NULL, FALSE); + if (!words) return; - } - if (g_str_equal (value, "off")) - *out_autoneg = FALSE; - else if (g_str_equal (value, "on")) - *out_autoneg = TRUE; - else - PARSE_WARNING ("Auto-negotiation unknown value: %s", value); -} + if (words[0] && words[0][0] == '-') { + /* /sbin/ethtool $opts */ + if (NM_IN_STRSET (words[0], "-K", "--features", "--offload")) { + if (!words[1]) { + /* first argument must be the interface name. This is invalid. */ + return; + } -static void -parse_ethtool_option_speed (const char *value, guint32 *out_speed) -{ - if (!value) { - PARSE_WARNING ("Speed option missing"); - return; - } + if (!*out_s_ethtool) + *out_s_ethtool = NM_SETTING_ETHTOOL (nm_setting_ethtool_new ()); - *out_speed = _nm_utils_ascii_str_to_int64 (value, 10, 0, G_MAXUINT32, 0); - if (errno) - PARSE_WARNING ("Speed value '%s' is invalid", value); -} + for (i = 2; words[i]; ) { + const char *opt = words[i]; + const char *opt_val = words[++i]; + const NMEthtoolData *d = NULL; + NMTernary onoff = NM_TERNARY_DEFAULT; -static void -parse_ethtool_option_duplex (const char *value, const char **out_duplex) -{ - if (!value) { - PARSE_WARNING ("Duplex option missing"); - return; - } + if (nm_streq0 (opt_val, "on")) + onoff = NM_TERNARY_TRUE; + else if (nm_streq0 (opt_val, "off")) + onoff = NM_TERNARY_FALSE; - if (g_str_equal (value, "half")) - *out_duplex = "half"; - else if (g_str_equal (value, "full")) - *out_duplex = "full"; - else - PARSE_WARNING ("Duplex unknown value: %s", value); + d = nms_ifcfg_rh_utils_get_ethtool_by_name (opt); -} + if (!d) { + if (onoff != NM_TERNARY_DEFAULT) { + /* the next value is just the on/off argument. Skip it too. */ + i++; + } -static void -parse_ethtool_option_wol (const char *value, NMSettingWiredWakeOnLan *out_flags) -{ - NMSettingWiredWakeOnLan wol_flags = NM_SETTING_WIRED_WAKE_ON_LAN_NONE; + /* silently ignore unsupported offloading features. */ + continue; + } - if (!value) { - PARSE_WARNING ("Wake-on-LAN options missing"); + i++; + + if (onoff == NM_TERNARY_DEFAULT) { + PARSE_WARNING ("Expects on/off argument for feature '%s'", opt); + continue; + } + + nm_setting_ethtool_set_feature (*out_s_ethtool, + d->optname, + onoff); + } + } return; } - for (; *value; value++) { - switch (*value) { - case 'p': - wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_PHY; - break; - case 'u': - wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_UNICAST; - break; - case 'm': - wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_MULTICAST; - break; - case 'b': - wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_BROADCAST; - break; - case 'a': - wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_ARP; - break; - case 'g': - wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC; - break; - case 's': - break; - case 'd': - wol_flags = NM_SETTING_WIRED_WAKE_ON_LAN_NONE; - break; - default: - PARSE_WARNING ("unrecognized Wake-on-LAN option '%c'", *value); + /* /sbin/ethtool -s ${REALDEVICE} $opts */ + for (i = 0; words[i]; ) { + const char *opt = words[i]; + const char *opt_val = words[++i]; + + if (nm_streq (opt, "autoneg")) { + if (!opt_val) { + PARSE_WARNING ("Auto-negotiation option missing"); + break; + } + i++; + + if (nm_streq (opt_val, "off")) + *out_autoneg = FALSE; + else if (nm_streq (opt_val, "on")) + *out_autoneg = TRUE; + else + PARSE_WARNING ("Auto-negotiation unknown value: %s", opt_val); + continue; } - } - *out_flags = wol_flags; -} + if (nm_streq (opt, "speed")) { + guint32 speed; -static void parse_ethtool_option_sopass (const char *value, char **out_password) -{ - if (!value) { - PARSE_WARNING ("Wake-on-LAN password missing"); - return; - } + if (!opt_val) { + PARSE_WARNING ("Speed option missing"); + break; + } + i++; - g_clear_pointer (out_password, g_free); - if (!nm_utils_hwaddr_valid (value, ETH_ALEN)) { - PARSE_WARNING ("Wake-on-LAN password '%s' is invalid", value); - return; - } + speed = _nm_utils_ascii_str_to_int64 (opt_val, 10, 0, G_MAXUINT32, 0); + if (errno == 0) + *out_speed = speed; + else + PARSE_WARNING ("Speed value '%s' is invalid", opt_val); + continue; + } - *out_password = g_strdup (value); -} + if (nm_streq (opt, "duplex")) { + if (!opt_val) { + PARSE_WARNING ("Duplex option missing"); + break; + } + i++; -static void -parse_ethtool_option (const char *value, - NMSettingWiredWakeOnLan *out_flags, - char **out_password, - gboolean *out_autoneg, - guint32 *out_speed, - const char **out_duplex) -{ - gs_free const char **words = NULL; - const char *const *iter; - const char *opt_val, *opt; + if (nm_streq (opt_val, "half")) + *out_duplex = "half"; + else if (nm_streq (opt_val, "full")) + *out_duplex = "full"; + else + PARSE_WARNING ("Duplex unknown value: %s", opt_val); + continue; + } - words = nm_utils_strsplit_set (value, "\t "); - if (!words) - return; + if (nm_streq (opt, "wol")) { + NMSettingWiredWakeOnLan wol_flags = NM_SETTING_WIRED_WAKE_ON_LAN_NONE; - iter = words; - - while (iter[0]) { - opt = iter++[0]; - opt_val = iter[0]; - - if (nm_streq (opt, "autoneg")) - parse_ethtool_option_autoneg (opt_val, out_autoneg); - else if (nm_streq (opt, "speed")) - parse_ethtool_option_speed (opt_val, out_speed); - else if (nm_streq (opt, "duplex")) - parse_ethtool_option_duplex (opt_val, out_duplex); - else if (nm_streq (opt, "wol")) - parse_ethtool_option_wol (opt_val, out_flags); - else if (nm_streq (opt, "sopass")) - parse_ethtool_option_sopass (opt_val, out_password); - else { - /* Silently skip unknown options */ + if (!opt_val) { + PARSE_WARNING ("Wake-on-LAN options missing"); + break; + } + i++; + + for (; *opt_val; opt_val++) { + switch (*opt_val) { + case 'p': + wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_PHY; + break; + case 'u': + wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_UNICAST; + break; + case 'm': + wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_MULTICAST; + break; + case 'b': + wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_BROADCAST; + break; + case 'a': + wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_ARP; + break; + case 'g': + wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC; + break; + case 's': + break; + case 'd': + wol_flags = NM_SETTING_WIRED_WAKE_ON_LAN_NONE; + break; + default: + PARSE_WARNING ("unrecognized Wake-on-LAN option '%c'", *opt_val); + } + } + + *out_flags = wol_flags; continue; } - if (iter[0]) - iter++; + if (nm_streq (opt, "sopass")) { + if (!opt_val) { + PARSE_WARNING ("Wake-on-LAN password missing"); + break; + } + i++; + + if (nm_utils_hwaddr_valid (opt_val, ETH_ALEN)) { + g_clear_pointer (out_password, g_free); + *out_password = g_strdup (opt_val); + } else + PARSE_WARNING ("Wake-on-LAN password '%s' is invalid", opt_val); + continue; + } + + /* Silently skip unknown options */ } } static void -parse_ethtool_options (shvarFile *ifcfg, NMSettingWired *s_wired, const char *value) +parse_ethtool_options (shvarFile *ifcfg, NMConnection *connection) { + NMSettingWired *s_wired; + gs_unref_object NMSettingEthtool *s_ethtool = NULL; NMSettingWiredWakeOnLan wol_flags = NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT; - gs_free char *wol_password = NULL, *wol_value = NULL; - gboolean ignore_wol_password = FALSE, autoneg = FALSE; + gs_free char *ethtool_opts_free = NULL; + const char *ethtool_opts; + gs_free char *wol_password = NULL; + gs_free char *wol_value_free = NULL; + const char *tmp; + gboolean autoneg = FALSE; guint32 speed = 0; const char *duplex = NULL; - if (value) { - gs_free const char **opts = NULL; - const char *const *iter; - + ethtool_opts = svGetValue (ifcfg, "ETHTOOL_OPTS", ðtool_opts_free); + if (ethtool_opts) { /* WAKE_ON_LAN_IGNORE is inferred from a specified but empty ETHTOOL_OPTS */ - if (!value[0]) + if (!ethtool_opts[0]) wol_flags = NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE; - - opts = nm_utils_strsplit_set (value, ";"); - for (iter = opts; iter && iter[0]; iter++) { - /* in case of repeated wol_passwords, parse_ethtool_option() - * will do the right thing and clear wol_password before resetting. */ - parse_ethtool_option (iter[0], &wol_flags, &wol_password, &autoneg, &speed, &duplex); + else { + gs_free const char **opts = NULL; + const char *const *iter; + + opts = nm_utils_strsplit_set (ethtool_opts, ";", FALSE); + for (iter = opts; iter && iter[0]; iter++) { + /* in case of repeated wol_passwords, parse_ethtool_option() + * will do the right thing and clear wol_password before resetting. */ + parse_ethtool_option (iter[0], + &wol_flags, + &wol_password, + &autoneg, + &speed, + &duplex, + &s_ethtool); + } } } /* ETHTOOL_WAKE_ON_LAN = ignore overrides WoL settings in ETHTOOL_OPTS */ - 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; - else - PARSE_WARNING ("invalid ETHTOOL_WAKE_ON_LAN value '%s'", wol_value); - } + tmp = svGetValueStr (ifcfg, "ETHTOOL_WAKE_ON_LAN", &wol_value_free); + if (nm_streq0 (tmp, "ignore")) + wol_flags = NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE; + else if (tmp) + PARSE_WARNING ("invalid ETHTOOL_WAKE_ON_LAN value '%s'", tmp); if ( wol_password && !NM_FLAGS_HAS (wol_flags, NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC)) { PARSE_WARNING ("Wake-on-LAN password not expected"); - ignore_wol_password = TRUE; + nm_clear_g_free (&wol_password); } - g_object_set (s_wired, - NM_SETTING_WIRED_WAKE_ON_LAN, wol_flags, - NM_SETTING_WIRED_WAKE_ON_LAN_PASSWORD, ignore_wol_password ? NULL : wol_password, - NM_SETTING_WIRED_AUTO_NEGOTIATE, autoneg, - NM_SETTING_WIRED_SPEED, speed, - NM_SETTING_WIRED_DUPLEX, duplex, - NULL); + s_wired = nm_connection_get_setting_wired (connection); + if (s_wired) { + g_object_set (s_wired, + NM_SETTING_WIRED_WAKE_ON_LAN, wol_flags, + NM_SETTING_WIRED_WAKE_ON_LAN_PASSWORD, wol_password, + NM_SETTING_WIRED_AUTO_NEGOTIATE, autoneg, + NM_SETTING_WIRED_SPEED, speed, + NM_SETTING_WIRED_DUPLEX, duplex, + NULL); + } + + if (s_ethtool) { + nm_connection_add_setting (connection, + NM_SETTING (g_steal_pointer (&s_ethtool))); + } } static NMSetting * @@ -4230,7 +4424,7 @@ make_wired_setting (shvarFile *ifcfg, gs_free const char **chans = NULL; guint32 num_chans; - chans = nm_utils_strsplit_set (value, ","); + chans = nm_utils_strsplit_set (value, ",", FALSE); num_chans = NM_PTRARRAY_LEN (chans); if (num_chans < 2 || num_chans > 3) { PARSE_WARNING ("invalid SUBCHANNELS '%s' (%u channels, 2 or 3 expected)", @@ -4318,10 +4512,6 @@ make_wired_setting (shvarFile *ifcfg, nm_clear_g_free (&value); } - parse_ethtool_options (ifcfg, s_wired, - svGetValue (ifcfg, "ETHTOOL_OPTS", &value)); - nm_clear_g_free (&value); - return (NMSetting *) g_steal_pointer (&s_wired); } @@ -4557,7 +4747,7 @@ make_bond_setting (shvarFile *ifcfg, gs_free const char **items = NULL; const char *const *iter; - items = nm_utils_strsplit_set (v, " "); + items = nm_utils_strsplit_set (v, " ", FALSE); for (iter = items; iter && *iter; iter++) { gs_strfreev char **keys = NULL; const char *key, *val; @@ -4835,7 +5025,7 @@ handle_bridging_opts (NMSetting *setting, gs_free const char **items = NULL; const char *const *iter; - items = nm_utils_strsplit_set (value, " "); + items = nm_utils_strsplit_set (value, " ", FALSE); for (iter = items; iter && *iter; iter++) { gs_strfreev char **keys = NULL; const char *key, *val; @@ -5055,7 +5245,7 @@ parse_prio_map_list (NMSettingVlan *s_vlan, v = svGetValueStr (ifcfg, key, &value); if (!v) return; - list = nm_utils_strsplit_set (v, ","); + list = nm_utils_strsplit_set (v, ",", FALSE); for (iter = list; iter && *iter; iter++) { if (!strchr (*iter, ':')) @@ -5077,7 +5267,7 @@ make_vlan_setting (shvarFile *ifcfg, const char *v = NULL; int vlan_id = -1; guint32 vlan_flags = 0; - gint gvrp, reorder_hdr; + int gvrp, reorder_hdr; v = svGetValueStr (ifcfg, "VLAN_ID", &value); if (v) { @@ -5160,7 +5350,7 @@ make_vlan_setting (shvarFile *ifcfg, gs_free const char **strv = NULL; const char *const *ptr; - strv = nm_utils_strsplit_set (v, ", "); + strv = nm_utils_strsplit_set (v, ", ", FALSE); for (ptr = strv; ptr && *ptr; ptr++) { if (nm_streq (*ptr, "GVRP") && gvrp == -1) vlan_flags |= NM_VLAN_FLAG_GVRP; @@ -5302,7 +5492,7 @@ check_dns_search_domains (shvarFile *ifcfg, NMSetting *s_ip4, NMSetting *s_ip6) gs_free const char **searches = NULL; const char *const *item; - searches = nm_utils_strsplit_set (v, " "); + searches = nm_utils_strsplit_set (v, " ", FALSE); if (searches) { for (item = searches; *item; item++) { if (!nm_setting_ip_config_add_dns_search (NM_SETTING_IP_CONFIG (s_ip6), *item)) @@ -5321,12 +5511,13 @@ connection_from_file_full (const char *filename, GError **error, gboolean *out_ignore_error) { - nm_auto_shvar_file_close shvarFile *parsed = NULL; + nm_auto_shvar_file_close shvarFile *main_ifcfg = NULL; nm_auto_shvar_file_close shvarFile *network_ifcfg = NULL; gs_unref_object NMConnection *connection = NULL; gs_free char *type = NULL; char *devtype, *bootproto; NMSetting *s_ip4, *s_ip6, *s_tc, *s_proxy, *s_port, *s_dcb = NULL, *s_user; + NMSetting *s_sriov, *s_match; const char *ifcfg_name = NULL; gboolean has_ip4_defroute = FALSE; gboolean has_complex_routes_v4; @@ -5348,14 +5539,14 @@ connection_from_file_full (const char *filename, return NULL; } - parsed = svOpenFile (filename, error); - if (!parsed) + main_ifcfg = svOpenFile (filename, error); + if (!main_ifcfg) return NULL; network_ifcfg = svOpenFile (network_file, NULL); - if (!svGetValueBoolean (parsed, "NM_CONTROLLED", TRUE)) { - connection = create_unhandled_connection (filename, parsed, "unmanaged", out_unhandled); + if (!svGetValueBoolean (main_ifcfg, "NM_CONTROLLED", TRUE)) { + connection = create_unhandled_connection (filename, main_ifcfg, "unmanaged", out_unhandled); if (!connection) { NM_SET_OUT (out_ignore_error, TRUE); g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED, @@ -5365,7 +5556,7 @@ connection_from_file_full (const char *filename, } /* iBFT is handled by the iBFT settings plugin */ - bootproto = svGetValueStr_cp (parsed, "BOOTPROTO"); + bootproto = svGetValueStr_cp (main_ifcfg, "BOOTPROTO"); if (bootproto && !g_ascii_strcasecmp (bootproto, "ibft")) { NM_SET_OUT (out_ignore_error, TRUE); g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, @@ -5375,19 +5566,19 @@ connection_from_file_full (const char *filename, } g_free (bootproto); - devtype = svGetValueStr_cp (parsed, "DEVICETYPE"); + devtype = svGetValueStr_cp (main_ifcfg, "DEVICETYPE"); if (devtype) { if (!strcasecmp (devtype, TYPE_TEAM)) type = g_strdup (TYPE_TEAM); else if (!strcasecmp (devtype, TYPE_TEAM_PORT)) { gs_free char *device = NULL; - type = svGetValueStr_cp (parsed, "TYPE"); - device = svGetValueStr_cp (parsed, "DEVICE"); + type = svGetValueStr_cp (main_ifcfg, "TYPE"); + device = svGetValueStr_cp (main_ifcfg, "DEVICE"); if (type) { /* nothing to do */ - } else if (device && is_vlan_device (device, parsed)) + } else if (device && is_vlan_device (device, main_ifcfg)) type = g_strdup (TYPE_VLAN); else type = g_strdup (TYPE_ETHERNET); @@ -5400,26 +5591,26 @@ connection_from_file_full (const char *filename, /* Team and TeamPort types are also accepted by the mere * presence of TEAM_CONFIG/TEAM_MASTER. They don't require * DEVICETYPE. */ - t = svGetValueStr_cp (parsed, "TEAM_CONFIG"); + t = svGetValueStr_cp (main_ifcfg, "TEAM_CONFIG"); if (t) type = g_strdup (TYPE_TEAM); } if (!type) - type = svGetValueStr_cp (parsed, "TYPE"); + type = svGetValueStr_cp (main_ifcfg, "TYPE"); if (!type) { gs_free char *tmp = NULL; char *device; - if ((tmp = svGetValueStr_cp (parsed, "IPV6TUNNELIPV4"))) { + if ((tmp = svGetValueStr_cp (main_ifcfg, "IPV6TUNNELIPV4"))) { NM_SET_OUT (out_ignore_error, TRUE); g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Ignoring unsupported connection due to IPV6TUNNELIPV4"); return NULL; } - device = svGetValueStr_cp (parsed, "DEVICE"); + device = svGetValueStr_cp (main_ifcfg, "DEVICE"); if (!device) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "File '%s' had neither TYPE nor DEVICE keys.", filename); @@ -5435,11 +5626,11 @@ connection_from_file_full (const char *filename, } if (!test_type) { - if (is_bond_device (device, parsed)) + if (is_bond_device (device, main_ifcfg)) type = g_strdup (TYPE_BOND); - else if (is_vlan_device (device, parsed)) + else if (is_vlan_device (device, main_ifcfg)) type = g_strdup (TYPE_VLAN); - else if (is_wifi_device (device, parsed)) + else if (is_wifi_device (device, main_ifcfg)) type = g_strdup (TYPE_WIRELESS); else { gs_free char *p_path = NULL; @@ -5505,14 +5696,14 @@ 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)) { + if (svGetValueStr (main_ifcfg, "BONDING_OPTS", &bond_options)) { /* initscripts consider these as bond masters */ g_free (type); type = g_strdup (TYPE_BOND); } } - if (svGetValueBoolean (parsed, "BONDING_MASTER", FALSE) && + if (svGetValueBoolean (main_ifcfg, "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"); @@ -5521,21 +5712,21 @@ connection_from_file_full (const char *filename, /* Construct the connection */ if (!strcasecmp (type, TYPE_ETHERNET)) - connection = wired_connection_from_ifcfg (filename, parsed, error); + connection = wired_connection_from_ifcfg (filename, main_ifcfg, error); else if (!strcasecmp (type, TYPE_WIRELESS)) - connection = wireless_connection_from_ifcfg (filename, parsed, error); + connection = wireless_connection_from_ifcfg (filename, main_ifcfg, error); else if (!strcasecmp (type, TYPE_INFINIBAND)) - connection = infiniband_connection_from_ifcfg (filename, parsed, error); + connection = infiniband_connection_from_ifcfg (filename, main_ifcfg, error); else if (!strcasecmp (type, TYPE_BOND)) - connection = bond_connection_from_ifcfg (filename, parsed, error); + connection = bond_connection_from_ifcfg (filename, main_ifcfg, error); else if (!strcasecmp (type, TYPE_TEAM)) - connection = team_connection_from_ifcfg (filename, parsed, error); + connection = team_connection_from_ifcfg (filename, main_ifcfg, error); else if (!strcasecmp (type, TYPE_VLAN)) - connection = vlan_connection_from_ifcfg (filename, parsed, error); + connection = vlan_connection_from_ifcfg (filename, main_ifcfg, error); else if (!strcasecmp (type, TYPE_BRIDGE)) - connection = bridge_connection_from_ifcfg (filename, parsed, error); + connection = bridge_connection_from_ifcfg (filename, main_ifcfg, error); else { - connection = create_unhandled_connection (filename, parsed, "unrecognized", out_unhandled); + connection = create_unhandled_connection (filename, main_ifcfg, "unrecognized", out_unhandled); if (!connection) { PARSE_WARNING ("connection type was unrecognized but device was not uniquely identified; device may be managed"); g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, @@ -5547,6 +5738,8 @@ connection_from_file_full (const char *filename, if (!connection) return NULL; + parse_ethtool_options (main_ifcfg, connection); + has_complex_routes_v4 = utils_has_complex_routes (filename, AF_INET); has_complex_routes_v6 = utils_has_complex_routes (filename, AF_INET6); @@ -5559,7 +5752,7 @@ connection_from_file_full (const char *filename, PARSE_WARNING ("'rule-' and 'rule6-' files are present; you will need to use a dispatcher script to apply these routes"); } - s_ip6 = make_ip6_setting (parsed, + s_ip6 = make_ip6_setting (main_ifcfg, network_ifcfg, !has_complex_routes_v4 && !has_complex_routes_v6, error); @@ -5568,7 +5761,7 @@ connection_from_file_full (const char *filename, else nm_connection_add_setting (connection, s_ip6); - s_ip4 = make_ip4_setting (parsed, + s_ip4 = make_ip4_setting (main_ifcfg, network_ifcfg, !has_complex_routes_v4 && !has_complex_routes_v6, &has_ip4_defroute, @@ -5582,7 +5775,11 @@ connection_from_file_full (const char *filename, nm_connection_add_setting (connection, s_ip4); } - s_tc = make_tc_setting (parsed); + s_sriov = make_sriov_setting (main_ifcfg); + if (s_sriov) + nm_connection_add_setting (connection, s_sriov); + + s_tc = make_tc_setting (main_ifcfg); if (s_tc) nm_connection_add_setting (connection, s_tc); @@ -5590,27 +5787,31 @@ connection_from_file_full (const char *filename, * config fails for some reason, we read DOMAIN and put the * values into IPv6 config instead of IPv4. */ - check_dns_search_domains (parsed, s_ip4, s_ip6); + check_dns_search_domains (main_ifcfg, s_ip4, s_ip6); - s_proxy = make_proxy_setting (parsed); + s_proxy = make_proxy_setting (main_ifcfg); if (s_proxy) nm_connection_add_setting (connection, s_proxy); - s_user = make_user_setting (parsed); + s_user = make_user_setting (main_ifcfg); if (s_user) nm_connection_add_setting (connection, s_user); + s_match = make_match_setting (main_ifcfg); + if (s_match) + nm_connection_add_setting (connection, s_match); + /* Bridge port? */ - s_port = make_bridge_port_setting (parsed); + s_port = make_bridge_port_setting (main_ifcfg); if (s_port) nm_connection_add_setting (connection, s_port); /* Team port? */ - s_port = make_team_port_setting (parsed); + s_port = make_team_port_setting (main_ifcfg); if (s_port) nm_connection_add_setting (connection, s_port); - if (!make_dcb_setting (parsed, &s_dcb, error)) + if (!make_dcb_setting (main_ifcfg, &s_dcb, error)) return NULL; if (s_dcb) nm_connection_add_setting (connection, s_dcb); |