summary refs log tree commit diff
path: root/src/settings/plugins
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2011-08-23 19:16:47 +0200
committerMichael Biebl <biebl@debian.org>2011-08-23 19:16:47 +0200
commit263bf4c0c89bb88dc995acd9a6a2de9095fbd461 (patch)
tree7224326afe367409e7150e49fad9029f81fe24b8 /src/settings/plugins
parentd465e5fac63f36bcf4069e36827f4b62c494556d (diff)
Imported Upstream version 0.9.0 upstream/0.9.0
Diffstat (limited to 'src/settings/plugins')
-rw-r--r--src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c45
-rw-r--r--src/settings/plugins/ifcfg-rh/plugin.c24
-rw-r--r--src/settings/plugins/ifcfg-rh/reader.c167
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-8021x-peap-mschapv22
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c129
-rw-r--r--src/settings/plugins/ifcfg-rh/writer.c41
-rw-r--r--src/settings/plugins/ifnet/plugin.c3
-rw-r--r--src/settings/plugins/keyfile/common.h3
-rw-r--r--src/settings/plugins/keyfile/plugin.c3
-rw-r--r--src/settings/plugins/keyfile/reader.c67
-rw-r--r--src/settings/plugins/keyfile/tests/keyfiles/Makefile.am5
-rw-r--r--src/settings/plugins/keyfile/tests/keyfiles/Makefile.in5
-rw-r--r--src/settings/plugins/keyfile/tests/keyfiles/Test_Intlist_SSID11
-rw-r--r--src/settings/plugins/keyfile/tests/keyfiles/Test_Wired_TLS_Blob22
-rw-r--r--src/settings/plugins/keyfile/tests/keyfiles/Test_Wired_TLS_Path_Missing22
-rw-r--r--src/settings/plugins/keyfile/tests/test-keyfile.c299
-rw-r--r--src/settings/plugins/keyfile/utils.c7
-rw-r--r--src/settings/plugins/keyfile/writer.c10
18 files changed, 731 insertions, 134 deletions
diff --git a/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c b/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c
index 433f933b..04d3d3e4 100644
--- a/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c
+++ b/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c
@@ -15,7 +15,7 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
- * Copyright (C) 2008 - 2010 Red Hat, Inc.
+ * Copyright (C) 2008 - 2011 Red Hat, Inc.
  */
 
 #include <string.h>
@@ -181,12 +181,13 @@ nm_ifcfg_connection_get_unmanaged_spec (NMIfcfgConnection *self)
 static void
 commit_changes (NMSettingsConnection *connection,
                 NMSettingsConnectionCommitFunc callback,
-	            gpointer user_data)
+                gpointer user_data)
 {
 	NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (connection);
 	GError *error = NULL;
 	NMConnection *reread;
 	char *unmanaged = NULL, *keyfile = NULL, *routefile = NULL, *route6file = NULL;
+	gboolean same = FALSE;
 
 	/* 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
@@ -200,28 +201,36 @@ commit_changes (NMSettingsConnection *connection,
 	g_free (routefile);
 	g_free (route6file);
 
-	if (reread && nm_connection_compare (NM_CONNECTION (connection),
-	                                     reread,
-	                                     NM_SETTING_COMPARE_FLAG_EXACT))
-		goto out;
+	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);
 
-	if (!writer_update_connection (NM_CONNECTION (connection),
-	                               IFCFG_DIR,
-	                               priv->path,
-	                               priv->keyfile,
-	                               &error)) {
+		/* 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, callback, user_data);
+			return;
+		}
+	}
+
+	if (writer_update_connection (NM_CONNECTION (connection),
+	                              IFCFG_DIR,
+	                              priv->path,
+	                              priv->keyfile,
+	                              &error)) {
+		/* Chain up to parent to handle success */
+		NM_SETTINGS_CONNECTION_CLASS (nm_ifcfg_connection_parent_class)->commit_changes (connection, callback, user_data);
+	} else {
+		/* Otherwise immediate error */
 		callback (connection, error, user_data);
 		g_error_free (error);
-		return;
 	}
-
-out:
-	if (reread)
-		g_object_unref (reread);
-	NM_SETTINGS_CONNECTION_CLASS (nm_ifcfg_connection_parent_class)->commit_changes (connection, callback, user_data);
 }
 
-static void 
+static void
 do_delete (NMSettingsConnection *connection,
 	       NMSettingsConnectionDeleteFunc callback,
 	       gpointer user_data)
diff --git a/src/settings/plugins/ifcfg-rh/plugin.c b/src/settings/plugins/ifcfg-rh/plugin.c
index 7915c467..ed0dceca 100644
--- a/src/settings/plugins/ifcfg-rh/plugin.c
+++ b/src/settings/plugins/ifcfg-rh/plugin.c
@@ -269,19 +269,24 @@ connection_new_or_changed (SCPluginIfcfg *self,
 
 	/* Successfully read connection changes */
 
-	/* When the connections are the same, nothing is done */
-	if (nm_connection_compare (NM_CONNECTION (existing),
-	                           NM_CONNECTION (new),
-	                           NM_SETTING_COMPARE_FLAG_EXACT)) {
+	old_unmanaged = nm_ifcfg_connection_get_unmanaged_spec (NM_IFCFG_CONNECTION (existing));
+	new_unmanaged = nm_ifcfg_connection_get_unmanaged_spec (NM_IFCFG_CONNECTION (new));
+
+	/* When interface is unmanaged or the connections and unmanaged specs are the same
+	 * there's nothing to do */
+	if (   (g_strcmp0 (old_unmanaged, new_unmanaged) == 0 && new_unmanaged != NULL)
+	    || (   nm_connection_compare (NM_CONNECTION (existing),
+	                                  NM_CONNECTION (new),
+	                                  NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS |
+	                                    NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS)
+	        && g_strcmp0 (old_unmanaged, new_unmanaged) == 0)) {
+
 		g_object_unref (new);
 		return;
 	}
 
 	PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "updating %s", path);
 
-	old_unmanaged = nm_ifcfg_connection_get_unmanaged_spec (NM_IFCFG_CONNECTION (existing));
-	new_unmanaged = nm_ifcfg_connection_get_unmanaged_spec (NM_IFCFG_CONNECTION (new));
-
 	if (new_unmanaged) {
 		if (!old_unmanaged) {
 			/* Unexport the connection by telling the settings service it's
@@ -289,6 +294,11 @@ connection_new_or_changed (SCPluginIfcfg *self,
 			 * unmanaged specs have changed.
 			 */
 			nm_settings_connection_signal_remove (NM_SETTINGS_CONNECTION (existing));
+			/* Remove the path so that claim_connection() doesn't complain later when
+			 * interface gets managed and connection is re-added. */
+			nm_connection_set_path (NM_CONNECTION (existing), NULL);
+
+			g_object_set (existing, NM_IFCFG_CONNECTION_UNMANAGED, new_unmanaged, NULL);
 			g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED);
 		}
 	} else {
diff --git a/src/settings/plugins/ifcfg-rh/reader.c b/src/settings/plugins/ifcfg-rh/reader.c
index a6f9ca85..cdf5889e 100644
--- a/src/settings/plugins/ifcfg-rh/reader.c
+++ b/src/settings/plugins/ifcfg-rh/reader.c
@@ -176,9 +176,9 @@ read_mac_address (shvarFile *ifcfg, const char *key, GByteArray **array, GError
 
 	mac = ether_aton (value);
 	if (!mac) {
-		g_free (value);
 		g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
 		             "%s: the MAC address '%s' was invalid.", key, value);
+		g_free (value);
 		return FALSE;
 	}
 
@@ -574,7 +574,8 @@ read_full_ip4_address (shvarFile *ifcfg,
 	if (!nm_ip4_address_get_prefix (addr)) {
 		if (!read_ip4_address (ifcfg, netmask_tag, &tmp, error))
 			goto error;
-		nm_ip4_address_set_prefix (addr, nm_utils_ip4_netmask_to_prefix (tmp));
+		if (tmp)
+			nm_ip4_address_set_prefix (addr, nm_utils_ip4_netmask_to_prefix (tmp));
 	}
 
 	/* Try to autodetermine the prefix for the address' class */
@@ -661,7 +662,8 @@ read_one_ip4_route (shvarFile *ifcfg,
 	/* Prefix */
 	if (!read_ip4_address (ifcfg, netmask_tag, &tmp, error))
 		goto out;
-	nm_ip4_route_set_prefix (route, nm_utils_ip4_netmask_to_prefix (tmp));
+	if (tmp)
+		nm_ip4_route_set_prefix (route, nm_utils_ip4_netmask_to_prefix (tmp));
 
 	/* Validate the prefix */
 	if (  !nm_ip4_route_get_prefix (route)
@@ -788,7 +790,7 @@ read_route_file_legacy (const char *filename, NMSettingIP4Config *s_ip4, GError
 		if (prefix) {
 			errno = 0;
 			prefix_int = strtol (prefix, NULL, 10);
-			if (errno || prefix_int < 0 || prefix_int > 32) {
+			if (errno || prefix_int <= 0 || prefix_int > 32) {
 				g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
 					     "Invalid IP4 route destination prefix '%s'", prefix);
 				g_free (prefix);
@@ -973,9 +975,9 @@ read_route6_file (const char *filename, NMSettingIP6Config *s_ip6, GError **erro
 
 	const char *pattern_empty = "^\\s*(\\#.*)?$";
 	const char *pattern_to1 = "^\\s*(" IPV6_ADDR_REGEX "|default)"  /* IPv6 or 'default' keyword */
-	                          "(?:/(\\d{1,2}))?";                   /* optional prefix */
+	                          "(?:/(\\d{1,3}))?";                   /* optional prefix */
 	const char *pattern_to2 = "to\\s+(" IPV6_ADDR_REGEX "|default)" /* IPv6 or 'default' keyword */
-	                          "(?:/(\\d{1,2}))?";                   /* optional prefix */
+	                          "(?:/(\\d{1,3}))?";                   /* optional prefix */
 	const char *pattern_via = "via\\s+(" IPV6_ADDR_REGEX ")";       /* IPv6 of gateway */
 	const char *pattern_metric = "metric\\s+(\\d+)";                /* metric */
 
@@ -1041,7 +1043,7 @@ read_route6_file (const char *filename, NMSettingIP6Config *s_ip6, GError **erro
 		if (prefix) {
 			errno = 0;
 			prefix_int = strtol (prefix, NULL, 10);
-			if (errno || prefix_int < 0 || prefix_int > 128) {
+			if (errno || prefix_int <= 0 || prefix_int > 128) {
 				g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
 					     "Invalid IP6 route destination prefix '%s'", prefix);
 				g_free (prefix);
@@ -1228,15 +1230,11 @@ make_ip4_setting (shvarFile *ifcfg,
 		    && !tmp_ip4_0 && !tmp_prefix_0 && !tmp_netmask_0
 		    && !tmp_ip4_1 && !tmp_prefix_1 && !tmp_netmask_1
 		    && !tmp_ip4_2 && !tmp_prefix_2 && !tmp_netmask_2) {
-			if (valid_ip6_config) {
+			if (valid_ip6_config)
 				/* Nope, no IPv4 */
-				g_object_set (s_ip4,
-				              NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_DISABLED,
-				              NULL);
-				return NM_SETTING (s_ip4);
-			}
-
-			method = NM_SETTING_IP4_CONFIG_METHOD_AUTO;
+				method = NM_SETTING_IP4_CONFIG_METHOD_DISABLED;
+			else
+				method = NM_SETTING_IP4_CONFIG_METHOD_AUTO;
 		}
 		g_free (tmp_ip4);
 		g_free (tmp_prefix);
@@ -1260,6 +1258,9 @@ make_ip4_setting (shvarFile *ifcfg,
 	              NM_SETTING_IP4_CONFIG_MAY_FAIL, !svTrueValue (ifcfg, "IPV4_FAILURE_FATAL", TRUE),
 	              NULL);
 
+	if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) == 0)
+		return NM_SETTING (s_ip4);
+
 	/* Handle manual settings */
 	if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL)) {
 		NMIP4Address *addr;
@@ -1418,7 +1419,7 @@ make_ip6_setting (shvarFile *ifcfg,
 	char *value = NULL;
 	char *str_value;
 	char *route6_path = NULL;
-	gboolean bool_value, ipv6forwarding, ipv6_autoconf, dhcp6 = FALSE;
+	gboolean ipv6init, ipv6forwarding, ipv6_autoconf, dhcp6 = FALSE;
 	char *method = NM_SETTING_IP6_CONFIG_METHOD_MANUAL;
 	guint32 i;
 	shvarFile *network_ifcfg;
@@ -1431,26 +1432,6 @@ make_ip6_setting (shvarFile *ifcfg,
 		return NULL;
 	}
 
-	/* Is IPV6 enabled? Set method to "ignored", when not enabled */
-	str_value = svGetValue (ifcfg, "IPV6INIT", FALSE);
-	bool_value = svTrueValue (ifcfg, "IPV6INIT", FALSE);
-	if (!str_value) {
-		network_ifcfg = svNewFile (network_file);
-		if (network_ifcfg) {
-			bool_value = svTrueValue (network_ifcfg, "IPV6INIT", FALSE);
-			svCloseFile (network_ifcfg);
-		}
-	}
-	g_free (str_value);
-
-	if (!bool_value) {
-		/* IPv6 is disabled */
-		g_object_set (s_ip6,
-		              NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE,
-		              NULL);
-		return NM_SETTING (s_ip6);
-	}
-
 	/* First check if IPV6_DEFROUTE is set for this device; IPV6_DEFROUTE has the
 	 * opposite meaning from never-default. The default if IPV6_DEFROUTE is not
 	 * specified is IPV6_DEFROUTE=yes which means that this connection can be used
@@ -1493,23 +1474,39 @@ make_ip6_setting (shvarFile *ifcfg,
 	}
 
 	/* Find out method property */
-	ipv6forwarding = svTrueValue (ifcfg, "IPV6FORWARDING", FALSE);
-	ipv6_autoconf = svTrueValue (ifcfg, "IPV6_AUTOCONF", !ipv6forwarding);
-	dhcp6 = svTrueValue (ifcfg, "DHCPV6C", FALSE);
-
-	if (ipv6_autoconf)
-		method = NM_SETTING_IP6_CONFIG_METHOD_AUTO;
-	else if (dhcp6)
-		method = NM_SETTING_IP6_CONFIG_METHOD_DHCP;
+	/* Is IPV6 enabled? Set method to "ignored", when not enabled */
+	str_value = svGetValue (ifcfg, "IPV6INIT", FALSE);
+	ipv6init = svTrueValue (ifcfg, "IPV6INIT", FALSE);
+	if (!str_value) {
+		network_ifcfg = svNewFile (network_file);
+		if (network_ifcfg) {
+			ipv6init = svTrueValue (network_ifcfg, "IPV6INIT", FALSE);
+			svCloseFile (network_ifcfg);
+		}
+	}
+	g_free (str_value);
+
+	if (!ipv6init)
+		method = NM_SETTING_IP6_CONFIG_METHOD_IGNORE;  /* IPv6 is disabled */
 	else {
-		/* IPV6_AUTOCONF=no and no IPv6 address -> method 'link-local' */
-		str_value = svGetValue (ifcfg, "IPV6ADDR", FALSE);
-		if (!str_value)
-			str_value = svGetValue (ifcfg, "IPV6ADDR_SECONDARIES", FALSE);
+		ipv6forwarding = svTrueValue (ifcfg, "IPV6FORWARDING", FALSE);
+		ipv6_autoconf = svTrueValue (ifcfg, "IPV6_AUTOCONF", !ipv6forwarding);
+		dhcp6 = svTrueValue (ifcfg, "DHCPV6C", FALSE);
+
+		if (ipv6_autoconf)
+			method = NM_SETTING_IP6_CONFIG_METHOD_AUTO;
+		else if (dhcp6)
+			method = NM_SETTING_IP6_CONFIG_METHOD_DHCP;
+		else {
+			/* IPV6_AUTOCONF=no and no IPv6 address -> method 'link-local' */
+			str_value = svGetValue (ifcfg, "IPV6ADDR", FALSE);
+			if (!str_value)
+				str_value = svGetValue (ifcfg, "IPV6ADDR_SECONDARIES", FALSE);
 
-		if (!str_value)
-			method = NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL;
-		g_free (str_value);
+			if (!str_value)
+				method = NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL;
+			g_free (str_value);
+		}
 	}
 	/* TODO - handle other methods */
 
@@ -1521,6 +1518,10 @@ make_ip6_setting (shvarFile *ifcfg,
 	              NM_SETTING_IP6_CONFIG_MAY_FAIL, !svTrueValue (ifcfg, "IPV6_FAILURE_FATAL", FALSE),
 	              NULL);
 
+	/* Don't bother to read IP, DNS and routes when IPv6 is disabled */
+	if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE) == 0)
+		return NM_SETTING (s_ip6);
+
 	if (!strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) {
 		NMIP6Address *addr;
 		char *val;
@@ -2234,6 +2235,7 @@ eap_peap_reader (const char *eap_method,
                  gboolean phase2,
                  GError **error)
 {
+	char *anon_ident = NULL;
 	char *ca_cert = NULL;
 	char *real_cert_path = NULL;
 	char *inner_auth = NULL;
@@ -2275,6 +2277,10 @@ eap_peap_reader (const char *eap_method,
 	if (svTrueValue (ifcfg, "IEEE_8021X_PEAP_FORCE_NEW_LABEL", FALSE))
 		g_object_set (s_8021x, NM_SETTING_802_1X_PHASE1_PEAPLABEL, "1", NULL);
 
+	anon_ident = svGetValue (ifcfg, "IEEE_8021X_ANON_IDENTITY", FALSE);
+	if (anon_ident && strlen (anon_ident))
+		g_object_set (s_8021x, NM_SETTING_802_1X_ANONYMOUS_IDENTITY, anon_ident, NULL);
+
 	inner_auth = svGetValue (ifcfg, "IEEE_8021X_INNER_AUTH_METHODS", FALSE);
 	if (!inner_auth) {
 		g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
@@ -2324,6 +2330,7 @@ done:
 	g_free (peapver);
 	g_free (real_cert_path);
 	g_free (ca_cert);
+	g_free (anon_ident);
 	return success;
 }
 
@@ -2737,6 +2744,7 @@ make_wireless_setting (shvarFile *ifcfg,
 {
 	NMSettingWireless *s_wireless;
 	GByteArray *array = NULL;
+	GSList *macaddr_blacklist = NULL;
 	char *value;
 
 	s_wireless = NM_SETTING_WIRELESS (nm_setting_wireless_new ());
@@ -2770,6 +2778,33 @@ make_wireless_setting (shvarFile *ifcfg,
 			g_object_set (s_wireless, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, array, NULL);
 			g_byte_array_free (array, TRUE);
 		}
+	} else {
+		PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: %s", (*error)->message);
+		g_clear_error (error);
+	}
+
+	value = svGetValue (ifcfg, "HWADDR_BLACKLIST", FALSE);
+	if (value) {
+		char **list = NULL, **iter;
+		struct ether_addr addr;
+
+		list = g_strsplit_set (value, " \t", 0);
+		for (iter = list; iter && *iter; iter++) {
+			if (**iter == '\0')
+				continue;
+			if (!ether_aton_r (*iter, &addr)) {
+				PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: invalid MAC in HWADDR_BLACKLIST '%s'", *iter);
+				continue;
+			}
+			macaddr_blacklist = g_slist_prepend (macaddr_blacklist, *iter);
+		}
+		if (macaddr_blacklist) {
+			macaddr_blacklist = g_slist_reverse (macaddr_blacklist);
+			g_object_set (s_wireless, NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST, macaddr_blacklist, NULL);
+			g_slist_free (macaddr_blacklist);
+		}
+		g_free (value);
+		g_strfreev (list);
 	}
 
 	value = svGetValue (ifcfg, "ESSID", TRUE);
@@ -3030,6 +3065,7 @@ make_wired_setting (shvarFile *ifcfg,
 	char *value = NULL;
 	int mtu;
 	GByteArray *mac = NULL;
+	GSList *macaddr_blacklist = NULL;
 	char *nettype;
 
 	s_wired = NM_SETTING_WIRED (nm_setting_wired_new ());
@@ -3162,6 +3198,33 @@ make_wired_setting (shvarFile *ifcfg,
 			g_object_set (s_wired, NM_SETTING_WIRED_CLONED_MAC_ADDRESS, mac, NULL);
 			g_byte_array_free (mac, TRUE);
 		}
+	} else {
+		PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: %s", (*error)->message);
+		g_clear_error (error);
+	}
+
+	value = svGetValue (ifcfg, "HWADDR_BLACKLIST", FALSE);
+	if (value) {
+		char **list = NULL, **iter;
+		struct ether_addr addr;
+
+		list = g_strsplit_set (value, " \t", 0);
+		for (iter = list; iter && *iter; iter++) {
+			if (**iter == '\0')
+				continue;
+			if (!ether_aton_r (*iter, &addr)) {
+				PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: invalid MAC in HWADDR_BLACKLIST '%s'", *iter);
+				continue;
+			}
+			macaddr_blacklist = g_slist_prepend (macaddr_blacklist, *iter);
+		}
+		if (macaddr_blacklist) {
+			macaddr_blacklist = g_slist_reverse (macaddr_blacklist);
+			g_object_set (s_wired, NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST, macaddr_blacklist, NULL);
+			g_slist_free (macaddr_blacklist);
+		}
+		g_free (value);
+		g_strfreev (list);
 	}
 
 	value = svGetValue (ifcfg, "KEY_MGMT", FALSE);
@@ -3246,7 +3309,7 @@ is_wireless_device (const char *iface)
 	g_return_val_if_fail (iface != NULL, FALSE);
 
 	fd = socket(AF_INET, SOCK_DGRAM, 0);
-	if (!fd)
+	if (fd == -1)
 		return FALSE;
 
 	memset (&wrq, 0, sizeof (struct iwreq));
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-8021x-peap-mschapv2 b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-8021x-peap-mschapv2
index 6d68eca1..27bcbbf9 100644
--- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-8021x-peap-mschapv2
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-8021x-peap-mschapv2
@@ -12,4 +12,4 @@ IEEE_8021X_CA_CERT=test_ca_cert.pem
 IEEE_8021X_PEAP_VERSION=1
 IEEE_8021X_PEAP_FORCE_NEW_LABEL=yes
 IEEE_8021X_INNER_AUTH_METHODS=MSCHAPV2
-
+IEEE_8021X_ANON_IDENTITY=somebody
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 e6013f8d..d1f08aa9 100644
--- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
+++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
@@ -2707,6 +2707,7 @@ test_read_wired_8021x_peap_mschapv2 (void)
 	GError *error = NULL;
 	const char *tmp;
 	const char *expected_identity = "David Smith";
+	const char *expected_anon_identity = "somebody";
 	const char *expected_password = "foobar baz";
 	gboolean success = FALSE;
 	const char *expected_ca_cert_path;
@@ -2793,6 +2794,19 @@ test_read_wired_8021x_peap_mschapv2 (void)
 	        NM_SETTING_802_1X_SETTING_NAME,
 	        NM_SETTING_802_1X_IDENTITY);
 
+	/* Anonymous Identity */
+	tmp = nm_setting_802_1x_get_anonymous_identity (s_8021x);
+	ASSERT (tmp != NULL,
+	        "wired-8021x-peap-mschapv2-verify-8021x", "failed to verify %s: missing %s / %s key",
+	        TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2,
+	        NM_SETTING_802_1X_SETTING_NAME,
+	        NM_SETTING_802_1X_ANONYMOUS_IDENTITY);
+	ASSERT (strcmp (tmp, expected_anon_identity) == 0,
+	        "wired-8021x-peap-mschapv2-verify-8021x", "failed to verify %s: unexpected %s / %s key value",
+	        TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2,
+	        NM_SETTING_802_1X_SETTING_NAME,
+	        NM_SETTING_802_1X_ANONYMOUS_IDENTITY);
+
 	/* Password */
 	tmp = nm_setting_802_1x_get_password (s_8021x);
 	ASSERT (tmp != NULL,
@@ -6491,7 +6505,7 @@ test_write_wired_static (void)
 	struct in6_addr ip6, ip6_1, ip6_2;
 	struct in6_addr route1_dest, route2_dest, route1_nexthop, route2_nexthop;
 	struct in6_addr dns6_1, dns6_2;
-	const guint32 route1_prefix = 64, route2_prefix = 0;
+	const guint32 route1_prefix = 64, route2_prefix = 128;
 	const guint32 route1_metric = 99, route2_metric = 1;
 	NMIP4Address *addr;
 	NMIP6Address *addr6;
@@ -6774,6 +6788,7 @@ test_write_wired_dhcp (void)
 
 	g_object_set (s_ip6,
 	              NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE,
+	              NM_SETTING_IP6_CONFIG_MAY_FAIL, TRUE,
 	              NULL);
 
 	/* Save the ifcfg */
@@ -7234,7 +7249,10 @@ test_write_wired_static_routes (void)
 	        NM_SETTING_IP6_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
 
-	g_object_set (s_ip6, NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE, NULL);
+	g_object_set (s_ip6,
+	              NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE,
+	              NM_SETTING_IP6_CONFIG_MAY_FAIL, TRUE,
+	              NULL);
 
 	ASSERT (nm_connection_verify (connection, &error) == TRUE,
 	        "wired-static-routes-write", "failed to verify connection: %s",
@@ -7350,7 +7368,10 @@ test_write_wired_dhcp_8021x_peap_mschapv2 (void)
 	        NM_SETTING_IP6_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
 
-	g_object_set (s_ip6, NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE, NULL);
+	g_object_set (s_ip6,
+	              NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE,
+	              NM_SETTING_IP6_CONFIG_MAY_FAIL, TRUE,
+	              NULL);
 
 	/* 802.1x setting */
 	s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
@@ -7361,6 +7382,7 @@ test_write_wired_dhcp_8021x_peap_mschapv2 (void)
 
 	g_object_set (s_8021x,
 	              NM_SETTING_802_1X_IDENTITY, "Bob Saget",
+	              NM_SETTING_802_1X_ANONYMOUS_IDENTITY, "barney",
 	              NM_SETTING_802_1X_PASSWORD, "Kids, it was back in October 2008...",
 	              NM_SETTING_802_1X_PHASE1_PEAPVER, "1",
 	              NM_SETTING_802_1X_PHASE1_PEAPLABEL, "1",
@@ -7508,7 +7530,10 @@ test_write_wired_8021x_tls (NMSetting8021xCKScheme scheme,
 	/* IP6 setting */
 	s_ip6 = (NMSettingIP6Config *) nm_setting_ip6_config_new ();
 	g_assert (s_ip6);
-	g_object_set (s_ip6, NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE, NULL);
+	g_object_set (s_ip6,
+	              NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE,
+	              NM_SETTING_IP6_CONFIG_MAY_FAIL, TRUE,
+	              NULL);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
 
 	/* 802.1x setting */
@@ -7753,7 +7778,10 @@ test_write_wifi_open (void)
 	        NM_SETTING_IP6_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
 
-	g_object_set (s_ip6, NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE, NULL);
+	g_object_set (s_ip6,
+	              NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE,
+	              NM_SETTING_IP6_CONFIG_MAY_FAIL, TRUE,
+	              NULL);
 
 	ASSERT (nm_connection_verify (connection, &error) == TRUE,
 	        "wifi-open-write", "failed to verify connection: %s",
@@ -7892,7 +7920,10 @@ test_write_wifi_open_hex_ssid (void)
 	        NM_SETTING_IP6_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
 
-	g_object_set (s_ip6, NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE, NULL);
+	g_object_set (s_ip6,
+	              NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE,
+	              NM_SETTING_IP6_CONFIG_MAY_FAIL, TRUE,
+	              NULL);
 
 	ASSERT (nm_connection_verify (connection, &error) == TRUE,
 	        "wifi-open-hex-ssid-write", "failed to verify connection: %s",
@@ -8035,7 +8066,10 @@ test_write_wifi_wep (void)
 	        NM_SETTING_IP6_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
 
-	g_object_set (s_ip6, NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE, NULL);
+	g_object_set (s_ip6,
+	              NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE,
+	              NM_SETTING_IP6_CONFIG_MAY_FAIL, TRUE,
+	              NULL);
 
 	ASSERT (nm_connection_verify (connection, &error) == TRUE,
 	        "wifi-wep-write", "failed to verify connection: %s",
@@ -8198,7 +8232,10 @@ test_write_wifi_wep_adhoc (void)
 	        NM_SETTING_IP6_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
 
-	g_object_set (s_ip6, NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE, NULL);
+	g_object_set (s_ip6,
+	              NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE,
+	              NM_SETTING_IP6_CONFIG_MAY_FAIL, TRUE,
+	              NULL);
 
 	ASSERT (nm_connection_verify (connection, &error) == TRUE,
 	        "wifi-wep-adhoc-write", "failed to verify connection: %s",
@@ -8351,7 +8388,10 @@ test_write_wifi_wep_passphrase (void)
 	        NM_SETTING_IP6_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
 
-	g_object_set (s_ip6, NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE, NULL);
+	g_object_set (s_ip6,
+	              NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE,
+	              NM_SETTING_IP6_CONFIG_MAY_FAIL, TRUE,
+	              NULL);
 
 	ASSERT (nm_connection_verify (connection, &error) == TRUE,
 	        "wifi-wep-passphrase-write", "failed to verify connection: %s",
@@ -8506,7 +8546,10 @@ test_write_wifi_wep_40_ascii (void)
 	        NM_SETTING_IP6_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
 
-	g_object_set (s_ip6, NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE, NULL);
+	g_object_set (s_ip6,
+	              NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE,
+	              NM_SETTING_IP6_CONFIG_MAY_FAIL, TRUE,
+	              NULL);
 
 	ASSERT (nm_connection_verify (connection, &error) == TRUE,
 	        "wifi-wep-40-ascii-write", "failed to verify connection: %s",
@@ -8661,7 +8704,10 @@ test_write_wifi_wep_104_ascii (void)
 	        NM_SETTING_IP6_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
 
-	g_object_set (s_ip6, NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE, NULL);
+	g_object_set (s_ip6,
+	              NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE,
+	              NM_SETTING_IP6_CONFIG_MAY_FAIL, TRUE,
+	              NULL);
 
 	ASSERT (nm_connection_verify (connection, &error) == TRUE,
 	        "wifi-wep-104-ascii-write", "failed to verify connection: %s",
@@ -8813,7 +8859,10 @@ test_write_wifi_leap (void)
 	        NM_SETTING_IP6_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
 
-	g_object_set (s_ip6, NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE, NULL);
+	g_object_set (s_ip6,
+	              NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE,
+	              NM_SETTING_IP6_CONFIG_MAY_FAIL, TRUE,
+	              NULL);
 
 	ASSERT (nm_connection_verify (connection, &error) == TRUE,
 	        "wifi-leap-write", "failed to verify connection: %s",
@@ -8949,7 +8998,11 @@ test_write_wifi_leap_secret_flags (NMSettingSecretFlags flags)
 	s_ip6 = (NMSettingIP6Config *) nm_setting_ip6_config_new ();
 	g_assert (s_ip6);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
-	g_object_set (s_ip6, NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE, NULL);
+
+	g_object_set (s_ip6,
+	              NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE,
+	              NM_SETTING_IP6_CONFIG_MAY_FAIL, TRUE,
+	              NULL);
 
 	success = nm_connection_verify (connection, &error);
 	g_assert_no_error (error);
@@ -9114,7 +9167,10 @@ test_write_wifi_wpa_psk (const char *name,
 	        NM_SETTING_IP6_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
 
-	g_object_set (s_ip6, NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE, NULL);
+	g_object_set (s_ip6,
+	              NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE,
+	              NM_SETTING_IP6_CONFIG_MAY_FAIL, TRUE,
+	              NULL);
 
 	ASSERT (nm_connection_verify (connection, &error) == TRUE,
 	        test_name, "failed to verify connection: %s",
@@ -9277,7 +9333,10 @@ test_write_wifi_wpa_psk_adhoc (void)
 	        NM_SETTING_IP6_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
 
-	g_object_set (s_ip6, NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE, NULL);
+	g_object_set (s_ip6,
+	              NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE,
+	              NM_SETTING_IP6_CONFIG_MAY_FAIL, TRUE,
+	              NULL);
 
 	ASSERT (nm_connection_verify (connection, &error) == TRUE,
 	        "wifi-wpa-psk-adhoc-write", "failed to verify connection: %s",
@@ -9458,7 +9517,10 @@ test_write_wifi_wpa_eap_tls (void)
 	        NM_SETTING_IP6_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
 
-	g_object_set (s_ip6, NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE, NULL);
+	g_object_set (s_ip6,
+	              NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE,
+	              NM_SETTING_IP6_CONFIG_MAY_FAIL, TRUE,
+	              NULL);
 
 	ASSERT (nm_connection_verify (connection, &error) == TRUE,
 	        "wifi-wpa-eap-tls-write", "failed to verify connection: %s",
@@ -9657,7 +9719,10 @@ test_write_wifi_wpa_eap_ttls_tls (void)
 	        NM_SETTING_IP6_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
 
-	g_object_set (s_ip6, NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE, NULL);
+	g_object_set (s_ip6,
+	              NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE,
+	              NM_SETTING_IP6_CONFIG_MAY_FAIL, TRUE,
+	              NULL);
 
 	ASSERT (nm_connection_verify (connection, &error) == TRUE,
 	        "wifi-wpa-eap-ttls-tls-write", "failed to verify connection: %s",
@@ -9828,7 +9893,10 @@ test_write_wifi_wpa_eap_ttls_mschapv2 (void)
 	        NM_SETTING_IP6_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
 
-	g_object_set (s_ip6, NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE, NULL);
+	g_object_set (s_ip6,
+	              NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE,
+	              NM_SETTING_IP6_CONFIG_MAY_FAIL, TRUE,
+	              NULL);
 
 	ASSERT (nm_connection_verify (connection, &error) == TRUE,
 	        "wifi-wpa-eap-ttls-mschapv2-write", "failed to verify connection: %s",
@@ -9970,7 +10038,10 @@ test_write_wifi_wpa_then_open (void)
 	g_assert (s_ip6);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
 
-	g_object_set (s_ip6, NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE, NULL);
+	g_object_set (s_ip6,
+	              NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE,
+	              NM_SETTING_IP6_CONFIG_MAY_FAIL, TRUE,
+	              NULL);
 
 	success = nm_connection_verify (connection, &error);
 	g_assert_no_error (error);
@@ -10154,9 +10225,13 @@ test_write_wifi_dynamic_wep_leap (void)
 	/* IP6 setting */
 	s_ip6 = (NMSettingIP6Config *) nm_setting_ip6_config_new ();
 	g_assert (s_ip6);
-	g_object_set (s_ip6, NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE, NULL);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
 
+	g_object_set (s_ip6,
+	              NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE,
+	              NM_SETTING_IP6_CONFIG_MAY_FAIL, TRUE,
+	              NULL);
+
 	success = nm_connection_verify (connection, &error);
 	g_assert_no_error (error);
 	g_assert (success);
@@ -10688,6 +10763,7 @@ test_write_wired_qeth_dhcp (void)
 
 	g_object_set (s_ip6,
 	              NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE,
+	              NM_SETTING_IP6_CONFIG_MAY_FAIL, TRUE,
 	              NULL);
 
 	/* Verify */
@@ -10804,7 +10880,11 @@ test_write_wired_ctc_dhcp (void)
 	s_ip6 = (NMSettingIP6Config *) nm_setting_ip6_config_new ();
 	g_assert (s_ip6);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
-	g_object_set (s_ip6, NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE, NULL);
+
+	g_object_set (s_ip6,
+	              NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE,
+	              NM_SETTING_IP6_CONFIG_MAY_FAIL, TRUE,
+	              NULL);
 
 	/* Verify */
 	success = nm_connection_verify (connection, &error);
@@ -10939,6 +11019,7 @@ test_write_permissions (void)
 
 	g_object_set (s_ip6,
 	              NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE,
+	              NM_SETTING_IP6_CONFIG_MAY_FAIL, TRUE,
 	              NULL);
 
 	/* Verify */
@@ -11040,7 +11121,11 @@ test_write_wifi_wep_agent_keys (void)
 	s_ip6 = (NMSettingIP6Config *) nm_setting_ip6_config_new ();
 	g_assert (s_ip6);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
-	g_object_set (s_ip6, NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE, NULL);
+
+	g_object_set (s_ip6,
+	              NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE,
+	              NM_SETTING_IP6_CONFIG_MAY_FAIL, TRUE,
+	              NULL);
 
 	/* Wifi setting */
 	s_wifi = (NMSettingWireless *) nm_setting_wireless_new ();
diff --git a/src/settings/plugins/ifcfg-rh/writer.c b/src/settings/plugins/ifcfg-rh/writer.c
index 6b66b232..192226ac 100644
--- a/src/settings/plugins/ifcfg-rh/writer.c
+++ b/src/settings/plugins/ifcfg-rh/writer.c
@@ -758,6 +758,7 @@ write_wireless_setting (NMConnection *connection,
 	char buf[33];
 	guint32 mtu, chan, i;
 	gboolean adhoc = FALSE, hex_ssid = FALSE;
+	const GSList *macaddr_blacklist;
 
 	s_wireless = (NMSettingWireless *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS);
 	if (!s_wireless) {
@@ -786,6 +787,23 @@ write_wireless_setting (NMConnection *connection,
 		g_free (tmp);
 	}
 
+	svSetValue (ifcfg, "HWADDR_BLACKLIST", NULL, FALSE);
+	macaddr_blacklist = nm_setting_wireless_get_mac_address_blacklist (s_wireless);
+	if (macaddr_blacklist) {
+		const GSList *iter;
+		GString *blacklist_str = g_string_new (NULL);
+
+		for (iter = macaddr_blacklist; iter; iter = g_slist_next (iter)) {
+			g_string_append (blacklist_str, iter->data);
+			g_string_append_c (blacklist_str, ' ');
+
+		}
+		if (blacklist_str->len > 0)
+			g_string_truncate (blacklist_str, blacklist_str->len - 1);
+		svSetValue (ifcfg, "HWADDR_BLACKLIST", blacklist_str->str, FALSE);
+		g_string_free (blacklist_str, TRUE);
+	}
+
 	svSetValue (ifcfg, "MTU", NULL, FALSE);
 	mtu = nm_setting_wireless_get_mtu (s_wireless);
 	if (mtu) {
@@ -934,6 +952,7 @@ write_wired_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
 	guint32 mtu, num_opts, i;
 	const GPtrArray *s390_subchannels;
 	GString *str;
+	const GSList *macaddr_blacklist;
 
 	s_wired = (NMSettingWired *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRED);
 	if (!s_wired) {
@@ -961,6 +980,23 @@ write_wired_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
 		g_free (tmp);
 	}
 
+	svSetValue (ifcfg, "HWADDR_BLACKLIST", NULL, FALSE);
+	macaddr_blacklist = nm_setting_wired_get_mac_address_blacklist (s_wired);
+	if (macaddr_blacklist) {
+		const GSList *iter;
+		GString *blacklist_str = g_string_new (NULL);
+
+		for (iter = macaddr_blacklist; iter; iter = g_slist_next (iter)) {
+			g_string_append (blacklist_str, iter->data);
+			g_string_append_c (blacklist_str, ' ');
+
+		}
+		if (blacklist_str->len > 0)
+			g_string_truncate (blacklist_str, blacklist_str->len - 1);
+		svSetValue (ifcfg, "HWADDR_BLACKLIST", blacklist_str->str, FALSE);
+		g_string_free (blacklist_str, TRUE);
+	}
+
 	svSetValue (ifcfg, "MTU", NULL, FALSE);
 	mtu = nm_setting_wired_get_mtu (s_wired);
 	if (mtu) {
@@ -1316,13 +1352,14 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
 	if (utils_has_route_file_new_syntax (route_path)) {
 		shvarFile *routefile;
 
-		g_free (route_path);
 		routefile = utils_get_route_ifcfg (ifcfg->fileName, TRUE);
 		if (!routefile) {
 			g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
-			             "Could not create route file '%s'", routefile->fileName);
+			             "Could not create route file '%s'", route_path);
+			g_free (route_path);
 			goto out;
 		}
+		g_free (route_path);
 
 		num = nm_setting_ip4_config_get_num_routes (s_ip4);
 		for (i = 0; i < 256; i++) {
diff --git a/src/settings/plugins/ifnet/plugin.c b/src/settings/plugins/ifnet/plugin.c
index 69b7bc80..59083688 100644
--- a/src/settings/plugins/ifnet/plugin.c
+++ b/src/settings/plugins/ifnet/plugin.c
@@ -278,7 +278,8 @@ reload_connections (gpointer config)
 			if (auto_refresh && is_true (auto_refresh)) {
 				if (!nm_connection_compare (NM_CONNECTION (old),
 				                            NM_CONNECTION (new),
-				                            NM_SETTING_COMPARE_FLAG_EXACT)) {
+				                            NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS |
+				                              NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS)) {
 					PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Auto refreshing %s", conn_name);
 
 					/* Remove and re-add to disconnect and reconnect with new settings */
diff --git a/src/settings/plugins/keyfile/common.h b/src/settings/plugins/keyfile/common.h
index 6c8f9ceb..7d94a705 100644
--- a/src/settings/plugins/keyfile/common.h
+++ b/src/settings/plugins/keyfile/common.h
@@ -23,9 +23,6 @@
 
 #include <glib.h>
 
-#define SWP_TAG ".swp"
-#define SWPX_TAG ".swpx"
-
 #define KEYFILE_PLUGIN_NAME "keyfile"
 #define KEYFILE_PLUGIN_INFO "(c) 2007 - 2010 Red Hat, Inc.  To report bugs please use the NetworkManager mailing list."
 
diff --git a/src/settings/plugins/keyfile/plugin.c b/src/settings/plugins/keyfile/plugin.c
index ffc614bc..af69c200 100644
--- a/src/settings/plugins/keyfile/plugin.c
+++ b/src/settings/plugins/keyfile/plugin.c
@@ -231,7 +231,8 @@ dir_changed (GFileMonitor *monitor,
 			if (tmp) {
 				if (!nm_connection_compare (NM_CONNECTION (connection),
 				                            NM_CONNECTION (tmp),
-				                            NM_SETTING_COMPARE_FLAG_EXACT)) {
+				                            NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS |
+				                              NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS)) {
 					PLUGIN_PRINT (KEYFILE_PLUGIN_NAME, "updating %s", full_path);
 					update_connection_settings (connection, tmp);
 				}
diff --git a/src/settings/plugins/keyfile/reader.c b/src/settings/plugins/keyfile/reader.c
index a8eaaa8e..c4136e05 100644
--- a/src/settings/plugins/keyfile/reader.c
+++ b/src/settings/plugins/keyfile/reader.c
@@ -16,7 +16,7 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
  * Copyright (C) 2008 - 2009 Novell, Inc.
- * Copyright (C) 2008 - 2010 Red Hat, Inc.
+ * Copyright (C) 2008 - 2011 Red Hat, Inc.
  */
 
 #include <errno.h>
@@ -40,6 +40,7 @@
 #include <ctype.h>
 
 #include "nm-dbus-glib-types.h"
+#include "nm-system-config-interface.h"
 #include "reader.h"
 #include "common.h"
 
@@ -735,29 +736,27 @@ get_uchar_array (GKeyFile *keyfile,
                  const char *key)
 {
 	GByteArray *array = NULL;
-	char *p, *tmp_string;
+	char *tmp_string;
 	gint *tmp_list;
 	gsize length;
 	int i;
 
-	/* New format: just a string.  We try parsing the new format if there are
-	 * no ';' in the string or it's not just numbers.
+	/* New format: just a string
+	 * Old format: integer list; e.g. 11;25;38
 	 */
-	p = tmp_string = g_key_file_get_string (keyfile, setting_name, key, NULL);
+	tmp_string = g_key_file_get_string (keyfile, setting_name, key, NULL);
 	if (tmp_string) {
 		gboolean new_format = FALSE;
+		GRegex *regex;
+		GMatchInfo *match_info;
+		const char *pattern = "^[[:space:]]*[[:digit:]]{1,3}[[:space:]]*(;[[:space:]]*[[:digit:]]{1,3}[[:space:]]*)*(;[[:space:]]*)?$";
 
-		if (strchr (p, ';') == NULL)
-			new_format = TRUE;
-		else {
+		regex = g_regex_new (pattern, 0, 0, NULL);
+		g_regex_match (regex, tmp_string, 0, &match_info);
+		if (!g_match_info_matches (match_info))
 			new_format = TRUE;
-			while (p && *p) {
-				if (!isdigit (*p++)) {
-					new_format = FALSE;
-					break;
-				}
-			}
-		}
+		g_match_info_free (match_info);
+		g_regex_unref (regex);
 
 		if (new_format) {
 			array = g_byte_array_sized_new (strlen (tmp_string));
@@ -835,6 +834,24 @@ get_cert_path (const char *keyfile_path, GByteArray *cert_path)
 
 #define SCHEME_PATH "file://"
 
+static const char *certext[] = { ".pem", ".cert", ".crt", ".cer", ".p12", ".der", ".key" };
+
+static gboolean
+has_cert_ext (GByteArray *array)
+{
+	int i;
+
+	for (i = 0; i < G_N_ELEMENTS (certext); i++) {
+		guint32 extlen = strlen (certext[i]);
+
+		if (array->len <= extlen)
+			continue;
+		if (memcmp (&array->data[array->len - extlen], certext[i], extlen) == 0)
+			return TRUE;
+	}
+	return FALSE;
+}
+
 static void
 cert_parser (NMSetting *setting, const char *key, GKeyFile *keyfile, const char *keyfile_path)
 {
@@ -859,17 +876,31 @@ cert_parser (NMSetting *setting, const char *key, GKeyFile *keyfile, const char
 		           && g_utf8_validate ((const char *) array->data, array->len, NULL)) {
 			GByteArray *val;
 			char *path;
+			gboolean exists;
+
+			/* Might be a bare path without the file:// prefix; in that case
+			 * if it's an absolute path, use that, otherwise treat it as a
+			 * relative path to the current directory.
+			 */
 
 			path = get_cert_path (keyfile_path, array);
-			if (g_file_test (path, G_FILE_TEST_EXISTS)) {
+			exists = g_file_test (path, G_FILE_TEST_EXISTS);
+			if (   exists
+			    || memchr (array->data, '/', array->len)
+			    || has_cert_ext (array)) {
 				/* Construct the proper value as required for the PATH scheme */
 				val = g_byte_array_sized_new (strlen (SCHEME_PATH) + array->len + 1);
 				g_byte_array_append (val, (const guint8 *) SCHEME_PATH, strlen (SCHEME_PATH));
-				g_byte_array_append (val, array->data, array->len);
+				g_byte_array_append (val, (const guint8 *) path, strlen (path));
 				g_byte_array_append (val, (const guint8 *) "\0", 1);
 				g_object_set (setting, key, val, NULL);
 				g_byte_array_free (val, TRUE);
 				success = TRUE;
+
+				/* Warn if the certificate didn't exist */
+				if (exists == FALSE) {
+					PLUGIN_WARN (KEYFILE_PLUGIN_NAME, "   certificate or key %s does not exist", path);
+				}
 			}
 			g_free (path);
 		}
@@ -881,7 +912,7 @@ cert_parser (NMSetting *setting, const char *key, GKeyFile *keyfile, const char
 
 		g_byte_array_free (array, TRUE);
 	} else {
-		g_warning ("%s: ignoring invalid SSID for %s / %s",
+		g_warning ("%s: ignoring invalid key/cert value for %s / %s",
 		           __func__, setting_name, key);
 	}
 }
diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Makefile.am b/src/settings/plugins/keyfile/tests/keyfiles/Makefile.am
index 0ce03209..302db866 100644
--- a/src/settings/plugins/keyfile/tests/keyfiles/Makefile.am
+++ b/src/settings/plugins/keyfile/tests/keyfiles/Makefile.am
@@ -7,8 +7,11 @@ KEYFILES = \
 	ATT_Data_Connect_BT \
 	ATT_Data_Connect_Plain \
 	Test_String_SSID \
+	Test_Intlist_SSID \
 	Test_Wired_TLS_Old \
-	Test_Wired_TLS_New
+	Test_Wired_TLS_New \
+	Test_Wired_TLS_Blob \
+	Test_Wired_TLS_Path_Missing
 
 CERTS = \
 	test-ca-cert.pem \
diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Makefile.in b/src/settings/plugins/keyfile/tests/keyfiles/Makefile.in
index 2c3c1630..083615b0 100644
--- a/src/settings/plugins/keyfile/tests/keyfiles/Makefile.in
+++ b/src/settings/plugins/keyfile/tests/keyfiles/Makefile.in
@@ -277,8 +277,11 @@ KEYFILES = \
 	ATT_Data_Connect_BT \
 	ATT_Data_Connect_Plain \
 	Test_String_SSID \
+	Test_Intlist_SSID \
 	Test_Wired_TLS_Old \
-	Test_Wired_TLS_New
+	Test_Wired_TLS_New \
+	Test_Wired_TLS_Blob \
+	Test_Wired_TLS_Path_Missing
 
 CERTS = \
 	test-ca-cert.pem \
diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_Intlist_SSID b/src/settings/plugins/keyfile/tests/keyfiles/Test_Intlist_SSID
new file mode 100644
index 00000000..6d2bc0fa
--- /dev/null
+++ b/src/settings/plugins/keyfile/tests/keyfiles/Test_Intlist_SSID
@@ -0,0 +1,11 @@
+[connection]
+id=Test 
+uuid=2f962388-e5f3-45af-a62c-ac220b8f7baa
+type=802-11-wireless
+
+[802-11-wireless]
+ssid=98;108;97;104;49;50;51;52;
+
+[ipv4]
+method=auto
+
diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_Wired_TLS_Blob b/src/settings/plugins/keyfile/tests/keyfiles/Test_Wired_TLS_Blob
new file mode 100644
index 00000000..9f4ef62f
--- /dev/null
+++ b/src/settings/plugins/keyfile/tests/keyfiles/Test_Wired_TLS_Blob
@@ -0,0 +1,22 @@
+
+[connection]
+id=Wired TLS
+uuid=5ee46013-9469-4c6a-a60a-0c7a1e1c7488
+type=802-3-ethernet
+
+[802-1x]
+eap=tls;
+identity=Bill Smith
+ca-cert=48;130;2;52;48;130;1;161;2;16;2;173;102;126;78;69;254;94;87;111;60;152;25;94;221;192;48;13;6;9;42;134;72;134;247;13;1;1;2;5;0;48;95;49;11;48;9;6;3;85;4;6;19;2;85;83;49;32;48;30;6;3;85;4;10;19;23;82;83;65;32;68;97;116;97;32;83;101;99;117;114;105;116;121;44;32;73;110;99;46;49;46;48;44;6;3;85;4;11;19;37;83;101;99;117;114;101;32;83;101;114;118;101;114;32;67;101;114;116;105;102;105;99;97;116;105;111;110;32;65;117;116;104;111;114;105;116;121;48;30;23;13;57;52;49;49;48;57;48;48;48;48;48;48;90;23;13;49;48;48;49;48;55;50;51;53;57;53;57;90;48;95;49;11;48;9;6;3;85;4;6;19;2;85;83;49;32;48;30;6;3;85;4;10;19;23;82;83;65;32;68;97;116;97;32;83;101;99;117;114;105;116;121;44;32;73;110;99;46;49;46;48;44;6;3;85;4;11;19;37;83;101;99;117;114;101;32;83;101;114;118;101;114;32;67;101;114;116;105;102;105;99;97;116;105;111;110;32;65;117;116;104;111;114;105;116;121;48;129;155;48;13;6;9;42;134;72;134;247;13;1;1;1;5;0;3;129;137;0;48;129;133;2;126;0;146;206;122;193;174;131;62;90;170;137;131;87;172;37;1;118;12;173;174;142;44;55;206;235;53;120;100;84;3;229;132;64;81;201;191;143;8;226;138;130;8;210;22;134;55;85;233;177;33;2;173;118;104;129;154;5;162;75;201;75;37;102;34;86;108;136;7;143;247;129;89;109;132;7;101;112;19;113;118;62;155;119;76;227;80;137;86;152;72;185;29;167;41;26;19;46;74;17;89;156;30;21;213;73;84;44;115;58;105;130;177;151;57;156;109;112;103;72;229;221;45;214;200;30;123;2;3;1;0;1;48;13;6;9;42;134;72;134;247;13;1;1;2;5;0;3;126;0;101;221;126;225;178;236;176;226;58;224;236;113;70;154;25;17;184;211;199;160;180;3;64;38;2;62;9;156;225;18;179;209;90;246;55;165;183;97;3;182;91;22;105;59;198;68;8;12;136;83;12;107;151;73;199;62;53;220;108;185;187;170;223;92;187;58;47;147;96;182;169;75;77;242;32;247;205;95;127;100;123;142;220;0;92;215;250;119;202;57;22;89;111;14;234;211;181;131;127;77;77;66;86;118;180;201;95;4;248;56;248;235;210;95;117;95;205;123;252;229;142;128;124;252;80;
+client-cert=102;105;108;101;58;47;47;47;104;111;109;101;47;100;99;98;119;47;68;101;115;107;116;111;112;47;99;101;114;116;105;110;102;114;97;47;99;108;105;101;110;116;46;112;101;109;0;
+private-key=102;105;108;101;58;47;47;47;104;111;109;101;47;100;99;98;119;47;68;101;115;107;116;111;112;47;99;101;114;116;105;110;102;114;97;47;99;108;105;101;110;116;46;112;101;109;0;
+private-key-password=12345testing
+
+[ipv4]
+method=auto
+
+[802-3-ethernet]
+duplex=full
+
+[ipv6]
+method=ignore
diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_Wired_TLS_Path_Missing b/src/settings/plugins/keyfile/tests/keyfiles/Test_Wired_TLS_Path_Missing
new file mode 100644
index 00000000..2b39538e
--- /dev/null
+++ b/src/settings/plugins/keyfile/tests/keyfiles/Test_Wired_TLS_Path_Missing
@@ -0,0 +1,22 @@
+
+[connection]
+id=Wired TLS
+uuid=5ee46013-9469-4c6a-a60a-0c7a1e1c7488
+type=802-3-ethernet
+
+[802-1x]
+eap=tls;
+identity=Bill Smith
+ca-cert=/some/random/cert/path.pem
+client-cert=test-key-and-cert.pem
+private-key=test-key-and-cert.pem
+private-key-password=12345testing
+
+[ipv4]
+method=auto
+
+[802-3-ethernet]
+duplex=full
+
+[ipv6]
+method=ignore
diff --git a/src/settings/plugins/keyfile/tests/test-keyfile.c b/src/settings/plugins/keyfile/tests/test-keyfile.c
index bfe5aa43..3bbaaaec 100644
--- a/src/settings/plugins/keyfile/tests/test-keyfile.c
+++ b/src/settings/plugins/keyfile/tests/test-keyfile.c
@@ -1438,6 +1438,131 @@ test_write_string_ssid (void)
 	g_object_unref (connection);
 }
 
+#define TEST_INTLIST_SSID_FILE TEST_KEYFILES_DIR"/Test_Intlist_SSID"
+
+static void
+test_read_intlist_ssid (void)
+{
+	NMConnection *connection;
+	NMSettingWireless *s_wifi;
+	GError *error = NULL;
+	gboolean success;
+	const GByteArray *array;
+	const char *expected_ssid = "blah1234";
+
+	connection = nm_keyfile_plugin_connection_from_file (TEST_INTLIST_SSID_FILE, &error);
+	g_assert_no_error (error);
+	g_assert (connection);
+
+	success = nm_connection_verify (connection, &error);
+	g_assert_no_error (error);
+	g_assert (success);
+
+	/* SSID */
+	s_wifi = nm_connection_get_setting_wireless (connection);
+	g_assert (s_wifi);
+
+	array = nm_setting_wireless_get_ssid (s_wifi);
+	g_assert (array != NULL);
+	g_assert_cmpint (array->len, ==, strlen (expected_ssid));
+	g_assert_cmpint (memcmp (array->data, expected_ssid, strlen (expected_ssid)), ==, 0);
+
+	g_object_unref (connection);
+}
+
+static void
+test_write_intlist_ssid (void)
+{
+	NMConnection *connection;
+	NMSettingConnection *s_con;
+	NMSettingWireless *s_wifi;
+	NMSettingIP4Config *s_ip4;
+	char *uuid, *testfile = NULL;
+	GByteArray *ssid;
+	unsigned char tmpssid[] = { 65, 49, 50, 51, 0, 50, 50 };
+	gboolean success;
+	NMConnection *reread;
+	GError *error = NULL;
+	pid_t owner_grp;
+	uid_t owner_uid;
+	GKeyFile *keyfile;
+	gint *intlist;
+	gsize len = 0, i;
+
+	connection = nm_connection_new ();
+	g_assert (connection);
+
+	/* Connection setting */
+
+	s_con = NM_SETTING_CONNECTION (nm_setting_connection_new ());
+	g_assert (s_con);
+	nm_connection_add_setting (connection, NM_SETTING (s_con));
+
+	uuid = nm_utils_uuid_generate ();
+	g_object_set (s_con,
+	              NM_SETTING_CONNECTION_ID, "Intlist SSID Test",
+	              NM_SETTING_CONNECTION_UUID, uuid,
+	              NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME,
+	              NULL);
+	g_free (uuid);
+
+	/* Wireless setting */
+	s_wifi = NM_SETTING_WIRELESS (nm_setting_wireless_new ());
+	g_assert (s_wifi);
+	nm_connection_add_setting (connection, NM_SETTING (s_wifi));
+
+	ssid = g_byte_array_sized_new (sizeof (tmpssid));
+	g_byte_array_append (ssid, &tmpssid[0], sizeof (tmpssid));
+	g_object_set (s_wifi, NM_SETTING_WIRELESS_SSID, ssid, NULL);
+	g_byte_array_free (ssid, TRUE);
+
+	/* IP4 setting */
+	s_ip4 = NM_SETTING_IP4_CONFIG (nm_setting_ip4_config_new ());
+	g_assert (s_ip4);
+	nm_connection_add_setting (connection, NM_SETTING (s_ip4));
+	g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL);
+
+	/* Write out the connection */
+	owner_uid = geteuid ();
+	owner_grp = getegid ();
+	success = nm_keyfile_plugin_write_test_connection (connection, TEST_SCRATCH_DIR, owner_uid, owner_grp, &testfile, &error);
+	g_assert_no_error (error);
+	g_assert (success);
+	g_assert (testfile != NULL);
+
+	/* Ensure the SSID was written out as an int list */
+	keyfile = g_key_file_new ();
+	success = g_key_file_load_from_file (keyfile, testfile, 0, &error);
+	g_assert_no_error (error);
+	g_assert (success);
+
+	intlist = g_key_file_get_integer_list (keyfile, NM_SETTING_WIRELESS_SETTING_NAME, NM_SETTING_WIRELESS_SSID, &len, &error);
+	g_assert_no_error (error);
+	g_assert (intlist);
+	g_assert_cmpint (len, ==, sizeof (tmpssid));
+
+	for (i = 0; i < len; i++)
+		g_assert_cmpint (intlist[i], ==, tmpssid[i]);
+	g_free (intlist);
+
+	g_key_file_free (keyfile);
+
+	/* Read the connection back in and compare it to the one we just wrote out */
+	reread = nm_keyfile_plugin_connection_from_file (testfile, &error);
+	g_assert_no_error (error);
+	g_assert (reread);
+
+	success = nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT);
+	g_assert (success);
+
+	g_clear_error (&error);
+	unlink (testfile);
+	g_free (testfile);
+
+	g_object_unref (reread);
+	g_object_unref (connection);
+}
+
 #define TEST_BT_DUN_FILE TEST_KEYFILES_DIR"/ATT_Data_Connect_BT"
 
 static void
@@ -1953,6 +2078,133 @@ test_write_gsm_connection (void)
 	g_object_unref (connection);
 }
 
+#define TEST_WIRED_TLS_BLOB_FILE TEST_KEYFILES_DIR"/Test_Wired_TLS_Blob"
+
+static void
+test_read_wired_8021x_tls_blob_connection (void)
+{
+	NMConnection *connection;
+	NMSetting *s_wired;
+	NMSetting8021x *s_8021x;
+	GError *error = NULL;
+	const char *tmp;
+	gboolean success;
+	const GByteArray *array;
+
+	connection = nm_keyfile_plugin_connection_from_file (TEST_WIRED_TLS_BLOB_FILE, &error);
+	if (connection == NULL) {
+		g_assert (error);
+		g_warning ("Failed to read %s: %s", TEST_WIRED_TLS_BLOB_FILE, error->message);
+		g_assert (connection);
+	}
+
+	success = nm_connection_verify (connection, &error);
+	if (!success) {
+		g_assert (error);
+		g_warning ("Failed to verify %s: %s", TEST_WIRED_TLS_BLOB_FILE, error->message);
+		g_assert (success);
+	}
+
+	/* ===== Wired Setting ===== */
+	s_wired = nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRED);
+	g_assert (s_wired != NULL);
+
+	/* ===== 802.1x Setting ===== */
+	s_8021x = (NMSetting8021x *) nm_connection_get_setting (connection, NM_TYPE_SETTING_802_1X);
+	g_assert (s_8021x != NULL);
+
+	g_assert (nm_setting_802_1x_get_num_eap_methods (s_8021x) == 1);
+	tmp = nm_setting_802_1x_get_eap_method (s_8021x, 0);
+	g_assert (g_strcmp0 (tmp, "tls") == 0);
+
+	tmp = nm_setting_802_1x_get_identity (s_8021x);
+	g_assert (g_strcmp0 (tmp, "Bill Smith") == 0);
+
+	tmp = nm_setting_802_1x_get_private_key_password (s_8021x);
+	g_assert (g_strcmp0 (tmp, "12345testing") == 0);
+
+	g_assert_cmpint (nm_setting_802_1x_get_ca_cert_scheme (s_8021x), ==, NM_SETTING_802_1X_CK_SCHEME_BLOB);
+
+	/* Make sure it's not a path, since it's a blob */
+	tmp = nm_setting_802_1x_get_ca_cert_path (s_8021x);
+	g_assert (tmp == NULL);
+
+	/* Validate the path */
+	array = nm_setting_802_1x_get_ca_cert_blob (s_8021x);
+	g_assert (array != NULL);
+	g_assert_cmpint (array->len, ==, 568);
+
+	tmp = nm_setting_802_1x_get_client_cert_path (s_8021x);
+	g_assert_cmpstr (tmp, ==, "/home/dcbw/Desktop/certinfra/client.pem");
+
+	tmp = nm_setting_802_1x_get_private_key_path (s_8021x);
+	g_assert_cmpstr (tmp, ==, "/home/dcbw/Desktop/certinfra/client.pem");
+
+	g_object_unref (connection);
+}
+
+#define TEST_WIRED_TLS_PATH_MISSING_FILE TEST_KEYFILES_DIR"/Test_Wired_TLS_Path_Missing"
+
+static void
+test_read_wired_8021x_tls_bad_path_connection (void)
+{
+	NMConnection *connection;
+	NMSetting *s_wired;
+	NMSetting8021x *s_8021x;
+	GError *error = NULL;
+	const char *tmp;
+	char *tmp2;
+	gboolean success;
+
+	connection = nm_keyfile_plugin_connection_from_file (TEST_WIRED_TLS_PATH_MISSING_FILE, &error);
+	if (connection == NULL) {
+		g_assert (error);
+		g_warning ("Failed to read %s: %s", TEST_WIRED_TLS_PATH_MISSING_FILE, error->message);
+		g_assert (connection);
+	}
+
+	success = nm_connection_verify (connection, &error);
+	if (!success) {
+		g_assert (error);
+		g_warning ("Failed to verify %s: %s", TEST_WIRED_TLS_BLOB_FILE, error->message);
+		g_assert (success);
+	}
+
+	/* ===== Wired Setting ===== */
+	s_wired = nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRED);
+	g_assert (s_wired != NULL);
+
+	/* ===== 802.1x Setting ===== */
+	s_8021x = (NMSetting8021x *) nm_connection_get_setting (connection, NM_TYPE_SETTING_802_1X);
+	g_assert (s_8021x != NULL);
+
+	g_assert (nm_setting_802_1x_get_num_eap_methods (s_8021x) == 1);
+	tmp = nm_setting_802_1x_get_eap_method (s_8021x, 0);
+	g_assert (g_strcmp0 (tmp, "tls") == 0);
+
+	tmp = nm_setting_802_1x_get_identity (s_8021x);
+	g_assert (g_strcmp0 (tmp, "Bill Smith") == 0);
+
+	tmp = nm_setting_802_1x_get_private_key_password (s_8021x);
+	g_assert (g_strcmp0 (tmp, "12345testing") == 0);
+
+	g_assert_cmpint (nm_setting_802_1x_get_ca_cert_scheme (s_8021x), ==, NM_SETTING_802_1X_CK_SCHEME_PATH);
+
+	tmp = nm_setting_802_1x_get_ca_cert_path (s_8021x);
+	g_assert_cmpstr (tmp, ==, "/some/random/cert/path.pem");
+
+	tmp2 = g_strdup_printf (TEST_KEYFILES_DIR "/test-key-and-cert.pem");
+
+	tmp = nm_setting_802_1x_get_client_cert_path (s_8021x);
+	g_assert_cmpstr (tmp, ==, tmp2);
+
+	tmp = nm_setting_802_1x_get_private_key_path (s_8021x);
+	g_assert_cmpstr (tmp, ==, tmp2);
+
+	g_free (tmp2);
+	g_object_unref (connection);
+}
+
 #define TEST_WIRED_TLS_OLD_FILE TEST_KEYFILES_DIR"/Test_Wired_TLS_Old"
 
 static void
@@ -2019,6 +2271,7 @@ test_read_wired_8021x_tls_new_connection (void)
 	NMSetting8021x *s_8021x;
 	GError *error = NULL;
 	const char *tmp;
+	char *tmp2;
 	gboolean success;
 
 	connection = nm_keyfile_plugin_connection_from_file (TEST_WIRED_TLS_NEW_FILE, &error);
@@ -2053,15 +2306,20 @@ test_read_wired_8021x_tls_new_connection (void)
 	tmp = nm_setting_802_1x_get_private_key_password (s_8021x);
 	g_assert (g_strcmp0 (tmp, "12345testing") == 0);
 
+	tmp2 = g_strdup_printf (TEST_KEYFILES_DIR "/test-ca-cert.pem");
 	tmp = nm_setting_802_1x_get_ca_cert_path (s_8021x);
-	g_assert (g_strcmp0 (tmp, "test-ca-cert.pem") == 0);
+	g_assert_cmpstr (tmp, ==, tmp2);
+	g_free (tmp2);
+
+	tmp2 = g_strdup_printf (TEST_KEYFILES_DIR "/test-key-and-cert.pem");
 
 	tmp = nm_setting_802_1x_get_client_cert_path (s_8021x);
-	g_assert (g_strcmp0 (tmp, "test-key-and-cert.pem") == 0);
+	g_assert_cmpstr (tmp, ==, tmp2);
 
 	tmp = nm_setting_802_1x_get_private_key_path (s_8021x);
-	g_assert (g_strcmp0 (tmp, "test-key-and-cert.pem") == 0);
+	g_assert_cmpstr (tmp, ==, tmp2);
 
+	g_free (tmp2);
 	g_object_unref (connection);
 }
 
@@ -2153,16 +2411,23 @@ create_wired_tls_connection (NMSetting8021xCKScheme scheme)
 	return connection;
 }
 
+static char *
+get_path (const char *file, gboolean relative)
+{
+	return relative ? g_path_get_basename (file) : g_strdup (file);
+}
+
 static void
 test_write_wired_8021x_tls_connection_path (void)
 {
 	NMConnection *connection;
-	char *tmp;
+	char *tmp, *tmp2;
 	gboolean success;
 	NMConnection *reread;
 	char *testfile = NULL;
 	GError *error = NULL;
 	GKeyFile *keyfile;
+	gboolean relative = FALSE;
 
 	connection = create_wired_tls_connection (NM_SETTING_802_1X_CK_SCHEME_PATH);
 	g_assert (connection != NULL);
@@ -2200,12 +2465,22 @@ test_write_wired_8021x_tls_connection_path (void)
 		g_assert (success);
 	}
 
+	/* Depending on whether this test is being run from 'make check' or
+	 * 'make distcheck' we might be using relative paths (check) or
+	 * absolute ones (distcheck).
+	 */
+	tmp2 = g_path_get_dirname (testfile);
+	if (g_strcmp0 (tmp2, TEST_KEYFILES_DIR) == 0)
+		relative = TRUE;
+
 	/* CA cert */
 	tmp = g_key_file_get_string (keyfile,
 	                             NM_SETTING_802_1X_SETTING_NAME,
 	                             NM_SETTING_802_1X_CA_CERT,
 	                             NULL);
-	g_assert (g_strcmp0 (tmp, TEST_WIRED_TLS_CA_CERT) == 0);
+	tmp2 = get_path (TEST_WIRED_TLS_CA_CERT, relative);
+	g_assert_cmpstr (tmp, ==, tmp2);
+	g_free (tmp2);
 	g_free (tmp);
 
 	/* Client cert */
@@ -2213,7 +2488,9 @@ test_write_wired_8021x_tls_connection_path (void)
 	                             NM_SETTING_802_1X_SETTING_NAME,
 	                             NM_SETTING_802_1X_CLIENT_CERT,
 	                             NULL);
-	g_assert (g_strcmp0 (tmp, TEST_WIRED_TLS_CLIENT_CERT) == 0);
+	tmp2 = get_path (TEST_WIRED_TLS_CLIENT_CERT, relative);
+	g_assert_cmpstr (tmp, ==, tmp2);
+	g_free (tmp2);
 	g_free (tmp);
 
 	/* Private key */
@@ -2221,7 +2498,9 @@ test_write_wired_8021x_tls_connection_path (void)
 	                             NM_SETTING_802_1X_SETTING_NAME,
 	                             NM_SETTING_802_1X_PRIVATE_KEY,
 	                             NULL);
-	g_assert (g_strcmp0 (tmp, TEST_WIRED_TLS_PRIVKEY) == 0);
+	tmp2 = get_path (TEST_WIRED_TLS_PRIVKEY, relative);
+	g_assert_cmpstr (tmp, ==, tmp2);
+	g_free (tmp2);
 	g_free (tmp);
 
 	g_key_file_free (keyfile);
@@ -2334,12 +2613,18 @@ int main (int argc, char **argv)
 	test_read_string_ssid ();
 	test_write_string_ssid ();
 
+	test_read_intlist_ssid ();
+	test_write_intlist_ssid ();
+
 	test_read_bt_dun_connection ();
 	test_write_bt_dun_connection ();
 
 	test_read_gsm_connection ();
 	test_write_gsm_connection ();
 
+	test_read_wired_8021x_tls_blob_connection ();
+	test_read_wired_8021x_tls_bad_path_connection ();
+
 	test_read_wired_8021x_tls_old_connection ();
 	test_read_wired_8021x_tls_new_connection ();
 	test_write_wired_8021x_tls_connection_path ();
diff --git a/src/settings/plugins/keyfile/utils.c b/src/settings/plugins/keyfile/utils.c
index 7b93a245..f3531172 100644
--- a/src/settings/plugins/keyfile/utils.c
+++ b/src/settings/plugins/keyfile/utils.c
@@ -74,6 +74,11 @@ check_suffix (const char *base, const char *tag)
 	return FALSE;
 }
 
+#define SWP_TAG ".swp"
+#define SWPX_TAG ".swpx"
+#define PEM_TAG ".pem"
+#define DER_TAG ".der"
+
 gboolean
 nm_keyfile_plugin_utils_should_ignore_file (const char *filename)
 {
@@ -88,6 +93,8 @@ nm_keyfile_plugin_utils_should_ignore_file (const char *filename)
 	/* Ignore files with certain patterns */
 	if (   (check_prefix (base, ".") && check_suffix (base, SWP_TAG))   /* vim temporary files: .filename.swp */
 	    || (check_prefix (base, ".") && check_suffix (base, SWPX_TAG))  /* vim temporary files: .filename.swpx */
+	    || check_suffix (base, PEM_TAG)                                 /* 802.1x certificates and keys */
+	    || check_suffix (base, DER_TAG)                                 /* 802.1x certificates and keys */
 	    || check_mkstemp_suffix (base)                                  /* temporary files created by mkstemp() */
 	    || base[strlen (base) - 1] == '~')
 		ignore = TRUE;
diff --git a/src/settings/plugins/keyfile/writer.c b/src/settings/plugins/keyfile/writer.c
index eeb14556..060093ce 100644
--- a/src/settings/plugins/keyfile/writer.c
+++ b/src/settings/plugins/keyfile/writer.c
@@ -668,6 +668,16 @@ cert_writer (GKeyFile *file,
 	if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) {
 		path = objtype->path_func (NM_SETTING_802_1X (setting));
 		g_assert (path);
+
+		/* If the path is rooted in the keyfile directory, just use a
+		 * relative path instead of an absolute one.
+		 */
+		if (g_str_has_prefix (path, keyfile_dir)) {
+			path += strlen (keyfile_dir);
+			while (*path == '/')
+				path++;
+		}
+
 		g_key_file_set_string (file, setting_name, key, path);
 	} else if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) {
 		const GByteArray *blob;