summary refs log tree commit diff
path: root/libnm-core/nm-keyfile-reader.c
diff options
context:
space:
mode:
Diffstat (limited to 'libnm-core/nm-keyfile-reader.c')
-rw-r--r--libnm-core/nm-keyfile-reader.c101
1 files changed, 82 insertions, 19 deletions
diff --git a/libnm-core/nm-keyfile-reader.c b/libnm-core/nm-keyfile-reader.c
index c071264d..eb257eeb 100644
--- a/libnm-core/nm-keyfile-reader.c
+++ b/libnm-core/nm-keyfile-reader.c
@@ -35,6 +35,8 @@
 #include "nm-core-internal.h"
 #include "nm-keyfile-utils.h"
 
+#include "nm-setting-user.h"
+
 typedef struct {
 	NMConnection *connection;
 	GKeyFile *keyfile;
@@ -429,6 +431,31 @@ read_one_ip_address_or_route (KeyfileReaderInfo *info,
 }
 
 static void
+fill_route_attributes (GKeyFile *kf, NMIPRoute *route, const char *setting, const char *key, int family)
+{
+	gs_free char *value = NULL;
+	gs_unref_hashtable GHashTable *hash = NULL;
+	GHashTableIter iter;
+	char *name;
+	GVariant *variant;
+
+	value = nm_keyfile_plugin_kf_get_string (kf, setting, key, NULL);
+	if (!value || !value[0])
+		return;
+
+	hash = nm_utils_parse_variant_attributes (value, ',', '=', TRUE,
+	                                          nm_ip_route_get_variant_attribute_spec (),
+	                                          NULL);
+	if (hash) {
+		g_hash_table_iter_init (&iter, hash);
+		while (g_hash_table_iter_next (&iter, (gpointer *) &name, (gpointer *) &variant)) {
+			if (nm_ip_route_attribute_validate (name, variant, family, NULL, NULL))
+				nm_ip_route_set_attribute (route, name, g_variant_ref (variant));
+		}
+	}
+}
+
+static void
 ip_address_or_route_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key)
 {
 	const char *setting_name = nm_setting_get_name (setting);
@@ -454,6 +481,7 @@ ip_address_or_route_parser (KeyfileReaderInfo *info, NMSetting *setting, const c
 		for (key_basename = key_names; *key_basename; key_basename++) {
 			char *key_name;
 			gpointer item;
+			char options_key[128];
 
 			/* -1 means no suffix */
 			if (i >= 0)
@@ -463,6 +491,11 @@ ip_address_or_route_parser (KeyfileReaderInfo *info, NMSetting *setting, const c
 
 			item = read_one_ip_address_or_route (info, key, setting_name, key_name, ipv6, routes,
 			                                     gateway ? NULL : &gateway, setting);
+			if (item && routes) {
+				nm_sprintf_buf (options_key, "%s_options", key_name);
+				fill_route_attributes (info->keyfile, item, setting_name, options_key, ipv6 ? AF_INET6 : AF_INET);
+			}
+
 			g_free (key_name);
 
 			if (info->error) {
@@ -637,7 +670,6 @@ mac_address_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key
 			buf_arr = g_new (guint8, buf_len);
 			for (i = 0; i < length; i++) {
 				int val = tmp_list[i];
-				const guint8 v = (guint8) (val & 0xFF);
 
 				if (val < 0 || val > 255) {
 					handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN,
@@ -645,7 +677,7 @@ mac_address_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key
 					             val);
 					return;
 				}
-				buf_arr[i] = v;
+				buf_arr[i] = (guint8) val;
 			}
 		}
 	}
@@ -684,31 +716,59 @@ mac_address_parser_INFINIBAND (KeyfileReaderInfo *info, NMSetting *setting, cons
 static void
 read_hash_of_string (GKeyFile *file, NMSetting *setting, const char *key)
 {
-	char **keys, **iter;
-	char *value;
+	gs_strfreev char **keys = NULL;
+	const char *const*iter;
 	const char *setting_name = nm_setting_get_name (setting);
+	gboolean is_vpn;
 
 	keys = nm_keyfile_plugin_kf_get_keys (file, setting_name, NULL, NULL);
 	if (!keys || !*keys)
 		return;
 
-	for (iter = keys; *iter; iter++) {
-		value = nm_keyfile_plugin_kf_get_string (file, setting_name, *iter, NULL);
-		if (!value)
-			continue;
-
-		if (NM_IS_SETTING_VPN (setting)) {
-			/* Add any item that's not a class property to the data hash */
-			if (!g_object_class_find_property (G_OBJECT_GET_CLASS (setting), *iter))
-				nm_setting_vpn_add_data_item (NM_SETTING_VPN (setting), *iter, value);
+	if (   (is_vpn = NM_IS_SETTING_VPN (setting))
+	    || NM_IS_SETTING_BOND (setting)) {
+		for (iter = (const char *const*) keys; *iter; iter++) {
+			gs_free char *to_free = NULL;
+			gs_free char *value = NULL;
+			const char *name;
+
+			value = nm_keyfile_plugin_kf_get_string (file, setting_name, *iter, NULL);
+			if (!value)
+				continue;
+
+			name = nm_keyfile_key_decode (*iter, &to_free);
+
+			if (is_vpn) {
+				/* Add any item that's not a class property to the data hash */
+				if (!g_object_class_find_property (G_OBJECT_GET_CLASS (setting), name))
+					nm_setting_vpn_add_data_item (NM_SETTING_VPN (setting), name, value);
+			} else {
+				if (strcmp (name, "interface-name"))
+					nm_setting_bond_add_option (NM_SETTING_BOND (setting), name, value);
+			}
 		}
-		if (NM_IS_SETTING_BOND (setting)) {
-			if (strcmp (*iter, "interface-name"))
-				nm_setting_bond_add_option (NM_SETTING_BOND (setting), *iter, value);
+		return;
+	}
+
+	if (NM_IS_SETTING_USER (setting)) {
+		gs_unref_hashtable GHashTable *data = NULL;
+
+		data = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+		for (iter = (const char *const*) keys; *iter; iter++) {
+			gs_free char *to_free = NULL;
+			char *value = NULL;
+			const char *name;
+
+			value = nm_keyfile_plugin_kf_get_string (file, setting_name, *iter, NULL);
+			if (!value)
+				continue;
+			name = nm_keyfile_key_decode (*iter, &to_free);
+			g_hash_table_insert (data,
+			                     g_steal_pointer (&to_free) ?: g_strdup (name),
+			                     value);
 		}
-		g_free (value);
+		g_object_set (setting, NM_SETTING_USER_DATA, data, NULL);
 	}
-	g_strfreev (keys);
 }
 
 static gsize
@@ -1425,6 +1485,9 @@ read_one_setting_value (NMSetting *setting,
 	if (NM_IS_SETTING_VPN (setting))
 		check_for_key = FALSE;
 
+	if (NM_IS_SETTING_USER (setting))
+		check_for_key = FALSE;
+
 	/* Bonding 'options' don't have the exact key name. The options are right under [bond] group. */
 	if (NM_IS_SETTING_BOND (setting))
 		check_for_key = FALSE;
@@ -1574,7 +1637,7 @@ read_one_setting_value (NMSetting *setting,
 			else {
 				if (!handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN,
 				                  _("too large FLAGS property '%s' (%llu)"),
-				                  G_VALUE_TYPE_NAME (value), (long long unsigned) uint_val))
+				                  G_VALUE_TYPE_NAME (value), (unsigned long long) uint_val))
 					goto out_error;
 			}
 		}