about summary refs log tree commit diff
path: root/src/settings/plugins/ifcfg-rh
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2014-07-06 03:04:17 +0200
committerMichael Biebl <biebl@debian.org>2014-07-06 03:04:17 +0200
commit3ce667b6ee6b86291bbe60ef93cba7f11a5c5400 (patch)
treeaf3daa7221e898b72f3de26eb2cf0c1b1c8661b0 /src/settings/plugins/ifcfg-rh
parentf02d31d95af29678092d1ff01f714621bc9dcc0f (diff)
parent33491bc4279481db8ae47213e34a6d695a0e8830 (diff)
Merge tag 'upstream/0.9.10.0'
Upstream version 0.9.10.0
Diffstat (limited to 'src/settings/plugins/ifcfg-rh')
-rw-r--r--src/settings/plugins/ifcfg-rh/Makefile.am17
-rw-r--r--src/settings/plugins/ifcfg-rh/Makefile.in46
-rw-r--r--src/settings/plugins/ifcfg-rh/common.h30
-rw-r--r--src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c286
-rw-r--r--src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.h11
-rw-r--r--src/settings/plugins/ifcfg-rh/plugin.c578
-rw-r--r--src/settings/plugins/ifcfg-rh/reader.c2169
-rw-r--r--src/settings/plugins/ifcfg-rh/reader.h12
-rw-r--r--src/settings/plugins/ifcfg-rh/shvar.c612
-rw-r--r--src/settings/plugins/ifcfg-rh/shvar.h63
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/Makefile.am56
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/Makefile.in305
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am43
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.in70
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem012
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0:12
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0:22
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0:992
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem112
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem1:12
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem212
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem2:13
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bridge-main1
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb43
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-bad-booleans12
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-bad-percent12
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-bad-uints12
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-default-app-priorities7
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-pgpct-not-10012
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-short-booleans12
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-short-percent12
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-short-uints12
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-fcoe-fabric6
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-fcoe-vn2vn6
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-nm-controlled-unrecognized6
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-noip3
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-master6
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-port5
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-port-empty-config4
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-unrecognized7
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-hidden10
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-802-1X-subj-matches17
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-802-1x-ttls-eapgtc13
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcp-plus-ip26
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcp-send-hostname12
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-static-routes-legacy1
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/route6-test-wired-ipv6-manual3
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh-utils.c7
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c3967
-rw-r--r--src/settings/plugins/ifcfg-rh/utils.c144
-rw-r--r--src/settings/plugins/ifcfg-rh/utils.h7
-rw-r--r--src/settings/plugins/ifcfg-rh/writer.c729
-rw-r--r--src/settings/plugins/ifcfg-rh/writer.h3
53 files changed, 6300 insertions, 3162 deletions
diff --git a/src/settings/plugins/ifcfg-rh/Makefile.am b/src/settings/plugins/ifcfg-rh/Makefile.am
index 3faa60d4..c5e458af 100644
--- a/src/settings/plugins/ifcfg-rh/Makefile.am
+++ b/src/settings/plugins/ifcfg-rh/Makefile.am
@@ -1,5 +1,7 @@
 SUBDIRS = . tests
 
+@GNOME_CODE_COVERAGE_RULES@
+
 nm-ifcfg-rh-glue.h: nm-ifcfg-rh.xml
 	$(AM_V_GEN) dbus-binding-tool --prefix=nm_ifcfg_rh --mode=glib-server --output=$@ $<
 
@@ -23,27 +25,26 @@ libifcfg_rh_io_la_SOURCES = \
 	utils.h
 
 AM_CPPFLAGS = \
-	-I$(top_srcdir)/src/wifi \
+	-I$(top_srcdir)/src/ \
+	-I$(top_srcdir)/src/logging \
+	-I$(top_srcdir)/src/platform \
 	-I$(top_srcdir)/src/settings \
 	-I$(top_srcdir)/src/posix-signals \
+	-I$(top_srcdir)/src/config \
 	-I$(top_srcdir)/include \
 	-I$(top_builddir)/include \
 	-I$(top_srcdir)/libnm-glib \
 	-I$(top_srcdir)/libnm-util \
 	-I$(top_builddir)/libnm-util \
+	-DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \
 	$(GLIB_CFLAGS) \
 	$(DBUS_CFLAGS) \
+	$(POLKIT_CFLAGS) \
 	$(NSS_CFLAGS) \
+	-DG_LOG_DOMAIN=\""NetworkManager-ifcfg-rh"\" \
 	-DSYSCONFDIR=\"$(sysconfdir)\" \
 	-DSBINDIR=\"$(sbindir)\"
 
-libifcfg_rh_io_la_LIBADD = \
-	$(top_builddir)/src/wifi/libwifi-utils.la \
-	$(top_builddir)/src/posix-signals/libnm-posix-signals.la \
-	$(top_builddir)/libnm-util/libnm-util.la \
-	$(GLIB_LIBS) \
-	$(NSS_LIBS)
-
 libnm_settings_plugin_ifcfg_rh_la_SOURCES = \
 	plugin.c \
 	plugin.h \
diff --git a/src/settings/plugins/ifcfg-rh/Makefile.in b/src/settings/plugins/ifcfg-rh/Makefile.in
index 848d470c..7b1a7dda 100644
--- a/src/settings/plugins/ifcfg-rh/Makefile.in
+++ b/src/settings/plugins/ifcfg-rh/Makefile.in
@@ -83,7 +83,8 @@ subdir = src/settings/plugins/ifcfg-rh
 DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
 	$(top_srcdir)/build-aux/depcomp
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_lib_readline.m4 \
+	$(top_srcdir)/m4/compiler_warnings.m4 \
 	$(top_srcdir)/m4/gettext.m4 \
 	$(top_srcdir)/m4/gnome-code-coverage.m4 \
 	$(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \
@@ -131,12 +132,7 @@ am__uninstall_files_from_dir = { \
 am__installdirs = "$(DESTDIR)$(pkglibdir)" \
 	"$(DESTDIR)$(dbusservicedir)"
 LTLIBRARIES = $(noinst_LTLIBRARIES) $(pkglib_LTLIBRARIES)
-am__DEPENDENCIES_1 =
-libifcfg_rh_io_la_DEPENDENCIES =  \
-	$(top_builddir)/src/wifi/libwifi-utils.la \
-	$(top_builddir)/src/posix-signals/libnm-posix-signals.la \
-	$(top_builddir)/libnm-util/libnm-util.la $(am__DEPENDENCIES_1) \
-	$(am__DEPENDENCIES_1)
+libifcfg_rh_io_la_LIBADD =
 am_libifcfg_rh_io_la_OBJECTS = shvar.lo reader.lo writer.lo errors.lo \
 	utils.lo
 libifcfg_rh_io_la_OBJECTS = $(am_libifcfg_rh_io_la_OBJECTS)
@@ -144,6 +140,7 @@ AM_V_lt = $(am__v_lt_@AM_V@)
 am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
 am__v_lt_0 = --silent
 am__v_lt_1 = 
+am__DEPENDENCIES_1 =
 libnm_settings_plugin_ifcfg_rh_la_DEPENDENCIES =  \
 	$(top_builddir)/libnm-util/libnm-util.la \
 	$(top_builddir)/libnm-glib/libnm-glib.la libifcfg-rh-io.la \
@@ -287,12 +284,15 @@ CXXFLAGS = @CXXFLAGS@
 CYGPATH_W = @CYGPATH_W@
 DATADIRNAME = @DATADIRNAME@
 DBUS_CFLAGS = @DBUS_CFLAGS@
+DBUS_GLIB_100_CFLAGS = @DBUS_GLIB_100_CFLAGS@
+DBUS_GLIB_100_LIBS = @DBUS_GLIB_100_LIBS@
 DBUS_LIBS = @DBUS_LIBS@
 DBUS_SYS_DIR = @DBUS_SYS_DIR@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
 DHCLIENT_PATH = @DHCLIENT_PATH@
 DHCPCD_PATH = @DHCPCD_PATH@
+DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@
 DLLTOOL = @DLLTOOL@
 DNSMASQ_PATH = @DNSMASQ_PATH@
 DSYMUTIL = @DSYMUTIL@
@@ -317,7 +317,6 @@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
 GNUTLS_LIBS = @GNUTLS_LIBS@
 GREP = @GREP@
 GTKDOC_CHECK = @GTKDOC_CHECK@
-GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@
 GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@
 GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@
 GTKDOC_MKPDF = @GTKDOC_MKPDF@
@@ -362,12 +361,16 @@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
 LIBICONV = @LIBICONV@
 LIBINTL = @LIBINTL@
 LIBM = @LIBM@
+LIBNDP_CFLAGS = @LIBNDP_CFLAGS@
+LIBNDP_LIBS = @LIBNDP_LIBS@
 LIBNL_CFLAGS = @LIBNL_CFLAGS@
 LIBNL_LIBS = @LIBNL_LIBS@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
 LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@
 LIBSOUP_LIBS = @LIBSOUP_LIBS@
+LIBTEAMDCTL_CFLAGS = @LIBTEAMDCTL_CFLAGS@
+LIBTEAMDCTL_LIBS = @LIBTEAMDCTL_LIBS@
 LIBTOOL = @LIBTOOL@
 LIPO = @LIPO@
 LN_S = @LN_S@
@@ -384,6 +387,8 @@ MOC = @MOC@
 MSGFMT = @MSGFMT@
 MSGFMT_015 = @MSGFMT_015@
 MSGMERGE = @MSGMERGE@
+NEWT_CFLAGS = @NEWT_CFLAGS@
+NEWT_LIBS = @NEWT_LIBS@
 NM = @NM@
 NMEDIT = @NMEDIT@
 NM_MAJOR_VERSION = @NM_MAJOR_VERSION@
@@ -411,11 +416,16 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
 POLKIT_CFLAGS = @POLKIT_CFLAGS@
 POLKIT_LIBS = @POLKIT_LIBS@
 POSUB = @POSUB@
+PPPD_PATH = @PPPD_PATH@
 PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@
+PPPOE_PATH = @PPPOE_PATH@
 QT_CFLAGS = @QT_CFLAGS@
 QT_LIBS = @QT_LIBS@
 RANLIB = @RANLIB@
+READLINE_LIBS = @READLINE_LIBS@
 SED = @SED@
+SELINUX_CFLAGS = @SELINUX_CFLAGS@
+SELINUX_LIBS = @SELINUX_LIBS@
 SET_MAKE = @SET_MAKE@
 SHELL = @SHELL@
 STRIP = @STRIP@
@@ -430,6 +440,7 @@ UDEV_BASE_DIR = @UDEV_BASE_DIR@
 USE_NLS = @USE_NLS@
 UUID_CFLAGS = @UUID_CFLAGS@
 UUID_LIBS = @UUID_LIBS@
+VALGRIND_RULES = @VALGRIND_RULES@
 VAPIGEN = @VAPIGEN@
 VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@
 VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@
@@ -492,6 +503,7 @@ psdir = @psdir@
 sbindir = @sbindir@
 sharedstatedir = @sharedstatedir@
 srcdir = @srcdir@
+subdirs = @subdirs@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 target_alias = @target_alias@
@@ -502,6 +514,7 @@ with_dhclient = @with_dhclient@
 with_dhcpcd = @with_dhcpcd@
 with_netconfig = @with_netconfig@
 with_resolvconf = @with_resolvconf@
+with_valgrind = @with_valgrind@
 SUBDIRS = . tests
 BUILT_SOURCES = \
 	nm-ifcfg-rh-glue.h
@@ -521,27 +534,26 @@ libifcfg_rh_io_la_SOURCES = \
 	utils.h
 
 AM_CPPFLAGS = \
-	-I$(top_srcdir)/src/wifi \
+	-I$(top_srcdir)/src/ \
+	-I$(top_srcdir)/src/logging \
+	-I$(top_srcdir)/src/platform \
 	-I$(top_srcdir)/src/settings \
 	-I$(top_srcdir)/src/posix-signals \
+	-I$(top_srcdir)/src/config \
 	-I$(top_srcdir)/include \
 	-I$(top_builddir)/include \
 	-I$(top_srcdir)/libnm-glib \
 	-I$(top_srcdir)/libnm-util \
 	-I$(top_builddir)/libnm-util \
+	-DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \
 	$(GLIB_CFLAGS) \
 	$(DBUS_CFLAGS) \
+	$(POLKIT_CFLAGS) \
 	$(NSS_CFLAGS) \
+	-DG_LOG_DOMAIN=\""NetworkManager-ifcfg-rh"\" \
 	-DSYSCONFDIR=\"$(sysconfdir)\" \
 	-DSBINDIR=\"$(sbindir)\"
 
-libifcfg_rh_io_la_LIBADD = \
-	$(top_builddir)/src/wifi/libwifi-utils.la \
-	$(top_builddir)/src/posix-signals/libnm-posix-signals.la \
-	$(top_builddir)/libnm-util/libnm-util.la \
-	$(GLIB_LIBS) \
-	$(NSS_LIBS)
-
 libnm_settings_plugin_ifcfg_rh_la_SOURCES = \
 	plugin.c \
 	plugin.h \
@@ -1000,6 +1012,8 @@ uninstall-am: uninstall-dbusserviceDATA uninstall-pkglibLTLIBRARIES
 	uninstall-pkglibLTLIBRARIES
 
 
+@GNOME_CODE_COVERAGE_RULES@
+
 nm-ifcfg-rh-glue.h: nm-ifcfg-rh.xml
 	$(AM_V_GEN) dbus-binding-tool --prefix=nm_ifcfg_rh --mode=glib-server --output=$@ $<
 
diff --git a/src/settings/plugins/ifcfg-rh/common.h b/src/settings/plugins/ifcfg-rh/common.h
index fc8ce22a..d9627bdd 100644
--- a/src/settings/plugins/ifcfg-rh/common.h
+++ b/src/settings/plugins/ifcfg-rh/common.h
@@ -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.
  *
- * (C) Copyright 2008 - 2011 Red Hat, Inc.
+ * (C) Copyright 2008 - 2013 Red Hat, Inc.
  */
 
 #ifndef __COMMON_H__
@@ -39,7 +39,7 @@
 #define IFCFG_DIR SYSCONFDIR"/sysconfig/network-scripts"
 
 #define IFCFG_PLUGIN_NAME "ifcfg-rh"
-#define IFCFG_PLUGIN_INFO "(c) 2007 - 2010 Red Hat, Inc.  To report bugs please use the NetworkManager mailing list."
+#define IFCFG_PLUGIN_INFO "(c) 2007 - 2013 Red Hat, Inc.  To report bugs please use the NetworkManager mailing list."
 
 #define TYPE_ETHERNET   "Ethernet"
 #define TYPE_WIRELESS   "Wireless"
@@ -47,11 +47,37 @@
 #define TYPE_BRIDGE     "Bridge"
 #define TYPE_BOND       "Bond"
 #define TYPE_VLAN       "Vlan"
+#define TYPE_TEAM       "Team"
+#define TYPE_TEAM_PORT  "TeamPort"
 
 #define SECRET_FLAG_AGENT "user"
 #define SECRET_FLAG_NOT_SAVED "ask"
 #define SECRET_FLAG_NOT_REQUIRED "unused"
 
+/* DCB key names */
+#define KEY_DCB_APP_FCOE_ENABLE     "DCB_APP_FCOE_ENABLE"
+#define KEY_DCB_APP_FCOE_ADVERTISE  "DCB_APP_FCOE_ADVERTISE"
+#define KEY_DCB_APP_FCOE_WILLING    "DCB_APP_FCOE_WILLING"
+#define KEY_DCB_APP_FCOE_MODE       "DCB_APP_FCOE_MODE"
+#define KEY_DCB_APP_ISCSI_ENABLE    "DCB_APP_ISCSI_ENABLE"
+#define KEY_DCB_APP_ISCSI_ADVERTISE "DCB_APP_ISCSI_ADVERTISE"
+#define KEY_DCB_APP_ISCSI_WILLING   "DCB_APP_ISCSI_WILLING"
+#define KEY_DCB_APP_FIP_ENABLE      "DCB_APP_FIP_ENABLE"
+#define KEY_DCB_APP_FIP_ADVERTISE   "DCB_APP_FIP_ADVERTISE"
+#define KEY_DCB_APP_FIP_WILLING     "DCB_APP_FIP_WILLING"
+#define KEY_DCB_PFC_ENABLE          "DCB_PFC_ENABLE"
+#define KEY_DCB_PFC_ADVERTISE       "DCB_PFC_ADVERTISE"
+#define KEY_DCB_PFC_WILLING         "DCB_PFC_WILLING"
+#define KEY_DCB_PFC_UP              "DCB_PFC_UP"
+#define KEY_DCB_PG_ENABLE           "DCB_PG_ENABLE"
+#define KEY_DCB_PG_ADVERTISE        "DCB_PG_ADVERTISE"
+#define KEY_DCB_PG_WILLING          "DCB_PG_WILLING"
+#define KEY_DCB_PG_ID               "DCB_PG_ID"
+#define KEY_DCB_PG_PCT              "DCB_PG_PCT"
+#define KEY_DCB_PG_UPPCT            "DCB_PG_UPPCT"
+#define KEY_DCB_PG_STRICT           "DCB_PG_STRICT"
+#define KEY_DCB_PG_UP2TC            "DCB_PG_UP2TC"
+
 #define IFCFG_PLUGIN_ERROR (ifcfg_plugin_error_quark ())
 GQuark ifcfg_plugin_error_quark (void);
 
diff --git a/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c b/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c
index 04d3d3e4..3db06f17 100644
--- a/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c
+++ b/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c
@@ -35,10 +35,12 @@
 #include <nm-setting-8021x.h>
 
 #include "common.h"
+#include "nm-config.h"
 #include "nm-ifcfg-connection.h"
 #include "reader.h"
 #include "writer.h"
 #include "nm-inotify-helper.h"
+#include "utils.h"
 
 G_DEFINE_TYPE (NMIfcfgConnection, nm_ifcfg_connection, NM_TYPE_SETTINGS_CONNECTION)
 
@@ -59,12 +61,14 @@ typedef struct {
 	char *route6file;
 	int route6file_wd;
 
-	char *unmanaged;
+	char *unmanaged_spec;
+	char *unrecognized_spec;
 } NMIfcfgConnectionPrivate;
 
 enum {
 	PROP_0,
-	PROP_UNMANAGED,
+	PROP_UNMANAGED_SPEC,
+	PROP_UNRECOGNIZED_SPEC,
 	LAST_PROP
 };
 
@@ -96,86 +100,159 @@ files_changed_cb (NMInotifyHelper *ih,
 }
 
 NMIfcfgConnection *
-nm_ifcfg_connection_new (const char *full_path,
-                         NMConnection *source,
+nm_ifcfg_connection_new (NMConnection *source,
+                         const char *full_path,
                          GError **error,
                          gboolean *ignore_error)
 {
 	GObject *object;
-	NMIfcfgConnectionPrivate *priv;
 	NMConnection *tmp;
-	char *unmanaged = NULL;
-	char *keyfile = NULL;
-	char *routefile = NULL;
-	char *route6file = NULL;
-	NMInotifyHelper *ih;
+	char *unhandled_spec = NULL;
+	const char *unmanaged_spec = NULL, *unrecognized_spec = NULL;
+	gboolean update_unsaved = TRUE;
 
-	g_return_val_if_fail (full_path != NULL, NULL);
+	g_assert (source || full_path);
 
 	/* If we're given a connection already, prefer that instead of re-reading */
 	if (source)
 		tmp = g_object_ref (source);
 	else {
+		char *keyfile = NULL, *routefile = NULL, *route6file = NULL;
+
 		tmp = connection_from_file (full_path, NULL, NULL, NULL,
-		                            &unmanaged,
+		                            &unhandled_spec,
 		                            &keyfile,
 		                            &routefile,
 		                            &route6file,
 		                            error,
 		                            ignore_error);
+		g_free (keyfile);
+		g_free (routefile);
+		g_free (route6file);
 		if (!tmp)
 			return NULL;
+
+		/* If we just read the connection from disk, it's clearly not Unsaved */
+		update_unsaved = FALSE;
 	}
 
+	if (unhandled_spec && g_str_has_prefix (unhandled_spec, "unmanaged:"))
+		unmanaged_spec = unhandled_spec + strlen ("unmanaged:");
+	else if (unhandled_spec && g_str_has_prefix (unhandled_spec, "unrecognized:"))
+		unrecognized_spec = unhandled_spec + strlen ("unrecognized:");
+
 	object = (GObject *) g_object_new (NM_TYPE_IFCFG_CONNECTION,
-	                                   NM_IFCFG_CONNECTION_UNMANAGED, unmanaged,
+	                                   NM_IFCFG_CONNECTION_UNMANAGED_SPEC, unmanaged_spec,
+	                                   NM_IFCFG_CONNECTION_UNRECOGNIZED_SPEC, unrecognized_spec,
 	                                   NULL);
-	if (!object)
-		goto out;
-
-	/* Update our settings with what was read from the file */
-	if (!nm_settings_connection_replace_settings (NM_SETTINGS_CONNECTION (object), tmp, error)) {
-		g_object_unref (object);
-		object = NULL;
-		goto out;
+	if (object) {
+		/* Update our settings with what was read from the file */
+		if (nm_settings_connection_replace_settings (NM_SETTINGS_CONNECTION (object),
+		                                             tmp,
+		                                             update_unsaved,
+		                                             error)) {
+			/* Set the path and start monitoring */
+			if (full_path)
+				nm_ifcfg_connection_set_path (NM_IFCFG_CONNECTION (object), full_path);
+		} else {
+			g_object_unref (object);
+			object = NULL;
+		}
 	}
 
-	priv = NM_IFCFG_CONNECTION_GET_PRIVATE (object);
-	priv->path = g_strdup (full_path);
+	g_object_unref (tmp);
+	g_free (unhandled_spec);
+	return (NMIfcfgConnection *) object;
+}
+
+const char *
+nm_ifcfg_connection_get_path (NMIfcfgConnection *self)
+{
+	g_return_val_if_fail (NM_IS_IFCFG_CONNECTION (self), NULL);
+
+	return NM_IFCFG_CONNECTION_GET_PRIVATE (self)->path;
+}
+
+static void
+path_watch_stop (NMIfcfgConnection *self)
+{
+	NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (self);
+	NMInotifyHelper *ih;
 
 	ih = nm_inotify_helper_get ();
-	priv->ih_event_id = g_signal_connect (ih, "event", G_CALLBACK (files_changed_cb), object);
 
-	priv->file_wd = nm_inotify_helper_add_watch (ih, full_path);
+	if (priv->ih_event_id) {
+		g_signal_handler_disconnect (ih, priv->ih_event_id);
+		priv->ih_event_id = 0;
+	}
 
-	priv->keyfile = keyfile;
-	priv->keyfile_wd = nm_inotify_helper_add_watch (ih, keyfile);
+	if (priv->file_wd >= 0) {
+		nm_inotify_helper_remove_watch (ih, priv->file_wd);
+		priv->file_wd = -1;
+	}
 
-	priv->routefile = routefile;
-	priv->routefile_wd = nm_inotify_helper_add_watch (ih, routefile);
+	g_free (priv->keyfile);
+	priv->keyfile = NULL;
+	if (priv->keyfile_wd >= 0) {
+		nm_inotify_helper_remove_watch (ih, priv->keyfile_wd);
+		priv->keyfile_wd = -1;
+	}
 
-	priv->route6file = route6file;
-	priv->route6file_wd = nm_inotify_helper_add_watch (ih, route6file);
+	g_free (priv->routefile);
+	priv->routefile = NULL;
+	if (priv->routefile_wd >= 0) {
+		nm_inotify_helper_remove_watch (ih, priv->routefile_wd);
+		priv->routefile_wd = -1;
+	}
 
-out:
-	g_object_unref (tmp);
-	return (NMIfcfgConnection *) object;
+	g_free (priv->route6file);
+	priv->route6file = NULL;
+	if (priv->route6file_wd >= 0) {
+		nm_inotify_helper_remove_watch (ih, priv->route6file_wd);
+		priv->route6file_wd = -1;
+	}
+}
+
+void
+nm_ifcfg_connection_set_path (NMIfcfgConnection *self, const char *ifcfg_path)
+{
+	NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (self);
+
+	g_return_if_fail (ifcfg_path != NULL);
+
+	path_watch_stop (self);
+	g_free (priv->path);
+
+	priv->path = g_strdup (ifcfg_path);
+	priv->keyfile = utils_get_keys_path (ifcfg_path);
+	priv->routefile = utils_get_route_path (ifcfg_path);
+	priv->route6file = utils_get_route6_path (ifcfg_path);
+
+	if (nm_config_get_monitor_connection_files (nm_config_get ())) {
+		NMInotifyHelper *ih = nm_inotify_helper_get ();
+
+		priv->ih_event_id = g_signal_connect (ih, "event", G_CALLBACK (files_changed_cb), self);
+		priv->file_wd = nm_inotify_helper_add_watch (ih, ifcfg_path);
+		priv->keyfile_wd = nm_inotify_helper_add_watch (ih, priv->keyfile);
+		priv->routefile_wd = nm_inotify_helper_add_watch (ih, priv->routefile);
+		priv->route6file_wd = nm_inotify_helper_add_watch (ih, priv->route6file);
+	}
 }
 
 const char *
-nm_ifcfg_connection_get_path (NMIfcfgConnection *self)
+nm_ifcfg_connection_get_unmanaged_spec (NMIfcfgConnection *self)
 {
 	g_return_val_if_fail (NM_IS_IFCFG_CONNECTION (self), NULL);
 
-	return NM_IFCFG_CONNECTION_GET_PRIVATE (self)->path;
+	return NM_IFCFG_CONNECTION_GET_PRIVATE (self)->unmanaged_spec;
 }
 
 const char *
-nm_ifcfg_connection_get_unmanaged_spec (NMIfcfgConnection *self)
+nm_ifcfg_connection_get_unrecognized_spec (NMIfcfgConnection *self)
 {
 	g_return_val_if_fail (NM_IS_IFCFG_CONNECTION (self), NULL);
 
-	return NM_IFCFG_CONNECTION_GET_PRIVATE (self)->unmanaged;
+	return NM_IFCFG_CONNECTION_GET_PRIVATE (self)->unrecognized_spec;
 }
 
 static void
@@ -186,41 +263,50 @@ commit_changes (NMSettingsConnection *connection,
 	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;
+	gboolean same = FALSE, success = FALSE;
+	char *ifcfg_path = NULL;
 
 	/* To ensure we don't rewrite files that are only changed from other
 	 * processes on-disk, read the existing connection back in and only rewrite
 	 * it if it's really changed.
 	 */
-	reread = connection_from_file (priv->path, NULL, NULL, NULL,
-	                               &unmanaged, &keyfile, &routefile, &route6file,
-	                               NULL, NULL);
-	g_free (unmanaged);
-	g_free (keyfile);
-	g_free (routefile);
-	g_free (route6file);
-
-	if (reread) {
-		same = nm_connection_compare (NM_CONNECTION (connection),
-		                              reread,
-		                              NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS |
-		                                NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS);
-		g_object_unref (reread);
-
-		/* Don't bother writing anything out if in-memory and on-disk data are the same */
-		if (same) {
-			/* But chain up to parent to handle success - emits updated signal */
-			NM_SETTINGS_CONNECTION_CLASS (nm_ifcfg_connection_parent_class)->commit_changes (connection, callback, user_data);
-			return;
+	if (priv->path) {
+		reread = connection_from_file (priv->path, NULL, NULL, NULL,
+		                               NULL, NULL, NULL, NULL,
+		                               &error, NULL);
+		g_clear_error (&error);
+		if (reread) {
+			same = nm_connection_compare (NM_CONNECTION (connection),
+			                              reread,
+			                              NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS |
+			                                 NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS);
+			g_object_unref (reread);
+
+			/* Don't bother writing anything out if in-memory and on-disk data are the same */
+			if (same) {
+				/* But chain up to parent to handle success - emits updated signal */
+				NM_SETTINGS_CONNECTION_CLASS (nm_ifcfg_connection_parent_class)->commit_changes (connection, callback, user_data);
+				return;
+			}
+		}
+
+		success = writer_update_connection (NM_CONNECTION (connection),
+		                                    IFCFG_DIR,
+		                                    priv->path,
+		                                    priv->keyfile,
+		                                    &error);
+	} else {
+		success = writer_new_connection (NM_CONNECTION (connection),
+		                                 IFCFG_DIR,
+		                                 &ifcfg_path,
+		                                 &error);
+		if (success) {
+			nm_ifcfg_connection_set_path (NM_IFCFG_CONNECTION (connection), ifcfg_path);
+			g_free (ifcfg_path);
 		}
 	}
 
-	if (writer_update_connection (NM_CONNECTION (connection),
-	                              IFCFG_DIR,
-	                              priv->path,
-	                              priv->keyfile,
-	                              &error)) {
+	if (success) {
 		/* Chain up to parent to handle success */
 		NM_SETTINGS_CONNECTION_CLASS (nm_ifcfg_connection_parent_class)->commit_changes (connection, callback, user_data);
 	} else {
@@ -237,14 +323,16 @@ do_delete (NMSettingsConnection *connection,
 {
 	NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (connection);
 
-	g_unlink (priv->path);
-	if (priv->keyfile)
-		g_unlink (priv->keyfile);
-	if (priv->routefile)
-		g_unlink (priv->routefile);
+	if (priv->path) {
+		g_unlink (priv->path);
+		if (priv->keyfile)
+			g_unlink (priv->keyfile);
+		if (priv->routefile)
+			g_unlink (priv->routefile);
 
-	if (priv->route6file)
-		g_unlink (priv->route6file);
+		if (priv->route6file)
+			g_unlink (priv->route6file);
+	}
 
 	NM_SETTINGS_CONNECTION_CLASS (nm_ifcfg_connection_parent_class)->delete (connection, callback, user_data);
 }
@@ -259,31 +347,10 @@ nm_ifcfg_connection_init (NMIfcfgConnection *connection)
 static void
 finalize (GObject *object)
 {
-	NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (object);
-	NMInotifyHelper *ih;
-
 	nm_connection_clear_secrets (NM_CONNECTION (object));
 
-	ih = nm_inotify_helper_get ();
-
-	if (priv->ih_event_id)
-		g_signal_handler_disconnect (ih, priv->ih_event_id);
-
-	g_free (priv->path);
-	if (priv->file_wd >= 0)
-		nm_inotify_helper_remove_watch (ih, priv->file_wd);
-
-	g_free (priv->keyfile);
-	if (priv->keyfile_wd >= 0)
-		nm_inotify_helper_remove_watch (ih, priv->keyfile_wd);
-
-	g_free (priv->routefile);
-	if (priv->routefile_wd >= 0)
-		nm_inotify_helper_remove_watch (ih, priv->routefile_wd);
-
-	g_free (priv->route6file);
-	if (priv->route6file_wd >= 0)
-		nm_inotify_helper_remove_watch (ih, priv->route6file_wd);
+	path_watch_stop (NM_IFCFG_CONNECTION (object));
+	g_free (NM_IFCFG_CONNECTION_GET_PRIVATE (object)->path);
 
 	G_OBJECT_CLASS (nm_ifcfg_connection_parent_class)->finalize (object);
 }
@@ -295,8 +362,11 @@ set_property (GObject *object, guint prop_id,
 	NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (object);
 
 	switch (prop_id) {
-	case PROP_UNMANAGED:
-		priv->unmanaged = g_value_dup_string (value);
+	case PROP_UNMANAGED_SPEC:
+		priv->unmanaged_spec = g_value_dup_string (value);
+		break;
+	case PROP_UNRECOGNIZED_SPEC:
+		priv->unrecognized_spec = g_value_dup_string (value);
 		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -311,8 +381,11 @@ get_property (GObject *object, guint prop_id,
 	NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (object);
 
 	switch (prop_id) {
-	case PROP_UNMANAGED:
-		g_value_set_string (value, priv->unmanaged);
+	case PROP_UNMANAGED_SPEC:
+		g_value_set_string (value, priv->unmanaged_spec);
+		break;
+	case PROP_UNRECOGNIZED_SPEC:
+		g_value_set_string (value, priv->unrecognized_spec);
 		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -337,12 +410,19 @@ nm_ifcfg_connection_class_init (NMIfcfgConnectionClass *ifcfg_connection_class)
 
 	/* Properties */
 	g_object_class_install_property
-		(object_class, PROP_UNMANAGED,
-		 g_param_spec_string (NM_IFCFG_CONNECTION_UNMANAGED,
-						  "Unmanaged",
-						  "Unmanaged",
+		(object_class, PROP_UNMANAGED_SPEC,
+		 g_param_spec_string (NM_IFCFG_CONNECTION_UNMANAGED_SPEC,
+						  "Unmanaged spec",
+						  "Unmanaged spec",
 						  NULL,
 						  G_PARAM_READWRITE));
+	g_object_class_install_property
+		(object_class, PROP_UNRECOGNIZED_SPEC,
+		 g_param_spec_string (NM_IFCFG_CONNECTION_UNRECOGNIZED_SPEC,
+		                      "Unrecognized spec",
+		                      "Unrecognized spec",
+		                      NULL,
+		                      G_PARAM_READWRITE));
 
 	signals[IFCFG_CHANGED] =
 		g_signal_new ("ifcfg-changed",
diff --git a/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.h b/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.h
index 5a36dcdf..47422b5d 100644
--- a/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.h
+++ b/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.h
@@ -33,7 +33,8 @@ G_BEGIN_DECLS
 #define NM_IS_IFCFG_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_IFCFG_CONNECTION))
 #define NM_IFCFG_CONNECTION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_IFCFG_CONNECTION, NMIfcfgConnectionClass))
 
-#define NM_IFCFG_CONNECTION_UNMANAGED "unmanaged"
+#define NM_IFCFG_CONNECTION_UNMANAGED_SPEC    "unmanaged-spec"
+#define NM_IFCFG_CONNECTION_UNRECOGNIZED_SPEC "unrecognized-spec"
 
 typedef struct {
 	NMSettingsConnection parent;
@@ -45,14 +46,18 @@ typedef struct {
 
 GType nm_ifcfg_connection_get_type (void);
 
-NMIfcfgConnection *nm_ifcfg_connection_new (const char *filename,
-                                            NMConnection *source,
+NMIfcfgConnection *nm_ifcfg_connection_new (NMConnection *source,
+                                            const char *full_path,
                                             GError **error,
                                             gboolean *ignore_error);
 
 const char *nm_ifcfg_connection_get_path (NMIfcfgConnection *self);
 
+void        nm_ifcfg_connection_set_path (NMIfcfgConnection *self,
+                                          const char *ifcfg_path);
+
 const char *nm_ifcfg_connection_get_unmanaged_spec (NMIfcfgConnection *self);
+const char *nm_ifcfg_connection_get_unrecognized_spec (NMIfcfgConnection *self);
 
 gboolean nm_ifcfg_connection_update (NMIfcfgConnection *self,
                                      GHashTable *new_settings,
diff --git a/src/settings/plugins/ifcfg-rh/plugin.c b/src/settings/plugins/ifcfg-rh/plugin.c
index 50cbdf07..8a3f328c 100644
--- a/src/settings/plugins/ifcfg-rh/plugin.c
+++ b/src/settings/plugins/ifcfg-rh/plugin.c
@@ -27,6 +27,8 @@
 #include <errno.h>
 #include <net/ethernet.h>
 #include <netinet/ether.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 
 #include <gmodule.h>
 #include <glib-object.h>
@@ -37,6 +39,10 @@
 #include <dbus/dbus-glib.h>
 #include <dbus/dbus-glib-lowlevel.h>
 
+#if HAVE_SELINUX
+#include <selinux/selinux.h>
+#endif
+
 #include <nm-setting-connection.h>
 
 #include "common.h"
@@ -44,10 +50,13 @@
 #include "plugin.h"
 #include "nm-system-config-interface.h"
 #include "nm-settings-error.h"
+#include "nm-config.h"
+#include "nm-logging.h"
 
 #include "nm-ifcfg-connection.h"
 #include "nm-inotify-helper.h"
 #include "shvar.h"
+#include "reader.h"
 #include "writer.h"
 #include "utils.h"
 
@@ -64,7 +73,8 @@ static gboolean impl_ifcfgrh_get_ifcfg_details (SCPluginIfcfg *plugin,
 
 static void connection_new_or_changed (SCPluginIfcfg *plugin,
                                        const char *path,
-                                       NMIfcfgConnection *existing);
+                                       NMIfcfgConnection *existing,
+                                       char **out_old_path);
 
 static void system_config_interface_init (NMSystemConfigInterface *system_config_interface_class);
 
@@ -76,8 +86,9 @@ G_DEFINE_TYPE_EXTENDED (SCPluginIfcfg, sc_plugin_ifcfg, G_TYPE_OBJECT, 0,
 
 
 typedef struct {
-	GHashTable *connections;
+	GHashTable *connections;  /* uuid::connection */
 
+	gboolean initialized;
 	gulong ih_event_id;
 	int sc_network_wd;
 	GFileMonitor *hostname_monitor;
@@ -92,14 +103,6 @@ typedef struct {
 
 
 static void
-connection_unmanaged_changed (NMIfcfgConnection *connection,
-                              GParamSpec *pspec,
-                              gpointer user_data)
-{
-	g_signal_emit_by_name (SC_PLUGIN_IFCFG (user_data), NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED);
-}
-
-static void
 connection_ifcfg_changed (NMIfcfgConnection *connection, gpointer user_data)
 {
 	SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (user_data);
@@ -108,7 +111,14 @@ connection_ifcfg_changed (NMIfcfgConnection *connection, gpointer user_data)
 	path = nm_ifcfg_connection_get_path (connection);
 	g_return_if_fail (path != NULL);
 
-	connection_new_or_changed (plugin, path, connection);
+	connection_new_or_changed (plugin, path, connection, NULL);
+}
+
+static void
+connection_removed_cb (NMSettingsConnection *obj, gpointer user_data)
+{
+	g_hash_table_remove (SC_PLUGIN_IFCFG_GET_PRIVATE (user_data)->connections,
+	                     nm_connection_get_uuid (NM_CONNECTION (obj)));
 }
 
 static NMIfcfgConnection *
@@ -123,17 +133,17 @@ _internal_new_connection (SCPluginIfcfg *self,
 	GError *local = NULL;
 	gboolean ignore_error = FALSE;
 
-	if (!source) {
-		PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "parsing %s ... ", path);
-	}
+	if (!source)
+		nm_log_info (LOGD_SETTINGS, "parsing %s ... ", path);
 
-	connection = nm_ifcfg_connection_new (path, source, &local, &ignore_error);
+	connection = nm_ifcfg_connection_new (source, path, &local, &ignore_error);
 	if (!connection) {
-		if (!ignore_error) {
-			PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "    error: %s",
-			              (local && local->message) ? local->message : "(unknown)");
-		}
-		g_propagate_error (error, local);
+		if (!ignore_error)
+			nm_log_warn (LOGD_SETTINGS, "    %s", (local && local->message) ? local->message : "(unknown)");
+		if (local)
+			g_propagate_error (error, local);
+		else
+			g_set_error (error, IFCFG_PLUGIN_ERROR, 0, "(unknown)");
 		return NULL;
 	}
 
@@ -141,19 +151,27 @@ _internal_new_connection (SCPluginIfcfg *self,
 	g_assert (cid);
 
 	g_hash_table_insert (priv->connections,
-	                     (gpointer) nm_ifcfg_connection_get_path (connection),
+	                     g_strdup (nm_connection_get_uuid (NM_CONNECTION (connection))),
 	                     connection);
-	PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "    read connection '%s'", cid);
+	nm_log_info (LOGD_SETTINGS, "    read connection '%s'", cid);
+	g_signal_connect (connection, NM_SETTINGS_CONNECTION_REMOVED,
+	                  G_CALLBACK (connection_removed_cb),
+	                  self);
 
 	if (nm_ifcfg_connection_get_unmanaged_spec (connection)) {
-		PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "Ignoring connection '%s' and its "
-		              "device due to NM_CONTROLLED/BRIDGE/VLAN.", cid);
-	} else {
-		/* Wait for the connection to become unmanaged once it knows the
-		 * hardware IDs of its device, if/when the device gets plugged in.
-		 */
-		g_signal_connect (G_OBJECT (connection), "notify::" NM_IFCFG_CONNECTION_UNMANAGED,
-		                  G_CALLBACK (connection_unmanaged_changed), self);
+		const char *spec;
+		const char *device_id;
+
+		spec = nm_ifcfg_connection_get_unmanaged_spec (connection);
+		device_id = strchr (spec, ':');
+		if (device_id)
+			device_id++;
+		else
+			device_id = spec;
+		nm_log_warn (LOGD_SETTINGS, "    Ignoring connection '%s' / device '%s' due to NM_CONTROLLED=no.",
+		             cid, device_id);
+	} else if (nm_ifcfg_connection_get_unrecognized_spec (connection)) {
+		nm_log_warn (LOGD_SETTINGS, "    Ignoring connection '%s' of unrecognized type.", cid);
 	}
 
 	/* watch changes of ifcfg hardlinks */
@@ -163,108 +181,118 @@ _internal_new_connection (SCPluginIfcfg *self,
 	return connection;
 }
 
-static void
-read_connections (SCPluginIfcfg *plugin)
-{
-	GDir *dir;
-	GError *err = NULL;
-
-	dir = g_dir_open (IFCFG_DIR, 0, &err);
-	if (dir) {
-		const char *item;
-
-		while ((item = g_dir_read_name (dir))) {
-			char *full_path;
-
-			if (utils_should_ignore_file (item, TRUE))
-				continue;
-
-			full_path = g_build_filename (IFCFG_DIR, item, NULL);
-			if (utils_get_ifcfg_name (full_path, TRUE))
-				_internal_new_connection (plugin, full_path, NULL, NULL);
-			g_free (full_path);
-		}
-
-		g_dir_close (dir);
-	} else {
-		PLUGIN_WARN (IFCFG_PLUGIN_NAME, "Can not read directory '%s': %s", IFCFG_DIR, err->message);
-		g_error_free (err);
-	}
-}
-
 /* Monitoring */
 
-/* Callback for nm_settings_connection_replace_and_commit. Report any errors
- * encountered when commiting connection settings updates. */
-static void
-commit_cb (NMSettingsConnection *connection, GError *error, gpointer unused) 
-{
-	if (error) {
-		PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    error updating: %s",
-	             	 (error && error->message) ? error->message : "(unknown)");
-	}
-}
-
 static void
 remove_connection (SCPluginIfcfg *self, NMIfcfgConnection *connection)
 {
 	SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (self);
-	gboolean managed = FALSE;
-	const char *path;
+	gboolean unmanaged, unrecognized;
 
 	g_return_if_fail (self != NULL);
 	g_return_if_fail (connection != NULL);
 
-	managed = !nm_ifcfg_connection_get_unmanaged_spec (connection);
-	path = nm_ifcfg_connection_get_path (connection);
+	unmanaged = !!nm_ifcfg_connection_get_unmanaged_spec (connection);
+	unrecognized = !!nm_ifcfg_connection_get_unrecognized_spec (connection);
 
 	g_object_ref (connection);
-	g_hash_table_remove (priv->connections, path);
+	g_hash_table_remove (priv->connections, nm_connection_get_uuid (NM_CONNECTION (connection)));
 	nm_settings_connection_signal_remove (NM_SETTINGS_CONNECTION (connection));
 	g_object_unref (connection);
 
-	/* Emit unmanaged changes _after_ removing the connection */
-	if (managed == FALSE)
+	/* Emit changes _after_ removing the connection */
+	if (unmanaged)
 		g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED);
+	if (unrecognized)
+		g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNRECOGNIZED_SPECS_CHANGED);
+}
+
+static NMIfcfgConnection *
+find_by_path (SCPluginIfcfg *self, const char *path)
+{
+	SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (self);
+	GHashTableIter iter;
+	NMIfcfgConnection *candidate = NULL;
+
+	g_return_val_if_fail (path != NULL, NULL);
+
+	g_hash_table_iter_init (&iter, priv->connections);
+	while (g_hash_table_iter_next (&iter, NULL, (gpointer) &candidate)) {
+		if (g_strcmp0 (path, nm_ifcfg_connection_get_path (candidate)) == 0)
+			return candidate;
+	}
+	return NULL;
+}
+
+static NMIfcfgConnection *
+find_by_uuid_from_path (SCPluginIfcfg *self, const char *path)
+{
+	SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (self);
+	char *uuid;
+
+	g_return_val_if_fail (path != NULL, NULL);
+
+	uuid = uuid_from_file (path);
+	if (uuid)
+		return g_hash_table_lookup (priv->connections, uuid);
+	else
+		return NULL;
 }
 
 static void
 connection_new_or_changed (SCPluginIfcfg *self,
                            const char *path,
-                           NMIfcfgConnection *existing)
+                           NMIfcfgConnection *existing,
+                           char **out_old_path)
 {
+	SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (self);
 	NMIfcfgConnection *new;
 	GError *error = NULL;
 	gboolean ignore_error = FALSE;
 	const char *new_unmanaged = NULL, *old_unmanaged = NULL;
+	const char *new_unrecognized = NULL, *old_unrecognized = NULL;
+	gboolean unmanaged_changed, unrecognized_changed;
 
 	g_return_if_fail (self != NULL);
 	g_return_if_fail (path != NULL);
 
+	if (out_old_path)
+		*out_old_path = NULL;
+
+	if (!existing) {
+		/* See if it's a rename */
+		existing = find_by_uuid_from_path (self, path);
+		if (existing) {
+			const char *old_path = nm_ifcfg_connection_get_path (existing);
+			nm_log_info (LOGD_SETTINGS, "renaming %s -> %s", old_path, path);
+			if (out_old_path)
+				*out_old_path = g_strdup (old_path);
+			nm_ifcfg_connection_set_path (existing, path);
+		}
+	}
+
 	if (!existing) {
-		/* Completely new connection */
+		/* New connection */
 		new = _internal_new_connection (self, path, NULL, NULL);
 		if (new) {
-			if (nm_ifcfg_connection_get_unmanaged_spec (new)) {
+			if (nm_ifcfg_connection_get_unmanaged_spec (new))
 				g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED);
-			} else {
-				/* Only managed connections are announced to the settings service */
+			else if (nm_ifcfg_connection_get_unrecognized_spec (new))
+				g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNRECOGNIZED_SPECS_CHANGED);
+			else
 				g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED, new);
-			}
 		}
 		return;
 	}
 
-	new = (NMIfcfgConnection *) nm_ifcfg_connection_new (path, NULL, &error, &ignore_error);
+	new = (NMIfcfgConnection *) nm_ifcfg_connection_new (NULL, path, &error, &ignore_error);
 	if (!new) {
 		/* errors reading connection; remove it */
-		if (!ignore_error) {
-			PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    error: %s",
-			             (error && error->message) ? error->message : "(unknown)");
-		}
+		if (!ignore_error)
+			nm_log_warn (LOGD_SETTINGS, "    %s", (error && error->message) ? error->message : "(unknown)");
 		g_clear_error (&error);
 
-		PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "removed %s.", path);
+		nm_log_info (LOGD_SETTINGS, "removed %s.", path);
 		remove_connection (self, existing);
 		return;
 	}
@@ -273,57 +301,71 @@ connection_new_or_changed (SCPluginIfcfg *self,
 
 	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)) {
-
+	unmanaged_changed = g_strcmp0 (old_unmanaged, new_unmanaged);
+
+	old_unrecognized = nm_ifcfg_connection_get_unrecognized_spec (NM_IFCFG_CONNECTION (existing));
+	new_unrecognized = nm_ifcfg_connection_get_unrecognized_spec (NM_IFCFG_CONNECTION (new));
+	unrecognized_changed = g_strcmp0 (old_unrecognized, new_unrecognized);
+
+	if (   !unmanaged_changed
+	    && !unrecognized_changed
+	    && 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_object_unref (new);
 		return;
 	}
 
-	PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "updating %s", path);
+	nm_log_info (LOGD_SETTINGS, "updating %s", path);
+	g_object_set (existing,
+	              NM_IFCFG_CONNECTION_UNMANAGED_SPEC, new_unmanaged,
+	              NM_IFCFG_CONNECTION_UNRECOGNIZED_SPEC, new_unrecognized,
+	              NULL);
 
-	if (new_unmanaged) {
-		if (!old_unmanaged) {
+	if (new_unmanaged || new_unrecognized) {
+		if (!old_unmanaged && !old_unrecognized) {
+			g_object_ref (existing);
 			/* Unexport the connection by telling the settings service it's
-			 * been removed, and notify the settings service by signalling that
-			 * unmanaged specs have changed.
+			 * been removed.
 			 */
 			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);
+			/* signal_remove() will end up removing the connection from our hash,
+			 * so add it back now.
+			 */
+			g_hash_table_insert (priv->connections,
+			                     g_strdup (nm_connection_get_uuid (NM_CONNECTION (existing))),
+			                     existing);
 		}
 	} else {
-		if (old_unmanaged) {  /* now managed */
-			const char *cid;
+		const char *cid = nm_connection_get_id (NM_CONNECTION (new));
 
-			cid = nm_connection_get_id (NM_CONNECTION (new));
-			g_assert (cid);
-
-			PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "Managing connection '%s' and its "
-			              "device because NM_CONTROLLED was true.", cid);
+		if (old_unmanaged /* && !new_unmanaged */) {
+			nm_log_info (LOGD_SETTINGS, "Managing connection '%s' and its device because NM_CONTROLLED was true.", cid);
+			g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED, existing);
+		} else if (old_unrecognized /* && !new_unrecognized */) {
+			nm_log_info (LOGD_SETTINGS, "Managing connection '%s' because it is now a recognized type.", cid);
 			g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED, existing);
 		}
 
-		nm_settings_connection_replace_and_commit (NM_SETTINGS_CONNECTION (existing),
-		                                           NM_CONNECTION (new),
-		                                           commit_cb, NULL);
-
-		/* Update unmanaged status */
-		g_object_set (existing, NM_IFCFG_CONNECTION_UNMANAGED, new_unmanaged, NULL);
-		g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED);
+		if (!nm_settings_connection_replace_settings (NM_SETTINGS_CONNECTION (existing),
+		                                              NM_CONNECTION (new),
+		                                              FALSE,  /* don't set Unsaved */
+		                                              &error)) {
+			/* Shouldn't ever get here as 'new' was verified by the reader already */
+			g_assert_no_error (error);
+		}
 	}
 	g_object_unref (new);
+
+	if (unmanaged_changed)
+		g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED);
+	if (unrecognized_changed)
+		g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNRECOGNIZED_SPECS_CHANGED);
 }
 
 static void
@@ -334,8 +376,7 @@ ifcfg_dir_changed (GFileMonitor *monitor,
                    gpointer user_data)
 {
 	SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (user_data);
-	SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
-	char *path, *name;
+	char *path, *base, *ifcfg_path;
 	NMIfcfgConnection *connection;
 
 	path = g_file_get_path (file);
@@ -344,27 +385,34 @@ ifcfg_dir_changed (GFileMonitor *monitor,
 		return;
 	}
 
-	/* Given any ifcfg, keys, or routes file, get the ifcfg file path */
-	name = utils_get_ifcfg_path (path);
-	g_free (path);
-	if (name) {
-		connection = g_hash_table_lookup (priv->connections, name);
+	base = g_file_get_basename (file);
+	if (utils_is_ifcfg_alias_file (base, NULL)) {
+		/* Alias file changed. Get the base ifcfg file from it */
+		ifcfg_path = utils_get_ifcfg_from_alias (path);
+	} else {
+		/* Given any ifcfg, keys, or routes file, get the ifcfg file path */
+		ifcfg_path = utils_get_ifcfg_path (path);
+	}
+	if (ifcfg_path) {
+		connection = find_by_path (plugin, ifcfg_path);
 		switch (event_type) {
 		case G_FILE_MONITOR_EVENT_DELETED:
-			PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "removed %s.", name);
+			nm_log_info (LOGD_SETTINGS, "removed %s.", ifcfg_path);
 			if (connection)
 				remove_connection (plugin, connection);
 			break;
 		case G_FILE_MONITOR_EVENT_CREATED:
 		case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
 			/* Update or new */
-			connection_new_or_changed (plugin, name, connection);
+			connection_new_or_changed (plugin, ifcfg_path, connection, NULL);
 			break;
 		default:
 			break;
 		}
-		g_free (name);
+		g_free (ifcfg_path);
 	}
+	g_free (path);
+	g_free (base);
 }
 
 static void
@@ -374,8 +422,6 @@ setup_ifcfg_monitoring (SCPluginIfcfg *plugin)
 	GFile *file;
 	GFileMonitor *monitor;
 
-	priv->connections = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
-
 	file = g_file_new_for_path (IFCFG_DIR "/");
 	monitor = g_file_monitor_directory (file, G_FILE_MONITOR_NONE, NULL, NULL);
 	g_object_unref (file);
@@ -387,6 +433,70 @@ setup_ifcfg_monitoring (SCPluginIfcfg *plugin)
 	}
 }
 
+static void
+read_connections (SCPluginIfcfg *plugin)
+{
+	SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
+	GDir *dir;
+	GError *err = NULL;
+	const char *item;
+	GHashTable *oldconns;
+	GHashTableIter iter;
+	gpointer key, value;
+	NMIfcfgConnection *connection;
+
+	dir = g_dir_open (IFCFG_DIR, 0, &err);
+	if (!dir) {
+		nm_log_warn (LOGD_SETTINGS, "Could not read directory '%s': %s", IFCFG_DIR, err->message);
+		g_error_free (err);
+		return;
+	}
+
+	oldconns = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+	g_hash_table_iter_init (&iter, priv->connections);
+	while (g_hash_table_iter_next (&iter, NULL, &value)) {
+		const char *ifcfg_path = nm_ifcfg_connection_get_path (value);
+		if (ifcfg_path)
+			g_hash_table_insert (oldconns, g_strdup (ifcfg_path), value);
+	}
+
+	while ((item = g_dir_read_name (dir))) {
+		char *full_path, *old_path;
+
+		if (utils_should_ignore_file (item, TRUE))
+			continue;
+		if (utils_is_ifcfg_alias_file (item, NULL))
+			continue;
+
+		full_path = g_build_filename (IFCFG_DIR, item, NULL);
+		if (!utils_get_ifcfg_name (full_path, TRUE))
+			goto next;
+
+		connection = g_hash_table_lookup (oldconns, full_path);
+		g_hash_table_remove (oldconns, full_path);
+		connection_new_or_changed (plugin, full_path, connection, &old_path);
+
+		if (old_path) {
+			g_hash_table_remove (oldconns, old_path);
+			g_free (old_path);
+		}
+
+	next:
+		g_free (full_path);
+	}
+
+	g_dir_close (dir);
+
+	g_hash_table_iter_init (&iter, oldconns);
+	while (g_hash_table_iter_next (&iter, &key, &value)) {
+		nm_log_info (LOGD_SETTINGS, "removed %s.", (char *)key);
+		g_hash_table_iter_remove (&iter);
+		remove_connection (plugin, value);
+	}
+
+	g_hash_table_destroy (oldconns);
+}
+
 static GSList *
 get_connections (NMSystemConfigInterface *config)
 {
@@ -394,75 +504,123 @@ get_connections (NMSystemConfigInterface *config)
 	SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
 	GSList *list = NULL;
 	GHashTableIter iter;
-	gpointer value;
+	NMIfcfgConnection *connection;
 
-	if (!priv->connections) {
-		setup_ifcfg_monitoring (plugin);
+	if (!priv->initialized) {
+		if (nm_config_get_monitor_connection_files (nm_config_get ()))
+			setup_ifcfg_monitoring (plugin);
 		read_connections (plugin);
+		priv->initialized = TRUE;
 	}
 
 	g_hash_table_iter_init (&iter, priv->connections);
-	while (g_hash_table_iter_next (&iter, NULL, &value)) {
-		NMIfcfgConnection *exported = NM_IFCFG_CONNECTION (value);
-
-		if (!nm_ifcfg_connection_get_unmanaged_spec (exported))
-			list = g_slist_prepend (list, value);
+	while (g_hash_table_iter_next (&iter, NULL, (gpointer) &connection)) {
+		if (   !nm_ifcfg_connection_get_unmanaged_spec (connection)
+		    && !nm_ifcfg_connection_get_unrecognized_spec (connection))
+			list = g_slist_prepend (list, connection);
 	}
 
 	return list;
 }
 
-static void
-check_unmanaged (gpointer key, gpointer data, gpointer user_data)
+static gboolean
+load_connection (NMSystemConfigInterface *config,
+                 const char *filename)
 {
-	GSList **list = (GSList **) user_data;
-	NMIfcfgConnection *connection = NM_IFCFG_CONNECTION (data);
-	const char *unmanaged_spec;
-	GSList *iter;
+	SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (config);
+	NMIfcfgConnection *connection;
+	int dir_len = strlen (IFCFG_DIR);
 
-	unmanaged_spec = nm_ifcfg_connection_get_unmanaged_spec (connection);
-	if (!unmanaged_spec)
-		return;
+	if (   strncmp (filename, IFCFG_DIR, dir_len) != 0
+	    || filename[dir_len] != '/'
+	    || strchr (filename + dir_len + 1, '/') != NULL)
+		return FALSE;
 
-	/* Just return if the unmanaged spec is already in the list */
-	for (iter = *list; iter; iter = g_slist_next (iter)) {
-		if (!strcmp ((char *) iter->data, unmanaged_spec))
-			return;
-	}
+	if (utils_should_ignore_file (filename + dir_len + 1, TRUE))
+		return FALSE;
 
-	*list = g_slist_prepend (*list, g_strdup (unmanaged_spec));
+	connection = find_by_path (plugin, filename);
+	connection_new_or_changed (plugin, filename, connection, NULL);
+	if (!connection)
+		connection = find_by_path (plugin, filename);
+
+	return (connection != NULL);
 }
 
-static GSList *
-get_unmanaged_specs (NMSystemConfigInterface *config)
+static void
+reload_connections (NMSystemConfigInterface *config)
 {
 	SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (config);
+
+	read_connections (plugin);
+}
+
+static GSList *
+get_unhandled_specs (NMSystemConfigInterface *config,
+                     const char *property)
+{
 	SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (config);
-	GSList *list = NULL;
+	GSList *list = NULL, *list_iter;
+	GHashTableIter iter;
+	gpointer connection;
+	char *spec;
+	gboolean found;
 
-	if (!priv->connections) {
-		setup_ifcfg_monitoring (plugin);
-		read_connections (plugin);
+	g_hash_table_iter_init (&iter, priv->connections);
+	while (g_hash_table_iter_next (&iter, NULL, &connection)) {
+		g_object_get (connection, property, &spec, NULL);
+		if (spec) {
+			/* Ignore duplicates */
+			for (list_iter = list, found = FALSE; list_iter; list_iter = g_slist_next (list_iter)) {
+				if (g_str_equal (list_iter->data, spec)) {
+					found = TRUE;
+					break;
+				}
+			}
+			if (found)
+				g_free (spec);
+			else
+				list = g_slist_prepend (list, spec);
+		}
 	}
-
-	g_hash_table_foreach (priv->connections, check_unmanaged, &list);
 	return list;
 }
 
+static GSList *
+get_unmanaged_specs (NMSystemConfigInterface *config)
+{
+	return get_unhandled_specs (config, NM_IFCFG_CONNECTION_UNMANAGED_SPEC);
+}
+
+static GSList *
+get_unrecognized_specs (NMSystemConfigInterface *config)
+{
+	return get_unhandled_specs (config, NM_IFCFG_CONNECTION_UNRECOGNIZED_SPEC);
+}
+
 static NMSettingsConnection *
 add_connection (NMSystemConfigInterface *config,
                 NMConnection *connection,
+                gboolean save_to_disk,
                 GError **error)
 {
 	SCPluginIfcfg *self = SC_PLUGIN_IFCFG (config);
 	NMIfcfgConnection *added = NULL;
 	char *path = NULL;
 
-	/* Write it out first, then add the connection to our internal list */
-	if (writer_new_connection (connection, IFCFG_DIR, &path, error)) {
-		added = _internal_new_connection (self, path, connection, error);
-		g_free (path);
+	/* Ensure we reject attempts to add the connection long before we're
+	 * asked to write it to disk.
+	 */
+	if (!writer_can_write_connection (connection, error))
+		return NULL;
+
+	if (save_to_disk) {
+		if (!writer_new_connection (connection, IFCFG_DIR, &path, error))
+			return NULL;
 	}
+
+	added = _internal_new_connection (self, path, connection, error);
+	g_free (path);
 	return (NMSettingsConnection *) added;
 }
 
@@ -481,9 +639,9 @@ plugin_get_hostname (SCPluginIfcfg *plugin)
 		return hostname;
 	}
 
-	network = svNewFile (SC_NETWORK_FILE);
+	network = svOpenFile (SC_NETWORK_FILE, NULL);
 	if (!network) {
-		PLUGIN_WARN (IFCFG_PLUGIN_NAME, "Could not get hostname: failed to read " SC_NETWORK_FILE);
+		nm_log_warn (LOGD_SETTINGS, "Could not get hostname: failed to read " SC_NETWORK_FILE);
 		return NULL;
 	}
 
@@ -508,20 +666,45 @@ plugin_set_hostname (SCPluginIfcfg *plugin, const char *hostname)
 {
 	SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
 	shvarFile *network;
-
-	if (!g_file_set_contents (HOSTNAME_FILE, hostname, -1, NULL)) {
-		PLUGIN_WARN (IFCFG_PLUGIN_NAME, "Could not save hostname: failed to create/open " HOSTNAME_FILE);
+	char *hostname_eol;
+	gboolean ret;
+#if HAVE_SELINUX
+	security_context_t se_ctx_prev, se_ctx = NULL;
+	struct stat file_stat = { .st_mode = 0 };
+
+	/* Get default context for HOSTNAME_FILE and set it for fscreate */
+	stat (HOSTNAME_FILE, &file_stat);
+	matchpathcon (HOSTNAME_FILE, file_stat.st_mode, &se_ctx);
+	matchpathcon_fini ();
+	getfscreatecon (&se_ctx_prev);
+	setfscreatecon (se_ctx);
+#endif
+
+	hostname_eol = g_strdup_printf ("%s\n", hostname);
+	ret = g_file_set_contents (HOSTNAME_FILE, hostname_eol, -1, NULL);
+
+#if HAVE_SELINUX
+	/* Restore previous context and cleanup */
+	setfscreatecon (se_ctx_prev);
+	freecon (se_ctx);
+	freecon (se_ctx_prev);
+#endif
+
+	if (!ret) {
+		nm_log_warn (LOGD_SETTINGS, "Could not save hostname: failed to create/open " HOSTNAME_FILE);
+		g_free (hostname_eol);
 		return FALSE;
 	}
 
 	g_free (priv->hostname);
 	priv->hostname = g_strdup (hostname);
+	g_free (hostname_eol);
 
 	/* Remove "HOSTNAME" from SC_NETWORK_FILE, if present */
-	network = svNewFile (SC_NETWORK_FILE);
+	network = svOpenFile (SC_NETWORK_FILE, NULL);
 	if (network) {
 		svSetValue (network, "HOSTNAME", NULL, FALSE);
-		svWriteFile (network, 0644);
+		svWriteFile (network, 0644, NULL);
 		svCloseFile (network);
 	}
 
@@ -579,7 +762,6 @@ impl_ifcfgrh_get_ifcfg_details (SCPluginIfcfg *plugin,
                                 const char **out_path,
                                 GError **error)
 {
-	SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
 	NMIfcfgConnection *connection;
 	NMSettingConnection *s_con;
 	const char *uuid;
@@ -593,8 +775,10 @@ impl_ifcfgrh_get_ifcfg_details (SCPluginIfcfg *plugin,
 		return FALSE;
 	}
 
-	connection = g_hash_table_lookup (priv->connections, in_ifcfg);
-	if (!connection || nm_ifcfg_connection_get_unmanaged_spec (connection)) {
+	connection = find_by_path (plugin, in_ifcfg);
+	if (   !connection
+	    || nm_ifcfg_connection_get_unmanaged_spec (connection)
+	    || nm_ifcfg_connection_get_unrecognized_spec (connection)) {
 		g_set_error (error,
 		             NM_SETTINGS_ERROR,
 		             NM_SETTINGS_ERROR_INVALID_CONNECTION,
@@ -650,6 +834,8 @@ sc_plugin_ifcfg_init (SCPluginIfcfg *plugin)
 	GFile *file;
 	GFileMonitor *monitor;
 
+	priv->connections = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
+
 	/* We watch SC_NETWORK_FILE via NMInotifyHelper (which doesn't track file creation but
 	 * *does* track modifications made via other hard links), since we expect it to always
 	 * exist. But we watch HOSTNAME_FILE via GFileMonitor (which has the opposite
@@ -674,8 +860,7 @@ sc_plugin_ifcfg_init (SCPluginIfcfg *plugin)
 
 	priv->bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
 	if (!priv->bus) {
-		PLUGIN_WARN (IFCFG_PLUGIN_NAME, "Couldn't connect to D-Bus: %s",
-		             error->message);
+		nm_log_warn (LOGD_SETTINGS, "Couldn't connect to D-Bus: %s", error->message);
 		g_clear_error (&error);
 	} else {
 		DBusConnection *tmp;
@@ -696,11 +881,10 @@ sc_plugin_ifcfg_init (SCPluginIfcfg *plugin)
 		                        G_TYPE_INVALID,
 		                        G_TYPE_UINT, &result,
 		                        G_TYPE_INVALID)) {
-			PLUGIN_WARN (IFCFG_PLUGIN_NAME, "Couldn't acquire D-Bus service: %s",
-			             error->message);
+			nm_log_warn (LOGD_SETTINGS, "Couldn't acquire D-Bus service: %s", error->message);
 			g_clear_error (&error);
 		} else if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
-			PLUGIN_WARN (IFCFG_PLUGIN_NAME, "Couldn't acquire ifcfgrh1 D-Bus service (already taken)");
+			nm_log_warn (LOGD_SETTINGS, "Couldn't acquire ifcfgrh1 D-Bus service (already taken)");
 		} else
 			success = TRUE;
 	}
@@ -745,8 +929,10 @@ dispose (GObject *object)
 
 	g_free (priv->hostname);
 
-	if (priv->connections)
+	if (priv->connections) {
 		g_hash_table_destroy (priv->connections);
+		priv->connections = NULL;
+	}
 
 	if (priv->ifcfg_monitor) {
 		if (priv->ifcfg_monitor_id)
@@ -760,12 +946,6 @@ dispose (GObject *object)
 }
 
 static void
-finalize (GObject *object)
-{
-	G_OBJECT_CLASS (sc_plugin_ifcfg_parent_class)->finalize (object);
-}
-
-static void
 get_property (GObject *object, guint prop_id,
 			  GValue *value, GParamSpec *pspec)
 {
@@ -817,7 +997,6 @@ sc_plugin_ifcfg_class_init (SCPluginIfcfgClass *req_class)
 	g_type_class_add_private (req_class, sizeof (SCPluginIfcfgPrivate));
 
 	object_class->dispose = dispose;
-	object_class->finalize = finalize;
 	object_class->get_property = get_property;
 	object_class->set_property = set_property;
 
@@ -847,26 +1026,27 @@ system_config_interface_init (NMSystemConfigInterface *system_config_interface_c
 	/* interface implementation */
 	system_config_interface_class->get_connections = get_connections;
 	system_config_interface_class->add_connection = add_connection;
+	system_config_interface_class->load_connection = load_connection;
+	system_config_interface_class->reload_connections = reload_connections;
 	system_config_interface_class->get_unmanaged_specs = get_unmanaged_specs;
+	system_config_interface_class->get_unrecognized_specs = get_unrecognized_specs;
 	system_config_interface_class->init = init;
 }
 
 G_MODULE_EXPORT GObject *
-nm_system_config_factory (const char *config_file)
+nm_system_config_factory (void)
 {
 	static SCPluginIfcfg *singleton = NULL;
 	SCPluginIfcfgPrivate *priv;
 
 	if (!singleton) {
 		singleton = SC_PLUGIN_IFCFG (g_object_new (SC_TYPE_PLUGIN_IFCFG, NULL));
-		if (singleton) {
-			priv = SC_PLUGIN_IFCFG_GET_PRIVATE (singleton);
-			if (priv->bus)
-				dbus_g_connection_register_g_object (priv->bus,
-				                                     DBUS_OBJECT_PATH,
-				                                     G_OBJECT (singleton));
-			PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "Acquired D-Bus service %s", DBUS_SERVICE_NAME);
-		}
+		priv = SC_PLUGIN_IFCFG_GET_PRIVATE (singleton);
+		if (priv->bus)
+			dbus_g_connection_register_g_object (priv->bus,
+			                                     DBUS_OBJECT_PATH,
+			                                     G_OBJECT (singleton));
+		nm_log_info (LOGD_SETTINGS, "Acquired D-Bus service %s", DBUS_SERVICE_NAME);
 	} else
 		g_object_ref (singleton);
 
diff --git a/src/settings/plugins/ifcfg-rh/reader.c b/src/settings/plugins/ifcfg-rh/reader.c
index a40bf21e..7a616707 100644
--- a/src/settings/plugins/ifcfg-rh/reader.c
+++ b/src/settings/plugins/ifcfg-rh/reader.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 - 2012 Red Hat, Inc.
+ * Copyright (C) 2008 - 2013 Red Hat, Inc.
  */
 
 #include <config.h>
@@ -44,12 +44,19 @@
 #include <nm-setting-wireless.h>
 #include <nm-setting-8021x.h>
 #include <nm-setting-bond.h>
+#include <nm-setting-team.h>
+#include <nm-setting-team-port.h>
 #include <nm-setting-bridge.h>
 #include <nm-setting-bridge-port.h>
+#include <nm-setting-dcb.h>
+#include <nm-setting-generic.h>
+#include <nm-utils-private.h>
 #include <nm-utils.h>
 
-#include "wifi-utils.h"
+#include "nm-platform.h"
 #include "nm-posix-signals.h"
+#include "NetworkManagerUtils.h"
+#include "nm-logging.h"
 
 #include "common.h"
 #include "shvar.h"
@@ -57,11 +64,7 @@
 
 #include "reader.h"
 
-#define PLUGIN_PRINT(pname, fmt, args...) \
-	{ g_message ("   " pname ": " fmt, ##args); }
-
-#define PLUGIN_WARN(pname, fmt, args...) \
-	{ g_warning ("   " pname ": " fmt, ##args); }
+#define PARSE_WARNING(msg...) nm_log_warn (LOGD_SETTINGS, "    " msg)
 
 static gboolean
 get_int (const char *str, int *value)
@@ -71,7 +74,7 @@ get_int (const char *str, int *value)
 
 	errno = 0;
 	tmp = strtol (str, &e, 0);
-	if (errno || *e != '\0')
+	if (errno || *e != '\0' || tmp > G_MAXINT || tmp < G_MININT)
 		return FALSE;
 	*value = (int) tmp;
 	return TRUE;
@@ -155,6 +158,17 @@ make_connection_setting (const char *file,
 	              NULL);
 	g_free (uuid);
 
+	value = svGetValue (ifcfg, "DEVICE", FALSE);
+	if (value) {
+		if (nm_utils_iface_valid_name (value)) {
+			g_object_set (s_con,
+			              NM_SETTING_CONNECTION_INTERFACE_NAME, value,
+			              NULL);
+		} else
+			PARSE_WARNING ("invalid DEVICE name '%s'", value);
+		g_free (value);
+	}
+
 	/* Missing ONBOOT is treated as "ONBOOT=true" by the old network service */
 	g_object_set (s_con, NM_SETTING_CONNECTION_AUTOCONNECT,
 	              svTrueValue (ifcfg, "ONBOOT", TRUE),
@@ -168,7 +182,7 @@ make_connection_setting (const char *file,
 		for (iter = items; iter && *iter; iter++) {
 			if (strlen (*iter)) {
 				if (!nm_setting_connection_add_permission (s_con, "user", *iter, NULL))
-					PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: invalid USERS item '%s'", *iter);
+					PARSE_WARNING ("invalid USERS item '%s'", *iter);
 			}
 		}
 		g_free (value);
@@ -192,8 +206,7 @@ make_connection_setting (const char *file,
 		for (iter = items; iter && *iter; iter++) {
 			if (strlen (*iter)) {
 				if (!nm_setting_connection_add_secondary (s_con, *iter))
-					PLUGIN_WARN (IFCFG_PLUGIN_NAME,
-					             "    warning: secondary connection UUID '%s' already added", *iter);
+					PARSE_WARNING ("secondary connection UUID '%s' already added", *iter);
 			}
 		}
 		g_free (value);
@@ -202,18 +215,31 @@ make_connection_setting (const char *file,
 
 	value = svGetValue (ifcfg, "BRIDGE", FALSE);
 	if (value) {
-		const char *bridge;
+		const char *old_value;
 
-		if ((bridge = nm_setting_connection_get_master (s_con))) {
-			PLUGIN_WARN (IFCFG_PLUGIN_NAME,
-			             "     warning: Already configured as slave of %s. "
-			             "Ignoring BRIDGE=\"%s\"", bridge, value);
-			g_free (value);
+		if ((old_value = nm_setting_connection_get_master (s_con))) {
+			PARSE_WARNING ("Already configured as slave of %s. Ignoring BRIDGE=\"%s\"",
+			               old_value, value);
+		} else {
+			g_object_set (s_con, NM_SETTING_CONNECTION_MASTER, value, NULL);
+			g_object_set (s_con, NM_SETTING_CONNECTION_SLAVE_TYPE,
+			              NM_SETTING_BRIDGE_SETTING_NAME, NULL);
 		}
+		g_free (value);
+	}
 
-		g_object_set (s_con, NM_SETTING_CONNECTION_MASTER, value, NULL);
-		g_object_set (s_con, NM_SETTING_CONNECTION_SLAVE_TYPE,
-		              NM_SETTING_BRIDGE_SETTING_NAME, NULL);
+	value = svGetValue (ifcfg, "GATEWAY_PING_TIMEOUT", FALSE);
+	if (value) {
+		long int tmp;
+		guint32 timeout;
+
+		errno = 0;
+		tmp = strtol (value, NULL, 10);
+		if (errno == 0 && tmp >= 0 && tmp < G_MAXINT32) {
+			timeout = (guint32) tmp;
+			g_object_set (s_con, NM_SETTING_CONNECTION_GATEWAY_PING_TIMEOUT, timeout, NULL);
+		} else
+			PARSE_WARNING ("invalid GATEWAY_PING_TIMEOUT time");
 		g_free (value);
 	}
 
@@ -229,8 +255,8 @@ read_mac_address (shvarFile *ifcfg, const char *key, int type,
 	g_return_val_if_fail (ifcfg != NULL, FALSE);
 	g_return_val_if_fail (array != NULL, FALSE);
 	g_return_val_if_fail (*array == NULL, FALSE);
-	g_return_val_if_fail (error != NULL, FALSE);
-	g_return_val_if_fail (*error == NULL, FALSE);
+	if (error)
+		g_return_val_if_fail (*error == NULL, FALSE);
 
 	value = svGetValue (ifcfg, key, FALSE);
 	if (!value || !strlen (value)) {
@@ -276,8 +302,7 @@ match_iscsiadm_tag (const char *line, const char *tag, gboolean *skip)
 
 	p = strchr (line, '=');
 	if (!p) {
-		g_warning ("%s: malformed iscsiadm record: no = in '%s'.",
-		           __func__, line);
+		PARSE_WARNING ("malformed iscsiadm record: no = in '%s'.", line);
 		*skip = TRUE;
 		return NULL;
 	}
@@ -308,10 +333,10 @@ fill_ip4_setting_from_ibft (shvarFile *ifcfg,
 	GByteArray *ifcfg_mac = NULL;
 	char **lines = NULL, **iter;
 	const char *method = NULL;
-	struct in_addr ipaddr;
-	struct in_addr gateway;
-	struct in_addr dns1;
-	struct in_addr dns2;
+	guint32 ipaddr;
+	guint32 gateway;
+	guint32 dns1;
+	guint32 dns2;
 	guint32 prefix = 0;
 
 	g_return_val_if_fail (s_ip4 != NULL, FALSE);
@@ -355,14 +380,14 @@ fill_ip4_setting_from_ibft (shvarFile *ifcfg,
 
 		if (!g_ascii_strcasecmp (*iter, "# BEGIN RECORD")) {
 			if (in_record) {
-				g_warning ("%s: malformed iscsiadm record: already parsing record.", __func__);
+				PARSE_WARNING ("malformed iscsiadm record: already parsing record.");
 				skip = TRUE;
 			}
 		} else if (!g_ascii_strcasecmp (*iter, "# END RECORD")) {
 			if (!skip && hwaddr_matched) {
 				/* Record is good; fill IP4 config with its info */
 				if (!method) {
-					g_warning ("%s: malformed iscsiadm record: missing BOOTPROTO.", __func__);
+					PARSE_WARNING ("malformed iscsiadm record: missing BOOTPROTO.");
 					goto done;
 				}
 
@@ -371,23 +396,23 @@ fill_ip4_setting_from_ibft (shvarFile *ifcfg,
 				if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL)) {
 					NMIP4Address *addr;
 
-				    if (!ipaddr.s_addr || !prefix) {
-						g_warning ("%s: malformed iscsiadm record: BOOTPROTO=static "
-						           "but missing IP address or prefix.", __func__);
+				    if (!ipaddr || !prefix) {
+						PARSE_WARNING ("malformed iscsiadm record: BOOTPROTO=static "
+						               "but missing IP address or prefix.");
 						goto done;
 					}
 
 					addr = nm_ip4_address_new ();
-					nm_ip4_address_set_address (addr, ipaddr.s_addr);
+					nm_ip4_address_set_address (addr, ipaddr);
 					nm_ip4_address_set_prefix (addr, prefix);
-					nm_ip4_address_set_gateway (addr, gateway.s_addr);
+					nm_ip4_address_set_gateway (addr, gateway);
 					nm_setting_ip4_config_add_address (s_ip4, addr);
 					nm_ip4_address_unref (addr);
 
-					if (dns1.s_addr)
-						nm_setting_ip4_config_add_dns (s_ip4, dns1.s_addr);
-					if (dns2.s_addr)
-						nm_setting_ip4_config_add_dns (s_ip4, dns2.s_addr);
+					if (dns1)
+						nm_setting_ip4_config_add_dns (s_ip4, dns1);
+					if (dns2)
+						nm_setting_ip4_config_add_dns (s_ip4, dns2);
 
 					// FIXME: DNS search domains?
 				}
@@ -413,7 +438,7 @@ fill_ip4_setting_from_ibft (shvarFile *ifcfg,
 
 			ibft_mac = ether_aton (p);
 			if (!ibft_mac) {
-				g_warning ("%s: malformed iscsiadm record: invalid hwaddress.", __func__);
+				PARSE_WARNING ("malformed iscsiadm record: invalid hwaddress.");
 				skip = TRUE;
 				continue;
 			}
@@ -435,8 +460,7 @@ fill_ip4_setting_from_ibft (shvarFile *ifcfg,
 			else if (!g_ascii_strcasecmp (p, "static"))
 				method = NM_SETTING_IP4_CONFIG_METHOD_MANUAL;
 			else {
-				g_warning ("%s: malformed iscsiadm record: unknown BOOTPROTO '%s'.",
-				           __func__, p);
+				PARSE_WARNING ("malformed iscsiadm record: unknown BOOTPROTO '%s'.", p);
 				skip = TRUE;
 				continue;
 			}
@@ -444,30 +468,27 @@ fill_ip4_setting_from_ibft (shvarFile *ifcfg,
 
 		if (!skip && (p = match_iscsiadm_tag (*iter, ISCSI_IPADDR_TAG, &skip))) {
 			if (inet_pton (AF_INET, p, &ipaddr) < 1) {
-				g_warning ("%s: malformed iscsiadm record: invalid IP address '%s'.",
-				           __func__, p);
+				PARSE_WARNING ("malformed iscsiadm record: invalid IP address '%s'.", p);
 				skip = TRUE;
 				continue;
 			}
 		}
 
 		if (!skip && (p = match_iscsiadm_tag (*iter, ISCSI_SUBNET_TAG, &skip))) {
-			struct in_addr mask;
+			guint32 mask;
 
 			if (inet_pton (AF_INET, p, &mask) < 1) {
-				g_warning ("%s: malformed iscsiadm record: invalid subnet mask '%s'.",
-				           __func__, p);
+				PARSE_WARNING ("malformed iscsiadm record: invalid subnet mask '%s'.", p);
 				skip = TRUE;
 				continue;
 			}
 
-			prefix = nm_utils_ip4_netmask_to_prefix (mask.s_addr);
+			prefix = nm_utils_ip4_netmask_to_prefix (mask);
 		}
 
 		if (!skip && (p = match_iscsiadm_tag (*iter, ISCSI_GATEWAY_TAG, &skip))) {
 			if (inet_pton (AF_INET, p, &gateway) < 1) {
-				g_warning ("%s: malformed iscsiadm record: invalid IP gateway '%s'.",
-				           __func__, p);
+				PARSE_WARNING ("malformed iscsiadm record: invalid IP gateway '%s'.", p);
 				skip = TRUE;
 				continue;
 			}
@@ -475,8 +496,7 @@ fill_ip4_setting_from_ibft (shvarFile *ifcfg,
 
 		if (!skip && (p = match_iscsiadm_tag (*iter, ISCSI_DNS1_TAG, &skip))) {
 			if (inet_pton (AF_INET, p, &dns1) < 1) {
-				g_warning ("%s: malformed iscsiadm record: invalid DNS1 address '%s'.",
-				           __func__, p);
+				PARSE_WARNING ("malformed iscsiadm record: invalid DNS1 address '%s'.", p);
 				skip = TRUE;
 				continue;
 			}
@@ -484,8 +504,7 @@ fill_ip4_setting_from_ibft (shvarFile *ifcfg,
 
 		if (!skip && (p = match_iscsiadm_tag (*iter, ISCSI_DNS2_TAG, &skip))) {
 			if (inet_pton (AF_INET, p, &dns2) < 1) {
-				g_warning ("%s: malformed iscsiadm record: invalid DNS2 address '%s'.",
-				           __func__, p);
+				PARSE_WARNING ("malformed iscsiadm record: invalid DNS2 address '%s'.", p);
 				skip = TRUE;
 				continue;
 			}
@@ -503,6 +522,7 @@ done:
 	return success;
 }
 
+/* Returns TRUE on missing address or valid address */
 static gboolean
 read_ip4_address (shvarFile *ifcfg,
                   const char *tag,
@@ -510,14 +530,14 @@ read_ip4_address (shvarFile *ifcfg,
                   GError **error)
 {
 	char *value = NULL;
-	struct in_addr ip4_addr;
+	guint32 ip4_addr;
 	gboolean success = FALSE;
 
 	g_return_val_if_fail (ifcfg != NULL, FALSE);
 	g_return_val_if_fail (tag != NULL, FALSE);
 	g_return_val_if_fail (out_addr != NULL, FALSE);
-	g_return_val_if_fail (error != NULL, FALSE);
-	g_return_val_if_fail (*error == NULL, FALSE);
+	if (error)
+		g_return_val_if_fail (*error == NULL, FALSE);
 
 	*out_addr = 0;
 
@@ -526,7 +546,7 @@ read_ip4_address (shvarFile *ifcfg,
 		return TRUE;
 
 	if (inet_pton (AF_INET, value, &ip4_addr) > 0) {
-		*out_addr = ip4_addr.s_addr;
+		*out_addr = ip4_addr;
 		success = TRUE;
 	} else {
 		g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
@@ -536,87 +556,125 @@ read_ip4_address (shvarFile *ifcfg,
 	return success;
 }
 
+/* Returns TRUE on valid address, including unspecified (::) */
 static gboolean
 parse_ip6_address (const char *value,
-                  struct in6_addr *out_addr,
-                  GError **error)
+                   struct in6_addr *out_addr,
+                   GError **error)
 {
 	struct in6_addr ip6_addr;
-	gboolean success = FALSE;
 
 	g_return_val_if_fail (value != NULL, FALSE);
 	g_return_val_if_fail (out_addr != NULL, FALSE);
-	g_return_val_if_fail (error != NULL, FALSE);
-	g_return_val_if_fail (*error == NULL, FALSE);
+	if (error)
+		g_return_val_if_fail (*error == NULL, FALSE);
 
 	*out_addr = in6addr_any;
-
-	if (inet_pton (AF_INET6, value, &ip6_addr) > 0) {
-		*out_addr = ip6_addr;
-		success = TRUE;
-	} else {
+	if (inet_pton (AF_INET6, value, &ip6_addr) <= 0) {
 		g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
 		             "Invalid IP6 address '%s'", value);
+		return FALSE;
 	}
-	return success;
+
+	*out_addr = ip6_addr;
+	return TRUE;
+}
+
+static char *
+get_numbered_tag (char *tag_name, int which)
+{
+	if (which == -1)
+		return g_strdup (tag_name);
+	return g_strdup_printf ("%s%u", tag_name, which);
+}
+
+static gboolean
+is_any_ip4_address_defined (shvarFile *ifcfg)
+{
+	int i;
+
+	for (i = -1; i <= 2; i++) {
+		char *tag;
+		char *value;
+
+		tag = get_numbered_tag ("IPADDR", i);
+		value = svGetValue (ifcfg, tag, FALSE);
+		g_free (tag);
+		if (value) {
+			g_free (value);
+			return TRUE;
+		}
+
+		tag = get_numbered_tag ("PREFIX", i);
+		value = svGetValue (ifcfg, tag, FALSE);
+		g_free(tag);
+		if (value) {
+			g_free (value);
+			return TRUE;
+		}
+
+		tag = get_numbered_tag ("NETMASK", i);
+		value = svGetValue (ifcfg, tag, FALSE);
+		g_free(tag);
+		if (value) {
+			g_free (value);
+			return TRUE;
+		}
+	}
+	return FALSE;
 }
 
-static NMIP4Address *
+/* Returns TRUE on missing address or valid address */
+static gboolean
 read_full_ip4_address (shvarFile *ifcfg,
                        const char *network_file,
                        gint32 which,
+                       NMIP4Address *addr,
                        GError **error)
 {
-	NMIP4Address *addr;
 	char *ip_tag, *prefix_tag, *netmask_tag, *gw_tag;
 	guint32 tmp;
 	gboolean success = FALSE;
 	shvarFile *network_ifcfg;
 	char *value;
 
-	g_return_val_if_fail (which >= -1, NULL);
-	g_return_val_if_fail (ifcfg != NULL, NULL);
-	g_return_val_if_fail (network_file != NULL, NULL);
-
-	addr = nm_ip4_address_new ();
-	if (which == -1) {
-		ip_tag = g_strdup ("IPADDR");
-		prefix_tag = g_strdup ("PREFIX");
-		netmask_tag = g_strdup ("NETMASK");
-		gw_tag = g_strdup ("GATEWAY");
-	} else {
-		ip_tag = g_strdup_printf ("IPADDR%u", which);
-		prefix_tag = g_strdup_printf ("PREFIX%u", which);
-		netmask_tag = g_strdup_printf ("NETMASK%u", which);
-		gw_tag = g_strdup_printf ("GATEWAY%u", which);
-	}
+	g_return_val_if_fail (which >= -1, FALSE);
+	g_return_val_if_fail (ifcfg != NULL, FALSE);
+	g_return_val_if_fail (network_file != NULL, FALSE);
+	g_return_val_if_fail (addr != NULL, FALSE);
+	if (error)
+		g_return_val_if_fail (*error == NULL, FALSE);
+
+	ip_tag = get_numbered_tag ("IPADDR", which);
+	prefix_tag = get_numbered_tag ("PREFIX", which);
+	netmask_tag = get_numbered_tag ("NETMASK", which);
+	gw_tag = get_numbered_tag ("GATEWAY", which);
 
 	/* IP address */
 	if (!read_ip4_address (ifcfg, ip_tag, &tmp, error))
-		goto error;
-	if (!tmp) {
-		nm_ip4_address_unref (addr);
-		addr = NULL;
-		success = TRUE;  /* done */
-		goto error;
+		goto done;
+	if (tmp)
+		nm_ip4_address_set_address (addr, tmp);
+	else if (!nm_ip4_address_get_address (addr)) {
+		success = TRUE;
+		goto done;
 	}
-	nm_ip4_address_set_address (addr, tmp);
 
 	/* Gateway */
 	if (!read_ip4_address (ifcfg, gw_tag, &tmp, error))
-		goto error;
+		goto done;
 	if (tmp)
 		nm_ip4_address_set_gateway (addr, tmp);
 	else {
 		gboolean read_success;
 
 		/* If no gateway in the ifcfg, try /etc/sysconfig/network instead */
-		network_ifcfg = svNewFile (network_file);
+		network_ifcfg = svOpenFile (network_file, NULL);
 		if (network_ifcfg) {
 			read_success = read_ip4_address (network_ifcfg, "GATEWAY", &tmp, error);
 			svCloseFile (network_ifcfg);
 			if (!read_success)
-				goto error;
+				goto done;
 			nm_ip4_address_set_gateway (addr, tmp);
 		}
 	}
@@ -632,7 +690,7 @@ read_full_ip4_address (shvarFile *ifcfg,
 			g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
 			             "Invalid IP4 prefix '%s'", value);
 			g_free (value);
-			goto error;
+			goto done;
 		}
 		nm_ip4_address_set_prefix (addr, (guint32) prefix);
 		g_free (value);
@@ -641,7 +699,7 @@ read_full_ip4_address (shvarFile *ifcfg,
 	/* Fall back to NETMASK if no PREFIX was specified */
 	if (!nm_ip4_address_get_prefix (addr)) {
 		if (!read_ip4_address (ifcfg, netmask_tag, &tmp, error))
-			goto error;
+			goto done;
 		if (tmp)
 			nm_ip4_address_set_prefix (addr, nm_utils_ip4_netmask_to_prefix (tmp));
 	}
@@ -654,8 +712,7 @@ read_full_ip4_address (shvarFile *ifcfg,
 		nm_ip4_address_set_prefix (addr, prefix);
 
 		value = svGetValue (ifcfg, ip_tag, FALSE);
-		PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: missing %s, assuming %s/%u",
-		             prefix_tag, value, prefix);
+		PARSE_WARNING ("missing %s, assuming %s/%u", prefix_tag, value, prefix);
 		g_free (value);
 	}
 
@@ -664,28 +721,26 @@ read_full_ip4_address (shvarFile *ifcfg,
 		g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
 		             "Missing or invalid IP4 prefix '%d'",
 		             nm_ip4_address_get_prefix (addr));
-		goto error;
+		goto done;
 	}
 
 	success = TRUE;
 
-error:
-	if (!success) {
-		nm_ip4_address_unref (addr);
-		addr = NULL;
-	}
-
+done:
 	g_free (ip_tag);
 	g_free (prefix_tag);
 	g_free (netmask_tag);
 	g_free (gw_tag);
-	return addr;
+
+	return success;
 }
 
-static NMIP4Route *
+/* Returns TRUE on missing route or valid route */
+static gboolean
 read_one_ip4_route (shvarFile *ifcfg,
                     const char *network_file,
                     guint32 which,
+                    NMIP4Route **out_route,
                     GError **error)
 {
 	NMIP4Route *route;
@@ -693,8 +748,12 @@ read_one_ip4_route (shvarFile *ifcfg,
 	guint32 tmp;
 	gboolean success = FALSE;
 
-	g_return_val_if_fail (ifcfg != NULL, NULL);
-	g_return_val_if_fail (network_file != NULL, NULL);
+	g_return_val_if_fail (ifcfg != NULL, FALSE);
+	g_return_val_if_fail (network_file != NULL, FALSE);
+	g_return_val_if_fail (out_route != NULL, FALSE);
+	g_return_val_if_fail (*out_route == NULL, FALSE);
+	if (error)
+		g_return_val_if_fail (*error == NULL, FALSE);
 
 	route = nm_ip4_route_new ();
 
@@ -713,7 +772,7 @@ read_one_ip4_route (shvarFile *ifcfg,
 		if (!val) {
 			nm_ip4_route_unref (route);
 			route = NULL;
-			success = TRUE;  /* done */
+			success = TRUE;  /* missing route = success */
 			goto out;
 		}
 		g_free (val);
@@ -758,19 +817,18 @@ read_one_ip4_route (shvarFile *ifcfg,
 		g_free (value);
 	}
 
+	*out_route = route;
 	success = TRUE;
 
 out:
-	if (!success) {
+	if (!success && route)
 		nm_ip4_route_unref (route);
-		route = NULL;
-	}
 
 	g_free (ip_tag);
 	g_free (netmask_tag);
 	g_free (gw_tag);
 	g_free (metric_tag);
-	return route;
+	return success;
 }
 
 static gboolean
@@ -782,8 +840,8 @@ read_route_file_legacy (const char *filename, NMSettingIP4Config *s_ip4, GError
 	GRegex *regex_to1, *regex_to2, *regex_via, *regex_metric;
 	GMatchInfo *match_info;
 	NMIP4Route *route;
-	struct in_addr ip4_addr;
-	char *dest = NULL, *prefix = NULL, *next_hop = NULL, *metric = NULL;
+	guint32 ip4_addr;
+	char *dest = NULL, *prefix = NULL, *metric = NULL;
 	long int prefix_int, metric_int;
 	gboolean success = FALSE;
 
@@ -797,16 +855,13 @@ read_route_file_legacy (const char *filename, NMSettingIP4Config *s_ip4, GError
 
 	g_return_val_if_fail (filename != NULL, FALSE);
 	g_return_val_if_fail (s_ip4 != NULL, FALSE);
-	g_return_val_if_fail (error != NULL, FALSE);
-	g_return_val_if_fail (*error == NULL, FALSE);
+	if (error)
+		g_return_val_if_fail (*error == NULL, FALSE);
 
 	/* Read the route file */
-	if (!g_file_get_contents (filename, &contents, &len, NULL))
-		return FALSE;
-
-	if (len == 0) {
+	if (!g_file_get_contents (filename, &contents, &len, NULL) || !len) {
 		g_free (contents);
-		return FALSE;
+		return TRUE;  /* missing/empty = success */
 	}
 
 	/* Create regexes for pieces to be matched */
@@ -847,7 +902,7 @@ read_route_file_legacy (const char *filename, NMSettingIP4Config *s_ip4, GError
 			g_free (dest);
 			goto error;
 		}
-		nm_ip4_route_set_dest (route, ip4_addr.s_addr);
+		nm_ip4_route_set_dest (route, ip4_addr);
 		g_free (dest);
 
 		/* Prefix - is optional; 32 if missing */
@@ -869,22 +924,23 @@ read_route_file_legacy (const char *filename, NMSettingIP4Config *s_ip4, GError
 
 		/* Next hop */
 		g_regex_match (regex_via, *iter, 0, &match_info);
-		if (!g_match_info_matches (match_info)) {
-			g_match_info_free (match_info);
-			g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
-			             "Missing IP4 route gateway address in record: '%s'", *iter);
-			goto error;
-		}
-		next_hop = g_match_info_fetch (match_info, 1);
-		g_match_info_free (match_info);
-		if (inet_pton (AF_INET, next_hop, &ip4_addr) != 1) {
-			g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
-			             "Invalid IP4 route gateway address '%s'", next_hop);
+		if (g_match_info_matches (match_info)) {
+			char *next_hop = g_match_info_fetch (match_info, 1);
+			if (inet_pton (AF_INET, next_hop, &ip4_addr) != 1) {
+				g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
+				             "Invalid IP4 route gateway address '%s'",
+				             next_hop);
+				g_match_info_free (match_info);
+				g_free (next_hop);
+				goto error;
+			}
 			g_free (next_hop);
-			goto error;
+		} else {
+			/* we don't make distinction between missing GATEWAY IP and 0.0.0.0 */
+			ip4_addr = 0;
 		}
-		nm_ip4_route_set_next_hop (route, ip4_addr.s_addr);
-		g_free (next_hop);
+		nm_ip4_route_set_next_hop (route, ip4_addr);
+		g_match_info_free (match_info);
 
 		/* Metric */
 		g_regex_match (regex_metric, *iter, 0, &match_info);
@@ -907,7 +963,7 @@ read_route_file_legacy (const char *filename, NMSettingIP4Config *s_ip4, GError
 		g_match_info_free (match_info);
 
 		if (!nm_setting_ip4_config_add_route (s_ip4, route))
-			PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: duplicate IP4 route");
+			PARSE_WARNING ("duplicate IP4 route");
 
 	}
 
@@ -925,11 +981,12 @@ error:
 	return success;
 }
 
-static NMIP6Address *
+static gboolean
 parse_full_ip6_address (shvarFile *ifcfg,
                         const char *network_file,
                         const char *addr_str,
                         int i,
+                        NMIP6Address **out_address,
                         GError **error)
 {
 	NMIP6Address *addr = NULL;
@@ -940,11 +997,13 @@ parse_full_ip6_address (shvarFile *ifcfg,
 	struct in6_addr tmp = IN6ADDR_ANY_INIT;
 	gboolean success = FALSE;
 
-	g_return_val_if_fail (addr_str != NULL, NULL);
-	g_return_val_if_fail (error != NULL, NULL);
-	g_return_val_if_fail (*error == NULL, NULL);
+	g_return_val_if_fail (addr_str != NULL, FALSE);
+	g_return_val_if_fail (out_address != NULL, FALSE);
+	g_return_val_if_fail (*out_address == NULL, FALSE);
+	if (error)
+		g_return_val_if_fail (*error == NULL, FALSE);
 
-	/* Split the adddress and prefix */
+	/* Split the address and prefix */
 	list = g_strsplit_set (addr_str, "/", 2);
 	if (g_strv_length (list) < 1) {
 		g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
@@ -957,9 +1016,12 @@ parse_full_ip6_address (shvarFile *ifcfg,
 
 	addr = nm_ip6_address_new ();
 	/* IP address */
-	if (ip_val) {
-		if (!parse_ip6_address (ip_val, &tmp, error))
-			goto error;
+	if (!parse_ip6_address (ip_val, &tmp, error))
+		goto error;
+	if (IN6_IS_ADDR_UNSPECIFIED (&tmp)) {
+		g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
+		             "Invalid IP6 address '%s'", ip_val);
+		goto error;
 	}
 	nm_ip6_address_set_address (addr, &tmp);
 
@@ -990,7 +1052,7 @@ parse_full_ip6_address (shvarFile *ifcfg,
 	}
 	if (!value) {
 		/* If no gateway in the ifcfg, try global /etc/sysconfig/network instead */
-		network_ifcfg = svNewFile (network_file);
+		network_ifcfg = svOpenFile (network_file, NULL);
 		if (network_ifcfg) {
 			value = svGetValue (network_ifcfg, "IPV6_DEFAULTGW", FALSE);
 			svCloseFile (network_ifcfg);
@@ -1006,17 +1068,16 @@ parse_full_ip6_address (shvarFile *ifcfg,
 		nm_ip6_address_set_gateway (addr, &tmp);
 	}
 
+	*out_address = addr;
 	success = TRUE;
 
 error:
-	if (!success) {
+	if (!success && addr)
 		nm_ip6_address_unref (addr);
-		addr = NULL;
-	}
 
 	g_strfreev (list);
 	g_free (value);
-	return addr;
+	return success;
 }
 
 /* IPv6 address is very complex to describe completely by a regular expression,
@@ -1036,7 +1097,7 @@ read_route6_file (const char *filename, NMSettingIP6Config *s_ip6, GError **erro
 	GMatchInfo *match_info;
 	NMIP6Route *route;
 	struct in6_addr ip6_addr;
-	char *dest = NULL, *prefix = NULL, *next_hop = NULL, *metric = NULL;
+	char *dest = NULL, *prefix = NULL, *metric = NULL;
 	long int prefix_int, metric_int;
 	gboolean success = FALSE;
 
@@ -1050,16 +1111,13 @@ read_route6_file (const char *filename, NMSettingIP6Config *s_ip6, GError **erro
 
 	g_return_val_if_fail (filename != NULL, FALSE);
 	g_return_val_if_fail (s_ip6 != NULL, FALSE);
-	g_return_val_if_fail (error != NULL, FALSE);
-	g_return_val_if_fail (*error == NULL, FALSE);
+	if (error)
+		g_return_val_if_fail (*error == NULL, FALSE);
 
 	/* Read the route file */
-	if (!g_file_get_contents (filename, &contents, &len, NULL))
-		return FALSE;
-
-	if (len == 0) {
+	if (!g_file_get_contents (filename, &contents, &len, NULL) || !len) {
 		g_free (contents);
-		return FALSE;
+		return TRUE;  /* missing/empty = success */
 	}
 
 	/* Create regexes for pieces to be matched */
@@ -1096,8 +1154,7 @@ read_route6_file (const char *filename, NMSettingIP6Config *s_ip6, GError **erro
 			/* Ignore default route - NM handles it internally */
 			g_free (dest);
 			g_match_info_free (match_info);
-			PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: ignoring manual default route: '%s' (%s)",
-			             *iter, filename);
+			PARSE_WARNING ("ignoring manual default route: '%s' (%s)", *iter, filename);
 			continue;
 		}
 		if (inet_pton (AF_INET6, dest, &ip6_addr) != 1) {
@@ -1128,22 +1185,23 @@ read_route6_file (const char *filename, NMSettingIP6Config *s_ip6, GError **erro
 
 		/* Next hop */
 		g_regex_match (regex_via, *iter, 0, &match_info);
-		if (!g_match_info_matches (match_info)) {
-			g_match_info_free (match_info);
-			g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
-			             "Missing IP6 route gateway address in record: '%s'", *iter);
-			goto error;
-		}
-		next_hop = g_match_info_fetch (match_info, 1);
-		g_match_info_free (match_info);
-		if (inet_pton (AF_INET6, next_hop, &ip6_addr) != 1) {
-			g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
-			             "Invalid IP6 route gateway address '%s'", next_hop);
+		if (g_match_info_matches (match_info)) {
+			char *next_hop = g_match_info_fetch (match_info, 1);
+			if (inet_pton (AF_INET6, next_hop, &ip6_addr) != 1) {
+				g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
+				             "Invalid IPv6 route nexthop address '%s'",
+				             next_hop);
+				g_match_info_free (match_info);
+				g_free (next_hop);
+				goto error;
+			}
 			g_free (next_hop);
-			goto error;
+		} else {
+			/* Missing "via" is taken as :: */
+			ip6_addr = in6addr_any;
 		}
 		nm_ip6_route_set_next_hop (route, &ip6_addr);
-		g_free (next_hop);
+		g_match_info_free (match_info);
 
 		/* Metric */
 		g_regex_match (regex_metric, *iter, 0, &match_info);
@@ -1166,7 +1224,7 @@ read_route6_file (const char *filename, NMSettingIP6Config *s_ip6, GError **erro
 		g_match_info_free (match_info);
 
 		if (!nm_setting_ip6_config_add_route (s_ip6, route))
-			PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: duplicate IP6 route");
+			PARSE_WARNING ("duplicate IP6 route");
 	}
 
 	success = TRUE;
@@ -1188,24 +1246,18 @@ static NMSetting *
 make_ip4_setting (shvarFile *ifcfg,
                   const char *network_file,
                   const char *iscsiadm_path,
-                  gboolean can_disable_ip4,
                   GError **error)
 {
 	NMSettingIP4Config *s_ip4 = NULL;
 	char *value = NULL;
 	char *route_path = NULL;
-	char *method = NM_SETTING_IP4_CONFIG_METHOD_MANUAL;
+	char *method;
 	gint32 i;
 	shvarFile *network_ifcfg;
 	shvarFile *route_ifcfg;
-	gboolean never_default = FALSE, tmp_success;
+	gboolean never_default = FALSE;
 
 	s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
-	if (!s_ip4) {
-		g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
-		             "Could not allocate IP4 setting");
-		return NULL;
-	}
 
 	/* First check if DEFROUTE is set for this device; DEFROUTE has the
 	 * opposite meaning from never-default. The default if DEFROUTE is not
@@ -1215,7 +1267,7 @@ make_ip4_setting (shvarFile *ifcfg,
 	never_default = !svTrueValue (ifcfg, "DEFROUTE", TRUE);
 
 	/* Then check if GATEWAYDEV; it's global and overrides DEFROUTE */
-	network_ifcfg = svNewFile (network_file);
+	network_ifcfg = svOpenFile (network_file, NULL);
 	if (network_ifcfg) {
 		char *gatewaydev;
 
@@ -1235,93 +1287,47 @@ make_ip4_setting (shvarFile *ifcfg,
 	}
 
 	value = svGetValue (ifcfg, "BOOTPROTO", FALSE);
-	if (value) {
-		if (!g_ascii_strcasecmp (value, "bootp") || !g_ascii_strcasecmp (value, "dhcp"))
-			method = NM_SETTING_IP4_CONFIG_METHOD_AUTO;
-		else if (!g_ascii_strcasecmp (value, "ibft")) {
-			g_free (value);
-			g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_NEVER_DEFAULT, never_default, NULL);
-			/* iSCSI Boot Firmware Table: need to read values from the iSCSI 
-			 * firmware for this device and create the IP4 setting using those.
-			 */
-			if (fill_ip4_setting_from_ibft (ifcfg, s_ip4, iscsiadm_path, error))
-				return NM_SETTING (s_ip4);
-			g_object_unref (s_ip4);
-			return NULL;
-		} else if (!g_ascii_strcasecmp (value, "autoip")) {
-			g_free (value);
-			g_object_set (s_ip4,
-			              NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL,
-			              NM_SETTING_IP4_CONFIG_NEVER_DEFAULT, never_default,
-			              NULL);
-			return NM_SETTING (s_ip4);
-		} else if (!g_ascii_strcasecmp (value, "shared")) {
-			g_free (value);
-			g_object_set (s_ip4,
-			              NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_SHARED,
-			              NM_SETTING_IP4_CONFIG_NEVER_DEFAULT, never_default,
-			              NULL);
+
+	if (!value || !*value || !g_ascii_strcasecmp (value, "none")) {
+		if (is_any_ip4_address_defined (ifcfg))
+			method = NM_SETTING_IP4_CONFIG_METHOD_MANUAL;
+		else
+			method = NM_SETTING_IP4_CONFIG_METHOD_DISABLED;
+	} else if (!g_ascii_strcasecmp (value, "bootp") || !g_ascii_strcasecmp (value, "dhcp")) {
+		method = NM_SETTING_IP4_CONFIG_METHOD_AUTO;
+	} else if (!g_ascii_strcasecmp (value, "static")) {
+		method = NM_SETTING_IP4_CONFIG_METHOD_MANUAL;
+	} else if (!g_ascii_strcasecmp (value, "ibft")) {
+		g_free (value);
+		g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_NEVER_DEFAULT, never_default, NULL);
+		/* iSCSI Boot Firmware Table: need to read values from the iSCSI
+		 * firmware for this device and create the IP4 setting using those.
+		 */
+		if (fill_ip4_setting_from_ibft (ifcfg, s_ip4, iscsiadm_path, error))
 			return NM_SETTING (s_ip4);
-		} else if (!g_ascii_strcasecmp (value, "none") || !g_ascii_strcasecmp (value, "static")) {
-			/* Static IP */
-		} else if (strlen (value)) {
-			g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
-			             "Unknown BOOTPROTO '%s'", value);
-			g_free (value);
-			goto done;
-		}
+		g_object_unref (s_ip4);
+		return NULL;
+	} else if (!g_ascii_strcasecmp (value, "autoip")) {
 		g_free (value);
+		g_object_set (s_ip4,
+		              NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL,
+		              NM_SETTING_IP4_CONFIG_NEVER_DEFAULT, never_default,
+		              NULL);
+		return NM_SETTING (s_ip4);
+	} else if (!g_ascii_strcasecmp (value, "shared")) {
+		g_free (value);
+		g_object_set (s_ip4,
+		              NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_SHARED,
+		              NM_SETTING_IP4_CONFIG_NEVER_DEFAULT, never_default,
+		              NULL);
+		return NM_SETTING (s_ip4);
 	} else {
-		char *tmp_ip4, *tmp_prefix, *tmp_netmask;
-		char *tmp_ip4_0, *tmp_prefix_0, *tmp_netmask_0;
-		char *tmp_ip4_1, *tmp_prefix_1, *tmp_netmask_1;
-		char *tmp_ip4_2, *tmp_prefix_2, *tmp_netmask_2;
-
-		/* If there is no BOOTPROTO, no IPADDR, no PREFIX, no NETMASK, but
-		 * valid IPv6 configuration, assume that IPv4 is disabled.  Otherwise,
-		 * if there is no IPv6 configuration, assume DHCP is to be used.
-		 * Happens with minimal ifcfg files like the following that anaconda
-		 * sometimes used to write out:
-		 *
-		 * DEVICE=eth0
-		 * HWADDR=11:22:33:44:55:66
-		 *
-		 */
-		tmp_ip4 = svGetValue (ifcfg, "IPADDR", FALSE);
-		tmp_prefix = svGetValue (ifcfg, "PREFIX", FALSE);
-		tmp_netmask = svGetValue (ifcfg, "NETMASK", FALSE);
-		tmp_ip4_0 = svGetValue (ifcfg, "IPADDR0", FALSE);
-		tmp_prefix_0 = svGetValue (ifcfg, "PREFIX0", FALSE);
-		tmp_netmask_0 = svGetValue (ifcfg, "NETMASK0", FALSE);
-		tmp_ip4_1 = svGetValue (ifcfg, "IPADDR1", FALSE);
-		tmp_prefix_1 = svGetValue (ifcfg, "PREFIX1", FALSE);
-		tmp_netmask_1 = svGetValue (ifcfg, "NETMASK1", FALSE);
-		tmp_ip4_2 = svGetValue (ifcfg, "IPADDR2", FALSE);
-		tmp_prefix_2 = svGetValue (ifcfg, "PREFIX2", FALSE);
-		tmp_netmask_2 = svGetValue (ifcfg, "NETMASK2", FALSE);
-		if (   !tmp_ip4   && !tmp_prefix   && !tmp_netmask
-		    && !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 (can_disable_ip4)
-				/* Nope, no IPv4 */
-				method = NM_SETTING_IP4_CONFIG_METHOD_DISABLED;
-			else
-				method = NM_SETTING_IP4_CONFIG_METHOD_AUTO;
-		}
-		g_free (tmp_ip4);
-		g_free (tmp_prefix);
-		g_free (tmp_netmask);
-		g_free (tmp_ip4_0);
-		g_free (tmp_prefix_0);
-		g_free (tmp_netmask_0);
-		g_free (tmp_ip4_1);
-		g_free (tmp_prefix_1);
-		g_free (tmp_netmask_1);
-		g_free (tmp_ip4_2);
-		g_free (tmp_prefix_2);
-		g_free (tmp_netmask_2);
+		g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
+		             "Unknown BOOTPROTO '%s'", value);
+		g_free (value);
+		goto done;
 	}
+	g_free (value);
 
 	g_object_set (s_ip4,
 	              NM_SETTING_IP4_CONFIG_METHOD, method,
@@ -1334,27 +1340,8 @@ make_ip4_setting (shvarFile *ifcfg,
 	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;
-
-		for (i = -1; i < 256; i++) {
-			addr = read_full_ip4_address (ifcfg, network_file, i, error);
-			if (error && *error)
-				goto done;
-			if (!addr) {
-				/* The first mandatory variable is 2-indexed (IPADDR2)
-				 * Variables IPADDR, IPADDR0 and IPADDR1 are optional */
-				if (i > 1)
-					break;
-				continue;
-			}
-
-			if (!nm_setting_ip4_config_add_address (s_ip4, addr))
-				PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: duplicate IP4 address");
-			nm_ip4_address_unref (addr);
-		}
-	} else if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) {
+	/* Handle DHCP settings */
+	if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) {
 		value = svGetValue (ifcfg, "DHCP_HOSTNAME", FALSE);
 		if (value && strlen (value))
 			g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_DHCP_HOSTNAME, value, NULL);
@@ -1371,27 +1358,54 @@ make_ip4_setting (shvarFile *ifcfg,
 		g_free (value);
 	}
 
+	/* Read static IP addresses.
+	 * Read them even for AUTO method - in this case the addresses are
+	 * added to the automatic ones. Note that this is not currently supported by
+	 * the legacy 'network' service (ifup-eth).
+	 */
+	for (i = -1; i < 256; i++) {
+		NMIP4Address *addr = NULL;
+
+		addr = nm_ip4_address_new ();
+		if (!read_full_ip4_address (ifcfg, network_file, i, addr, error)) {
+			nm_ip4_address_unref (addr);
+			goto done;
+		}
+		if (!nm_ip4_address_get_address (addr)) {
+			nm_ip4_address_unref (addr);
+
+			/* The first mandatory variable is 2-indexed (IPADDR2)
+			 * Variables IPADDR, IPADDR0 and IPADDR1 are optional */
+			if (i > 1)
+				break;
+			continue;
+		}
+
+		if (!nm_setting_ip4_config_add_address (s_ip4, addr))
+			PARSE_WARNING ("duplicate IP4 address");
+		nm_ip4_address_unref (addr);
+	}
+
 	/* DNS servers
 	 * Pick up just IPv4 addresses (IPv6 addresses are taken by make_ip6_setting())
 	 */
-	for (i = 1, tmp_success = TRUE; i <= 10 && tmp_success; i++) {
+	for (i = 1; i <= 10; i++) {
 		char *tag;
 		guint32 dns;
 		struct in6_addr ip6_dns;
-		GError *tmp_err = NULL;
 
 		tag = g_strdup_printf ("DNS%u", i);
-		tmp_success = read_ip4_address (ifcfg, tag, &dns, error);
-		if (!tmp_success) {
-			/* if it's IPv6, don't exit */
+		if (!read_ip4_address (ifcfg, tag, &dns, error)) {
+			gboolean valid = TRUE;
+
+			/* Ignore IPv6 addresses */
 			dns = 0;
 			value = svGetValue (ifcfg, tag, FALSE);
-			if (value) {
-				tmp_success = parse_ip6_address (value, &ip6_dns, &tmp_err);
-				g_clear_error (&tmp_err);
-				g_free (value);
-			}
-			if (!tmp_success) {
+			if (value)
+				valid = parse_ip6_address (value, &ip6_dns, NULL);
+			g_free (value);
+
+			if (!valid) {
 				g_free (tag);
 				goto done;
 			}
@@ -1399,7 +1413,7 @@ make_ip4_setting (shvarFile *ifcfg,
 		}
 
 		if (dns && !nm_setting_ip4_config_add_dns (s_ip4, dns))
-			PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: duplicate DNS server %s", tag);
+			PARSE_WARNING ("duplicate DNS server %s", tag);
 		g_free (tag);
 	}
 
@@ -1414,7 +1428,7 @@ make_ip4_setting (shvarFile *ifcfg,
 			for (item = searches; *item; item++) {
 				if (strlen (*item)) {
 					if (!nm_setting_ip4_config_add_dns_search (s_ip4, *item))
-						PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: duplicate DNS domain '%s'", *item);
+						PARSE_WARNING ("duplicate DNS domain '%s'", *item);
 				}
 			}
 			g_strfreev (searches);
@@ -1433,29 +1447,27 @@ make_ip4_setting (shvarFile *ifcfg,
 	/* First test new/legacy syntax */
 	if (utils_has_route_file_new_syntax (route_path)) {
 		/* Parse route file in new syntax */
-		g_free (route_path);
 		route_ifcfg = utils_get_route_ifcfg (ifcfg->fileName, FALSE);
 		if (route_ifcfg) {
-			NMIP4Route *route;
 			for (i = 0; i < 256; i++) {
-				route = read_one_ip4_route (route_ifcfg, network_file, i, error);
-				if (error && *error) {
+				NMIP4Route *route = NULL;
+
+				if (!read_one_ip4_route (route_ifcfg, network_file, i, &route, error)) {
 					svCloseFile (route_ifcfg);
 					goto done;
 				}
+
 				if (!route)
 					break;
 
 				if (!nm_setting_ip4_config_add_route (s_ip4, route))
-					PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: duplicate IP4 route");
+					PARSE_WARNING ("duplicate IP4 route");
 				nm_ip4_route_unref (route);
 			}
 			svCloseFile (route_ifcfg);
 		}
 	} else {
-		read_route_file_legacy (route_path, s_ip4, error);
-		g_free (route_path);
-		if (error && *error)
+		if (!read_route_file_legacy (route_path, s_ip4, error))
 			goto done;
 	}
 
@@ -1471,7 +1483,7 @@ make_ip4_setting (shvarFile *ifcfg,
 				for (item = searches; *item; item++) {
 					if (strlen (*item)) {
 						if (!nm_setting_ip4_config_add_dns_search (s_ip4, *item))
-							PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: duplicate DNS search '%s'", *item);
+							PARSE_WARNING ("duplicate DNS search '%s'", *item);
 					}
 				}
 				g_strfreev (searches);
@@ -1483,10 +1495,111 @@ make_ip4_setting (shvarFile *ifcfg,
 	return NM_SETTING (s_ip4);
 
 done:
+	g_free (route_path);
 	g_object_unref (s_ip4);
 	return NULL;
 }
 
+static void
+read_aliases (NMSettingIP4Config *s_ip4, const char *filename, const char *network_file)
+{
+	GDir *dir;
+	char *dirname, *base;
+	shvarFile *parsed;
+	NMIP4Address *base_addr;
+	GError *err = NULL;
+
+	g_return_if_fail (s_ip4 != NULL);
+	g_return_if_fail (filename != NULL);
+
+	base_addr = nm_setting_ip4_config_get_address (s_ip4, 0);
+	if (!base_addr)
+		return;
+
+	dirname = g_path_get_dirname (filename);
+	g_return_if_fail (dirname != NULL);
+	base = g_path_get_basename (filename);
+	g_return_if_fail (base != NULL);
+
+	dir = g_dir_open (dirname, 0, &err);
+	if (dir) {
+		const char *item;
+		NMIP4Address *addr;
+		gboolean ok;
+
+		while ((item = g_dir_read_name (dir))) {
+			char *full_path, *device;
+			const char *p;
+
+			if (!utils_is_ifcfg_alias_file (item, base))
+				continue;
+
+			full_path = g_build_filename (dirname, item, NULL);
+
+			p = strchr (item, ':');
+			g_assert (p != NULL); /* we know this is true from utils_is_ifcfg_alias_file() */
+			for (p++; *p; p++) {
+				if (!g_ascii_isalnum (*p) && *p != '_')
+					break;
+			}
+			if (*p) {
+				PARSE_WARNING ("ignoring alias file '%s' with invalid name", full_path);
+				g_free (full_path);
+				continue;
+			}
+
+			parsed = svOpenFile (full_path, &err);
+			if (!parsed) {
+				PARSE_WARNING ("couldn't parse alias file '%s': %s", full_path, err->message);
+				g_free (full_path);
+				g_clear_error (&err);
+				continue;
+			}
+
+			device = svGetValue (parsed, "DEVICE", FALSE);
+			if (!device) {
+				PARSE_WARNING ("alias file '%s' has no DEVICE", full_path);
+				svCloseFile (parsed);
+				g_free (full_path);
+				continue;
+			}
+			/* We know that item starts with IFCFG_TAG from utils_is_ifcfg_alias_file() */
+			if (strcmp (device, item + strlen (IFCFG_TAG)) != 0) {
+				PARSE_WARNING ("alias file '%s' has invalid DEVICE (%s) for filename",
+				               full_path, device);
+				g_free (device);
+				svCloseFile (parsed);
+				g_free (full_path);
+				continue;
+			}
+
+			addr = nm_ip4_address_dup (base_addr);
+			ok = read_full_ip4_address (parsed, network_file, -1, addr, &err);
+			svCloseFile (parsed);
+			if (ok) {
+				if (!NM_UTILS_PRIVATE_CALL (nm_setting_ip4_config_add_address_with_label (s_ip4, addr, device)))
+					PARSE_WARNING ("duplicate IP4 address in alias file %s", item);
+			} else {
+				PARSE_WARNING ("error reading IP4 address from alias file '%s': %s",
+				               full_path, err ? err->message : "no address");
+				g_clear_error (&err);
+			}
+			nm_ip4_address_unref (addr);
+
+			g_free (device);
+			g_free (full_path);
+		}
+
+		g_dir_close (dir);
+	} else {
+		PARSE_WARNING ("can not read directory '%s': %s", dirname, err->message);
+		g_error_free (err);
+	}
+
+	g_free (base);
+	g_free (dirname);
+}
+
 static NMSetting *
 make_ip6_setting (shvarFile *ifcfg,
                   const char *network_file,
@@ -1499,19 +1612,16 @@ make_ip6_setting (shvarFile *ifcfg,
 	char *route6_path = NULL;
 	gboolean ipv6init, ipv6forwarding, ipv6_autoconf, dhcp6 = FALSE;
 	char *method = NM_SETTING_IP6_CONFIG_METHOD_MANUAL;
+	char *ipv6addr, *ipv6addr_secondaries;
+	char **list = NULL, **iter;
 	guint32 i;
 	shvarFile *network_ifcfg;
-	gboolean never_default = FALSE, tmp_success;
+	gboolean never_default = FALSE;
 	gboolean ip6_privacy = FALSE, ip6_privacy_prefer_public_ip;
 	char *ip6_privacy_str;
 	NMSettingIP6ConfigPrivacy ip6_privacy_val;
 
 	s_ip6 = (NMSettingIP6Config *) nm_setting_ip6_config_new ();
-	if (!s_ip6) {
-		g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
-		             "Could not allocate IP6 setting");
-		return NULL;
-	}
 
 	/* 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
@@ -1524,7 +1634,7 @@ make_ip6_setting (shvarFile *ifcfg,
 	 * they are global and override IPV6_DEFROUTE
 	 * When both are set, the device specified in IPV6_DEFAULTGW takes preference.
 	 */
-	network_ifcfg = svNewFile (network_file);
+	network_ifcfg = svOpenFile (network_file, NULL);
 	if (network_ifcfg) {
 		char *ipv6_defaultgw, *ipv6_defaultdev;
 		char *default_dev = NULL;
@@ -1559,7 +1669,7 @@ make_ip6_setting (shvarFile *ifcfg,
 	str_value = svGetValue (ifcfg, "IPV6INIT", FALSE);
 	ipv6init = svTrueValue (ifcfg, "IPV6INIT", FALSE);
 	if (!str_value) {
-		network_ifcfg = svNewFile (network_file);
+		network_ifcfg = svOpenFile (network_file, NULL);
 		if (network_ifcfg) {
 			ipv6init = svTrueValue (network_ifcfg, "IPV6INIT", FALSE);
 			svCloseFile (network_ifcfg);
@@ -1620,38 +1730,8 @@ make_ip6_setting (shvarFile *ifcfg,
 	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;
-		char *ipv6addr, *ipv6addr_secondaries;
-		char **list = NULL, **iter;
-
-		ipv6addr = svGetValue (ifcfg, "IPV6ADDR", FALSE);
-		ipv6addr_secondaries = svGetValue (ifcfg, "IPV6ADDR_SECONDARIES", FALSE);
-
-		val = g_strjoin (ipv6addr && ipv6addr_secondaries ? " " : NULL,
-		                 ipv6addr ? ipv6addr : "",
-		                 ipv6addr_secondaries ? ipv6addr_secondaries : "",
-		                 NULL);
-		g_free (ipv6addr);
-		g_free (ipv6addr_secondaries);
-
-		list = g_strsplit_set (val, " ", 0);
-		g_free (val);
-		for (iter = list, i = 0; iter && *iter; iter++, i++) {
-			addr = parse_full_ip6_address (ifcfg, network_file, *iter, i, error);
-			if (!addr) {
-				g_strfreev (list);
-				goto error;
-			}
-
-			if (!nm_setting_ip6_config_add_address (s_ip6, addr))
-				PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: duplicate IP6 address");
-			nm_ip6_address_unref (addr);
-		}
-		g_strfreev (list);
-	} else if (   !strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO)
-	           || !strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_DHCP)) {
+	if (   !strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO)
+	    || !strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_DHCP)) {
 		/* METHOD_AUTO may trigger DHCPv6, so save the hostname to send to DHCP */
 		value = svGetValue (ifcfg, "DHCP_HOSTNAME", FALSE);
 		if (value && value[0])
@@ -1659,33 +1739,66 @@ make_ip6_setting (shvarFile *ifcfg,
 		g_free (value);
 	}
 
+	/* Read static IP addresses.
+	 * Read them even for AUTO and DHCP methods - in this case the addresses are
+	 * added to the automatic ones. Note that this is not currently supported by
+	 * the legacy 'network' service (ifup-eth).
+	 */
+	ipv6addr = svGetValue (ifcfg, "IPV6ADDR", FALSE);
+	ipv6addr_secondaries = svGetValue (ifcfg, "IPV6ADDR_SECONDARIES", FALSE);
+
+	value = g_strjoin (ipv6addr && ipv6addr_secondaries ? " " : NULL,
+	                   ipv6addr ? ipv6addr : "",
+	                   ipv6addr_secondaries ? ipv6addr_secondaries : "",
+	                   NULL);
+	g_free (ipv6addr);
+	g_free (ipv6addr_secondaries);
+
+	list = g_strsplit_set (value, " ", 0);
+	g_free (value);
+	for (iter = list, i = 0; iter && *iter; iter++, i++) {
+		NMIP6Address *addr = NULL;
+
+		if (!parse_full_ip6_address (ifcfg, network_file, *iter, i, &addr, error)) {
+			g_strfreev (list);
+			goto error;
+		}
+
+		if (!nm_setting_ip6_config_add_address (s_ip6, addr))
+			PARSE_WARNING ("duplicate IP6 address");
+		nm_ip6_address_unref (addr);
+	}
+	g_strfreev (list);
+
 	/* DNS servers
 	 * Pick up just IPv6 addresses (IPv4 addresses are taken by make_ip4_setting())
 	 */
-	for (i = 1, tmp_success = TRUE; i <= 10 && tmp_success; i++) {
+	for (i = 1; i <= 10; i++) {
 		char *tag;
 		struct in6_addr ip6_dns;
+		guint32 ip4_addr;
 
-		ip6_dns = in6addr_any;
 		tag = g_strdup_printf ("DNS%u", i);
 		value = svGetValue (ifcfg, tag, FALSE);
-		if (value)
-			tmp_success = parse_ip6_address (value, &ip6_dns, error);
+		if (!value) {
+			g_free (tag);
+			break; /* all done */
+		}
 
-		if (!tmp_success) {
-			struct in_addr ip4_addr;
+		ip6_dns = in6addr_any;
+		if (parse_ip6_address (value, &ip6_dns, NULL)) {
+			if (!IN6_IS_ADDR_UNSPECIFIED (&ip6_dns) && !nm_setting_ip6_config_add_dns (s_ip6, &ip6_dns))
+				PARSE_WARNING ("duplicate DNS server %s", tag);
+		} else {
+			/* Maybe an IPv4 address? If so ignore it */
 			if (inet_pton (AF_INET, value, &ip4_addr) != 1) {
 				g_free (tag);
 				g_free (value);
+				PARSE_WARNING ("duplicate IP6 address");
 				goto error;
 			}
-			/* ignore error - it is IPv4 address */
-			tmp_success = TRUE;
-			g_clear_error (error);
 		}
 
-		if (!IN6_IS_ADDR_UNSPECIFIED (&ip6_dns) && !nm_setting_ip6_config_add_dns (s_ip6, &ip6_dns))
-			PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: duplicate DNS server %s", tag);
 		g_free (tag);
 		g_free (value);
 	}
@@ -1700,14 +1813,14 @@ make_ip6_setting (shvarFile *ifcfg,
 		goto error;
 	}
 
-	read_route6_file (route6_path, s_ip6, error);
-	g_free (route6_path);
-	if (error && *error)
+	if (!read_route6_file (route6_path, s_ip6, error))
 		goto error;
 
+	g_free (route6_path);
 	return NM_SETTING (s_ip6);
 
 error:
+	g_free (route6_path);
 	g_object_unref (s_ip6);
 	return NULL;
 }
@@ -1726,6 +1839,423 @@ check_if_bond_slave (shvarFile *ifcfg,
 		              NULL);
 		g_free (value);
 	}
+
+	/* We should be checking for SLAVE=yes as well, but NM used to not set that,
+	 * so for backward-compatibility, we don't check.
+	 */
+}
+
+static void
+check_if_team_slave (shvarFile *ifcfg,
+                     NMSettingConnection *s_con)
+{
+	char *value;
+
+	value = svGetValue (ifcfg, "DEVICETYPE", FALSE);
+	if (!value)
+		return;
+	if (strcasecmp (value, TYPE_TEAM_PORT)) {
+		g_free (value);
+		return;
+	}
+	g_free (value);
+	value = svGetValue (ifcfg, "TEAM_MASTER", FALSE);
+	if (!value)
+		return;
+	g_object_set (s_con, NM_SETTING_CONNECTION_MASTER, value, NULL);
+	g_object_set (s_con, NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_TEAM_SETTING_NAME, NULL);
+	g_free (value);
+}
+
+typedef struct {
+	const char *enable_key;
+	const char *advertise_key;
+	const char *willing_key;
+	const char *flags_prop;
+} DcbFlagsProperty;
+
+enum {
+	DCB_APP_FCOE_FLAGS = 0,
+	DCB_APP_ISCSI_FLAGS = 1,
+	DCB_APP_FIP_FLAGS = 2,
+	DCB_PFC_FLAGS = 3,
+	DCB_PG_FLAGS = 4,
+};
+
+static DcbFlagsProperty dcb_flags_props[] = {
+	{ KEY_DCB_APP_FCOE_ENABLE,  KEY_DCB_APP_FCOE_ADVERTISE,  KEY_DCB_APP_FCOE_WILLING,  NM_SETTING_DCB_APP_FCOE_FLAGS },
+	{ KEY_DCB_APP_ISCSI_ENABLE, KEY_DCB_APP_ISCSI_ADVERTISE, KEY_DCB_APP_ISCSI_WILLING, NM_SETTING_DCB_APP_ISCSI_FLAGS },
+	{ KEY_DCB_APP_FIP_ENABLE,   KEY_DCB_APP_FIP_ADVERTISE,   KEY_DCB_APP_FIP_WILLING,   NM_SETTING_DCB_APP_FIP_FLAGS },
+	{ KEY_DCB_PFC_ENABLE,       KEY_DCB_PFC_ADVERTISE,       KEY_DCB_PFC_WILLING,       NM_SETTING_DCB_PRIORITY_FLOW_CONTROL_FLAGS },
+	{ KEY_DCB_PG_ENABLE,        KEY_DCB_PG_ADVERTISE,        KEY_DCB_PG_WILLING,        NM_SETTING_DCB_PRIORITY_GROUP_FLAGS },
+	{ NULL },
+};
+
+static NMSettingDcbFlags
+read_dcb_flags (shvarFile *ifcfg, DcbFlagsProperty *property)
+{
+	NMSettingDcbFlags flags = NM_SETTING_DCB_FLAG_NONE;
+
+	if (svTrueValue (ifcfg, property->enable_key, FALSE))
+		flags |= NM_SETTING_DCB_FLAG_ENABLE;
+	if (svTrueValue (ifcfg, property->advertise_key, FALSE))
+		flags |= NM_SETTING_DCB_FLAG_ADVERTISE;
+	if (svTrueValue (ifcfg, property->willing_key, FALSE))
+		flags |= NM_SETTING_DCB_FLAG_WILLING;
+
+	return flags;
+}
+
+static gboolean
+read_dcb_app (shvarFile *ifcfg,
+              NMSettingDcb *s_dcb,
+              const char *app,
+              DcbFlagsProperty *flags_prop,
+              const char *priority_prop,
+              GError **error)
+{
+	NMSettingDcbFlags flags = NM_SETTING_DCB_FLAG_NONE;
+	char *tmp, *val;
+	gboolean success = TRUE;
+	int priority = -1;
+
+	flags = read_dcb_flags (ifcfg, flags_prop);
+
+	/* Priority */
+	tmp = g_strdup_printf ("DCB_APP_%s_PRIORITY", app);
+	val = svGetValue (ifcfg, tmp, FALSE);
+	if (val) {
+		success = get_int (val, &priority);
+		if (success)
+			success = (priority >= 0 && priority <= 7);
+		if (!success) {
+			g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
+			             "Invalid %s value '%s' (expected 0 - 7)",
+			             tmp, val);
+		}
+		g_free (val);
+
+		if (!(flags & NM_SETTING_DCB_FLAG_ENABLE))
+			PARSE_WARNING ("ignoring DCB %s priority; app not enabled", app);
+	}
+	g_free (tmp);
+
+	if (success) {
+		g_object_set (G_OBJECT (s_dcb),
+		              flags_prop->flags_prop, flags,
+		              priority_prop, (guint) priority,
+		              NULL);
+	}
+
+	return success;
+}
+
+typedef void (*DcbSetBoolFunc) (NMSettingDcb *, guint, gboolean);
+
+static gboolean
+read_dcb_bool_array (shvarFile *ifcfg,
+                     NMSettingDcb *s_dcb,
+                     NMSettingDcbFlags flags,
+                     const char *prop,
+                     const char *desc,
+                     DcbSetBoolFunc set_func,
+                     GError **error)
+{
+	char *val;
+	gboolean success = FALSE;
+	guint i;
+
+	val = svGetValue (ifcfg, prop, FALSE);
+	if (!val)
+		return TRUE;
+
+	if (!(flags & NM_SETTING_DCB_FLAG_ENABLE)) {
+		PARSE_WARNING ("ignoring %s; %s is not enabled", prop, desc);
+		success = TRUE;
+		goto out;
+	}
+
+	val = g_strstrip (val);
+	if (strlen (val) != 8) {
+		PARSE_WARNING ("%s value '%s' must be 8 characters long", prop, val);
+		g_set_error_literal (error, IFCFG_PLUGIN_ERROR, 0, "boolean array must be 8 characters");
+		goto out;
+	}
+
+	/* All characters must be either 0 or 1 */
+	for (i = 0; i < 8; i++) {
+		if (val[i] != '0' && val[i] != '1') {
+			PARSE_WARNING ("invalid %s value '%s': not all 0s and 1s", prop, val);
+			g_set_error_literal (error, IFCFG_PLUGIN_ERROR, 0, "invalid boolean digit");
+			goto out;
+		}
+		set_func (s_dcb, i, (val[i] == '1'));
+	}
+	success = TRUE;
+
+out:
+	g_free (val);
+	return success;
+}
+
+typedef void (*DcbSetUintFunc) (NMSettingDcb *, guint, guint);
+
+static gboolean
+read_dcb_uint_array (shvarFile *ifcfg,
+                     NMSettingDcb *s_dcb,
+                     NMSettingDcbFlags flags,
+                     const char *prop,
+                     const char *desc,
+                     gboolean f_allowed,
+                     DcbSetUintFunc set_func,
+                     GError **error)
+{
+	char *val;
+	gboolean success = FALSE;
+	guint i;
+
+	val = svGetValue (ifcfg, prop, FALSE);
+	if (!val)
+		return TRUE;
+
+	if (!(flags & NM_SETTING_DCB_FLAG_ENABLE)) {
+		PARSE_WARNING ("ignoring %s; %s is not enabled", prop, desc);
+		success = TRUE;
+		goto out;
+	}
+
+	val = g_strstrip (val);
+	if (strlen (val) != 8) {
+		PARSE_WARNING ("%s value '%s' must be 8 characters long", prop, val);
+		g_set_error_literal (error, IFCFG_PLUGIN_ERROR, 0, "uint array must be 8 characters");
+		goto out;
+	}
+
+	/* All characters must be either 0 - 7 or (optionally) f */
+	for (i = 0; i < 8; i++) {
+		if (val[i] >= '0' && val[i] <= '7')
+			set_func (s_dcb, i, val[i] - '0');
+		else if (f_allowed && (val[i] == 'f' || val[i] == 'F'))
+			set_func (s_dcb, i, 15);
+		else {
+			PARSE_WARNING ("invalid %s value '%s': not 0 - 7%s",
+			               prop, val, f_allowed ? " or 'f'" : "");
+			g_set_error_literal (error, IFCFG_PLUGIN_ERROR, 0, "invalid uint digit");
+			goto out;
+		}
+	}
+	success = TRUE;
+
+out:
+	g_free (val);
+	return success;
+}
+
+static gboolean
+read_dcb_percent_array (shvarFile *ifcfg,
+                        NMSettingDcb *s_dcb,
+                        NMSettingDcbFlags flags,
+                        const char *prop,
+                        const char *desc,
+                        gboolean sum_pct,
+                        DcbSetUintFunc set_func,
+                        GError **error)
+{
+	char *val;
+	gboolean success = FALSE;
+	char **split = NULL, **iter;
+	int tmp;
+	guint i, sum = 0;
+
+	val = svGetValue (ifcfg, prop, FALSE);
+	if (!val)
+		return TRUE;
+
+	if (!(flags & NM_SETTING_DCB_FLAG_ENABLE)) {
+		PARSE_WARNING ("ignoring %s; %s is not enabled", prop, desc);
+		success = TRUE;
+		goto out;
+	}
+
+	val = g_strstrip (val);
+	split = g_strsplit_set (val, ",", 0);
+	if (!split || (g_strv_length (split) != 8)) {
+		PARSE_WARNING ("invalid %s percentage list value '%s'", prop, val);
+		g_set_error_literal (error, IFCFG_PLUGIN_ERROR, 0, "percent array must be 8 elements");
+		goto out;
+	}
+
+	for (iter = split, i = 0; iter && *iter; iter++, i++) {
+		if (!get_int (*iter, &tmp) || tmp < 0 || tmp > 100) {
+			PARSE_WARNING ("invalid %s percentage value '%s'", prop, *iter);
+			g_set_error_literal (error, IFCFG_PLUGIN_ERROR, 0, "invalid percent element");
+			goto out;
+		}
+		set_func (s_dcb, i, (guint) tmp);
+		sum += (guint) tmp;
+	}
+
+	if (sum_pct && (sum != 100)) {
+		PARSE_WARNING ("%s percentages do not equal 100%%", prop);
+		g_set_error_literal (error, IFCFG_PLUGIN_ERROR, 0, "invalid percentage sum");
+		goto out;
+	}
+
+	success = TRUE;
+
+out:
+	if (split)
+		g_strfreev (split);
+	g_free (val);
+	return success;
+}
+
+static gboolean
+make_dcb_setting (shvarFile *ifcfg,
+                  const char *network_file,
+                  NMSetting **out_setting,
+                  GError **error)
+{
+	NMSettingDcb *s_dcb = NULL;
+	gboolean dcb_on;
+	NMSettingDcbFlags flags = NM_SETTING_DCB_FLAG_NONE;
+	char *val;
+
+	g_return_val_if_fail (out_setting != NULL, FALSE);
+
+	dcb_on = !!svTrueValue (ifcfg, "DCB", FALSE);
+	if (!dcb_on)
+		return TRUE;
+
+	s_dcb = (NMSettingDcb *) nm_setting_dcb_new ();
+	g_assert (s_dcb);
+
+	/* FCOE */
+	if (!read_dcb_app (ifcfg, s_dcb, "FCOE",
+	                   &dcb_flags_props[DCB_APP_FCOE_FLAGS],
+	                   NM_SETTING_DCB_APP_FCOE_PRIORITY,
+	                   error)) {
+		g_object_unref (s_dcb);
+		return FALSE;
+	}
+	if (nm_setting_dcb_get_app_fcoe_flags (s_dcb) & NM_SETTING_DCB_FLAG_ENABLE) {
+		val = svGetValue (ifcfg, KEY_DCB_APP_FCOE_MODE, FALSE);
+		if (val) {
+			if (strcmp (val, NM_SETTING_DCB_FCOE_MODE_FABRIC) == 0 ||
+			    strcmp (val, NM_SETTING_DCB_FCOE_MODE_VN2VN) == 0)
+				g_object_set (G_OBJECT (s_dcb), NM_SETTING_DCB_APP_FCOE_MODE, val, NULL);
+			else {
+				PARSE_WARNING ("invalid FCoE mode '%s'", val);
+				g_set_error_literal (error, IFCFG_PLUGIN_ERROR, 0, "invalid FCoE mode");
+				g_free (val);
+				g_object_unref (s_dcb);
+				return FALSE;
+			}
+			g_free (val);
+		}
+	}
+
+	/* iSCSI */
+	if (!read_dcb_app (ifcfg, s_dcb, "ISCSI",
+	                   &dcb_flags_props[DCB_APP_ISCSI_FLAGS],
+	                   NM_SETTING_DCB_APP_ISCSI_PRIORITY,
+	                   error)) {
+		g_object_unref (s_dcb);
+		return FALSE;
+	}
+
+	/* FIP */
+	if (!read_dcb_app (ifcfg, s_dcb, "FIP",
+	                   &dcb_flags_props[DCB_APP_FIP_FLAGS],
+	                   NM_SETTING_DCB_APP_FIP_PRIORITY,
+	                   error)) {
+		g_object_unref (s_dcb);
+		return FALSE;
+	}
+
+	/* Priority Flow Control */
+	flags = read_dcb_flags (ifcfg, &dcb_flags_props[DCB_PFC_FLAGS]);
+	g_object_set (G_OBJECT (s_dcb), NM_SETTING_DCB_PRIORITY_FLOW_CONTROL_FLAGS, flags, NULL);
+
+	if (!read_dcb_bool_array (ifcfg,
+	                          s_dcb,
+	                          flags,
+	                          KEY_DCB_PFC_UP,
+	                          "PFC",
+	                          nm_setting_dcb_set_priority_flow_control,
+	                          error)) {
+		g_object_unref (s_dcb);
+		return FALSE;
+	}
+
+	/* Priority Groups */
+	flags = read_dcb_flags (ifcfg, &dcb_flags_props[DCB_PG_FLAGS]);
+	g_object_set (G_OBJECT (s_dcb), NM_SETTING_DCB_PRIORITY_GROUP_FLAGS, flags, NULL);
+
+	if (!read_dcb_uint_array (ifcfg,
+	                          s_dcb,
+	                          flags,
+	                          KEY_DCB_PG_ID,
+	                          "PGID",
+	                          TRUE,
+	                          nm_setting_dcb_set_priority_group_id,
+	                          error)) {
+		g_object_unref (s_dcb);
+		return FALSE;
+	}
+
+	/* Group bandwidth */
+	if (!read_dcb_percent_array (ifcfg,
+	                             s_dcb,
+	                             flags,
+	                             KEY_DCB_PG_PCT,
+	                             "PGPCT",
+	                             TRUE,
+	                             nm_setting_dcb_set_priority_group_bandwidth,
+	                             error)) {
+		g_object_unref (s_dcb);
+		return FALSE;
+	}
+
+	/* Priority bandwidth */
+	if (!read_dcb_percent_array (ifcfg,
+	                             s_dcb,
+	                             flags,
+	                             KEY_DCB_PG_UPPCT,
+	                             "UPPCT",
+	                             FALSE,
+	                             nm_setting_dcb_set_priority_bandwidth,
+	                             error)) {
+		g_object_unref (s_dcb);
+		return FALSE;
+	}
+
+	/* Strict Bandwidth */
+	if (!read_dcb_bool_array (ifcfg,
+	                          s_dcb,
+	                          flags,
+	                          KEY_DCB_PG_STRICT,
+	                          "STRICT",
+	                          nm_setting_dcb_set_priority_strict_bandwidth,
+	                          error)) {
+		g_object_unref (s_dcb);
+		return FALSE;
+	}
+
+	if (!read_dcb_uint_array (ifcfg,
+	                          s_dcb,
+	                          flags,
+	                          KEY_DCB_PG_UP2TC,
+	                          "UP2TC",
+	                          FALSE,
+	                          nm_setting_dcb_set_priority_traffic_class,
+	                          error)) {
+		g_object_unref (s_dcb);
+		return FALSE;
+	}
+
+	*out_setting = NM_SETTING (s_dcb);
+	return TRUE;
 }
 
 static gboolean
@@ -1998,12 +2528,12 @@ fill_wpa_ciphers (shvarFile *ifcfg,
 		 */
 		if (adhoc) {
 			if (group && (i > 0)) {
-				PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: ignoring group cipher '%s' (only one group cipher allowed in Ad-Hoc mode)",
-				             *iter);
+				PARSE_WARNING ("ignoring group cipher '%s' (only one group cipher allowed "
+				               "in Ad-Hoc mode)", *iter);
 				continue;
 			} else if (!group) {
-				PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: ignoring pairwise cipher '%s' (pairwise not used in Ad-Hoc mode)",
-				             *iter);
+				PARSE_WARNING ("ignoring pairwise cipher '%s' (pairwise not used "
+				               "in Ad-Hoc mode)", *iter);
 				continue;
 			}
 		}
@@ -2023,9 +2553,9 @@ fill_wpa_ciphers (shvarFile *ifcfg,
 		else if (group && !strcmp (*iter, "WEP40"))
 			nm_setting_wireless_security_add_group (wsec, "wep40");
 		else {
-			PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: ignoring invalid %s cipher '%s'",
-			             group ? "CIPHER_GROUP" : "CIPHER_PAIRWISE",
-			             *iter);
+			PARSE_WARNING ("ignoring invalid %s cipher '%s'",
+			               group ? "CIPHER_GROUP" : "CIPHER_PAIRWISE",
+			               *iter);
 		}
 	}
 
@@ -2240,10 +2770,8 @@ eap_tls_reader (const char *eap_method,
 		g_free (real_path);
 		real_path = NULL;
 	} else {
-		PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: missing %s for EAP"
-		             " method '%s'; this is insecure!",
-		             ca_cert_key,
-		             eap_method);
+		PARSE_WARNING ("missing %s for EAP method '%s'; this is insecure!",
+		               ca_cert_key, eap_method);
 	}
 
 	/* Read and set private key password flags */
@@ -2373,10 +2901,8 @@ eap_peap_reader (const char *eap_method,
 		                                    error))
 			goto done;
 	} else {
-		PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: missing "
-		             "IEEE_8021X_CA_CERT for EAP method '%s'; this is"
-		             " insecure!",
-		             eap_method);
+		PARSE_WARNING ("missing IEEE_8021X_CA_CERT for EAP method '%s'; this is insecure!",
+		               eap_method);
 	}
 
 	peapver = svGetValue (ifcfg, "IEEE_8021X_PEAP_VERSION", FALSE);
@@ -2479,10 +3005,8 @@ eap_ttls_reader (const char *eap_method,
 		                                    error))
 			goto done;
 	} else {
-		PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: missing "
-		             "IEEE_8021X_CA_CERT for EAP method '%s'; this is"
-		             " insecure!",
-		             eap_method);
+		PARSE_WARNING ("missing IEEE_8021X_CA_CERT for EAP method '%s'; this is insecure!",
+		               eap_method);
 	}
 
 	anon_ident = svGetValue (ifcfg, "IEEE_8021X_ANON_IDENTITY", FALSE);
@@ -2516,10 +3040,12 @@ eap_ttls_reader (const char *eap_method,
 			if (!eap_tls_reader (*iter, ifcfg, keys, s_8021x, TRUE, error))
 				goto done;
 			g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTHEAP, "tls", NULL);
-		} else if (!strcmp (*iter, "eap-mschapv2") || !strcmp (*iter, "eap-md5")) {
+		} else if (   !strcmp (*iter, "eap-mschapv2")
+		           || !strcmp (*iter, "eap-md5")
+		           || !strcmp (*iter, "eap-gtc")) {
 			if (!eap_simple_reader (*iter, ifcfg, keys, s_8021x, TRUE, error))
 				goto done;
-			g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTHEAP, (*iter + strlen ("eap-")), NULL);
+			g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTHEAP, (*iter + STRLEN ("eap-")), NULL);
 		} else {
 			g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
 			             "Unknown IEEE_8021X_INNER_AUTH_METHOD '%s'.",
@@ -2577,9 +3103,9 @@ eap_fast_reader (const char *eap_method,
 			else if (strcmp (*iter, "allow-auth") == 0)
 				allow_auth = TRUE;
 			else {
-				PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: invalid IEEE_8021X_FAST_PROVISIONING '%s' "
-				             "(space-separated list of these values [allow-auth, allow-unauth] expected)",
-				             *iter);
+				PARSE_WARNING ("invalid IEEE_8021X_FAST_PROVISIONING '%s' "
+				               "(space-separated list of these values [allow-auth, allow-unauth] expected)",
+				               *iter);
 			}
 		}
 		g_strfreev (list);
@@ -2664,6 +3190,7 @@ static EAPReader eap_readers[] = {
 	{ "mschap", eap_simple_reader, TRUE },
 	{ "mschapv2", eap_simple_reader, TRUE },
 	{ "leap", eap_simple_reader, FALSE },
+	{ "pwd", eap_simple_reader, FALSE },
 	{ "tls", eap_tls_reader, FALSE },
 	{ "peap", eap_peap_reader, FALSE },
 	{ "ttls", eap_ttls_reader, FALSE },
@@ -2671,6 +3198,39 @@ static EAPReader eap_readers[] = {
 	{ NULL, NULL }
 };
 
+static void
+read_8021x_list_value (shvarFile *ifcfg,
+                       const char *ifcfg_var_name,
+                       NMSetting8021x *setting,
+                       const char *prop_name)
+{
+	char *value;
+	char **strv, **iter;
+	GSList *gslist = NULL;
+
+	g_return_if_fail (ifcfg != NULL);
+	g_return_if_fail (ifcfg_var_name != NULL);
+	g_return_if_fail (prop_name != NULL);
+
+	value = svGetValue (ifcfg, ifcfg_var_name, FALSE);
+	if (!value)
+		return;
+
+	strv = g_strsplit_set (value, " \t", 0);
+	for (iter = strv; iter && *iter; iter++) {
+		if (*iter[0] == '\0')
+			continue;
+		gslist = g_slist_prepend (gslist, *iter);
+	}
+	if (gslist) {
+		gslist = g_slist_reverse (gslist);
+		g_object_set (setting, prop_name, gslist, NULL);
+		g_slist_free (gslist);
+	}
+	g_strfreev (strv);
+	g_free (value);
+}
+
 static NMSetting8021x *
 fill_8021x (shvarFile *ifcfg,
             const char *file,
@@ -2715,9 +3275,8 @@ fill_8021x (shvarFile *ifcfg,
 			 * used with TTLS or PEAP or whatever.
 			 */
 			if (wifi && eap->wifi_phase2_only) {
-				PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: ignored invalid "
-				             "IEEE_8021X_EAP_METHOD '%s'; not allowed for wifi.",
-				             lower);
+				PARSE_WARNING ("ignored invalid IEEE_8021X_EAP_METHOD '%s'; not allowed for wifi.",
+				               lower);
 				goto next;
 			}
 
@@ -2733,11 +3292,8 @@ fill_8021x (shvarFile *ifcfg,
 			eap++;
 		}
 
-		if (!found) {
-			PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: ignored unknown"
-			             "IEEE_8021X_EAP_METHOD '%s'.",
-			             lower);
-		}
+		if (!found)
+			PARSE_WARNING ("ignored unknown IEEE_8021X_EAP_METHOD '%s'.", lower);
 		g_free (lower);
 	}
 
@@ -2747,6 +3303,19 @@ fill_8021x (shvarFile *ifcfg,
 		goto error;
 	}
 
+	value = svGetValue (ifcfg, "IEEE_8021X_SUBJECT_MATCH", FALSE);
+	g_object_set (s_8021x, NM_SETTING_802_1X_SUBJECT_MATCH, value, NULL);
+	g_free (value);
+
+	value = svGetValue (ifcfg, "IEEE_8021X_PHASE2_SUBJECT_MATCH", FALSE);
+	g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_SUBJECT_MATCH, value, NULL);
+	g_free (value);
+
+	read_8021x_list_value (ifcfg, "IEEE_8021X_ALTSUBJECT_MATCHES",
+	                       s_8021x, NM_SETTING_802_1X_ALTSUBJECT_MATCHES);
+	read_8021x_list_value (ifcfg, "IEEE_8021X_PHASE2_ALTSUBJECT_MATCHES",
+	                       s_8021x, NM_SETTING_802_1X_PHASE2_ALTSUBJECT_MATCHES);
+
 	if (list)
 		g_strfreev (list);
 	if (keys)
@@ -2816,6 +3385,7 @@ make_wpa_setting (shvarFile *ifcfg,
 		g_free (allow_rsn);
 	}
 
+	/* coverity[dereference] */
 	if (!strcmp (value, "WPA-PSK")) {
 		NMSettingSecretFlags psk_flags;
 
@@ -2966,8 +3536,6 @@ make_wireless_security_setting (shvarFile *ifcfg,
 
 static NMSetting *
 make_wireless_setting (shvarFile *ifcfg,
-                       gboolean nm_controlled,
-                       char **unmanaged,
                        GError **error)
 {
 	NMSettingWireless *s_wireless;
@@ -2980,20 +3548,7 @@ make_wireless_setting (shvarFile *ifcfg,
 	if (read_mac_address (ifcfg, "HWADDR", ARPHRD_ETHER, &array, error)) {
 		if (array) {
 			g_object_set (s_wireless, NM_SETTING_WIRELESS_MAC_ADDRESS, array, NULL);
-
-			/* A connection can only be unmanaged if we know the MAC address */
-			if (!nm_controlled) {
-				*unmanaged = g_strdup_printf ("mac:%02x:%02x:%02x:%02x:%02x:%02x",
-				                              array->data[0], array->data[1], array->data[2],
-				                              array->data[3], array->data[4], array->data[5]);
-			}
-
 			g_byte_array_free (array, TRUE);
-		} else if (!nm_controlled) {
-			/* If NM_CONTROLLED=no but there wasn't a MAC address, notify
-			 * the user that the device cannot be unmanaged.
-			 */
-			PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: NM_CONTROLLED was false but HWADDR was missing; device will be managed");
 		}
 	} else {
 		g_object_unref (s_wireless);
@@ -3007,7 +3562,7 @@ make_wireless_setting (shvarFile *ifcfg,
 			g_byte_array_free (array, TRUE);
 		}
 	} else {
-		PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: %s", (*error)->message);
+		PARSE_WARNING ("%s", (*error)->message);
 		g_clear_error (error);
 	}
 
@@ -3021,7 +3576,7 @@ make_wireless_setting (shvarFile *ifcfg,
 			if (**iter == '\0')
 				continue;
 			if (!ether_aton_r (*iter, &addr)) {
-				PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: invalid MAC in HWADDR_BLACKLIST '%s'", *iter);
+				PARSE_WARNING ("invalid MAC in HWADDR_BLACKLIST '%s'", *iter);
 				continue;
 			}
 			macaddr_blacklist = g_slist_prepend (macaddr_blacklist, *iter);
@@ -3072,7 +3627,7 @@ make_wireless_setting (shvarFile *ifcfg,
 				p++;
 			}
 
-			tmp = utils_hexstr2bin (value + 2, value_len - 2);
+			tmp = nm_utils_hexstr2bin (value + 2, value_len - 2);
 			ssid_len  = (value_len - 2) / 2;
 			memcpy (buf, tmp, ssid_len);
 			p = &buf[0];
@@ -3092,17 +3647,8 @@ make_wireless_setting (shvarFile *ifcfg,
 		g_object_set (s_wireless, NM_SETTING_WIRELESS_SSID, array, NULL);
 		g_byte_array_free (array, TRUE);
 		g_free (value);
-	} else {
-		/* Only fail on lack of SSID if device is managed */
-		if (nm_controlled) {
-			g_set_error (error, IFCFG_PLUGIN_ERROR, 0, "Missing SSID");
-			goto error;
-		}
 	}
 
-	if (!nm_controlled)
-		goto done;
-
 	value = svGetValue (ifcfg, "MODE", FALSE);
 	if (value) {
 		char *lcase;
@@ -3180,7 +3726,11 @@ make_wireless_setting (shvarFile *ifcfg,
 		g_free (value);
 	}
 
-done:
+	g_object_set (s_wireless,
+	              NM_SETTING_WIRELESS_HIDDEN,
+	              svTrueValue (ifcfg, "SSID_HIDDEN", FALSE),
+	              NULL);
+
 	return NM_SETTING (s_wireless);
 
 error:
@@ -3192,8 +3742,6 @@ error:
 static NMConnection *
 wireless_connection_from_ifcfg (const char *file,
                                 shvarFile *ifcfg,
-                                gboolean nm_controlled,
-                                char **unmanaged,
                                 GError **error)
 {
 	NMConnection *connection = NULL;
@@ -3212,14 +3760,9 @@ wireless_connection_from_ifcfg (const char *file,
 	g_return_val_if_fail (*error == NULL, NULL);
 
 	connection = nm_connection_new ();
-	if (!connection) {
-		g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
-		             "Failed to allocate new connection for %s.", file);
-		return NULL;
-	}
 
 	/* Wireless */
-	wireless_setting = make_wireless_setting (ifcfg, nm_controlled, unmanaged, error);
+	wireless_setting = make_wireless_setting (ifcfg, error);
 	if (!wireless_setting) {
 		g_object_unref (connection);
 		return NULL;
@@ -3232,26 +3775,21 @@ wireless_connection_from_ifcfg (const char *file,
 	else
 		printable_ssid = g_strdup_printf ("unmanaged");
 
-	if (nm_controlled) {
-		mode = nm_setting_wireless_get_mode (NM_SETTING_WIRELESS (wireless_setting));
-		if (mode && !strcmp (mode, "adhoc"))
-			adhoc = TRUE;
-
-		/* Wireless security */
-		security_setting = make_wireless_security_setting (ifcfg, file, ssid, adhoc, &s_8021x, error);
-		if (*error) {
-			g_free (printable_ssid);
-			g_object_unref (connection);
-			return NULL;
-		}
-		if (security_setting) {
-			nm_connection_add_setting (connection, security_setting);
-			if (s_8021x)
-				nm_connection_add_setting (connection, NM_SETTING (s_8021x));
+	mode = nm_setting_wireless_get_mode (NM_SETTING_WIRELESS (wireless_setting));
+	if (mode && !strcmp (mode, "adhoc"))
+		adhoc = TRUE;
 
-			g_object_set (wireless_setting, NM_SETTING_WIRELESS_SEC,
-			              NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NULL);
-		}
+	/* Wireless security */
+	security_setting = make_wireless_security_setting (ifcfg, file, ssid, adhoc, &s_8021x, error);
+	if (*error) {
+		g_free (printable_ssid);
+		g_object_unref (connection);
+		return NULL;
+	}
+	if (security_setting) {
+		nm_connection_add_setting (connection, security_setting);
+		if (s_8021x)
+			nm_connection_add_setting (connection, NM_SETTING (s_8021x));
 	}
 
 	/* Connection */
@@ -3267,12 +3805,9 @@ wireless_connection_from_ifcfg (const char *file,
 	}
 	nm_connection_add_setting (connection, con_setting);
 
-	/* Don't verify if unmanaged since we may not have an SSID or whatever */
-	if (nm_controlled) {
-		if (!nm_connection_verify (connection, error)) {
-			g_object_unref (connection);
-			return NULL;
-		}
+	if (!nm_connection_verify (connection, error)) {
+		g_object_unref (connection);
+		return NULL;
 	}
 
 	return connection;
@@ -3281,8 +3816,6 @@ wireless_connection_from_ifcfg (const char *file,
 static NMSetting *
 make_wired_setting (shvarFile *ifcfg,
                     const char *file,
-                    gboolean nm_controlled,
-                    char **unmanaged,
                     NMSetting8021x **s_8021x,
                     GError **error)
 {
@@ -3302,7 +3835,7 @@ make_wired_setting (shvarFile *ifcfg,
 				g_object_set (s_wired, NM_SETTING_WIRED_MTU, mtu, NULL);
 		} else {
 			/* Shouldn't be fatal... */
-			PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: invalid MTU '%s'", value);
+			PARSE_WARNING ("invalid MTU '%s'", value);
 		}
 		g_free (value);
 	}
@@ -3310,14 +3843,6 @@ make_wired_setting (shvarFile *ifcfg,
 	if (read_mac_address (ifcfg, "HWADDR", ARPHRD_ETHER, &mac, error)) {
 		if (mac) {
 			g_object_set (s_wired, NM_SETTING_WIRED_MAC_ADDRESS, mac, NULL);
-
-			/* A connection can only be unmanaged if we know the MAC address */
-			if (!nm_controlled) {
-				*unmanaged = g_strdup_printf ("mac:%02x:%02x:%02x:%02x:%02x:%02x",
-				                              mac->data[0], mac->data[1], mac->data[2],
-				                              mac->data[3], mac->data[4], mac->data[5]);
-			}
-
 			g_byte_array_free (mac, TRUE);
 		}
 	} else {
@@ -3334,7 +3859,7 @@ make_wired_setting (shvarFile *ifcfg,
 		/* basic sanity checks */
 		while (*p) {
 			if (!g_ascii_isxdigit (*p) && (*p != ',') && (*p != '.')) {
-				PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: invalid SUBCHANNELS '%s'", value);
+				PARSE_WARNING ("invalid SUBCHANNELS '%s'", value);
 				success = FALSE;
 				break;
 			}
@@ -3347,8 +3872,8 @@ make_wired_setting (shvarFile *ifcfg,
 			chans = g_strsplit_set (value, ",", 0);
 			num_chans = g_strv_length (chans);
 			if (num_chans < 2 || num_chans > 3) {
-				PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: invalid SUBCHANNELS '%s' (%d channels, 2 or 3 expected)",
-				             value, g_strv_length (chans));
+				PARSE_WARNING ("invalid SUBCHANNELS '%s' (%d channels, 2 or 3 expected)",
+				               value, g_strv_length (chans));
 			} else {
 				GPtrArray *array = g_ptr_array_sized_new (num_chans);
 
@@ -3359,10 +3884,6 @@ make_wired_setting (shvarFile *ifcfg,
 
 				g_object_set (s_wired, NM_SETTING_WIRED_S390_SUBCHANNELS, array, NULL);
 				g_ptr_array_free (array, TRUE);
-
-				/* set the unmanaged spec too */
-				if (!nm_controlled && !*unmanaged)
-					*unmanaged = g_strdup_printf ("s390-subchannels:%s", value);
 			}
 			g_strfreev (chans);
 		}
@@ -3385,7 +3906,7 @@ make_wired_setting (shvarFile *ifcfg,
 		if (!strcmp (nettype, "qeth") || !strcmp (nettype, "lcs") || !strcmp (nettype, "ctc"))
 			g_object_set (s_wired, NM_SETTING_WIRED_S390_NETTYPE, nettype, NULL);
 		else
-			PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: unknown s390 NETTYPE '%s'", nettype);
+			PARSE_WARNING ("unknown s390 NETTYPE '%s'", nettype);
 	}
 	g_free (nettype);
 
@@ -3403,20 +3924,13 @@ make_wired_setting (shvarFile *ifcfg,
 				valid = nm_setting_wired_add_s390_option (s_wired, *iter, equals + 1);
 			}
 			if (!valid)
-				PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: invalid s390 OPTION '%s'", *iter);
+				PARSE_WARNING ("invalid s390 OPTION '%s'", *iter);
 			iter++;
 		}
 		g_strfreev (options);
 	}
 	g_free (value);
 
-	if (!nm_controlled && !*unmanaged) {
-		/* If NM_CONTROLLED=no but there wasn't a MAC address or z/VM
-		 * subchannels, notify the user that the device cannot be unmanaged.
-		 */
-		PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: NM_CONTROLLED was false but HWADDR or SUBCHANNELS was missing; device will be managed");
-	}
-
 	mac = NULL;
 	if (read_mac_address (ifcfg, "MACADDR", ARPHRD_ETHER, &mac, error)) {
 		if (mac) {
@@ -3424,7 +3938,7 @@ make_wired_setting (shvarFile *ifcfg,
 			g_byte_array_free (mac, TRUE);
 		}
 	} else {
-		PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: %s", (*error)->message);
+		PARSE_WARNING ("%s", (*error)->message);
 		g_clear_error (error);
 	}
 
@@ -3438,7 +3952,7 @@ make_wired_setting (shvarFile *ifcfg,
 			if (**iter == '\0')
 				continue;
 			if (!ether_aton_r (*iter, &addr)) {
-				PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: invalid MAC in HWADDR_BLACKLIST '%s'", *iter);
+				PARSE_WARNING ("invalid MAC in HWADDR_BLACKLIST '%s'", *iter);
 				continue;
 			}
 			macaddr_blacklist = g_slist_prepend (macaddr_blacklist, *iter);
@@ -3477,8 +3991,6 @@ error:
 static NMConnection *
 wired_connection_from_ifcfg (const char *file,
                              shvarFile *ifcfg,
-                             gboolean nm_controlled,
-                             char **unmanaged,
                              GError **error)
 {
 	NMConnection *connection = NULL;
@@ -3490,11 +4002,6 @@ wired_connection_from_ifcfg (const char *file,
 	g_return_val_if_fail (ifcfg != NULL, NULL);
 
 	connection = nm_connection_new ();
-	if (!connection) {
-		g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
-		             "Failed to allocate new connection for %s.", file);
-		return NULL;
-	}
 
 	con_setting = make_connection_setting (file, ifcfg, NM_SETTING_WIRED_SETTING_NAME, NULL, NULL);
 	if (!con_setting) {
@@ -3504,9 +4011,10 @@ wired_connection_from_ifcfg (const char *file,
 		return NULL;
 	}
 	check_if_bond_slave (ifcfg, NM_SETTING_CONNECTION (con_setting));
+	check_if_team_slave (ifcfg, NM_SETTING_CONNECTION (con_setting));
 	nm_connection_add_setting (connection, con_setting);
 
-	wired_setting = make_wired_setting (ifcfg, file, nm_controlled, unmanaged, &s_8021x, error);
+	wired_setting = make_wired_setting (ifcfg, file, &s_8021x, error);
 	if (!wired_setting) {
 		g_object_unref (connection);
 		return NULL;
@@ -3524,11 +4032,75 @@ wired_connection_from_ifcfg (const char *file,
 	return connection;
 }
 
+static gboolean
+parse_infiniband_p_key (shvarFile *ifcfg,
+                        int *out_p_key,
+                        char **out_parent,
+                        GError **error)
+{
+	char *device = NULL, *physdev = NULL, *pkey_id = NULL, *end;
+	char *ifname = NULL;
+	guint32 id = G_MAXUINT32;
+	gboolean ret = FALSE;
+
+	device = svGetValue (ifcfg, "DEVICE", FALSE);
+	if (!device) {
+		PARSE_WARNING ("InfiniBand connection specified PKEY but not DEVICE");
+		goto done;
+	}
+
+	physdev = svGetValue (ifcfg, "PHYSDEV", FALSE);
+	if (!physdev) {
+		PARSE_WARNING ("InfiniBand connection specified PKEY but not PHYSDEV");
+		goto done;
+	}
+
+	pkey_id = svGetValue (ifcfg, "PKEY_ID", FALSE);
+	if (!pkey_id) {
+		PARSE_WARNING ("InfiniBand connection specified PKEY but not PKEY_ID");
+		goto done;
+	}
+
+	if (g_str_has_prefix (pkey_id, "0x"))
+		id = strtoul (pkey_id, &end, 16);
+	else if (!g_str_has_prefix (pkey_id, "0"))
+		id = strtoul (pkey_id, &end, 10);
+	else
+		end = pkey_id;
+	if (end == pkey_id || *end || id > 0xFFFF) {
+		PARSE_WARNING ("invalid InfiniBand PKEY_ID '%s'", pkey_id);
+		goto done;
+	}
+	id = (id | 0x8000);
+
+	ifname = g_strdup_printf ("%s.%04x", physdev, id);
+	if (strcmp (device, ifname) != 0) {
+		PARSE_WARNING ("InfiniBand DEVICE (%s) does not match PHYSDEV+PKEY_ID (%s)",
+		               device, ifname);
+		goto done;
+	}
+
+	*out_p_key = id;
+	*out_parent = g_strdup (physdev);
+	ret = TRUE;
+
+ done:
+	g_free (device);
+	g_free (physdev);
+	g_free (pkey_id);
+	g_free (ifname);
+
+	if (!ret) {
+		g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
+		             "Failed to create InfiniBand setting.");
+	}
+	return ret;
+}
+
+
 static NMSetting *
 make_infiniband_setting (shvarFile *ifcfg,
                          const char *file,
-                         gboolean nm_controlled,
-                         char **unmanaged,
                          GError **error)
 {
 	NMSettingInfiniband *s_infiniband;
@@ -3545,7 +4117,7 @@ make_infiniband_setting (shvarFile *ifcfg,
 				g_object_set (s_infiniband, NM_SETTING_INFINIBAND_MTU, mtu, NULL);
 		} else {
 			/* Shouldn't be fatal... */
-			PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: invalid MTU '%s'", value);
+			PARSE_WARNING ("invalid MTU '%s'", value);
 		}
 		g_free (value);
 	}
@@ -3553,14 +4125,6 @@ make_infiniband_setting (shvarFile *ifcfg,
 	if (read_mac_address (ifcfg, "HWADDR", ARPHRD_INFINIBAND, &mac, error)) {
 		if (mac) {
 			g_object_set (s_infiniband, NM_SETTING_INFINIBAND_MAC_ADDRESS, mac, NULL);
-
-			/* A connection can only be unmanaged if we know the MAC address */
-			if (!nm_controlled) {
-				char *mac_str = nm_utils_hwaddr_ntoa (mac->data, ARPHRD_INFINIBAND);
-				*unmanaged = g_strdup_printf ("mac:%s", mac_str);
-				g_free (mac_str);
-			}
-
 			g_byte_array_free (mac, TRUE);
 		}
 	} else {
@@ -3573,11 +4137,19 @@ make_infiniband_setting (shvarFile *ifcfg,
 	else
 		g_object_set (s_infiniband, NM_SETTING_INFINIBAND_TRANSPORT_MODE, "datagram", NULL);
 
-	if (!nm_controlled && !*unmanaged) {
-		/* If NM_CONTROLLED=no but there wasn't a MAC address, notify
-		   the user that the device cannot be unmanaged.
-		 */
-		PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: NM_CONTROLLED was false but HWADDR was missing; device will be managed");
+	if (svTrueValue (ifcfg, "PKEY", FALSE)) {
+		int p_key;
+		char *parent;
+
+		if (!parse_infiniband_p_key (ifcfg, &p_key, &parent, error)) {
+			g_object_unref (s_infiniband);
+			return NULL;
+		}
+
+		g_object_set (s_infiniband,
+		              NM_SETTING_INFINIBAND_P_KEY, p_key,
+		              NM_SETTING_INFINIBAND_PARENT, parent,
+		              NULL);
 	}
 
 	return (NMSetting *) s_infiniband;
@@ -3586,8 +4158,6 @@ make_infiniband_setting (shvarFile *ifcfg,
 static NMConnection *
 infiniband_connection_from_ifcfg (const char *file,
                                   shvarFile *ifcfg,
-                                  gboolean nm_controlled,
-                                  char **unmanaged,
                                   GError **error)
 {
 	NMConnection *connection = NULL;
@@ -3598,11 +4168,6 @@ infiniband_connection_from_ifcfg (const char *file,
 	g_return_val_if_fail (ifcfg != NULL, NULL);
 
 	connection = nm_connection_new ();
-	if (!connection) {
-		g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
-		             "Failed to allocate new connection for %s.", file);
-		return NULL;
-	}
 
 	con_setting = make_connection_setting (file, ifcfg, NM_SETTING_INFINIBAND_SETTING_NAME, NULL, NULL);
 	if (!con_setting) {
@@ -3612,9 +4177,10 @@ infiniband_connection_from_ifcfg (const char *file,
 		return NULL;
 	}
 	check_if_bond_slave (ifcfg, NM_SETTING_CONNECTION (con_setting));
+	check_if_team_slave (ifcfg, NM_SETTING_CONNECTION (con_setting));
 	nm_connection_add_setting (connection, con_setting);
 
-	infiniband_setting = make_infiniband_setting (ifcfg, file, nm_controlled, unmanaged, error);
+	infiniband_setting = make_infiniband_setting (ifcfg, file, error);
 	if (!infiniband_setting) {
 		g_object_unref (connection);
 		return NULL;
@@ -3634,15 +4200,29 @@ handle_bond_option (NMSettingBond *s_bond,
                     const char *key,
                     const char *value)
 {
-	if (!nm_setting_bond_add_option (s_bond, key, value))
-		PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: invalid bonding option '%s'", key);
+	char *sanitized = NULL, *j;
+	const char *p = value;
+
+	/* Remove any quotes or +/- from arp_ip_target */
+	if (!g_strcmp0 (key, NM_SETTING_BOND_OPTION_ARP_IP_TARGET) && value && value[0]) {
+		if (*p == '\'' || *p == '"')
+			p++;
+		j = sanitized = g_malloc0 (strlen (p) + 1);
+		while (*p) {
+			if (*p != '+' && *p != '-' && *p != '\'' && *p != '"')
+				*j++ = *p;
+			p++;
+		}
+	}
+
+	if (!nm_setting_bond_add_option (s_bond, key, sanitized ? sanitized : value))
+		PARSE_WARNING ("invalid bonding option '%s'", key);
+	g_free (sanitized);
 }
 
 static NMSetting *
 make_bond_setting (shvarFile *ifcfg,
                    const char *file,
-                   gboolean nm_controlled,
-                   char **unmanaged,
                    GError **error)
 {
 	NMSettingBond *s_bond;
@@ -3693,8 +4273,6 @@ error:
 static NMConnection *
 bond_connection_from_ifcfg (const char *file,
                             shvarFile *ifcfg,
-                            gboolean nm_controlled,
-                            char **unmanaged,
                             GError **error)
 {
 	NMConnection *connection = NULL;
@@ -3707,11 +4285,6 @@ bond_connection_from_ifcfg (const char *file,
 	g_return_val_if_fail (ifcfg != NULL, NULL);
 
 	connection = nm_connection_new ();
-	if (!connection) {
-		g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
-		             "Failed to allocate new connection for %s.", file);
-		return NULL;
-	}
 
 	con_setting = make_connection_setting (file, ifcfg, NM_SETTING_BOND_SETTING_NAME, NULL, _("Bond"));
 	if (!con_setting) {
@@ -3722,14 +4295,125 @@ bond_connection_from_ifcfg (const char *file,
 	}
 	nm_connection_add_setting (connection, con_setting);
 
-	bond_setting = make_bond_setting (ifcfg, file, nm_controlled, unmanaged, error);
+	bond_setting = make_bond_setting (ifcfg, file, error);
 	if (!bond_setting) {
 		g_object_unref (connection);
 		return NULL;
 	}
 	nm_connection_add_setting (connection, bond_setting);
 
-	wired_setting = make_wired_setting (ifcfg, file, nm_controlled, unmanaged, &s_8021x, error);
+	wired_setting = make_wired_setting (ifcfg, file, &s_8021x, error);
+	if (!wired_setting) {
+		g_object_unref (connection);
+		return NULL;
+	}
+	nm_connection_add_setting (connection, wired_setting);
+
+	if (s_8021x)
+		nm_connection_add_setting (connection, NM_SETTING (s_8021x));
+
+	if (!nm_connection_verify (connection, error)) {
+		g_object_unref (connection);
+		return NULL;
+	}
+
+	return connection;
+}
+
+/* Check 'error' for errors. Missing config (NULL return value) is a valid case. */
+static char *
+read_team_config (shvarFile *ifcfg, const char *key, GError **error)
+{
+	char *value;
+	size_t l;
+
+	/* FIXME: validate the JSON at some point */
+	value = svGetValue (ifcfg, key, TRUE);
+	if (!value)
+		return NULL;
+
+	/* No reason Team config should be over 20k.  The config is read
+	 * verbatim, length-checked, then unescaped.  svUnescape() does not
+	 * deal well with extremely long strings.
+	 */
+	l = strlen (value);
+	if (l > 20000) {
+		g_set_error (error, IFCFG_PLUGIN_ERROR, 0, "%s too long (size %zd)", key, l);
+		g_free (value);
+		return NULL;
+	}
+	svUnescape (value);
+	return value;
+}
+
+static NMSetting *
+make_team_setting (shvarFile *ifcfg,
+                   const char *file,
+                   GError **error)
+{
+	NMSettingTeam *s_team;
+	char *value;
+	GError *local_err = NULL;
+
+	s_team = NM_SETTING_TEAM (nm_setting_team_new ());
+
+	value = svGetValue (ifcfg, "DEVICE", FALSE);
+	if (!value || !strlen (value)) {
+		g_set_error (error, IFCFG_PLUGIN_ERROR, 0, "mandatory DEVICE keyword missing");
+		goto error;
+	}
+
+	g_object_set (s_team, NM_SETTING_TEAM_INTERFACE_NAME, value, NULL);
+	g_free (value);
+
+	value = read_team_config (ifcfg, "TEAM_CONFIG", &local_err);
+	if (local_err) {
+		g_propagate_error (error, local_err);
+		goto error;
+	}
+	g_object_set (s_team, NM_SETTING_TEAM_CONFIG, value, NULL);
+	g_free (value);
+
+	return (NMSetting *) s_team;
+
+error:
+	g_object_unref (s_team);
+	return NULL;
+}
+
+static NMConnection *
+team_connection_from_ifcfg (const char *file,
+                            shvarFile *ifcfg,
+                            GError **error)
+{
+	NMConnection *connection = NULL;
+	NMSetting *con_setting = NULL;
+	NMSetting *team_setting = NULL;
+	NMSetting *wired_setting = NULL;
+	NMSetting8021x *s_8021x = NULL;
+
+	g_return_val_if_fail (file != NULL, NULL);
+	g_return_val_if_fail (ifcfg != NULL, NULL);
+
+	connection = nm_connection_new ();
+
+	con_setting = make_connection_setting (file, ifcfg, NM_SETTING_TEAM_SETTING_NAME, NULL, _("Team"));
+	if (!con_setting) {
+		g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
+		             "Failed to create connection setting.");
+		g_object_unref (connection);
+		return NULL;
+	}
+	nm_connection_add_setting (connection, con_setting);
+
+	team_setting = make_team_setting (ifcfg, file, error);
+	if (!team_setting) {
+		g_object_unref (connection);
+		return NULL;
+	}
+	nm_connection_add_setting (connection, team_setting);
+
+	wired_setting = make_wired_setting (ifcfg, file, &s_8021x, error);
 	if (!wired_setting) {
 		g_object_unref (connection);
 		return NULL;
@@ -3762,32 +4446,32 @@ handle_bridge_option (NMSetting *setting,
 
 	if (!strcmp (key, "priority")) {
 		if (stp == FALSE) {
-			PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: 'priority' invalid when STP is disabled");
+			PARSE_WARNING ("'priority' invalid when STP is disabled");
 		} else if (get_uint (value, &u))
 			g_object_set (setting, NM_SETTING_BRIDGE_PRIORITY, u, NULL);
 		else
-			PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: invalid priority value '%s'", value);
+			PARSE_WARNING ("invalid priority value '%s'", value);
 	} else if (!strcmp (key, "hello_time")) {
 		if (stp == FALSE) {
-			PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: 'hello_time' invalid when STP is disabled");
+			PARSE_WARNING ("'hello_time' invalid when STP is disabled");
 		} else if (get_uint (value, &u))
 			g_object_set (setting, NM_SETTING_BRIDGE_HELLO_TIME, u, NULL);
 		else
-			PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: invalid hello_time value '%s'", value);
+			PARSE_WARNING ("invalid hello_time value '%s'", value);
 	} else if (!strcmp (key, "max_age")) {
 		if (stp == FALSE) {
-			PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: 'max_age' invalid when STP is disabled");
+			PARSE_WARNING ("'max_age' invalid when STP is disabled");
 		} else if (get_uint (value, &u))
 			g_object_set (setting, NM_SETTING_BRIDGE_MAX_AGE, u, NULL);
 		else
-			PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: invalid max_age value '%s'", value);
+			PARSE_WARNING ("invalid max_age value '%s'", value);
 	} else if (!strcmp (key, "ageing_time")) {
 		if (get_uint (value, &u))
 			g_object_set (setting, NM_SETTING_BRIDGE_AGEING_TIME, u, NULL);
 		else
-			PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: invalid ageing_time value '%s'", value);
+			PARSE_WARNING ("invalid ageing_time value '%s'", value);
 	} else
-			PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: unhandled bridge option '%s'", key);
+			PARSE_WARNING ("unhandled bridge option '%s'", key);
 }
 
 static void
@@ -3820,8 +4504,6 @@ handle_bridging_opts (NMSetting *setting,
 static NMSetting *
 make_bridge_setting (shvarFile *ifcfg,
                      const char *file,
-                     gboolean nm_controlled,
-                     char **unmanaged,
                      GError **error)
 {
 	NMSettingBridge *s_bridge;
@@ -3829,6 +4511,7 @@ make_bridge_setting (shvarFile *ifcfg,
 	guint32 u;
 	gboolean stp = FALSE;
 	gboolean stp_set = FALSE;
+	GByteArray *array = NULL;
 
 	s_bridge = NM_SETTING_BRIDGE (nm_setting_bridge_new ());
 
@@ -3841,6 +4524,16 @@ make_bridge_setting (shvarFile *ifcfg,
 	g_object_set (s_bridge, NM_SETTING_BRIDGE_INTERFACE_NAME, value, NULL);
 	g_free (value);
 
+	if (read_mac_address (ifcfg, "MACADDR", ARPHRD_ETHER, &array, error)) {
+		if (array) {
+			g_object_set (s_bridge, NM_SETTING_BRIDGE_MAC_ADDRESS, array, NULL);
+			g_byte_array_free (array, TRUE);
+		}
+	} else {
+		PARSE_WARNING ("%s", (*error)->message);
+		g_clear_error (error);
+	}
+
 	value = svGetValue (ifcfg, "STP", FALSE);
 	if (value) {
 		if (!strcasecmp (value, "on") || !strcasecmp (value, "yes")) {
@@ -3851,7 +4544,7 @@ make_bridge_setting (shvarFile *ifcfg,
 			g_object_set (s_bridge, NM_SETTING_BRIDGE_STP, FALSE, NULL);
 			stp_set = TRUE;
 		} else
-			PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: invalid STP value '%s'", value);
+			PARSE_WARNING ("invalid STP value '%s'", value);
 		g_free (value);
 	}
 
@@ -3866,9 +4559,9 @@ make_bridge_setting (shvarFile *ifcfg,
 			if (get_uint (value, &u))
 				g_object_set (s_bridge, NM_SETTING_BRIDGE_FORWARD_DELAY, u, NULL);
 			else
-				PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: invalid forward delay value '%s'", value);
+				PARSE_WARNING ("invalid forward delay value '%s'", value);
 		} else
-			PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: DELAY invalid when STP is disabled");
+			PARSE_WARNING ("DELAY invalid when STP is disabled");
 		g_free (value);
 	}
 
@@ -3888,8 +4581,6 @@ error:
 static NMConnection *
 bridge_connection_from_ifcfg (const char *file,
                               shvarFile *ifcfg,
-                              gboolean nm_controlled,
-                              char **unmanaged,
                               GError **error)
 {
 	NMConnection *connection = NULL;
@@ -3900,11 +4591,6 @@ bridge_connection_from_ifcfg (const char *file,
 	g_return_val_if_fail (ifcfg != NULL, NULL);
 
 	connection = nm_connection_new ();
-	if (!connection) {
-		g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
-		             "Failed to allocate new connection for %s.", file);
-		return NULL;
-	}
 
 	con_setting = make_connection_setting (file, ifcfg, NM_SETTING_BRIDGE_SETTING_NAME, NULL, _("Bridge"));
 	if (!con_setting) {
@@ -3915,7 +4601,7 @@ bridge_connection_from_ifcfg (const char *file,
 	}
 	nm_connection_add_setting (connection, con_setting);
 
-	bridge_setting = make_bridge_setting (ifcfg, file, nm_controlled, unmanaged, error);
+	bridge_setting = make_bridge_setting (ifcfg, file, error);
 	if (!bridge_setting) {
 		g_object_unref (connection);
 		return NULL;
@@ -3942,40 +4628,60 @@ handle_bridge_port_option (NMSetting *setting,
 		if (get_uint (value, &u))
 			g_object_set (setting, NM_SETTING_BRIDGE_PORT_PRIORITY, u, NULL);
 		else
-			PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: invalid priority value '%s'", value);
+			PARSE_WARNING ("invalid priority value '%s'", value);
 	} else if (!strcmp (key, "path_cost")) {
 		if (get_uint (value, &u))
 			g_object_set (setting, NM_SETTING_BRIDGE_PORT_PATH_COST, u, NULL);
 		else
-			PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: invalid path_cost value '%s'", value);
+			PARSE_WARNING ("invalid path_cost value '%s'", value);
 	} else if (!strcmp (key, "hairpin_mode")) {
 		if (!strcasecmp (value, "on") || !strcasecmp (value, "yes") || !strcmp (value, "1"))
 			g_object_set (setting, NM_SETTING_BRIDGE_PORT_HAIRPIN_MODE, TRUE, NULL);
 		else if (!strcasecmp (value, "off") || !strcasecmp (value, "no"))
 			g_object_set (setting, NM_SETTING_BRIDGE_PORT_HAIRPIN_MODE, FALSE, NULL);
 		else
-			PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: invalid hairpin_mode value '%s'", value);
+			PARSE_WARNING ("invalid hairpin_mode value '%s'", value);
 	} else
-			PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: unhandled bridge port option '%s'", key);
+			PARSE_WARNING ("unhandled bridge port option '%s'", key);
 }
 
 static NMSetting *
-make_bridge_port_setting (shvarFile *ifcfg, GError **error)
+make_bridge_port_setting (shvarFile *ifcfg)
 {
-	NMSetting *s_port;
+	NMSetting *s_port = NULL;
 	char *value;
 
+	g_return_val_if_fail (ifcfg != NULL, FALSE);
+
 	value = svGetValue (ifcfg, "BRIDGE", FALSE);
-	if (!value)
-		return NULL;
-	g_free (value);
+	if (value) {
+		g_free (value);
+
+		s_port = nm_setting_bridge_port_new ();
+		value = svGetValue (ifcfg, "BRIDGING_OPTS", FALSE);
+		if (value)
+			handle_bridging_opts (s_port, FALSE, value, handle_bridge_port_option);
+		g_free (value);
+	}
 
-	s_port = nm_setting_bridge_port_new ();
+	return s_port;
+}
 
-	value = svGetValue (ifcfg, "BRIDGING_OPTS", FALSE);
+static NMSetting *
+make_team_port_setting (shvarFile *ifcfg)
+{
+	NMSetting *s_port = NULL;
+	char *value;
+	GError *error = NULL;
+
+	value = read_team_config (ifcfg, "TEAM_PORT_CONFIG", &error);
 	if (value) {
-		handle_bridging_opts (s_port, FALSE, value, handle_bridge_port_option);
+		s_port = nm_setting_team_port_new ();
+		g_object_set (s_port, NM_SETTING_TEAM_PORT_CONFIG, value, NULL);
 		g_free (value);
+	} else if (error) {
+		PARSE_WARNING ("%s", error->message);
+		g_error_free (error);
 	}
 
 	return s_port;
@@ -4007,6 +4713,21 @@ is_vlan_device (const char *name, shvarFile *parsed)
 	return FALSE;
 }
 
+static gboolean
+is_wifi_device (const char *name, shvarFile *parsed)
+{
+	int ifindex;
+
+	g_return_val_if_fail (name != NULL, FALSE);
+	g_return_val_if_fail (parsed != NULL, FALSE);
+
+	ifindex = nm_platform_link_get_ifindex (name);
+	if (ifindex == 0)
+		return FALSE;
+
+	return nm_platform_link_get_type (ifindex) == NM_LINK_TYPE_WIFI;
+}
+
 static void
 parse_prio_map_list (NMSettingVlan *s_vlan,
                      shvarFile *ifcfg,
@@ -4027,10 +4748,8 @@ parse_prio_map_list (NMSettingVlan *s_vlan,
 		if (!*iter || !strchr (*iter, ':'))
 			continue;
 
-		if (!nm_setting_vlan_add_priority_str (s_vlan, map, *iter)) {
-			PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: invalid %s priority map item '%s'",
-			             key, *iter);
-		}
+		if (!nm_setting_vlan_add_priority_str (s_vlan, map, *iter))
+			PARSE_WARNING ("invalid %s priority map item '%s'", key, *iter);
 	}
 	g_strfreev (list);
 }
@@ -4038,9 +4757,7 @@ parse_prio_map_list (NMSettingVlan *s_vlan,
 static NMSetting *
 make_vlan_setting (shvarFile *ifcfg,
                    const char *file,
-                   gboolean nm_controlled,
                    char **out_master,
-                   char **unmanaged,
                    NMSetting8021x **s_8021x,
                    GError **error)
 {
@@ -4160,8 +4877,6 @@ error:
 static NMConnection *
 vlan_connection_from_ifcfg (const char *file,
                             shvarFile *ifcfg,
-                            gboolean nm_controlled,
-                            char **unmanaged,
                             GError **error)
 {
 	NMConnection *connection = NULL;
@@ -4175,11 +4890,6 @@ vlan_connection_from_ifcfg (const char *file,
 	g_return_val_if_fail (ifcfg != NULL, NULL);
 
 	connection = nm_connection_new ();
-	if (!connection) {
-		g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
-			     "Failed to allocate new connection for %s.", file);
-		return NULL;
-	}
 
 	con_setting = make_connection_setting (file, ifcfg, NM_SETTING_VLAN_SETTING_NAME, NULL, "Vlan");
 	if (!con_setting) {
@@ -4190,7 +4900,7 @@ vlan_connection_from_ifcfg (const char *file,
 	}
 	nm_connection_add_setting (connection, con_setting);
 
-	vlan_setting = make_vlan_setting (ifcfg, file, nm_controlled, &master, unmanaged, &s_8021x, error);
+	vlan_setting = make_vlan_setting (ifcfg, file, &master, &s_8021x, error);
 	if (!vlan_setting) {
 		g_object_unref (connection);
 		return NULL;
@@ -4206,7 +4916,7 @@ vlan_connection_from_ifcfg (const char *file,
 		g_free (master);
 	}
 
-	wired_setting = make_wired_setting (ifcfg, file, nm_controlled, unmanaged, &s_8021x, error);
+	wired_setting = make_wired_setting (ifcfg, file, &s_8021x, error);
 	if (!wired_setting) {
 		g_object_unref (connection);
 		return NULL;
@@ -4223,36 +4933,140 @@ vlan_connection_from_ifcfg (const char *file,
 	return connection;
 }
 
+static NMConnection *
+create_unhandled_connection (const char *filename, shvarFile *ifcfg,
+                             const char *type, char **out_spec)
+{
+	NMConnection *connection;
+	NMSetting *s_con;
+	char *value;
+
+	g_assert (out_spec != NULL);
+
+	connection = nm_connection_new ();
+
+	/* Get NAME, UUID, etc. We need to set a connection type (generic) and add
+	 * an empty type-specific setting as well, to make sure it passes
+	 * nm_connection_verify() later.
+	 */
+	s_con = make_connection_setting (filename, ifcfg, NM_SETTING_GENERIC_SETTING_NAME,
+	                                 NULL, NULL);
+	nm_connection_add_setting (connection, s_con);
+
+	nm_connection_add_setting (connection, nm_setting_generic_new ());
+
+	/* Get a spec */
+	value = svGetValue (ifcfg, "HWADDR", FALSE);
+	if (value) {
+		char *lower = g_ascii_strdown (value, -1);
+		*out_spec = g_strdup_printf ("%s:mac:%s", type, lower);
+		g_free (lower);
+		g_free (value);
+		return connection;
+	}
+
+	value = svGetValue (ifcfg, "SUBCHANNELS", FALSE);
+	if (value) {
+		*out_spec = g_strdup_printf ("%s:s390-subchannels:%s", type, value);
+		g_free (value);
+		return connection;
+	}
+
+	value = svGetValue (ifcfg, "DEVICE", FALSE);
+	if (value) {
+		*out_spec = g_strdup_printf ("%s:interface-name:%s", type, value);
+		g_free (value);
+		return connection;
+	}
+
+	g_object_unref (connection);
+	return NULL;
+}
+
+char *
+uuid_from_file (const char *filename)
+{
+	const char *ifcfg_name = NULL;
+	shvarFile *ifcfg;
+	char *uuid;
+
+	g_return_val_if_fail (filename != NULL, NULL);
+
+	ifcfg_name = utils_get_ifcfg_name (filename, TRUE);
+	if (!ifcfg_name)
+		return NULL;
+
+	ifcfg = svOpenFile (filename, NULL);
+	if (!ifcfg)
+		return NULL;
+
+	/* Try for a UUID key before falling back to hashing the file name */
+	uuid = svGetValue (ifcfg, "UUID", FALSE);
+	if (!uuid || !strlen (uuid)) {
+		g_free (uuid);
+		uuid = nm_utils_uuid_generate_from_string (ifcfg->fileName);
+	}
+
+	svCloseFile (ifcfg);
+	return uuid;
+}
+
+static void
+check_dns_search_domains (shvarFile *ifcfg, NMSetting *s_ip4, NMSetting *s_ip6)
+{
+	if (!s_ip6)
+		return;
+
+	/* If there is no IPv4 config or it doesn't contain DNS searches,
+	 * read DOMAIN and put the domains into IPv6.
+	 */
+	if (!s_ip4 || nm_setting_ip4_config_get_num_dns_searches (NM_SETTING_IP4_CONFIG (s_ip4)) == 0) {
+		/* DNS searches */
+		char *value = svGetValue (ifcfg, "DOMAIN", FALSE);
+		if (value) {
+			char **searches = g_strsplit (value, " ", 0);
+			if (searches) {
+				char **item;
+				for (item = searches; *item; item++) {
+					if (strlen (*item)) {
+						if (!nm_setting_ip6_config_add_dns_search (NM_SETTING_IP6_CONFIG (s_ip6), *item))
+							PARSE_WARNING ("duplicate DNS domain '%s'", *item);
+					}
+				}
+				g_strfreev (searches);
+			}
+			g_free (value);
+		}
+	}
+}
+
 NMConnection *
 connection_from_file (const char *filename,
                       const char *network_file,  /* for unit tests only */
                       const char *test_type,     /* for unit tests only */
                       const char *iscsiadm_path, /* for unit tests only */
-                      char **unmanaged,
-                      char **keyfile,
-                      char **routefile,
-                      char **route6file,
-                      GError **out_error,
-                      gboolean *ignore_error)
+                      char **out_unhandled,
+                      char **out_keyfile,
+                      char **out_routefile,
+                      char **out_route6file,
+                      GError **error,
+                      gboolean *out_ignore_error)
 {
 	NMConnection *connection = NULL;
 	shvarFile *parsed;
-	char *type, *nmc = NULL, *bootproto;
-	NMSetting *s_ip4, *s_ip6, *s_port;
+	char *type, *devtype, *bootproto;
+	NMSetting *s_ip4, *s_ip6, *s_port, *s_dcb = NULL;
 	const char *ifcfg_name = NULL;
-	gboolean nm_controlled = TRUE;
-	gboolean can_disable_ip4 = FALSE;
-	GError *error = NULL;
 
 	g_return_val_if_fail (filename != NULL, NULL);
-	g_return_val_if_fail (unmanaged != NULL, NULL);
-	g_return_val_if_fail (*unmanaged == NULL, NULL);
-	g_return_val_if_fail (keyfile != NULL, NULL);
-	g_return_val_if_fail (*keyfile == NULL, NULL);
-	g_return_val_if_fail (routefile != NULL, NULL);
-	g_return_val_if_fail (*routefile == NULL, NULL);
-	g_return_val_if_fail (route6file != NULL, NULL);
-	g_return_val_if_fail (*route6file == NULL, NULL);
+	if (out_unhandled)
+		g_return_val_if_fail (*out_unhandled == NULL, NULL);
+	if (out_keyfile)
+		g_return_val_if_fail (*out_keyfile == NULL, NULL);
+	if (out_routefile)
+		g_return_val_if_fail (*out_routefile == NULL, NULL);
+	if (out_route6file)
+		g_return_val_if_fail (*out_route6file == NULL, NULL);
 
 	/* Non-NULL only for unit tests; normally use /etc/sysconfig/network */
 	if (!network_file)
@@ -4263,33 +5077,52 @@ connection_from_file (const char *filename,
 
 	ifcfg_name = utils_get_ifcfg_name (filename, TRUE);
 	if (!ifcfg_name) {
-		g_set_error (out_error, IFCFG_PLUGIN_ERROR, 0,
+		g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
 		             "Ignoring connection '%s' because it's not an ifcfg file.", filename);
 		return NULL;
 	}
 
-	parsed = svNewFile (filename);
-	if (!parsed) {
-		g_set_error (out_error, IFCFG_PLUGIN_ERROR, 0,
-		             "Couldn't parse file '%s'", filename);
+	parsed = svOpenFile (filename, error);
+	if (!parsed)
 		return NULL;
+
+	if (!svTrueValue (parsed, "NM_CONTROLLED", TRUE)) {
+		g_assert (out_unhandled != NULL);
+
+		connection = create_unhandled_connection (filename, parsed, "unmanaged", out_unhandled);
+		if (!connection)
+			PARSE_WARNING ("NM_CONTROLLED was false but device was not uniquely identified; device will be managed");
+		goto done;
+	}
+
+	type = NULL;
+
+	devtype = svGetValue (parsed, "DEVICETYPE", FALSE);
+	if (devtype) {
+		if (!strcasecmp (devtype, TYPE_TEAM))
+			type = g_strdup (TYPE_TEAM);
+		else if (!strcasecmp (devtype, TYPE_TEAM_PORT))
+			type = g_strdup (TYPE_ETHERNET);
+		g_free (devtype);
 	}
 
-	type = svGetValue (parsed, "TYPE", FALSE);
+	if (!type)
+		type = svGetValue (parsed, "TYPE", FALSE);
+
 	if (!type) {
 		char *device;
 
 		device = svGetValue (parsed, "DEVICE", FALSE);
 		if (!device) {
-			g_set_error (&error, IFCFG_PLUGIN_ERROR, 0,
+			g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
 			             "File '%s' had neither TYPE nor DEVICE keys.", filename);
 			goto done;
 		}
 
 		if (!strcmp (device, "lo")) {
-			if (ignore_error)
-				*ignore_error = TRUE;
-			g_set_error (&error, IFCFG_PLUGIN_ERROR, 0,
+			if (out_ignore_error)
+				*out_ignore_error = TRUE;
+			g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
 			             "Ignoring loopback device config.");
 			g_free (device);
 			goto done;
@@ -4300,8 +5133,7 @@ connection_from_file (const char *filename,
 				type = g_strdup (TYPE_BOND);
 			else if (is_vlan_device (device, parsed))
 				type = g_strdup (TYPE_VLAN);
-			/* Test wireless extensions */
-			else if (wifi_utils_is_wifi (device, NULL))
+			else if (is_wifi_device (device, parsed))
 				type = g_strdup (TYPE_WIRELESS);
 			else
 				type = g_strdup (TYPE_ETHERNET);
@@ -4322,90 +5154,82 @@ connection_from_file (const char *filename,
 		}
 	}
 
-	nmc = svGetValue (parsed, "NM_CONTROLLED", FALSE);
-	if (nmc) {
-		char *lower;
-
-		lower = g_ascii_strdown (nmc, -1);
-		g_free (nmc);
-
-		if (!strcmp (lower, "no") || !strcmp (lower, "n") || !strcmp (lower, "false"))
-			nm_controlled = FALSE;
-		g_free (lower);
-	}
-
 	if (svTrueValue (parsed, "BONDING_MASTER", FALSE) &&
 	    strcasecmp (type, TYPE_BOND)) {
-		g_set_error (&error, IFCFG_PLUGIN_ERROR, 0,
+		g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
 		             "BONDING_MASTER=yes key only allowed in TYPE=bond connections");
 		goto done;
 	}
 
 	/* Construct the connection */
 	if (!strcasecmp (type, TYPE_ETHERNET))
-		connection = wired_connection_from_ifcfg (filename, parsed, nm_controlled, unmanaged, &error);
+		connection = wired_connection_from_ifcfg (filename, parsed, error);
 	else if (!strcasecmp (type, TYPE_WIRELESS))
-		connection = wireless_connection_from_ifcfg (filename, parsed, nm_controlled, unmanaged, &error);
+		connection = wireless_connection_from_ifcfg (filename, parsed, error);
 	else if (!strcasecmp (type, TYPE_INFINIBAND))
-		connection = infiniband_connection_from_ifcfg (filename, parsed, nm_controlled, unmanaged, &error);
+		connection = infiniband_connection_from_ifcfg (filename, parsed, error);
 	else if (!strcasecmp (type, TYPE_BOND))
-		connection = bond_connection_from_ifcfg (filename, parsed, nm_controlled, unmanaged, &error);
+		connection = bond_connection_from_ifcfg (filename, parsed, error);
+	else if (!strcasecmp (type, TYPE_TEAM))
+		connection = team_connection_from_ifcfg (filename, parsed, error);
 	else if (!strcasecmp (type, TYPE_VLAN))
-		connection = vlan_connection_from_ifcfg (filename, parsed, nm_controlled, unmanaged, &error);
+		connection = vlan_connection_from_ifcfg (filename, parsed, error);
 	else if (!strcasecmp (type, TYPE_BRIDGE))
-		connection = bridge_connection_from_ifcfg (filename, parsed, nm_controlled, unmanaged, &error);
+		connection = bridge_connection_from_ifcfg (filename, parsed, error);
 	else {
-		g_set_error (&error, IFCFG_PLUGIN_ERROR, 0,
-		             "Unknown connection type '%s'", type);
-	}
+		g_assert (out_unhandled != NULL);
 
-	if (nm_controlled) {
-		g_free (*unmanaged);
-		*unmanaged = NULL;
+		connection = create_unhandled_connection (filename, parsed, "unrecognized", out_unhandled);
+		if (!connection)
+			PARSE_WARNING ("connection type was unrecognized but device was not uniquely identified; device may be managed");
+		goto done;
 	}
-
 	g_free (type);
 
-	/* Don't bother reading the connection fully if it's unmanaged or ignored */
-	if (!connection || *unmanaged)
+	if (!connection)
 		goto done;
 
-	s_ip6 = make_ip6_setting (parsed, network_file, iscsiadm_path, &error);
-	if (error) {
+	s_ip6 = make_ip6_setting (parsed, network_file, iscsiadm_path, error);
+	if (!s_ip6) {
 		g_object_unref (connection);
 		connection = NULL;
 		goto done;
-	} else if (s_ip6 && utils_ignore_ip_config (connection)) {
-		PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: ignoring IP6 configuration");
-		g_object_unref (s_ip6);
-	} else if (s_ip6) {
-		const char *method;
-
+	} else
 		nm_connection_add_setting (connection, s_ip6);
-		method = nm_setting_ip6_config_get_method (NM_SETTING_IP6_CONFIG (s_ip6));
-		if (method && strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE))
-			can_disable_ip4 = TRUE;
-	}
 
-	s_ip4 = make_ip4_setting (parsed, network_file, iscsiadm_path, can_disable_ip4, &error);
-	if (error) {
+	s_ip4 = make_ip4_setting (parsed, network_file, iscsiadm_path, error);
+	if (!s_ip4) {
 		g_object_unref (connection);
 		connection = NULL;
 		goto done;
-	} else if (s_ip4 && utils_ignore_ip_config (connection)) {
-		PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: ignoring IP4 configuration");
-		g_object_unref (s_ip4);
-	} else if (s_ip4)
+	} else {
+		read_aliases (NM_SETTING_IP4_CONFIG (s_ip4), filename, network_file);
 		nm_connection_add_setting (connection, s_ip4);
+	}
+
+	/* There is only one DOMAIN variable and it is read and put to IPv4 config
+	 * But if IPv4 is disabled or the config fails for some reason, we read
+	 * DOMAIN and put the values into IPv6 config instead.
+	 */
+	check_dns_search_domains (parsed, s_ip4, s_ip6);
 
 	/* Bridge port? */
-	s_port = make_bridge_port_setting (parsed, &error);
-	if (error) {
+	s_port = make_bridge_port_setting (parsed);
+	if (s_port)
+		nm_connection_add_setting (connection, s_port);
+
+	/* Team port? */
+	s_port = make_team_port_setting (parsed);
+	if (s_port)
+		nm_connection_add_setting (connection, s_port);
+
+	if (!make_dcb_setting (parsed, network_file, &s_dcb, error)) {
 		g_object_unref (connection);
 		connection = NULL;
 		goto done;
-	} else if (s_port)
-		nm_connection_add_setting (connection, s_port);
+	}
+	if (s_dcb)
+		nm_connection_add_setting (connection, s_dcb);
 
 	/* iSCSI / ibft connections are read-only since their settings are
 	 * stored in NVRAM and can only be changed in BIOS.
@@ -4423,21 +5247,22 @@ connection_from_file (const char *filename,
 	}
 	g_free (bootproto);
 
-	if (!nm_connection_verify (connection, &error)) {
+	nm_utils_normalize_connection (connection, TRUE);
+
+	if (!nm_connection_verify (connection, error)) {
 		g_object_unref (connection);
 		connection = NULL;
 	}
 
-	*keyfile = utils_get_keys_path (filename);
-	*routefile = utils_get_route_path (filename);
-	*route6file = utils_get_route6_path (filename);
+	if (out_keyfile)
+		*out_keyfile = utils_get_keys_path (filename);
+	if (out_routefile)
+		*out_routefile = utils_get_route_path (filename);
+	if (out_route6file)
+		*out_route6file = utils_get_route6_path (filename);
 
 done:
 	svCloseFile (parsed);
-	if (error && out_error)
-		*out_error = error;
-	else
-		g_clear_error (&error);
 	return connection;
 }
 
diff --git a/src/settings/plugins/ifcfg-rh/reader.h b/src/settings/plugins/ifcfg-rh/reader.h
index 97c727cc..371f4504 100644
--- a/src/settings/plugins/ifcfg-rh/reader.h
+++ b/src/settings/plugins/ifcfg-rh/reader.h
@@ -30,11 +30,13 @@ NMConnection *connection_from_file (const char *filename,
                                     const char *network_file,  /* for unit tests only */
                                     const char *test_type,     /* for unit tests only */
                                     const char *iscsiadm_path, /* for unit tests only */
-                                    char **unmanaged,
-                                    char **keyfile,
-                                    char **routefile,
-                                    char **route6file,
+                                    char **out_unhandled,
+                                    char **out_keyfile,
+                                    char **out_routefile,
+                                    char **out_route6file,
                                     GError **error,
-                                    gboolean *ignore_error);
+                                    gboolean *out_ignore_error);
+
+char *uuid_from_file (const char *filename);
 
 #endif  /* __READER_H__ */
diff --git a/src/settings/plugins/ifcfg-rh/shvar.c b/src/settings/plugins/ifcfg-rh/shvar.c
index cdbd7f24..4e8e29ce 100644
--- a/src/settings/plugins/ifcfg-rh/shvar.c
+++ b/src/settings/plugins/ifcfg-rh/shvar.c
@@ -1,15 +1,10 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
 /*
  * shvar.c
  *
  * Implementation of non-destructively reading/writing files containing
  * only shell variable declarations and full-line comments.
  *
- * Includes explicit inheritance mechanism intended for use with
- * Red Hat Linux ifcfg-* files.  There is no protection against
- * inheritance loops; they will generally cause stack overflows.
- * Furthermore, they are only intended for one level of inheritance;
- * the value setting algorithm assumes this.
- *
  * Copyright 1999,2000 Red Hat, Inc.
  *
  * This is free software; you can redistribute it and/or modify it
@@ -28,6 +23,7 @@
  *
  */
 
+#include <errno.h>
 #include <fcntl.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -39,103 +35,162 @@
 #include "shvar.h"
 
 /* Open the file <name>, returning a shvarFile on success and NULL on failure.
-   Add a wrinkle to let the caller specify whether or not to create the file
-   (actually, return a structure anyway) if it doesn't exist. */
+ * Add a wrinkle to let the caller specify whether or not to create the file
+ * (actually, return a structure anyway) if it doesn't exist.
+ */
 static shvarFile *
-svOpenFile(const char *name, gboolean create)
+svOpenFileInternal (const char *name, gboolean create, GError **error)
 {
-    shvarFile *s = NULL;
-    int closefd = 0;
-
-    s = g_malloc0(sizeof(shvarFile));
-
-    s->fd = -1;
-    if (create)
-	s->fd = open(name, O_RDWR); /* NOT O_CREAT */
- 
-    if (!create || s->fd == -1) {
-	/* try read-only */
-	s->fd = open(name, O_RDONLY); /* NOT O_CREAT */
-	if (s->fd != -1) closefd = 1;
-    }
-    s->fileName = g_strdup(name);
-
-    if (s->fd != -1) {
-	struct stat buf;
-	char *p, *q;
-
-	if (fstat(s->fd, &buf) < 0) goto bail;
-	s->arena = g_malloc0(buf.st_size + 1);
-
-	if (read(s->fd, s->arena, buf.st_size) < 0) goto bail;
-
-	/* we'd use g_strsplit() here, but we want a list, not an array */
-	for(p = s->arena; (q = strchr(p, '\n')) != NULL; p = q + 1) {
-		s->lineList = g_list_append(s->lineList, g_strndup(p, q - p));
+	shvarFile *s = NULL;
+	gboolean closefd = FALSE;
+	int errsv = 0;
+
+	s = g_slice_new0 (shvarFile);
+
+	s->fd = -1;
+	if (create)
+		s->fd = open (name, O_RDWR); /* NOT O_CREAT */
+
+	if (!create || s->fd == -1) {
+		/* try read-only */
+		s->fd = open (name, O_RDONLY); /* NOT O_CREAT */
+		if (s->fd == -1)
+			errsv = errno;
+		else
+			closefd = TRUE;
 	}
-
-	/* closefd is set if we opened the file read-only, so go ahead and
-	   close it, because we can't write to it anyway */
-	if (closefd) {
-	    close(s->fd);
-	    s->fd = -1;
+	s->fileName = g_strdup (name);
+
+	if (s->fd != -1) {
+		struct stat buf;
+		char *arena, *p, *q;
+		ssize_t nread, total = 0;
+
+		if (fstat (s->fd, &buf) < 0) {
+			errsv = errno;
+			goto bail;
+		}
+		arena = g_malloc (buf.st_size + 1);
+		arena[buf.st_size] = '\0';
+
+		while (total < buf.st_size) {
+			nread = read (s->fd, arena + total, buf.st_size - total);
+			if (nread == -1 && errno == EINTR)
+				continue;
+			if (nread <= 0) {
+				errsv = errno;
+				g_free (arena);
+				goto bail;
+			}
+			total += nread;
+		}
+
+		/* we'd use g_strsplit() here, but we want a list, not an array */
+		for (p = arena; (q = strchr (p, '\n')) != NULL; p = q + 1)
+			s->lineList = g_list_append (s->lineList, g_strndup (p, q - p));
+		g_free (arena);
+
+		/* closefd is set if we opened the file read-only, so go ahead and
+		 * close it, because we can't write to it anyway
+		 */
+		if (closefd) {
+			close (s->fd);
+			s->fd = -1;
+		}
+
+		return s;
 	}
 
-        return s;
-    }
+	if (create)
+		return s;
 
-    if (create) {
-        return s;
-    }
+ bail:
+	if (s->fd != -1)
+		close (s->fd);
+	g_free (s->fileName);
+	g_slice_free (shvarFile, s);
 
-bail:
-    if (s->fd != -1) close(s->fd);
-    g_free (s->arena);
-    g_free (s->fileName);
-    g_free (s);
-    return NULL;
+	g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errsv),
+	             "Could not read file '%s': %s",
+	             name, errsv ? strerror (errsv) : "Unknown error");
+	return NULL;
 }
 
 /* Open the file <name>, return shvarFile on success, NULL on failure */
 shvarFile *
-svNewFile(const char *name)
+svOpenFile (const char *name, GError **error)
 {
-    return svOpenFile(name, FALSE);
+	return svOpenFileInternal (name, FALSE, error);
 }
 
 /* Create a new file structure, returning actual data if the file exists,
- * and a suitable starting point if it doesn't. */
+ * and a suitable starting point if it doesn't.
+ */
 shvarFile *
-svCreateFile(const char *name)
+svCreateFile (const char *name)
 {
-    return svOpenFile(name, TRUE);
+	return svOpenFileInternal (name, TRUE, NULL);
 }
 
 /* remove escaped characters in place */
 void
-svUnescape(char *s) {
-    int len, i;
-
-    len = strlen(s);
-    if (len >= 2 && (s[0] == '"' || s[0] == '\'') && s[0] == s[len-1]) {
-	i = len - 2;
-	if (i == 0)
-	  s[0] = '\0';
-	else {
-	  memmove(s, s+1, i);
-	  s[i+1] = '\0';
-	  len = i;
+svUnescape (char *s)
+{
+	size_t len, idx_rd = 0, idx_wr = 0;
+	char c;
+
+	len = strlen (s);
+	if (len < 2) {
+		if (s[0] == '\\')
+			s[0] = '\0';
+		return;
 	}
-    }
-    for (i = 0; i < len; i++) {
-	if (s[i] == '\\') {
-	    memmove(s+i, s+i+1, len-(i+1));
-	    len--;
+
+	if ((s[0] == '"' || s[0] == '\'') && s[0] == s[len-1]) {
+		if (len == 2) {
+			s[0] = '\0';
+			return;
+		}
+		if (len == 3) {
+			if (s[1] == '\\') {
+				s[0] = '\0';
+			} else {
+				s[0] = s[1];
+				s[1] = '\0';
+			}
+			return;
+		}
+		s[--len] = '\0';
+		idx_rd = 1;
+	} else {
+		/* seek for the first escape... */
+		char *p = strchr (s, '\\');
+
+		if (!p)
+			return;
+		if (p[1] == '\0') {
+			p[0] = '\0';
+			return;
+		}
+		idx_wr = idx_rd = (p - s);
 	}
-	s[len] = '\0';
-    }
-}
 
+	/* idx_rd points to the first escape. Walk the string and shift the
+	 * characters from idx_rd to idx_wr.
+	 */
+	while ((c = s[idx_rd++])) {
+		if (c == '\\') {
+			if (s[idx_rd] == '\0') {
+				s[idx_wr] = '\0';
+				return;
+			}
+			s[idx_wr++] = s[idx_rd++];
+			continue;
+		}
+		s[idx_wr++] = c;
+	}
+	s[idx_wr] = '\0';
+}
 
 /* create a new string with all necessary characters escaped.
  * caller must free returned string
@@ -143,42 +198,46 @@ svUnescape(char *s) {
 static const char escapees[] = "\"'\\$~`";		/* must be escaped */
 static const char spaces[] = " \t|&;()<>";		/* only require "" */
 static const char newlines[] = "\n\r";			/* will be removed */
+
 char *
-svEscape(const char *s) {
-    char *new;
-    int i, j, mangle = 0, space = 0, newline = 0;
-    int newlen, slen;
-    static int esclen, splen;
-
-    if (!esclen) esclen = strlen(escapees);
-    if (!splen) splen = strlen(spaces);
-    slen = strlen(s);
-
-    for (i = 0; i < slen; i++) {
-	if (strchr(escapees, s[i])) mangle++;
-	if (strchr(spaces, s[i])) space++;
-	if (strchr(newlines, s[i])) newline++;
-    }
-    if (!mangle && !space && !newline) return strdup(s);
-
-    newlen = slen + mangle - newline + 3;	/* 3 is extra ""\0 */
-    new = g_malloc0(newlen);
-    if (!new) return NULL;
-
-    j = 0;
-    new[j++] = '"';
-    for (i = 0; i < slen; i++) {
-	if (strchr(newlines, s[i]))
-	    continue;
-	if (strchr(escapees, s[i])) {
-	    new[j++] = '\\';
+svEscape (const char *s)
+{
+	char *new;
+	int i, j, mangle = 0, space = 0, newline = 0;
+	int newlen, slen;
+
+	slen = strlen (s);
+
+	for (i = 0; i < slen; i++) {
+		if (strchr (escapees, s[i]))
+			mangle++;
+		if (strchr (spaces, s[i]))
+			space++;
+		if (strchr (newlines, s[i]))
+			newline++;
 	}
-	new[j++] = s[i];
-    }
-    new[j++] = '"';
-    g_assert(j == slen + mangle - newline + 2); /* j is the index of the '\0' */
+	if (!mangle && !space && !newline)
+		return strdup (s);
+
+	newlen = slen + mangle - newline + 3;	/* 3 is extra ""\0 */
+	new = g_malloc (newlen);
+
+	j = 0;
+	new[j++] = '"';
+	for (i = 0; i < slen; i++) {
+		if (strchr (newlines, s[i]))
+			continue;
+		if (strchr (escapees, s[i])) {
+			new[j++] = '\\';
+		}
+		new[j++] = s[i];
+	}
+	new[j++] = '"';
+	new[j++] = '\0'
+;
+	g_assert (j == slen + mangle - newline + 3);
 
-    return new;
+	return new;
 }
 
 /* Get the value associated with the key, and leave the current pointer
@@ -186,215 +245,190 @@ svEscape(const char *s) {
  * be freed by the caller.
  */
 char *
-svGetValue(shvarFile *s, const char *key, gboolean verbatim)
+svGetValue (shvarFile *s, const char *key, gboolean verbatim)
 {
-    char *value = NULL;
-    char *line;
-    char *keyString;
-    int len;
-
-    g_assert(s);
-    g_assert(key);
-
-    keyString = g_malloc0(strlen(key) + 2);
-    strcpy(keyString, key);
-    keyString[strlen(key)] = '=';
-    len = strlen(keyString);
-
-    for (s->current = s->lineList; s->current; s->current = s->current->next) {
-	line = s->current->data;
-	if (!strncmp(keyString, line, len)) {
-	    value = g_strdup(line + len);
-	    if (!verbatim)
-	      svUnescape(value);
-	    break;
+	char *value = NULL;
+	char *line;
+	char *keyString;
+	int len;
+
+	g_return_val_if_fail (s != NULL, NULL);
+	g_return_val_if_fail (key != NULL, NULL);
+
+	keyString = g_strdup_printf ("%s=", key);
+	len = strlen (keyString);
+
+	for (s->current = s->lineList; s->current; s->current = s->current->next) {
+		line = s->current->data;
+		if (!strncmp (keyString, line, len)) {
+			value = g_strdup (line + len);
+			if (!verbatim)
+				svUnescape (value);
+			break;
+		}
 	}
-    }
-    g_free(keyString);
+	g_free (keyString);
 
-    if (value) {
-	if (value[0]) {
-	    return value;
+	if (value && value[0]) {
+		return value;
 	} else {
-	    g_free(value);
-	    return NULL;
+		g_free (value);
+		return NULL;
 	}
-    }
-    if (s->parent) value = svGetValue(s->parent, key, verbatim);
-    return value;
 }
 
-/* return 1 if <key> resolves to any truth value (e.g. "yes", "y", "true")
- * return 0 if <key> resolves to any non-truth value (e.g. "no", "n", "false")
+/* return TRUE if <key> resolves to any truth value (e.g. "yes", "y", "true")
+ * return FALSE if <key> resolves to any non-truth value (e.g. "no", "n", "false")
  * return <default> otherwise
  */
-int
-svTrueValue(shvarFile *s, const char *key, int def)
+gboolean
+svTrueValue (shvarFile *s, const char *key, gboolean def)
 {
-    char *tmp;
-    int returnValue = def;
-
-    tmp = svGetValue(s, key, FALSE);
-    if (!tmp) return returnValue;
-
-    if ( (!strcasecmp("yes", tmp)) ||
-	 (!strcasecmp("true", tmp)) ||
-	 (!strcasecmp("t", tmp)) ||
-	 (!strcasecmp("y", tmp)) ) returnValue = 1;
-    else
-    if ( (!strcasecmp("no", tmp)) ||
-	 (!strcasecmp("false", tmp)) ||
-	 (!strcasecmp("f", tmp)) ||
-	 (!strcasecmp("n", tmp)) ) returnValue = 0;
-
-    g_free (tmp);
-    return returnValue;
+	char *tmp;
+	gboolean returnValue = def;
+
+	tmp = svGetValue (s, key, FALSE);
+	if (!tmp)
+		return returnValue;
+
+	if (   !g_ascii_strcasecmp ("yes", tmp)
+	    || !g_ascii_strcasecmp ("true", tmp)
+	    || !g_ascii_strcasecmp ("t", tmp)
+	    || !g_ascii_strcasecmp ("y", tmp))
+		returnValue = TRUE;
+	else if (   !g_ascii_strcasecmp ("no", tmp)
+	         || !g_ascii_strcasecmp ("false", tmp)
+	         || !g_ascii_strcasecmp ("f", tmp)
+	         || !g_ascii_strcasecmp ("n", tmp))
+		returnValue = FALSE;
+
+	g_free (tmp);
+	return returnValue;
 }
 
 
 /* Set the variable <key> equal to the value <value>.
  * If <key> does not exist, and the <current> pointer is set, append
- * the key=value pair after that line.  Otherwise, prepend the pair
- * to the top of the file.  Here's the algorithm, as the C code
- * seems to be rather dense:
- *
- * if (value == NULL), then:
- *     if val2 (parent): change line to key= or append line key=
- *     if val1 (this)  : delete line
- *     else noop
- * else use this table:
- *                                val2
- *             NULL              value               other
- * v   NULL    append line       noop                append line
- * a
- * l   value   noop              noop                noop
- * 1
- *     other   change line       delete line         change line
- *
- * No changes are ever made to the parent config file, only to the
- * specific file passed on the command line.
- *
+ * the key=value pair after that line.  Otherwise, append the pair
+ * to the bottom of the file.
  */
 void
-svSetValue(shvarFile *s, const char *key, const char *value, gboolean verbatim)
+svSetValue (shvarFile *s, const char *key, const char *value, gboolean verbatim)
 {
-    char *newval = NULL, *val1 = NULL, *val2 = NULL;
-    char *keyValue;
-
-    g_assert(s);
-    g_assert(key);
-    /* value may be NULL */
-
-    if (value)
-        newval = verbatim ? g_strdup(value) : svEscape(value);
-    keyValue = g_strdup_printf("%s=%s", key, newval ? newval : "");
-
-    val1 = svGetValue(s, key, FALSE);
-    if (val1 && newval && !strcmp(val1, newval)) goto bail;
-    if (s->parent) val2 = svGetValue(s->parent, key, FALSE);
-
-    if (!newval || !newval[0]) {
-	/* delete value somehow */
-	if (val2) {
-	    /* change/append line to get key= */
-	    if (s->current) s->current->data = keyValue;
-	    else s->lineList = g_list_append(s->lineList, keyValue);
-	    s->modified = 1;
-	    goto end;
-	} else if (val1) {
-	    /* delete line */
-	    s->lineList = g_list_remove_link(s->lineList, s->current);
-	    g_list_free_1(s->current);
-	    s->modified = 1;
+	char *newval = NULL, *oldval = NULL;
+	char *keyValue;
+
+	g_return_if_fail (s != NULL);
+	g_return_if_fail (key != NULL);
+	/* value may be NULL */
+
+	if (value)
+		newval = verbatim ? g_strdup (value) : svEscape (value);
+	keyValue = g_strdup_printf ("%s=%s", key, newval ? newval : "");
+
+	oldval = svGetValue (s, key, FALSE);
+
+	if (!newval || !newval[0]) {
+		/* delete value */
+		if (oldval) {
+			/* delete line */
+			s->lineList = g_list_remove_link (s->lineList, s->current);
+			g_list_free_1 (s->current);
+			s->modified = TRUE;
+		}
+		goto bail; /* do not need keyValue */
+	}
+
+	if (!oldval) {
+		/* append line */
+		s->lineList = g_list_append (s->lineList, keyValue);
+		s->modified = TRUE;
+		goto end;
+	}
+
+	if (strcmp (oldval, newval) != 0) {
+		/* change line */
+		if (s->current)
+			s->current->data = keyValue;
+		else
+			s->lineList = g_list_append (s->lineList, keyValue);
+		s->modified = TRUE;
 	}
-	goto bail; /* do not need keyValue */
-    }
-
-    if (!val1) {
-	if (val2 && !strcmp(val2, newval)) goto end;
-	/* append line */
-	s->lineList = g_list_append(s->lineList, keyValue);
-	s->modified = 1;
+
+ end:
+	g_free (newval);
+	g_free (oldval);
+	return;
+
+ bail:
+	g_free (keyValue);
 	goto end;
-    }
-
-    /* deal with a whole line of noops */
-    if (val1 && !strcmp(val1, newval)) goto end;
-
-    /* At this point, val1 && val1 != value */
-    if (val2 && !strcmp(val2, newval)) {
-	/* delete line */
-	s->lineList = g_list_remove_link(s->lineList, s->current);
-	g_list_free_1(s->current);
-	s->modified = 1;
-	goto bail; /* do not need keyValue */
-    } else {
-	/* change line */
-	if (s->current) s->current->data = keyValue;
-	else s->lineList = g_list_append(s->lineList, keyValue);
-	s->modified = 1;
-    }
-
-end:
-    g_free(newval);
-    g_free(val1);
-    g_free(val2);
-    return;
-
-bail:
-    g_free (keyValue);
-    goto end;
 }
 
-/* Write the current contents iff modified.  Returns -1 on error
- * and 0 on success.  Do not write if no values have been modified.
+/* Write the current contents iff modified.  Returns FALSE on error
+ * and TRUE on success.  Do not write if no values have been modified.
  * The mode argument is only used if creating the file, not if
  * re-writing an existing file, and is passed unchanged to the
  * open() syscall.
  */
-int
-svWriteFile(shvarFile *s, int mode)
+gboolean
+svWriteFile (shvarFile *s, int mode, GError **error)
 {
-    FILE *f;
-    int tmpfd;
-
-    if (s->modified) {
-	if (s->fd == -1)
-	    s->fd = open(s->fileName, O_WRONLY|O_CREAT, mode);
-	if (s->fd == -1)
-	    return -1;
-	if (ftruncate(s->fd, 0) < 0)
-	    return -1;
-
-	tmpfd = dup(s->fd);
-	f = fdopen(tmpfd, "w");
-	fseek(f, 0, SEEK_SET);
-	for (s->current = s->lineList; s->current; s->current = s->current->next) {
-	    char *line = s->current->data;
-	    fprintf(f, "%s\n", line);
+	FILE *f;
+	int tmpfd;
+
+	if (s->modified) {
+		if (s->fd == -1)
+			s->fd = open (s->fileName, O_WRONLY | O_CREAT, mode);
+		if (s->fd == -1) {
+			int errsv = errno;
+
+			g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errsv),
+			             "Could not open file '%s' for writing: %s",
+			             s->fileName, strerror (errsv));
+			return FALSE;
+		}
+		if (ftruncate (s->fd, 0) < 0) {
+			int errsv = errno;
+
+			g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errsv),
+			             "Could not overwrite file '%s': %s",
+			             s->fileName, strerror (errsv));
+			return FALSE;
+		}
+
+		tmpfd = dup (s->fd);
+		if (tmpfd == -1) {
+			int errsv = errno;
+
+			g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errsv),
+			             "Internal error writing file '%s': %s",
+			             s->fileName, strerror (errsv));
+			return FALSE;
+		}
+		f = fdopen (tmpfd, "w");
+		fseek (f, 0, SEEK_SET);
+		for (s->current = s->lineList; s->current; s->current = s->current->next) {
+			char *line = s->current->data;
+			fprintf (f, "%s\n", line);
+		}
+		fclose (f);
 	}
-	fclose(f);
-    }
 
-    return 0;
+	return TRUE;
 }
 
- 
-/* Close the file descriptor (if open) and delete the shvarFile.
- * Returns -1 on error and 0 on success.
- */
-int
-svCloseFile(shvarFile *s)
-{
 
-    g_assert(s);
+/* Close the file descriptor (if open) and free the shvarFile. */
+void
+svCloseFile (shvarFile *s)
+{
+	g_return_if_fail (s != NULL);
 
-    if (s->fd != -1) close(s->fd);
+	if (s->fd != -1)
+		close (s->fd);
 
-    g_free(s->arena);
-    g_free(s->fileName);
-    g_list_foreach (s->lineList, (GFunc) g_free, NULL);
-    g_list_free(s->lineList); /* implicitly frees s->current */
-    g_free(s);
-    return 0;
+	g_free (s->fileName);
+	g_list_free_full (s->lineList, g_free); /* implicitly frees s->current */
+	g_slice_free (shvarFile, s);
 }
diff --git a/src/settings/plugins/ifcfg-rh/shvar.h b/src/settings/plugins/ifcfg-rh/shvar.h
index 4b650d2a..4cbf1a31 100644
--- a/src/settings/plugins/ifcfg-rh/shvar.h
+++ b/src/settings/plugins/ifcfg-rh/shvar.h
@@ -1,3 +1,4 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
 /*
  * shvar.h
  *
@@ -32,79 +33,61 @@
 
 #include <glib.h>
 
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
+G_BEGIN_DECLS
 
 typedef struct _shvarFile shvarFile;
 struct _shvarFile {
-	char		*fileName;	/* read-only */
-	int		fd;		/* read-only */
-	char		*arena;		/* ignore */
-	GList		*lineList;	/* read-only */
-	GList		*current;	/* set implicitly or explicitly,
-					   points to element of lineList */
-	shvarFile	*parent;	/* set explicitly */
-	int		modified;	/* ignore */
+	char      *fileName;    /* read-only */
+	int        fd;          /* read-only */
+	GList     *lineList;    /* read-only */
+	GList     *current;     /* set implicitly or explicitly, points to element of lineList */
+	gboolean   modified;    /* ignore */
 };
 
 
-/* Create the file <name>, return shvarFile on success, NULL on failure */
-shvarFile *
-svCreateFile(const char *name);
+/* Create the file <name>, return a shvarFile (never fails) */
+shvarFile *svCreateFile (const char *name);
 
 /* Open the file <name>, return shvarFile on success, NULL on failure */
-shvarFile *
-svNewFile(const char *name);
+shvarFile *svOpenFile (const char *name, GError **error);
 
 /* Get the value associated with the key, and leave the current pointer
  * pointing at the line containing the value.  The char* returned MUST
  * be freed by the caller.
  */
-char *
-svGetValue(shvarFile *s, const char *key, gboolean verbatim);
+char *svGetValue (shvarFile *s, const char *key, gboolean verbatim);
 
-/* return 1 if <key> resolves to any truth value (e.g. "yes", "y", "true")
- * return 0 if <key> resolves to any non-truth value (e.g. "no", "n", "false")
+/* return TRUE if <key> resolves to any truth value (e.g. "yes", "y", "true")
+ * return FALSE if <key> resolves to any non-truth value (e.g. "no", "n", "false")
  * return <def> otherwise
  */
-int
-svTrueValue(shvarFile *s, const char *key, int def);
+gboolean svTrueValue (shvarFile *s, const char *key, gboolean def);
 
 /* Set the variable <key> equal to the value <value>.
  * If <key> does not exist, and the <current> pointer is set, append
  * the key=value pair after that line.  Otherwise, prepend the pair
  * to the top of the file.
  */
-void
-svSetValue(shvarFile *s, const char *key, const char *value, gboolean verbatim);
+void svSetValue (shvarFile *s, const char *key, const char *value, gboolean verbatim);
 
 
-/* Write the current contents iff modified.  Returns -1 on error
- * and 0 on success.  Do not write if no values have been modified.
+/* Write the current contents iff modified.  Returns FALSE on error
+ * and TRUE on success.  Do not write if no values have been modified.
  * The mode argument is only used if creating the file, not if
  * re-writing an existing file, and is passed unchanged to the
  * open() syscall.
  */
-int
-svWriteFile(shvarFile *s, int mode);
+gboolean svWriteFile (shvarFile *s, int mode, GError **error);
 
-/* Close the file descriptor (if open) and delete the shvarFile.
- * Returns -1 on error and 0 on success.
- */
-int
-svCloseFile(shvarFile *s);
+/* Close the file descriptor (if open) and free the shvarFile. */
+void svCloseFile (shvarFile *s);
 
 /* Return a new escaped string */
-char *
-svEscape(const char *s);
+char *svEscape (const char *s);
 
 /* Unescape a string in-place */
-void
-svUnescape(char *s);
+void svUnescape (char *s);
 
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
+G_END_DECLS
 
 #endif /* ! _SHVAR_H */
diff --git a/src/settings/plugins/ifcfg-rh/tests/Makefile.am b/src/settings/plugins/ifcfg-rh/tests/Makefile.am
index d1b75fc3..e758776d 100644
--- a/src/settings/plugins/ifcfg-rh/tests/Makefile.am
+++ b/src/settings/plugins/ifcfg-rh/tests/Makefile.am
@@ -2,43 +2,61 @@ if ENABLE_TESTS
 
 SUBDIRS=network-scripts
 
+@GNOME_CODE_COVERAGE_RULES@
+
 AM_CPPFLAGS = \
+	$(GLIB_CFLAGS) \
+	$(DBUS_CFLAGS) \
+	$(CODE_COVERAGE_CFLAGS) \
 	-I$(top_srcdir)/include \
 	-I$(top_builddir)/include \
 	-I$(top_srcdir)/libnm-util \
 	-I$(top_builddir)/libnm-util \
 	-I$(top_srcdir)/libnm-glib \
+	-I$(top_srcdir)/src/ \
+	-I$(top_srcdir)/src/logging \
+	-I$(top_srcdir)/src/platform \
+	-I$(top_srcdir)/src/settings \
+	-I$(top_srcdir)/src/posix-signals \
 	-I$(srcdir)/../ \
-	$(GLIB_CFLAGS)
+	-DG_LOG_DOMAIN=\""NetworkManager-ifcfg-rh"\" \
+	-DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \
+	-DTEST_IFCFG_DIR=\"$(abs_srcdir)\" \
+	-DTEST_SCRATCH_DIR=\"$(abs_builddir)/\" \
+	-DSYSCONFDIR=\"nonexistent\" \
+	-DSBINDIR=\"nonexistent\"
+
+AM_LDFLAGS = \
+	$(GLIB_LIBS) \
+	$(DBUS_LIBS) \
+	$(CODE_COVERAGE_LDFLAGS)
+
+AM_LDADD = \
+	$(top_builddir)/libnm-util/libnm-util.la \
+	$(top_builddir)/libnm-glib/libnm-glib.la
 
 noinst_PROGRAMS = test-ifcfg-rh test-ifcfg-rh-utils
 
 test_ifcfg_rh_SOURCES = \
-	test-ifcfg-rh.c
-
-test_ifcfg_rh_CPPFLAGS = \
-	$(AM_CPPFLAGS) \
-	$(DBUS_CFLAGS) \
-	-DTEST_IFCFG_DIR=\"$(abs_srcdir)\" \
-	-DTEST_SCRATCH_DIR=\"$(abs_builddir)/\"
+	test-ifcfg-rh.c \
+	../errors.c \
+	../reader.c \
+	../shvar.c \
+	../utils.c \
+	../writer.c
 
 test_ifcfg_rh_LDADD = \
-	$(top_builddir)/libnm-glib/libnm-glib.la \
-	$(top_builddir)/libnm-util/libnm-util.la \
-	$(top_builddir)/src/wifi/libwifi-utils.la \
-	$(builddir)/../libifcfg-rh-io.la \
-	$(LIBM)
-	$(DBUS_LIBS)
+	$(top_builddir)/src/libNetworkManager.la
 
 test_ifcfg_rh_utils_SOURCES = \
-	test-ifcfg-rh-utils.c
+	test-ifcfg-rh-utils.c \
+	../utils.c \
+	../shvar.c
 
 test_ifcfg_rh_utils_LDADD = \
-	$(builddir)/../libifcfg-rh-io.la
+	$(AM_LDADD)
 
-check-local: test-ifcfg-rh
-	$(abs_builddir)/test-ifcfg-rh-utils
-	$(abs_builddir)/test-ifcfg-rh
+TESTS = test-ifcfg-rh-utils test-ifcfg-rh
 
 EXTRA_DIST = \
 	iscsiadm-test-dhcp \
diff --git a/src/settings/plugins/ifcfg-rh/tests/Makefile.in b/src/settings/plugins/ifcfg-rh/tests/Makefile.in
index 94c0dc69..2018134a 100644
--- a/src/settings/plugins/ifcfg-rh/tests/Makefile.in
+++ b/src/settings/plugins/ifcfg-rh/tests/Makefile.in
@@ -80,11 +80,14 @@ build_triplet = @build@
 host_triplet = @host@
 @ENABLE_TESTS_TRUE@noinst_PROGRAMS = test-ifcfg-rh$(EXEEXT) \
 @ENABLE_TESTS_TRUE@	test-ifcfg-rh-utils$(EXEEXT)
+@ENABLE_TESTS_TRUE@TESTS = test-ifcfg-rh-utils$(EXEEXT) \
+@ENABLE_TESTS_TRUE@	test-ifcfg-rh$(EXEEXT)
 subdir = src/settings/plugins/ifcfg-rh/tests
 DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
 	$(top_srcdir)/build-aux/depcomp
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_lib_readline.m4 \
+	$(top_srcdir)/m4/compiler_warnings.m4 \
 	$(top_srcdir)/m4/gettext.m4 \
 	$(top_srcdir)/m4/gnome-code-coverage.m4 \
 	$(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \
@@ -103,27 +106,26 @@ CONFIG_HEADER = $(top_builddir)/config.h
 CONFIG_CLEAN_FILES =
 CONFIG_CLEAN_VPATH_FILES =
 PROGRAMS = $(noinst_PROGRAMS)
-am__test_ifcfg_rh_SOURCES_DIST = test-ifcfg-rh.c
-@ENABLE_TESTS_TRUE@am_test_ifcfg_rh_OBJECTS =  \
-@ENABLE_TESTS_TRUE@	test_ifcfg_rh-test-ifcfg-rh.$(OBJEXT)
+am__test_ifcfg_rh_SOURCES_DIST = test-ifcfg-rh.c ../errors.c \
+	../reader.c ../shvar.c ../utils.c ../writer.c
+@ENABLE_TESTS_TRUE@am_test_ifcfg_rh_OBJECTS = test-ifcfg-rh.$(OBJEXT) \
+@ENABLE_TESTS_TRUE@	errors.$(OBJEXT) reader.$(OBJEXT) \
+@ENABLE_TESTS_TRUE@	shvar.$(OBJEXT) utils.$(OBJEXT) \
+@ENABLE_TESTS_TRUE@	writer.$(OBJEXT)
 test_ifcfg_rh_OBJECTS = $(am_test_ifcfg_rh_OBJECTS)
-am__DEPENDENCIES_1 =
 @ENABLE_TESTS_TRUE@test_ifcfg_rh_DEPENDENCIES =  \
-@ENABLE_TESTS_TRUE@	$(top_builddir)/libnm-glib/libnm-glib.la \
-@ENABLE_TESTS_TRUE@	$(top_builddir)/libnm-util/libnm-util.la \
-@ENABLE_TESTS_TRUE@	$(top_builddir)/src/wifi/libwifi-utils.la \
-@ENABLE_TESTS_TRUE@	$(builddir)/../libifcfg-rh-io.la \
-@ENABLE_TESTS_TRUE@	$(am__DEPENDENCIES_1)
+@ENABLE_TESTS_TRUE@	$(top_builddir)/src/libNetworkManager.la
 AM_V_lt = $(am__v_lt_@AM_V@)
 am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
 am__v_lt_0 = --silent
 am__v_lt_1 = 
-am__test_ifcfg_rh_utils_SOURCES_DIST = test-ifcfg-rh-utils.c
+am__test_ifcfg_rh_utils_SOURCES_DIST = test-ifcfg-rh-utils.c \
+	../utils.c ../shvar.c
 @ENABLE_TESTS_TRUE@am_test_ifcfg_rh_utils_OBJECTS =  \
-@ENABLE_TESTS_TRUE@	test-ifcfg-rh-utils.$(OBJEXT)
+@ENABLE_TESTS_TRUE@	test-ifcfg-rh-utils.$(OBJEXT) \
+@ENABLE_TESTS_TRUE@	utils.$(OBJEXT) shvar.$(OBJEXT)
 test_ifcfg_rh_utils_OBJECTS = $(am_test_ifcfg_rh_utils_OBJECTS)
-@ENABLE_TESTS_TRUE@test_ifcfg_rh_utils_DEPENDENCIES =  \
-@ENABLE_TESTS_TRUE@	$(builddir)/../libifcfg-rh-io.la
+@ENABLE_TESTS_TRUE@test_ifcfg_rh_utils_DEPENDENCIES = $(AM_LDADD)
 AM_V_P = $(am__v_P_@AM_V@)
 am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
 am__v_P_0 = false
@@ -201,6 +203,28 @@ am__define_uniq_tagged_files = \
   done | $(am__uniquify_input)`
 ETAGS = etags
 CTAGS = ctags
+am__tty_colors_dummy = \
+  mgn= red= grn= lgn= blu= brg= std=; \
+  am__color_tests=no
+am__tty_colors = { \
+  $(am__tty_colors_dummy); \
+  if test "X$(AM_COLOR_TESTS)" = Xno; then \
+    am__color_tests=no; \
+  elif test "X$(AM_COLOR_TESTS)" = Xalways; then \
+    am__color_tests=yes; \
+  elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \
+    am__color_tests=yes; \
+  fi; \
+  if test $$am__color_tests = yes; then \
+    red=''; \
+    grn=''; \
+    lgn=''; \
+    blu=''; \
+    mgn=''; \
+    brg=''; \
+    std=''; \
+  fi; \
+}
 DIST_SUBDIRS = network-scripts
 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
 am__relativize = \
@@ -253,12 +277,15 @@ CXXFLAGS = @CXXFLAGS@
 CYGPATH_W = @CYGPATH_W@
 DATADIRNAME = @DATADIRNAME@
 DBUS_CFLAGS = @DBUS_CFLAGS@
+DBUS_GLIB_100_CFLAGS = @DBUS_GLIB_100_CFLAGS@
+DBUS_GLIB_100_LIBS = @DBUS_GLIB_100_LIBS@
 DBUS_LIBS = @DBUS_LIBS@
 DBUS_SYS_DIR = @DBUS_SYS_DIR@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
 DHCLIENT_PATH = @DHCLIENT_PATH@
 DHCPCD_PATH = @DHCPCD_PATH@
+DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@
 DLLTOOL = @DLLTOOL@
 DNSMASQ_PATH = @DNSMASQ_PATH@
 DSYMUTIL = @DSYMUTIL@
@@ -283,7 +310,6 @@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
 GNUTLS_LIBS = @GNUTLS_LIBS@
 GREP = @GREP@
 GTKDOC_CHECK = @GTKDOC_CHECK@
-GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@
 GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@
 GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@
 GTKDOC_MKPDF = @GTKDOC_MKPDF@
@@ -328,12 +354,16 @@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
 LIBICONV = @LIBICONV@
 LIBINTL = @LIBINTL@
 LIBM = @LIBM@
+LIBNDP_CFLAGS = @LIBNDP_CFLAGS@
+LIBNDP_LIBS = @LIBNDP_LIBS@
 LIBNL_CFLAGS = @LIBNL_CFLAGS@
 LIBNL_LIBS = @LIBNL_LIBS@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
 LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@
 LIBSOUP_LIBS = @LIBSOUP_LIBS@
+LIBTEAMDCTL_CFLAGS = @LIBTEAMDCTL_CFLAGS@
+LIBTEAMDCTL_LIBS = @LIBTEAMDCTL_LIBS@
 LIBTOOL = @LIBTOOL@
 LIPO = @LIPO@
 LN_S = @LN_S@
@@ -350,6 +380,8 @@ MOC = @MOC@
 MSGFMT = @MSGFMT@
 MSGFMT_015 = @MSGFMT_015@
 MSGMERGE = @MSGMERGE@
+NEWT_CFLAGS = @NEWT_CFLAGS@
+NEWT_LIBS = @NEWT_LIBS@
 NM = @NM@
 NMEDIT = @NMEDIT@
 NM_MAJOR_VERSION = @NM_MAJOR_VERSION@
@@ -377,11 +409,16 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
 POLKIT_CFLAGS = @POLKIT_CFLAGS@
 POLKIT_LIBS = @POLKIT_LIBS@
 POSUB = @POSUB@
+PPPD_PATH = @PPPD_PATH@
 PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@
+PPPOE_PATH = @PPPOE_PATH@
 QT_CFLAGS = @QT_CFLAGS@
 QT_LIBS = @QT_LIBS@
 RANLIB = @RANLIB@
+READLINE_LIBS = @READLINE_LIBS@
 SED = @SED@
+SELINUX_CFLAGS = @SELINUX_CFLAGS@
+SELINUX_LIBS = @SELINUX_LIBS@
 SET_MAKE = @SET_MAKE@
 SHELL = @SHELL@
 STRIP = @STRIP@
@@ -396,6 +433,7 @@ UDEV_BASE_DIR = @UDEV_BASE_DIR@
 USE_NLS = @USE_NLS@
 UUID_CFLAGS = @UUID_CFLAGS@
 UUID_LIBS = @UUID_LIBS@
+VALGRIND_RULES = @VALGRIND_RULES@
 VAPIGEN = @VAPIGEN@
 VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@
 VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@
@@ -458,6 +496,7 @@ psdir = @psdir@
 sbindir = @sbindir@
 sharedstatedir = @sharedstatedir@
 srcdir = @srcdir@
+subdirs = @subdirs@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 target_alias = @target_alias@
@@ -468,37 +507,57 @@ with_dhclient = @with_dhclient@
 with_dhcpcd = @with_dhcpcd@
 with_netconfig = @with_netconfig@
 with_resolvconf = @with_resolvconf@
+with_valgrind = @with_valgrind@
 @ENABLE_TESTS_TRUE@SUBDIRS = network-scripts
 @ENABLE_TESTS_TRUE@AM_CPPFLAGS = \
+@ENABLE_TESTS_TRUE@	$(GLIB_CFLAGS) \
+@ENABLE_TESTS_TRUE@	$(DBUS_CFLAGS) \
+@ENABLE_TESTS_TRUE@	$(CODE_COVERAGE_CFLAGS) \
 @ENABLE_TESTS_TRUE@	-I$(top_srcdir)/include \
 @ENABLE_TESTS_TRUE@	-I$(top_builddir)/include \
 @ENABLE_TESTS_TRUE@	-I$(top_srcdir)/libnm-util \
 @ENABLE_TESTS_TRUE@	-I$(top_builddir)/libnm-util \
 @ENABLE_TESTS_TRUE@	-I$(top_srcdir)/libnm-glib \
+@ENABLE_TESTS_TRUE@	-I$(top_srcdir)/src/ \
+@ENABLE_TESTS_TRUE@	-I$(top_srcdir)/src/logging \
+@ENABLE_TESTS_TRUE@	-I$(top_srcdir)/src/platform \
+@ENABLE_TESTS_TRUE@	-I$(top_srcdir)/src/settings \
+@ENABLE_TESTS_TRUE@	-I$(top_srcdir)/src/posix-signals \
 @ENABLE_TESTS_TRUE@	-I$(srcdir)/../ \
-@ENABLE_TESTS_TRUE@	$(GLIB_CFLAGS)
+@ENABLE_TESTS_TRUE@	-DG_LOG_DOMAIN=\""NetworkManager-ifcfg-rh"\" \
+@ENABLE_TESTS_TRUE@	-DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \
+@ENABLE_TESTS_TRUE@	-DTEST_IFCFG_DIR=\"$(abs_srcdir)\" \
+@ENABLE_TESTS_TRUE@	-DTEST_SCRATCH_DIR=\"$(abs_builddir)/\" \
+@ENABLE_TESTS_TRUE@	-DSYSCONFDIR=\"nonexistent\" \
+@ENABLE_TESTS_TRUE@	-DSBINDIR=\"nonexistent\"
 
-@ENABLE_TESTS_TRUE@test_ifcfg_rh_SOURCES = \
-@ENABLE_TESTS_TRUE@	test-ifcfg-rh.c
+@ENABLE_TESTS_TRUE@AM_LDFLAGS = \
+@ENABLE_TESTS_TRUE@	$(GLIB_LIBS) \
+@ENABLE_TESTS_TRUE@	$(DBUS_LIBS) \
+@ENABLE_TESTS_TRUE@	$(CODE_COVERAGE_LDFLAGS)
 
-@ENABLE_TESTS_TRUE@test_ifcfg_rh_CPPFLAGS = \
-@ENABLE_TESTS_TRUE@	$(AM_CPPFLAGS) \
-@ENABLE_TESTS_TRUE@	$(DBUS_CFLAGS) \
-@ENABLE_TESTS_TRUE@	-DTEST_IFCFG_DIR=\"$(abs_srcdir)\" \
-@ENABLE_TESTS_TRUE@	-DTEST_SCRATCH_DIR=\"$(abs_builddir)/\"
+@ENABLE_TESTS_TRUE@AM_LDADD = \
+@ENABLE_TESTS_TRUE@	$(top_builddir)/libnm-util/libnm-util.la \
+@ENABLE_TESTS_TRUE@	$(top_builddir)/libnm-glib/libnm-glib.la
+
+@ENABLE_TESTS_TRUE@test_ifcfg_rh_SOURCES = \
+@ENABLE_TESTS_TRUE@	test-ifcfg-rh.c \
+@ENABLE_TESTS_TRUE@	../errors.c \
+@ENABLE_TESTS_TRUE@	../reader.c \
+@ENABLE_TESTS_TRUE@	../shvar.c \
+@ENABLE_TESTS_TRUE@	../utils.c \
+@ENABLE_TESTS_TRUE@	../writer.c
 
 @ENABLE_TESTS_TRUE@test_ifcfg_rh_LDADD = \
-@ENABLE_TESTS_TRUE@	$(top_builddir)/libnm-glib/libnm-glib.la \
-@ENABLE_TESTS_TRUE@	$(top_builddir)/libnm-util/libnm-util.la \
-@ENABLE_TESTS_TRUE@	$(top_builddir)/src/wifi/libwifi-utils.la \
-@ENABLE_TESTS_TRUE@	$(builddir)/../libifcfg-rh-io.la \
-@ENABLE_TESTS_TRUE@	$(LIBM)
+@ENABLE_TESTS_TRUE@	$(top_builddir)/src/libNetworkManager.la
 
 @ENABLE_TESTS_TRUE@test_ifcfg_rh_utils_SOURCES = \
-@ENABLE_TESTS_TRUE@	test-ifcfg-rh-utils.c
+@ENABLE_TESTS_TRUE@	test-ifcfg-rh-utils.c \
+@ENABLE_TESTS_TRUE@	../utils.c \
+@ENABLE_TESTS_TRUE@	../shvar.c
 
 @ENABLE_TESTS_TRUE@test_ifcfg_rh_utils_LDADD = \
-@ENABLE_TESTS_TRUE@	$(builddir)/../libifcfg-rh-io.la
+@ENABLE_TESTS_TRUE@	$(AM_LDADD)
 
 @ENABLE_TESTS_TRUE@EXTRA_DIST = \
 @ENABLE_TESTS_TRUE@	iscsiadm-test-dhcp \
@@ -568,8 +627,13 @@ mostlyclean-compile:
 distclean-compile:
 	-rm -f *.tab.c
 
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/errors.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/reader.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shvar.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-ifcfg-rh-utils.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ifcfg_rh-test-ifcfg-rh.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-ifcfg-rh.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/writer.Po@am__quote@
 
 .c.o:
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@@ -592,19 +656,75 @@ distclean-compile:
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
 
-test_ifcfg_rh-test-ifcfg-rh.o: test-ifcfg-rh.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_ifcfg_rh_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_ifcfg_rh-test-ifcfg-rh.o -MD -MP -MF $(DEPDIR)/test_ifcfg_rh-test-ifcfg-rh.Tpo -c -o test_ifcfg_rh-test-ifcfg-rh.o `test -f 'test-ifcfg-rh.c' || echo '$(srcdir)/'`test-ifcfg-rh.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_ifcfg_rh-test-ifcfg-rh.Tpo $(DEPDIR)/test_ifcfg_rh-test-ifcfg-rh.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='test-ifcfg-rh.c' object='test_ifcfg_rh-test-ifcfg-rh.o' libtool=no @AMDEPBACKSLASH@
+errors.o: ../errors.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT errors.o -MD -MP -MF $(DEPDIR)/errors.Tpo -c -o errors.o `test -f '../errors.c' || echo '$(srcdir)/'`../errors.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/errors.Tpo $(DEPDIR)/errors.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='../errors.c' object='errors.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o errors.o `test -f '../errors.c' || echo '$(srcdir)/'`../errors.c
+
+errors.obj: ../errors.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT errors.obj -MD -MP -MF $(DEPDIR)/errors.Tpo -c -o errors.obj `if test -f '../errors.c'; then $(CYGPATH_W) '../errors.c'; else $(CYGPATH_W) '$(srcdir)/../errors.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/errors.Tpo $(DEPDIR)/errors.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='../errors.c' object='errors.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o errors.obj `if test -f '../errors.c'; then $(CYGPATH_W) '../errors.c'; else $(CYGPATH_W) '$(srcdir)/../errors.c'; fi`
+
+reader.o: ../reader.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT reader.o -MD -MP -MF $(DEPDIR)/reader.Tpo -c -o reader.o `test -f '../reader.c' || echo '$(srcdir)/'`../reader.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/reader.Tpo $(DEPDIR)/reader.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='../reader.c' object='reader.o' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_ifcfg_rh_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_ifcfg_rh-test-ifcfg-rh.o `test -f 'test-ifcfg-rh.c' || echo '$(srcdir)/'`test-ifcfg-rh.c
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o reader.o `test -f '../reader.c' || echo '$(srcdir)/'`../reader.c
 
-test_ifcfg_rh-test-ifcfg-rh.obj: test-ifcfg-rh.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_ifcfg_rh_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_ifcfg_rh-test-ifcfg-rh.obj -MD -MP -MF $(DEPDIR)/test_ifcfg_rh-test-ifcfg-rh.Tpo -c -o test_ifcfg_rh-test-ifcfg-rh.obj `if test -f 'test-ifcfg-rh.c'; then $(CYGPATH_W) 'test-ifcfg-rh.c'; else $(CYGPATH_W) '$(srcdir)/test-ifcfg-rh.c'; fi`
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_ifcfg_rh-test-ifcfg-rh.Tpo $(DEPDIR)/test_ifcfg_rh-test-ifcfg-rh.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='test-ifcfg-rh.c' object='test_ifcfg_rh-test-ifcfg-rh.obj' libtool=no @AMDEPBACKSLASH@
+reader.obj: ../reader.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT reader.obj -MD -MP -MF $(DEPDIR)/reader.Tpo -c -o reader.obj `if test -f '../reader.c'; then $(CYGPATH_W) '../reader.c'; else $(CYGPATH_W) '$(srcdir)/../reader.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/reader.Tpo $(DEPDIR)/reader.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='../reader.c' object='reader.obj' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_ifcfg_rh_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_ifcfg_rh-test-ifcfg-rh.obj `if test -f 'test-ifcfg-rh.c'; then $(CYGPATH_W) 'test-ifcfg-rh.c'; else $(CYGPATH_W) '$(srcdir)/test-ifcfg-rh.c'; fi`
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o reader.obj `if test -f '../reader.c'; then $(CYGPATH_W) '../reader.c'; else $(CYGPATH_W) '$(srcdir)/../reader.c'; fi`
+
+shvar.o: ../shvar.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT shvar.o -MD -MP -MF $(DEPDIR)/shvar.Tpo -c -o shvar.o `test -f '../shvar.c' || echo '$(srcdir)/'`../shvar.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/shvar.Tpo $(DEPDIR)/shvar.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='../shvar.c' object='shvar.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o shvar.o `test -f '../shvar.c' || echo '$(srcdir)/'`../shvar.c
+
+shvar.obj: ../shvar.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT shvar.obj -MD -MP -MF $(DEPDIR)/shvar.Tpo -c -o shvar.obj `if test -f '../shvar.c'; then $(CYGPATH_W) '../shvar.c'; else $(CYGPATH_W) '$(srcdir)/../shvar.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/shvar.Tpo $(DEPDIR)/shvar.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='../shvar.c' object='shvar.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o shvar.obj `if test -f '../shvar.c'; then $(CYGPATH_W) '../shvar.c'; else $(CYGPATH_W) '$(srcdir)/../shvar.c'; fi`
+
+utils.o: ../utils.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT utils.o -MD -MP -MF $(DEPDIR)/utils.Tpo -c -o utils.o `test -f '../utils.c' || echo '$(srcdir)/'`../utils.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/utils.Tpo $(DEPDIR)/utils.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='../utils.c' object='utils.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o utils.o `test -f '../utils.c' || echo '$(srcdir)/'`../utils.c
+
+utils.obj: ../utils.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT utils.obj -MD -MP -MF $(DEPDIR)/utils.Tpo -c -o utils.obj `if test -f '../utils.c'; then $(CYGPATH_W) '../utils.c'; else $(CYGPATH_W) '$(srcdir)/../utils.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/utils.Tpo $(DEPDIR)/utils.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='../utils.c' object='utils.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o utils.obj `if test -f '../utils.c'; then $(CYGPATH_W) '../utils.c'; else $(CYGPATH_W) '$(srcdir)/../utils.c'; fi`
+
+writer.o: ../writer.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT writer.o -MD -MP -MF $(DEPDIR)/writer.Tpo -c -o writer.o `test -f '../writer.c' || echo '$(srcdir)/'`../writer.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/writer.Tpo $(DEPDIR)/writer.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='../writer.c' object='writer.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o writer.o `test -f '../writer.c' || echo '$(srcdir)/'`../writer.c
+
+writer.obj: ../writer.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT writer.obj -MD -MP -MF $(DEPDIR)/writer.Tpo -c -o writer.obj `if test -f '../writer.c'; then $(CYGPATH_W) '../writer.c'; else $(CYGPATH_W) '$(srcdir)/../writer.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/writer.Tpo $(DEPDIR)/writer.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='../writer.c' object='writer.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o writer.obj `if test -f '../writer.c'; then $(CYGPATH_W) '../writer.c'; else $(CYGPATH_W) '$(srcdir)/../writer.c'; fi`
 
 mostlyclean-libtool:
 	-rm -f *.lo
@@ -711,6 +831,99 @@ cscopelist-am: $(am__tagged_files)
 distclean-tags:
 	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
 
+check-TESTS: $(TESTS)
+	@failed=0; all=0; xfail=0; xpass=0; skip=0; \
+	srcdir=$(srcdir); export srcdir; \
+	list=' $(TESTS) '; \
+	$(am__tty_colors); \
+	if test -n "$$list"; then \
+	  for tst in $$list; do \
+	    if test -f ./$$tst; then dir=./; \
+	    elif test -f $$tst; then dir=; \
+	    else dir="$(srcdir)/"; fi; \
+	    if $(TESTS_ENVIRONMENT) $${dir}$$tst $(AM_TESTS_FD_REDIRECT); then \
+	      all=`expr $$all + 1`; \
+	      case " $(XFAIL_TESTS) " in \
+	      *[\ \	]$$tst[\ \	]*) \
+		xpass=`expr $$xpass + 1`; \
+		failed=`expr $$failed + 1`; \
+		col=$$red; res=XPASS; \
+	      ;; \
+	      *) \
+		col=$$grn; res=PASS; \
+	      ;; \
+	      esac; \
+	    elif test $$? -ne 77; then \
+	      all=`expr $$all + 1`; \
+	      case " $(XFAIL_TESTS) " in \
+	      *[\ \	]$$tst[\ \	]*) \
+		xfail=`expr $$xfail + 1`; \
+		col=$$lgn; res=XFAIL; \
+	      ;; \
+	      *) \
+		failed=`expr $$failed + 1`; \
+		col=$$red; res=FAIL; \
+	      ;; \
+	      esac; \
+	    else \
+	      skip=`expr $$skip + 1`; \
+	      col=$$blu; res=SKIP; \
+	    fi; \
+	    echo "$${col}$$res$${std}: $$tst"; \
+	  done; \
+	  if test "$$all" -eq 1; then \
+	    tests="test"; \
+	    All=""; \
+	  else \
+	    tests="tests"; \
+	    All="All "; \
+	  fi; \
+	  if test "$$failed" -eq 0; then \
+	    if test "$$xfail" -eq 0; then \
+	      banner="$$All$$all $$tests passed"; \
+	    else \
+	      if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \
+	      banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \
+	    fi; \
+	  else \
+	    if test "$$xpass" -eq 0; then \
+	      banner="$$failed of $$all $$tests failed"; \
+	    else \
+	      if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \
+	      banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \
+	    fi; \
+	  fi; \
+	  dashes="$$banner"; \
+	  skipped=""; \
+	  if test "$$skip" -ne 0; then \
+	    if test "$$skip" -eq 1; then \
+	      skipped="($$skip test was not run)"; \
+	    else \
+	      skipped="($$skip tests were not run)"; \
+	    fi; \
+	    test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
+	      dashes="$$skipped"; \
+	  fi; \
+	  report=""; \
+	  if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
+	    report="Please report to $(PACKAGE_BUGREPORT)"; \
+	    test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
+	      dashes="$$report"; \
+	  fi; \
+	  dashes=`echo "$$dashes" | sed s/./=/g`; \
+	  if test "$$failed" -eq 0; then \
+	    col="$$grn"; \
+	  else \
+	    col="$$red"; \
+	  fi; \
+	  echo "$${col}$$dashes$${std}"; \
+	  echo "$${col}$$banner$${std}"; \
+	  test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \
+	  test -z "$$report" || echo "$${col}$$report$${std}"; \
+	  echo "$${col}$$dashes$${std}"; \
+	  test "$$failed" -eq 0; \
+	else :; fi
+
 distdir: $(DISTFILES)
 	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
 	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
@@ -766,9 +979,8 @@ distdir: $(DISTFILES)
 	      || exit 1; \
 	  fi; \
 	done
-@ENABLE_TESTS_FALSE@check-local:
 check-am: all-am
-	$(MAKE) $(AM_MAKEFLAGS) check-local
+	$(MAKE) $(AM_MAKEFLAGS) check-TESTS
 check: check-recursive
 all-am: Makefile $(PROGRAMS)
 installdirs: installdirs-recursive
@@ -877,7 +1089,7 @@ uninstall-am:
 .MAKE: $(am__recursive_targets) check-am install-am install-strip
 
 .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \
-	check-am check-local clean clean-generic clean-libtool \
+	check-TESTS check-am clean clean-generic clean-libtool \
 	clean-noinstPROGRAMS cscopelist-am ctags ctags-am distclean \
 	distclean-compile distclean-generic distclean-libtool \
 	distclean-tags distdir dvi dvi-am html html-am info info-am \
@@ -891,11 +1103,8 @@ uninstall-am:
 	mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
 	uninstall-am
 
-@ENABLE_TESTS_TRUE@	$(DBUS_LIBS)
 
-@ENABLE_TESTS_TRUE@check-local: test-ifcfg-rh
-@ENABLE_TESTS_TRUE@	$(abs_builddir)/test-ifcfg-rh-utils
-@ENABLE_TESTS_TRUE@	$(abs_builddir)/test-ifcfg-rh
+@ENABLE_TESTS_TRUE@@GNOME_CODE_COVERAGE_RULES@
 
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
 # Otherwise a system limit (for SysV at least) may be exceeded.
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am b/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am
index df3ebb12..1701aeeb 100644
--- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am
@@ -2,9 +2,13 @@ EXTRA_DIST = \
 	ifcfg-test-minimal \
 	ifcfg-test-variables-corner-cases-1 \
 	ifcfg-test-nm-controlled \
+	ifcfg-test-nm-controlled-unrecognized \
+	ifcfg-test-unrecognized \
 	ifcfg-test-wired-static \
 	ifcfg-test-wired-static-bootproto \
 	ifcfg-test-wired-dhcp \
+	ifcfg-test-wired-dhcp-plus-ip \
+	ifcfg-test-wired-dhcp-send-hostname \
 	ifcfg-test-wired-dhcp6-only \
 	ifcfg-test-wired-global-gateway \
 	network-test-wired-global-gateway \
@@ -17,7 +21,10 @@ EXTRA_DIST = \
 	keys-test-wired-8021x-peap-mschapv2 \
 	ifcfg-test-wired-8021x-tls-agent \
 	ifcfg-test-wired-8021x-tls-always \
+	ifcfg-test-wired-802-1X-subj-matches \
+	ifcfg-test-wired-802-1x-ttls-eapgtc \
 	ifcfg-test-onboot-no \
+	ifcfg-test-noip \
 	ifcfg-test-wifi-open \
 	ifcfg-test-wifi-open-auto \
 	ifcfg-test-wifi-open-ssid-quoted \
@@ -51,6 +58,7 @@ EXTRA_DIST = \
 	keys-test-wifi-wpa-eap-tls \
 	ifcfg-test-wifi-wpa-eap-ttls-tls \
 	keys-test-wifi-wpa-eap-ttls-tls \
+	ifcfg-test-wifi-hidden \
 	test_ca_cert.pem \
 	test1_key_and_cert.pem \
 	ifcfg-test-ibft-dhcp \
@@ -94,10 +102,41 @@ EXTRA_DIST = \
 	ifcfg-test-infiniband \
 	ifcfg-test-bond-main \
 	ifcfg-test-bond-slave \
-	ifcfg-test-bond-slave-ib
+	ifcfg-test-bond-slave-ib \
+	ifcfg-test-dcb \
+	ifcfg-test-dcb-default-app-priorities \
+	ifcfg-test-dcb-bad-booleans \
+	ifcfg-test-dcb-short-booleans \
+	ifcfg-test-dcb-bad-uints \
+	ifcfg-test-dcb-short-uints \
+	ifcfg-test-dcb-bad-percent \
+	ifcfg-test-dcb-short-percent \
+	ifcfg-test-dcb-pgpct-not-100 \
+	ifcfg-test-fcoe-fabric \
+	ifcfg-test-fcoe-vn2vn \
+	ifcfg-test-team-master \
+	ifcfg-test-team-port \
+	ifcfg-test-team-port-empty-config
+
+# make target dependencies can't have colons in their names, which ends up
+# meaning that we can't add the alias files to EXTRA_DIST
+ALIAS_FILES = \
+	ifcfg-aliasem0 \
+	ifcfg-aliasem0:1 \
+	ifcfg-aliasem0:2 \
+	ifcfg-aliasem0:99 \
+	ifcfg-aliasem1 \
+	ifcfg-aliasem1:1 \
+	ifcfg-aliasem2 \
+	ifcfg-aliasem2:1
+
+dist-hook:
+	@for f in $(ALIAS_FILES); do \
+		cp $(abs_srcdir)/$$f $(distdir)/; \
+	done
 
 check-local:
-	@for f in $(EXTRA_DIST); do \
+	@for f in $(EXTRA_DIST) $(ALIAS_FILES); do \
 		chmod 0600 $(abs_srcdir)/$$f; \
 	done
 
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.in b/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.in
index a8933e30..eff763e8 100644
--- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.in
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.in
@@ -80,7 +80,8 @@ host_triplet = @host@
 subdir = src/settings/plugins/ifcfg-rh/tests/network-scripts
 DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_lib_readline.m4 \
+	$(top_srcdir)/m4/compiler_warnings.m4 \
 	$(top_srcdir)/m4/gettext.m4 \
 	$(top_srcdir)/m4/gnome-code-coverage.m4 \
 	$(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \
@@ -144,12 +145,15 @@ CXXFLAGS = @CXXFLAGS@
 CYGPATH_W = @CYGPATH_W@
 DATADIRNAME = @DATADIRNAME@
 DBUS_CFLAGS = @DBUS_CFLAGS@
+DBUS_GLIB_100_CFLAGS = @DBUS_GLIB_100_CFLAGS@
+DBUS_GLIB_100_LIBS = @DBUS_GLIB_100_LIBS@
 DBUS_LIBS = @DBUS_LIBS@
 DBUS_SYS_DIR = @DBUS_SYS_DIR@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
 DHCLIENT_PATH = @DHCLIENT_PATH@
 DHCPCD_PATH = @DHCPCD_PATH@
+DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@
 DLLTOOL = @DLLTOOL@
 DNSMASQ_PATH = @DNSMASQ_PATH@
 DSYMUTIL = @DSYMUTIL@
@@ -174,7 +178,6 @@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
 GNUTLS_LIBS = @GNUTLS_LIBS@
 GREP = @GREP@
 GTKDOC_CHECK = @GTKDOC_CHECK@
-GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@
 GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@
 GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@
 GTKDOC_MKPDF = @GTKDOC_MKPDF@
@@ -219,12 +222,16 @@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
 LIBICONV = @LIBICONV@
 LIBINTL = @LIBINTL@
 LIBM = @LIBM@
+LIBNDP_CFLAGS = @LIBNDP_CFLAGS@
+LIBNDP_LIBS = @LIBNDP_LIBS@
 LIBNL_CFLAGS = @LIBNL_CFLAGS@
 LIBNL_LIBS = @LIBNL_LIBS@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
 LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@
 LIBSOUP_LIBS = @LIBSOUP_LIBS@
+LIBTEAMDCTL_CFLAGS = @LIBTEAMDCTL_CFLAGS@
+LIBTEAMDCTL_LIBS = @LIBTEAMDCTL_LIBS@
 LIBTOOL = @LIBTOOL@
 LIPO = @LIPO@
 LN_S = @LN_S@
@@ -241,6 +248,8 @@ MOC = @MOC@
 MSGFMT = @MSGFMT@
 MSGFMT_015 = @MSGFMT_015@
 MSGMERGE = @MSGMERGE@
+NEWT_CFLAGS = @NEWT_CFLAGS@
+NEWT_LIBS = @NEWT_LIBS@
 NM = @NM@
 NMEDIT = @NMEDIT@
 NM_MAJOR_VERSION = @NM_MAJOR_VERSION@
@@ -268,11 +277,16 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
 POLKIT_CFLAGS = @POLKIT_CFLAGS@
 POLKIT_LIBS = @POLKIT_LIBS@
 POSUB = @POSUB@
+PPPD_PATH = @PPPD_PATH@
 PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@
+PPPOE_PATH = @PPPOE_PATH@
 QT_CFLAGS = @QT_CFLAGS@
 QT_LIBS = @QT_LIBS@
 RANLIB = @RANLIB@
+READLINE_LIBS = @READLINE_LIBS@
 SED = @SED@
+SELINUX_CFLAGS = @SELINUX_CFLAGS@
+SELINUX_LIBS = @SELINUX_LIBS@
 SET_MAKE = @SET_MAKE@
 SHELL = @SHELL@
 STRIP = @STRIP@
@@ -287,6 +301,7 @@ UDEV_BASE_DIR = @UDEV_BASE_DIR@
 USE_NLS = @USE_NLS@
 UUID_CFLAGS = @UUID_CFLAGS@
 UUID_LIBS = @UUID_LIBS@
+VALGRIND_RULES = @VALGRIND_RULES@
 VAPIGEN = @VAPIGEN@
 VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@
 VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@
@@ -349,6 +364,7 @@ psdir = @psdir@
 sbindir = @sbindir@
 sharedstatedir = @sharedstatedir@
 srcdir = @srcdir@
+subdirs = @subdirs@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 target_alias = @target_alias@
@@ -359,13 +375,18 @@ with_dhclient = @with_dhclient@
 with_dhcpcd = @with_dhcpcd@
 with_netconfig = @with_netconfig@
 with_resolvconf = @with_resolvconf@
+with_valgrind = @with_valgrind@
 EXTRA_DIST = \
 	ifcfg-test-minimal \
 	ifcfg-test-variables-corner-cases-1 \
 	ifcfg-test-nm-controlled \
+	ifcfg-test-nm-controlled-unrecognized \
+	ifcfg-test-unrecognized \
 	ifcfg-test-wired-static \
 	ifcfg-test-wired-static-bootproto \
 	ifcfg-test-wired-dhcp \
+	ifcfg-test-wired-dhcp-plus-ip \
+	ifcfg-test-wired-dhcp-send-hostname \
 	ifcfg-test-wired-dhcp6-only \
 	ifcfg-test-wired-global-gateway \
 	network-test-wired-global-gateway \
@@ -378,7 +399,10 @@ EXTRA_DIST = \
 	keys-test-wired-8021x-peap-mschapv2 \
 	ifcfg-test-wired-8021x-tls-agent \
 	ifcfg-test-wired-8021x-tls-always \
+	ifcfg-test-wired-802-1X-subj-matches \
+	ifcfg-test-wired-802-1x-ttls-eapgtc \
 	ifcfg-test-onboot-no \
+	ifcfg-test-noip \
 	ifcfg-test-wifi-open \
 	ifcfg-test-wifi-open-auto \
 	ifcfg-test-wifi-open-ssid-quoted \
@@ -412,6 +436,7 @@ EXTRA_DIST = \
 	keys-test-wifi-wpa-eap-tls \
 	ifcfg-test-wifi-wpa-eap-ttls-tls \
 	keys-test-wifi-wpa-eap-ttls-tls \
+	ifcfg-test-wifi-hidden \
 	test_ca_cert.pem \
 	test1_key_and_cert.pem \
 	ifcfg-test-ibft-dhcp \
@@ -455,7 +480,34 @@ EXTRA_DIST = \
 	ifcfg-test-infiniband \
 	ifcfg-test-bond-main \
 	ifcfg-test-bond-slave \
-	ifcfg-test-bond-slave-ib
+	ifcfg-test-bond-slave-ib \
+	ifcfg-test-dcb \
+	ifcfg-test-dcb-default-app-priorities \
+	ifcfg-test-dcb-bad-booleans \
+	ifcfg-test-dcb-short-booleans \
+	ifcfg-test-dcb-bad-uints \
+	ifcfg-test-dcb-short-uints \
+	ifcfg-test-dcb-bad-percent \
+	ifcfg-test-dcb-short-percent \
+	ifcfg-test-dcb-pgpct-not-100 \
+	ifcfg-test-fcoe-fabric \
+	ifcfg-test-fcoe-vn2vn \
+	ifcfg-test-team-master \
+	ifcfg-test-team-port \
+	ifcfg-test-team-port-empty-config
+
+
+# make target dependencies can't have colons in their names, which ends up
+# meaning that we can't add the alias files to EXTRA_DIST
+ALIAS_FILES = \
+	ifcfg-aliasem0 \
+	ifcfg-aliasem0:1 \
+	ifcfg-aliasem0:2 \
+	ifcfg-aliasem0:99 \
+	ifcfg-aliasem1 \
+	ifcfg-aliasem1:1 \
+	ifcfg-aliasem2 \
+	ifcfg-aliasem2:1
 
 all: all-am
 
@@ -533,6 +585,9 @@ distdir: $(DISTFILES)
 	    || exit 1; \
 	  fi; \
 	done
+	$(MAKE) $(AM_MAKEFLAGS) \
+	  top_distdir="$(top_distdir)" distdir="$(distdir)" \
+	  dist-hook
 check-am: all-am
 	$(MAKE) $(AM_MAKEFLAGS) check-local
 check: check-am
@@ -637,7 +692,7 @@ uninstall-am:
 .MAKE: check-am install-am install-strip
 
 .PHONY: all all-am check check-am check-local clean clean-generic \
-	clean-libtool cscopelist-am ctags-am distclean \
+	clean-libtool cscopelist-am ctags-am dist-hook distclean \
 	distclean-generic distclean-libtool distdir dvi dvi-am html \
 	html-am info info-am install install-am install-data \
 	install-data-am install-dvi install-dvi-am install-exec \
@@ -650,8 +705,13 @@ uninstall-am:
 	uninstall-am
 
 
+dist-hook:
+	@for f in $(ALIAS_FILES); do \
+		cp $(abs_srcdir)/$$f $(distdir)/; \
+	done
+
 check-local:
-	@for f in $(EXTRA_DIST); do \
+	@for f in $(EXTRA_DIST) $(ALIAS_FILES); do \
 		chmod 0600 $(abs_srcdir)/$$f; \
 	done
 
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0 b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0
new file mode 100644
index 00000000..4f9d645c
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0
@@ -0,0 +1,12 @@
+TYPE=Ethernet
+DEVICE=aliasem0
+HWADDR=00:11:22:33:44:55
+BOOTPROTO=none
+ONBOOT=yes
+DNS1=4.2.2.1
+DNS2=4.2.2.2
+IPADDR=192.168.1.5
+PREFIX=24
+NETMASK=255.255.255.0
+GATEWAY=192.168.1.1
+IPV6INIT=no
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0:1 b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0:1
new file mode 100644
index 00000000..37c0df11
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0:1
@@ -0,0 +1,2 @@
+DEVICE=aliasem0:1
+IPADDR=192.168.1.6
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0:2 b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0:2
new file mode 100644
index 00000000..0c3b6a7e
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0:2
@@ -0,0 +1,2 @@
+DEVICE=aliasem0:2
+IPADDR=192.168.1.9
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0:99 b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0:99
new file mode 100644
index 00000000..5df3f154
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0:99
@@ -0,0 +1,2 @@
+DEVICE=aliasem0:99
+IPADDR=192.168.1.99
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem1 b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem1
new file mode 100644
index 00000000..f6fefc0d
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem1
@@ -0,0 +1,12 @@
+TYPE=Ethernet
+DEVICE=aliasem1
+HWADDR=00:11:22:33:44:55
+BOOTPROTO=none
+ONBOOT=yes
+DNS1=4.2.2.1
+DNS2=4.2.2.2
+IPADDR=192.168.1.5
+PREFIX=24
+NETMASK=255.255.255.0
+GATEWAY=192.168.1.1
+IPV6INIT=no
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem1:1 b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem1:1
new file mode 100644
index 00000000..21971611
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem1:1
@@ -0,0 +1,2 @@
+# bad, no DEVICE
+IPADDR=192.168.1.12
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem2 b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem2
new file mode 100644
index 00000000..92ed461e
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem2
@@ -0,0 +1,12 @@
+TYPE=Ethernet
+DEVICE=aliasem2
+HWADDR=00:11:22:33:44:55
+BOOTPROTO=none
+ONBOOT=yes
+DNS1=4.2.2.1
+DNS2=4.2.2.2
+IPADDR=192.168.1.5
+PREFIX=24
+NETMASK=255.255.255.0
+GATEWAY=192.168.1.1
+IPV6INIT=no
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem2:1 b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem2:1
new file mode 100644
index 00000000..ce0f23ba
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem2:1
@@ -0,0 +1,3 @@
+# bad: wrong DEVICE
+DEVICE=aliasem0:1
+IPADDR=192.168.1.20
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bridge-main b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bridge-main
index c406bbb3..8507628e 100644
--- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bridge-main
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bridge-main
@@ -5,3 +5,4 @@ BOOTPROTO=dhcp
 STP=on
 DELAY=0
 BRIDGING_OPTS="priority=32744 hello_time=7 max_age=39 ageing_time=235352"
+MACADDR=00:16:41:11:22:33
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb
new file mode 100644
index 00000000..6e6589d3
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb
@@ -0,0 +1,43 @@
+TYPE=Ethernet
+DEVICE=eth0
+HWADDR=00:11:22:33:44:ee
+BOOTPROTO=none
+IPADDR=1.2.3.4
+PREFIX=24
+GATEWAY=1.1.1.1
+
+# dcb global switch
+# use DCB=no to turn it off
+DCB=yes
+
+# application settings
+DCB_APP_FCOE_PRIORITY=7
+DCB_APP_FCOE_ENABLE=yes
+DCB_APP_FCOE_ADVERTISE=yes
+DCB_APP_FCOE_WILLING=yes
+
+DCB_APP_ISCSI_PRIORITY=6
+DCB_APP_ISCSI_ENABLE=yes
+DCB_APP_ISCSI_ADVERTISE=yes
+DCB_APP_ISCSI_WILLING=yes
+
+DCB_APP_FIP_PRIORITY=2
+DCB_APP_FIP_ENABLE=yes
+DCB_APP_FIP_ADVERTISE=yes
+DCB_APP_FIP_WILLING=yes
+
+# priority group settings
+DCB_PG_UP2TC=76543210
+DCB_PG_PCT=25,0,0,75,0,0,0,0
+DCB_PG_ID=0000111f
+DCB_PG_UPPCT=5,10,30,25,10,50,5,0
+DCB_PG_STRICT=00110101
+DCB_PG_ENABLE=yes
+DCB_PG_ADVERTISE=yes
+DCB_PG_WILLING=yes
+
+# priority flow control settings
+DCB_PFC_UP=10011010
+DCB_PFC_ENABLE=yes
+DCB_PFC_ADVERTISE=yes
+DCB_PFC_WILLING=no
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-bad-booleans b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-bad-booleans
new file mode 100644
index 00000000..2f46a082
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-bad-booleans
@@ -0,0 +1,12 @@
+TYPE=Ethernet
+DEVICE=eth0
+HWADDR=00:11:22:33:44:ee
+BOOTPROTO=none
+IPADDR=1.2.3.4
+PREFIX=24
+GATEWAY=1.1.1.1
+
+DCB=yes
+DCB_PG_STRICT=02030101
+DCB_PG_ENABLE=yes
+
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-bad-percent b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-bad-percent
new file mode 100644
index 00000000..0c5d7b88
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-bad-percent
@@ -0,0 +1,12 @@
+TYPE=Ethernet
+DEVICE=eth0
+HWADDR=00:11:22:33:44:ee
+BOOTPROTO=none
+IPADDR=1.2.3.4
+PREFIX=24
+GATEWAY=1.1.1.1
+
+DCB=yes
+DCB_PG_PCT=25,0,0,75,0,0,110,0
+DCB_PG_ENABLE=yes
+
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-bad-uints b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-bad-uints
new file mode 100644
index 00000000..8334999b
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-bad-uints
@@ -0,0 +1,12 @@
+TYPE=Ethernet
+DEVICE=eth0
+HWADDR=00:11:22:33:44:ee
+BOOTPROTO=none
+IPADDR=1.2.3.4
+PREFIX=24
+GATEWAY=1.1.1.1
+
+DCB=yes
+DCB_PG_UP2TC=96543210
+DCB_PG_ENABLE=yes
+
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-default-app-priorities b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-default-app-priorities
new file mode 100644
index 00000000..5bdcb63c
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-default-app-priorities
@@ -0,0 +1,7 @@
+TYPE=Ethernet
+DEVICE=eth0
+DCB=yes
+DCB_APP_FCOE_ENABLE=yes
+DCB_APP_ISCSI_ENABLE=yes
+DCB_APP_FIP_ENABLE=yes
+
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-pgpct-not-100 b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-pgpct-not-100
new file mode 100644
index 00000000..95eb7c5b
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-pgpct-not-100
@@ -0,0 +1,12 @@
+TYPE=Ethernet
+DEVICE=eth0
+HWADDR=00:11:22:33:44:ee
+BOOTPROTO=none
+IPADDR=1.2.3.4
+PREFIX=24
+GATEWAY=1.1.1.1
+
+DCB=yes
+DCB_PG_PCT=25,0,0,3,75,0,25,0
+DCB_PG_ENABLE=yes
+
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-short-booleans b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-short-booleans
new file mode 100644
index 00000000..fbe1cbbc
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-short-booleans
@@ -0,0 +1,12 @@
+TYPE=Ethernet
+DEVICE=eth0
+HWADDR=00:11:22:33:44:ee
+BOOTPROTO=none
+IPADDR=1.2.3.4
+PREFIX=24
+GATEWAY=1.1.1.1
+
+DCB=yes
+DCB_PG_STRICT=0111010
+DCB_PG_ENABLE=yes
+
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-short-percent b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-short-percent
new file mode 100644
index 00000000..07ba6b64
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-short-percent
@@ -0,0 +1,12 @@
+TYPE=Ethernet
+DEVICE=eth0
+HWADDR=00:11:22:33:44:ee
+BOOTPROTO=none
+IPADDR=1.2.3.4
+PREFIX=24
+GATEWAY=1.1.1.1
+
+DCB=yes
+DCB_PG_PCT=25,0,0,75,0,0,0
+DCB_PG_ENABLE=yes
+
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-short-uints b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-short-uints
new file mode 100644
index 00000000..05ae39cb
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-short-uints
@@ -0,0 +1,12 @@
+TYPE=Ethernet
+DEVICE=eth0
+HWADDR=00:11:22:33:44:ee
+BOOTPROTO=none
+IPADDR=1.2.3.4
+PREFIX=24
+GATEWAY=1.1.1.1
+
+DCB=yes
+DCB_PG_UP2TC=7654321
+DCB_PG_ENABLE=yes
+
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-fcoe-fabric b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-fcoe-fabric
new file mode 100644
index 00000000..cde1c28d
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-fcoe-fabric
@@ -0,0 +1,6 @@
+TYPE=Ethernet
+DEVICE=eth0
+DCB=yes
+DCB_APP_FCOE_ENABLE=yes
+DCB_APP_FCOE_MODE=fabric
+
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-fcoe-vn2vn b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-fcoe-vn2vn
new file mode 100644
index 00000000..20c08451
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-fcoe-vn2vn
@@ -0,0 +1,6 @@
+TYPE=Ethernet
+DEVICE=eth0
+DCB=yes
+DCB_APP_FCOE_ENABLE=yes
+DCB_APP_FCOE_MODE=vn2vn
+
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-nm-controlled-unrecognized b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-nm-controlled-unrecognized
new file mode 100644
index 00000000..58263ece
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-nm-controlled-unrecognized
@@ -0,0 +1,6 @@
+TYPE=IPoAC
+NAME=PigeonNet
+DEVICE=ipoac0
+BOOTPROTO=dhcp
+ONBOOT=yes
+NM_CONTROLLED=no
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-noip b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-noip
new file mode 100644
index 00000000..b5028daa
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-noip
@@ -0,0 +1,3 @@
+DEVICE=eth0
+HWADDR=00:11:22:33:44:ee
+BOOTPROTO=none
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-master b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-master
new file mode 100644
index 00000000..7edc736a
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-master
@@ -0,0 +1,6 @@
+DEVICE=team0
+ONBOOT=no
+DEVICETYPE=Team
+BOOTPROTO=dhcp
+TEAM_CONFIG="{ \"device\": \"team0\", \"link_watch\": { \"name\": \"ethtool\" } }"
+
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-port b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-port
new file mode 100644
index 00000000..966bec67
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-port
@@ -0,0 +1,5 @@
+TYPE=Ethernet
+TEAM_PORT_CONFIG="{ \"p4p1\": { \"prio\": -10, \"sticky\": true } }"
+DEVICE=p4p1
+TEAM_MASTER=team0
+DEVICETYPE=TeamPort
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-port-empty-config b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-port-empty-config
new file mode 100644
index 00000000..04df6938
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-port-empty-config
@@ -0,0 +1,4 @@
+TYPE=Ethernet
+DEVICE=p4p1
+TEAM_MASTER=team0
+DEVICETYPE=TeamPort
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-unrecognized b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-unrecognized
new file mode 100644
index 00000000..18da66c1
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-unrecognized
@@ -0,0 +1,7 @@
+TYPE=PPP-over-InfiniBand
+NAME=U Can't Touch This
+DEVICE=pppoipoib0
+HWADDR=00:11:22:33
+BOOTPROTO=dhcp
+ONBOOT=yes
+
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-hidden b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-hidden
new file mode 100644
index 00000000..08b9a730
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-hidden
@@ -0,0 +1,10 @@
+# Intel Corporation 82540EP Gigabit Ethernet Controller (Mobile)
+TYPE=Wireless
+DEVICE=eth2
+HWADDR=00:16:41:11:22:33
+BOOTPROTO=dhcp
+ONBOOT=yes
+ESSID=blahblah
+MODE=Managed
+SSID_HIDDEN=yes
+
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-802-1X-subj-matches b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-802-1X-subj-matches
new file mode 100644
index 00000000..70d69bf5
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-802-1X-subj-matches
@@ -0,0 +1,17 @@
+# Intel Corporation 82540EP Gigabit Ethernet Controller (Mobile)
+TYPE=Ethernet
+DEVICE=eth0
+HWADDR=00:11:22:33:44:ee
+BOOTPROTO=dhcp
+ONBOOT=yes
+NM_CONTROLLED=yes
+KEY_MGMT=IEEE8021X
+IEEE_8021X_EAP_METHODS=PEAP
+IEEE_8021X_IDENTITY="Jara Cimrman"
+IEEE_8021X_PEAP_VERSION=1
+IEEE_8021X_INNER_AUTH_METHODS=GTC
+IEEE_8021X_PASSWORD_FLAGS="user ask"
+IEEE_8021X_SUBJECT_MATCH=server1.yourdomain.tld
+IEEE_8021X_ALTSUBJECT_MATCHES="a.yourdomain.tld b.yourdomain.tld c.yourdomain.tld"
+IEEE_8021X_PHASE2_SUBJECT_MATCH=server2.yourdomain.tld
+IEEE_8021X_PHASE2_ALTSUBJECT_MATCHES="x.yourdomain.tld y.yourdomain.tld"
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-802-1x-ttls-eapgtc b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-802-1x-ttls-eapgtc
new file mode 100644
index 00000000..fad92772
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-802-1x-ttls-eapgtc
@@ -0,0 +1,13 @@
+# Intel Corporation 82540EP Gigabit Ethernet Controller (Mobile)
+TYPE=Ethernet
+DEVICE=eth0
+HWADDR=00:11:22:33:44:ee
+BOOTPROTO=dhcp
+ONBOOT=yes
+NM_CONTROLLED=yes
+KEY_MGMT=IEEE8021X
+IEEE_8021X_EAP_METHODS=TTLS
+IEEE_8021X_IDENTITY="Bill Smith"
+IEEE_8021X_CA_CERT=test_ca_cert.pem
+IEEE_8021X_INNER_AUTH_METHODS=EAP-GTC
+IEEE_8021X_PASSWORD_FLAGS=ask
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcp-plus-ip b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcp-plus-ip
new file mode 100644
index 00000000..f0c022a9
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcp-plus-ip
@@ -0,0 +1,26 @@
+# Intel Corporation 82540EP Gigabit Ethernet Controller (Mobile)
+TYPE=Ethernet
+DEVICE=eth0
+HWADDR=00:11:22:33:44:ee
+BOOTPROTO=dhcp
+ONBOOT=yes
+IPV6INIT=yes
+IPV6_AUTOCONF=yes
+USERCTL=yes
+NM_CONTROLLED=yes
+PEERDNS=no
+DNS1=4.2.2.1
+DNS2=4.2.2.2
+DNS3=1:2:3:4::a
+DNS4=1:2:3:4::b
+
+# additional IPs
+IPADDR0=1.2.3.4
+PREFIX0=24
+GATEWAY0=1.1.1.1
+IPADDR1=9.8.7.6
+PREFIX1=16
+
+IPV6ADDR="1001:abba::1234/56"
+IPV6ADDR_SECONDARIES="2001:abba::2234/64 3001:abba::3234/96"
+
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcp-send-hostname b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcp-send-hostname
new file mode 100644
index 00000000..cba380db
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcp-send-hostname
@@ -0,0 +1,12 @@
+# Intel Corporation 82540EP Gigabit Ethernet Controller (Mobile)
+TYPE=Ethernet
+DEVICE=eth0
+HWADDR=00:11:22:33:44:ee
+BOOTPROTO=dhcp
+ONBOOT=yes
+IPV6INIT=yes
+IPV6_AUTOCONF=yes
+USERCTL=yes
+NM_CONTROLLED=yes
+PEERDNS=no
+DHCP_HOSTNAME="svata-pulec"
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-static-routes-legacy b/src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-static-routes-legacy
index 3db42ab5..c9e422e7 100644
--- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-static-routes-legacy
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-static-routes-legacy
@@ -1,3 +1,4 @@
 1.2.3.0/24 via 222.173.190.239 metric 0
 3.2.1.0/24 via 202.254.171.190 metric 77
 7.7.7.7/32 via 10.0.2.2 metric 11
+8.8.8.8/32 metric 12
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/route6-test-wired-ipv6-manual b/src/settings/plugins/ifcfg-rh/tests/network-scripts/route6-test-wired-ipv6-manual
index 2a994c50..b3259ab7 100644
--- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/route6-test-wired-ipv6-manual
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/route6-test-wired-ipv6-manual
@@ -2,3 +2,6 @@
 
 # default route is ignored by ifcfg-rh reader, because NM handles it internally
 default via dead::beaf
+
+# routes without "via" are valid
+abbe::cafe/64 metric 777
diff --git a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh-utils.c b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh-utils.c
index e32ad789..39c81027 100644
--- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh-utils.c
+++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh-utils.c
@@ -23,11 +23,10 @@
 #include <unistd.h>
 #include <string.h>
 
-#include "nm-test-helpers.h"
-
 #include "common.h"
 #include "utils.h"
 
+#include "nm-test-utils.h"
 
 static void
 test_get_ifcfg_name (const char *desc,
@@ -114,10 +113,14 @@ test_ignored (const char *desc, const char *path, gboolean expected_ignored)
 	ASSERT (result == expected_ignored, desc, "unexpected ignore result for path '%s'", path);
 }
 
+NMTST_DEFINE ();
+
 int main (int argc, char **argv)
 {
 	char *base;
 
+	nmtst_init (&argc, &argv, TRUE);
+
 	/* The tests */
 	test_get_ifcfg_name ("get-ifcfg-name-bad", "/foo/bar/adfasdfadf", FALSE, NULL);
 	test_get_ifcfg_name ("get-ifcfg-name-good", "/foo/bar/ifcfg-FooBar", FALSE, "FooBar");
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 668dcd9b..c1b14f12 100644
--- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
+++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
@@ -45,13 +45,18 @@
 #include <nm-setting-cdma.h>
 #include <nm-setting-serial.h>
 #include <nm-setting-vlan.h>
+#include <nm-setting-dcb.h>
+#include <nm-utils-private.h>
 
-#include "nm-test-helpers.h"
+#include "NetworkManagerUtils.h"
 
 #include "common.h"
 #include "reader.h"
 #include "writer.h"
 #include "utils.h"
+#include "nm-logging.h"
+
+#include "nm-test-utils.h"
 
 #if 0
 static void
@@ -74,20 +79,11 @@ connection_diff (NMConnection *a, NMConnection *b)
 }
 #endif
 
-typedef enum {
-	CK_CA_CERT = 0,
-	CK_CLIENT_CERT = 1,
-	CK_PRIV_KEY = 2
-} CertKeyType;
-
 static gboolean
-verify_cert_or_key (CertKeyType ck_type,
-                    NMSetting8021x *s_compare,
+verify_cert_or_key (NMSetting8021x *s_compare,
                     const char *file,
                     const char *privkey_password,
-                    const char *ifcfg,
-                    const char *test_name,
-                    const char *setting_key)
+                    const char *property)
 {
 	NMSetting8021x *s_8021x;
 	GError *error = NULL;
@@ -96,512 +92,304 @@ verify_cert_or_key (CertKeyType ck_type,
 	gboolean phase2 = FALSE;
 	NMSetting8021xCKScheme scheme = NM_SETTING_802_1X_CK_SCHEME_UNKNOWN;
 
-	if (strstr (setting_key, "phase2"))
+	if (strstr (property, "phase2"))
 		phase2 = TRUE;
 
-	/* CA Cert */
 	s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
-	ASSERT (s_8021x != NULL,
-	        test_name, "failed to verify %s: could not create temp 802.1x setting",
-	        ifcfg);
 
-	if (ck_type == CK_CA_CERT) {
+	/* Load the certificate into an empty setting */
+	if (strstr (property, "ca-cert")) {
 		if (phase2)
 			success = nm_setting_802_1x_set_phase2_ca_cert (s_8021x, file, NM_SETTING_802_1X_CK_SCHEME_PATH, NULL, &error);
 		else
 			success = nm_setting_802_1x_set_ca_cert (s_8021x, file, NM_SETTING_802_1X_CK_SCHEME_PATH, NULL, &error);
-	} else if (ck_type == CK_CLIENT_CERT) {
+	} else if (strstr (property, "client-cert")) {
 		if (phase2)
 			success = nm_setting_802_1x_set_phase2_client_cert (s_8021x, file, NM_SETTING_802_1X_CK_SCHEME_PATH, NULL, &error);
 		else
 			success = nm_setting_802_1x_set_client_cert (s_8021x, file, NM_SETTING_802_1X_CK_SCHEME_PATH, NULL, &error);
-	} else if (ck_type == CK_PRIV_KEY) {
+	} else if (strstr (property, "private-key")) {
 		if (phase2)
 			success = nm_setting_802_1x_set_phase2_private_key (s_8021x, file, privkey_password, NM_SETTING_802_1X_CK_SCHEME_PATH, NULL, &error);
 		else
 			success = nm_setting_802_1x_set_private_key (s_8021x, file, privkey_password, NM_SETTING_802_1X_CK_SCHEME_PATH, NULL, &error);
 	}
-	ASSERT (success == TRUE,
-	        test_name, "failed to verify %s: could not load item for %s / %s: %s",
-	        ifcfg, NM_SETTING_802_1X_SETTING_NAME, setting_key, error->message);
+	g_assert_no_error (error);
+	g_assert_cmpint (success, ==, TRUE);
 
-	if (ck_type == CK_CA_CERT) {
+	/* Ensure it was loaded using the PATH scheme */
+	if (strstr (property, "ca-cert")) {
 		if (phase2)
 			scheme = nm_setting_802_1x_get_phase2_ca_cert_scheme (s_8021x);
 		else
 			scheme = nm_setting_802_1x_get_ca_cert_scheme (s_8021x);
-	} else if (ck_type == CK_CLIENT_CERT) {
+	} else if (strstr (property, "client-cert")) {
 		if (phase2)
 			scheme = nm_setting_802_1x_get_phase2_client_cert_scheme (s_8021x);
 		else
 			scheme = nm_setting_802_1x_get_client_cert_scheme (s_8021x);
-	} else if (ck_type == CK_PRIV_KEY) {
+	} else if (strstr (property, "private-key")) {
 		if (phase2)
 			scheme = nm_setting_802_1x_get_phase2_private_key_scheme (s_8021x);
 		else
 			scheme = nm_setting_802_1x_get_private_key_scheme (s_8021x);
 	}
-	ASSERT (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH,
-	        test_name, "failed to verify %s: unexpected cert/key scheme for %s / %s",
-	        ifcfg, NM_SETTING_802_1X_SETTING_NAME, setting_key);
+	g_assert_cmpint (scheme, ==, NM_SETTING_802_1X_CK_SCHEME_PATH);
 
-	if (ck_type == CK_CA_CERT) {
+	/* Grab the path back out */
+	if (strstr (property, "ca-cert")) {
 		if (phase2)
 			expected = nm_setting_802_1x_get_phase2_ca_cert_path (s_8021x);
 		else
 			expected = nm_setting_802_1x_get_ca_cert_path (s_8021x);
-	} else if (ck_type == CK_CLIENT_CERT) {
+	} else if (strstr (property, "client-cert")) {
 		if (phase2)
 			expected = nm_setting_802_1x_get_phase2_client_cert_path (s_8021x);
 		else
 			expected = nm_setting_802_1x_get_client_cert_path (s_8021x);
-	} else if (ck_type == CK_PRIV_KEY) {
+	} else if (strstr (property, "private-key")) {
 		if (phase2)
 			expected = nm_setting_802_1x_get_phase2_private_key_path (s_8021x);
 		else
 			expected = nm_setting_802_1x_get_private_key_path (s_8021x);
 	}
-	ASSERT (expected != NULL,
-	        test_name, "failed to verify %s: failed to get read item for %s / %s",
-	        ifcfg, NM_SETTING_802_1X_SETTING_NAME, setting_key);
+	g_assert_cmpstr (expected, ==, file);
 
-	if (ck_type == CK_CA_CERT) {
+	/* Compare the path with the expected path from the real setting */
+	if (strstr (property, "ca-cert")) {
 		if (phase2)
 			setting = nm_setting_802_1x_get_phase2_ca_cert_path (s_compare);
 		else
 			setting = nm_setting_802_1x_get_ca_cert_path (s_compare);
-	} else if (ck_type == CK_CLIENT_CERT) {
+	} else if (strstr (property, "client-cert")) {
 		if (phase2)
 			setting = nm_setting_802_1x_get_phase2_client_cert_path (s_compare);
 		else
 			setting = nm_setting_802_1x_get_client_cert_path (s_compare);
-	} else if (ck_type == CK_PRIV_KEY) {
+	} else if (strstr (property, "private-key")) {
 		if (phase2)
 			setting = nm_setting_802_1x_get_phase2_private_key_path (s_compare);
 		else
 			setting = nm_setting_802_1x_get_private_key_path (s_compare);
 	}
-	ASSERT (setting != NULL,
-	        test_name, "failed to verify %s: missing %s / %s key",
-	        ifcfg, NM_SETTING_802_1X_SETTING_NAME, setting_key);
-
-	ASSERT (strlen (setting) == strlen (expected),
-	        test_name, "failed to verify %s: unexpected %s / %s certificate length",
-	        test_name, NM_SETTING_802_1X_SETTING_NAME, setting_key);
-
-	ASSERT (strcmp (setting, expected) == 0,
-	        test_name, "failed to verify %s: %s / %s key certificate mismatch",
-	        ifcfg, NM_SETTING_802_1X_SETTING_NAME, setting_key);
+	g_assert_cmpstr (setting, ==, expected);
 
 	g_object_unref (s_8021x);
 	return TRUE;
 }
 
 
-#define TEST_IFCFG_MINIMAL TEST_IFCFG_DIR"/network-scripts/ifcfg-test-minimal"
-
 static void
-test_read_minimal (void)
+test_read_basic (void)
 {
 	NMConnection *connection;
 	NMSettingConnection *s_con;
 	NMSettingWired *s_wired;
 	NMSettingIP4Config *s_ip4;
-	char *unmanaged = NULL;
-	char *keyfile = NULL;
-	char *routefile = NULL;
-	char *route6file = NULL;
-	gboolean ignore_error = FALSE;
+	NMSettingIP6Config *s_ip6;
 	GError *error = NULL;
-	const char *tmp;
 	const GByteArray *array;
 	char expected_mac_address[ETH_ALEN] = { 0x00, 0x16, 0x41, 0x11, 0x22, 0x33 };
 	const char *expected_id = "System test-minimal";
 	guint64 expected_timestamp = 0;
+	gboolean success;
 
-	connection = connection_from_file (TEST_IFCFG_MINIMAL,
-	                                   NULL,
-	                                   TYPE_ETHERNET,
-	                                   NULL,
-	                                   &unmanaged,
-	                                   &keyfile,
-	                                   &routefile,
-	                                   &route6file,
-	                                   &error,
-	                                   &ignore_error);
-	ASSERT (connection != NULL,
-	        "minimal-wired-read", "failed to read %s: %s", TEST_IFCFG_MINIMAL, error->message);
-
-	ASSERT (nm_connection_verify (connection, &error),
-	        "minimal-wired-verify", "failed to verify %s: %s", TEST_IFCFG_MINIMAL, error->message);
+	connection = connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-minimal",
+	                                   NULL, TYPE_ETHERNET, NULL, NULL, NULL, NULL, NULL, &error, NULL);
+	g_assert_no_error (error);
+	g_assert (connection);
+	success = nm_connection_verify (connection, &error);
+	g_assert_no_error (error);
+	g_assert (success);
 
 	/* ===== CONNECTION SETTING ===== */
-
 	s_con = nm_connection_get_setting_connection (connection);
-	ASSERT (s_con != NULL,
-	        "minimal-wired-verify-connection", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_MINIMAL,
-	        NM_SETTING_CONNECTION_SETTING_NAME);
-
-	/* ID */
-	tmp = nm_setting_connection_get_id (s_con);
-	ASSERT (tmp != NULL,
-	        "minimal-wired-verify-connection", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_MINIMAL,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-	ASSERT (strcmp (tmp, expected_id) == 0,
-	        "minimal-wired-verify-connection", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_MINIMAL,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, expected_id);
+	g_assert_cmpint (nm_setting_connection_get_timestamp (s_con), ==, expected_timestamp);
+	g_assert (nm_setting_connection_get_autoconnect (s_con));
 
 	/* UUID can't be tested if the ifcfg does not contain the UUID key, because
 	 * the UUID is generated on the full path of the ifcfg file, which can change
 	 * depending on where the tests are run.
 	 */
 
-	/* Timestamp */
-	ASSERT (nm_setting_connection_get_timestamp (s_con) == expected_timestamp,
-	        "minimal-wired-verify-connection", "failed to verify %s: unexpected %s /%s key value",
-	        TEST_IFCFG_MINIMAL,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_TIMESTAMP);
-
-	/* Autoconnect */
-	ASSERT (nm_setting_connection_get_autoconnect (s_con) == TRUE,
-	        "minimal-wired-verify-connection", "failed to verify %s: unexpected %s /%s key value",
-	        TEST_IFCFG_MINIMAL,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_AUTOCONNECT);
-
 	/* ===== WIRED SETTING ===== */
-
 	s_wired = nm_connection_get_setting_wired (connection);
-	ASSERT (s_wired != NULL,
-	        "minimal-wired-verify-wired", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_MINIMAL,
-	        NM_SETTING_WIRED_SETTING_NAME);
+	g_assert (s_wired);
+	g_assert_cmpint (nm_setting_wired_get_mtu (s_wired), ==, 0);
 
 	/* MAC address */
 	array = nm_setting_wired_get_mac_address (s_wired);
-	ASSERT (array != NULL,
-	        "minimal-wired-verify-wired", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_MINIMAL,
-	        NM_SETTING_WIRED_SETTING_NAME,
-	        NM_SETTING_WIRED_MAC_ADDRESS);
-	ASSERT (array->len == ETH_ALEN,
-	        "minimal-wired-verify-wired", "failed to verify %s: unexpected %s / %s key value length",
-	        TEST_IFCFG_MINIMAL,
-	        NM_SETTING_WIRED_SETTING_NAME,
-	        NM_SETTING_WIRED_MAC_ADDRESS);
-	ASSERT (memcmp (array->data, &expected_mac_address[0], sizeof (expected_mac_address)) == 0,
-	        "minimal-wired-verify-wired", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_MINIMAL,
-	        NM_SETTING_WIRED_SETTING_NAME,
-	        NM_SETTING_WIRED_MAC_ADDRESS);
-
-	ASSERT (nm_setting_wired_get_mtu (s_wired) == 0,
-	        "minimal-wired-verify-wired", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_MINIMAL,
-	        NM_SETTING_WIRED_SETTING_NAME,
-	        NM_SETTING_WIRED_MTU);
+	g_assert (array);
+	g_assert_cmpint (array->len, ==, ETH_ALEN);
+	g_assert (memcmp (array->data, &expected_mac_address[0], ETH_ALEN) == 0);
 
 	/* ===== IPv4 SETTING ===== */
-
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
-	ASSERT (s_ip4 != NULL,
-	        "minimal-wired-verify-ip4", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_MINIMAL,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME);
-
-	/* Method */
-	tmp = nm_setting_ip4_config_get_method (s_ip4);
-	ASSERT (strcmp (tmp, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0,
-	        "minimal-wired-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_MINIMAL,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP4_CONFIG_METHOD);
+	g_assert (s_ip4);
+	g_assert_cmpstr (nm_setting_ip4_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_DISABLED);
+	g_assert (nm_setting_ip4_config_get_never_default (s_ip4) == FALSE);
 
-	ASSERT (nm_setting_ip4_config_get_never_default (s_ip4) == FALSE,
-	        "minimal-wired-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_MINIMAL,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP4_CONFIG_NEVER_DEFAULT);
+	/* ===== IPv6 SETTING ===== */
+	s_ip6 = nm_connection_get_setting_ip6_config (connection);
+	g_assert (s_ip6);
+	g_assert_cmpstr (nm_setting_ip6_config_get_method (s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_IGNORE);
+	g_assert (nm_setting_ip6_config_get_never_default (s_ip6) == FALSE);
 
-	g_free (unmanaged);
-	g_free (keyfile);
-	g_free (routefile);
-	g_free (route6file);
 	g_object_unref (connection);
 }
 
 static void
-test_read_variables_corner_cases (const char *file, const char *expected_id)
+test_read_variables_corner_cases (void)
 {
 	NMConnection *connection;
 	NMSettingConnection *s_con;
 	NMSettingWired *s_wired;
 	NMSettingIP4Config *s_ip4;
-	char *unmanaged = NULL;
-	char *keyfile = NULL;
-	char *routefile = NULL;
-	char *route6file = NULL;
-	gboolean ignore_error = FALSE;
 	GError *error = NULL;
-	const char *tmp;
 	const GByteArray *array;
 	char expected_mac_address[ETH_ALEN] = { 0x00, 0x16, 0x41, 0x11, 0x22, 0x33 };
 	const char *expected_zone = "'";
+	const char *expected_id = "\"";
 	guint64 expected_timestamp = 0;
+	gboolean success;
 
-	connection = connection_from_file (file,
-	                                   NULL,
-	                                   TYPE_ETHERNET,
-	                                   NULL,
-	                                   &unmanaged,
-	                                   &keyfile,
-	                                   &routefile,
-	                                   &route6file,
-	                                   &error,
-	                                   &ignore_error);
-	ASSERT (connection != NULL,
-	        "corner-cases-read", "failed to read %s: %s", file, error->message);
-
-	ASSERT (nm_connection_verify (connection, &error),
-	        "corner-cases-verify", "failed to verify %s: %s", file, error->message);
+	connection = connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-variables-corner-cases-1",
+	                                   NULL, TYPE_ETHERNET, NULL, NULL, NULL, NULL, NULL, &error, NULL);
+	g_assert_no_error (error);
+	g_assert (connection);
+	success = nm_connection_verify (connection, &error);
+	g_assert_no_error (error);
+	g_assert (success);
 
 	/* ===== CONNECTION SETTING ===== */
-
 	s_con = nm_connection_get_setting_connection (connection);
-	ASSERT (s_con != NULL,
-	        "corner-cases-verify-connection", "failed to verify %s: missing %s setting",
-	        file,
-	        NM_SETTING_CONNECTION_SETTING_NAME);
-
-	/* ID  - that is NAME= variable */
-	tmp = nm_setting_connection_get_id (s_con);
-	ASSERT (tmp != NULL,
-	        "corner-cases-verify-connection", "failed to verify %s: missing %s / %s key",
-	        file,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-	ASSERT (strcmp (tmp, expected_id) == 0,
-	        "corner-cases-verify-connection", "failed to verify %s: unexpected %s / %s key value",
-	        file,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-
-	/* ZONE */
-	tmp = nm_setting_connection_get_zone (s_con);
-	ASSERT (tmp != NULL,
-	        "corner-cases-verify-connection", "failed to verify %s: missing %s / %s key",
-	        file,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-	ASSERT (strcmp (tmp, expected_zone) == 0,
-	        "corner-cases-verify-connection", "failed to verify %s: unexpected %s / %s key value",
-	        file,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-
-
-	/* Timestamp */
-	ASSERT (nm_setting_connection_get_timestamp (s_con) == expected_timestamp,
-	        "corner-cases-verify-connection", "failed to verify %s: unexpected %s /%s key value",
-	        file,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_TIMESTAMP);
-
-	/* Autoconnect */
-	ASSERT (nm_setting_connection_get_autoconnect (s_con) == TRUE,
-	        "corner-cases-verify-connection", "failed to verify %s: unexpected %s /%s key value",
-	        file,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_AUTOCONNECT);
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, expected_id);
+	g_assert_cmpstr (nm_setting_connection_get_zone (s_con), ==, expected_zone);
+	g_assert_cmpint (nm_setting_connection_get_timestamp (s_con), ==, expected_timestamp);
+	g_assert (nm_setting_connection_get_autoconnect (s_con));
 
 	/* ===== WIRED SETTING ===== */
-
 	s_wired = nm_connection_get_setting_wired (connection);
-	ASSERT (s_wired != NULL,
-	        "corner-cases-verify-wired", "failed to verify %s: missing %s setting",
-	        file,
-	        NM_SETTING_WIRED_SETTING_NAME);
+	g_assert (s_wired);
+	g_assert_cmpint (nm_setting_wired_get_mtu (s_wired), ==, 0);
 
 	/* MAC address */
 	array = nm_setting_wired_get_mac_address (s_wired);
-	ASSERT (array != NULL,
-	        "corner-cases-verify-wired", "failed to verify %s: missing %s / %s key",
-	        file,
-	        NM_SETTING_WIRED_SETTING_NAME,
-	        NM_SETTING_WIRED_MAC_ADDRESS);
-	ASSERT (array->len == ETH_ALEN,
-	        "corner-cases-verify-wired", "failed to verify %s: unexpected %s / %s key value length",
-	        file,
-	        NM_SETTING_WIRED_SETTING_NAME,
-	        NM_SETTING_WIRED_MAC_ADDRESS);
-	ASSERT (memcmp (array->data, &expected_mac_address[0], sizeof (expected_mac_address)) == 0,
-	        "corner-cases-verify-wired", "failed to verify %s: unexpected %s / %s key value",
-	        file,
-	        NM_SETTING_WIRED_SETTING_NAME,
-	        NM_SETTING_WIRED_MAC_ADDRESS);
-
-	ASSERT (nm_setting_wired_get_mtu (s_wired) == 0,
-	        "corner-cases-verify-wired", "failed to verify %s: unexpected %s / %s key value",
-	        file,
-	        NM_SETTING_WIRED_SETTING_NAME,
-	        NM_SETTING_WIRED_MTU);
+	g_assert (array);
+	g_assert_cmpint (array->len, ==, ETH_ALEN);
+	g_assert (memcmp (array->data, &expected_mac_address[0], ETH_ALEN) == 0);
 
 	/* ===== IPv4 SETTING ===== */
-
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
-	ASSERT (s_ip4 != NULL,
-	        "corner-cases-verify-ip4", "failed to verify %s: missing %s setting",
-	        file,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME);
-
-	/* Method */
-	tmp = nm_setting_ip4_config_get_method (s_ip4);
-	ASSERT (strcmp (tmp, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0,
-	        "corner-cases-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        file,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP4_CONFIG_METHOD);
-
-	ASSERT (nm_setting_ip4_config_get_never_default (s_ip4) == FALSE,
-	        "corner-cases-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        file,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP4_CONFIG_NEVER_DEFAULT);
+	g_assert (s_ip4);
+	g_assert_cmpstr (nm_setting_ip4_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_DISABLED);
+	g_assert (nm_setting_ip4_config_get_never_default (s_ip4) == FALSE);
 
-	g_free (unmanaged);
-	g_free (keyfile);
-	g_free (routefile);
-	g_free (route6file);
 	g_object_unref (connection);
 }
 
-#define TEST_IFCFG_UNMANAGED TEST_IFCFG_DIR"/network-scripts/ifcfg-test-nm-controlled"
-
 static void
 test_read_unmanaged (void)
 {
 	NMConnection *connection;
 	NMSettingConnection *s_con;
-	NMSettingWired *s_wired;
-	NMSettingIP4Config *s_ip4;
-	char *unmanaged = NULL;
-	char *keyfile = NULL;
-	char *routefile = NULL;
-	char *route6file = NULL;
-	gboolean ignore_error = FALSE;
+	char *unhandled_spec = NULL;
 	GError *error = NULL;
-	const char *tmp;
-	const GByteArray *array;
-	char expected_mac_address[ETH_ALEN] = { 0x00, 0x11, 0x22, 0x33, 0xf8, 0x9f };
 	const char *expected_id = "System test-nm-controlled";
 	guint64 expected_timestamp = 0;
+	gboolean success;
 
-	connection = connection_from_file (TEST_IFCFG_UNMANAGED,
-	                                   NULL,
-	                                   TYPE_ETHERNET,
-	                                   NULL,
-	                                   &unmanaged,
-	                                   &keyfile,
-	                                   &routefile,
-	                                   &route6file,
-	                                   &error,
-	                                   &ignore_error);
-	ASSERT (connection != NULL,
-	        "unmanaged-read", "failed to read %s: %s", TEST_IFCFG_UNMANAGED, error->message);
-
-	ASSERT (nm_connection_verify (connection, &error),
-	        "unmanaged-verify", "failed to verify %s: %s", TEST_IFCFG_UNMANAGED, error->message);
-
-	ASSERT (unmanaged != NULL,
-	        "unmanaged-verify", "failed to verify %s: expected unmanaged", TEST_IFCFG_UNMANAGED);
-
-	ASSERT (strcmp (unmanaged, "mac:00:11:22:33:f8:9f") == 0,
-	        "unmanaged-verify", "failed to verify %s: expected unmanaged", TEST_IFCFG_UNMANAGED);
+	connection = connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-nm-controlled",
+	                                   NULL, TYPE_ETHERNET, NULL,
+	                                   &unhandled_spec,
+	                                   NULL, NULL, NULL, &error, NULL);
+	g_assert_no_error (error);
+	g_assert (connection);
+	success = nm_connection_verify (connection, &error);
+	g_assert_no_error (error);
+	g_assert (success);
+	g_assert_cmpstr (unhandled_spec, ==, "unmanaged:mac:00:11:22:33:f8:9f");
 
 	/* ===== CONNECTION SETTING ===== */
-
 	s_con = nm_connection_get_setting_connection (connection);
-	ASSERT (s_con != NULL,
-	        "unmanaged-verify-connection", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_UNMANAGED,
-	        NM_SETTING_CONNECTION_SETTING_NAME);
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, expected_id);
+	g_assert_cmpint (nm_setting_connection_get_timestamp (s_con), ==, expected_timestamp);
+	g_assert (nm_setting_connection_get_autoconnect (s_con));
 
-	/* ID */
-	tmp = nm_setting_connection_get_id (s_con);
-	ASSERT (tmp != NULL,
-	        "unmanaged-verify-connection", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_UNMANAGED,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-	ASSERT (strcmp (tmp, expected_id) == 0,
-	        "unmanaged-verify-connection", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_UNMANAGED,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
+	g_free (unhandled_spec);
+	g_object_unref (connection);
+}
 
-	/* Timestamp */
-	ASSERT (nm_setting_connection_get_timestamp (s_con) == expected_timestamp,
-	        "unmanaged-verify-connection", "failed to verify %s: unexpected %s /%s key value",
-	        TEST_IFCFG_UNMANAGED,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_TIMESTAMP);
+static void
+test_read_unmanaged_unrecognized (void)
+{
+	NMConnection *connection;
+	NMSettingConnection *s_con;
+	char *unhandled_spec = NULL;
+	GError *error = NULL;
+	const char *expected_id = "PigeonNet";
+	guint64 expected_timestamp = 0;
+	gboolean success;
 
-	/* Autoconnect */
-	/* Since the unmanaged connections are not completely read, defaults will
-	 * be used for many settings.
-	 */
-	ASSERT (nm_setting_connection_get_autoconnect (s_con) == TRUE,
-	        "unmanaged-verify-connection", "failed to verify %s: unexpected %s /%s key value",
-	        TEST_IFCFG_UNMANAGED,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_AUTOCONNECT);
+	connection = connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-nm-controlled-unrecognized",
+	                                   NULL, NULL, NULL,
+	                                   &unhandled_spec,
+	                                   NULL, NULL, NULL, &error, NULL);
+	g_assert_no_error (error);
+	g_assert (connection);
+	success = nm_connection_verify (connection, &error);
+	g_assert_no_error (error);
+	g_assert (success);
+	g_assert_cmpstr (unhandled_spec, ==, "unmanaged:interface-name:ipoac0");
 
-	/* ===== WIRED SETTING ===== */
+	/* ===== CONNECTION SETTING ===== */
+	s_con = nm_connection_get_setting_connection (connection);
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, expected_id);
+	g_assert_cmpint (nm_setting_connection_get_timestamp (s_con), ==, expected_timestamp);
 
-	s_wired = nm_connection_get_setting_wired (connection);
-	ASSERT (s_wired != NULL,
-	        "unmanaged-verify-wired", "failed to verify %s: missing %s setting",
-	        TEST_IFCFG_UNMANAGED,
-	        NM_SETTING_WIRED_SETTING_NAME);
+	g_object_unref (connection);
+}
 
-	/* MAC address */
-	array = nm_setting_wired_get_mac_address (s_wired);
-	ASSERT (array != NULL,
-	        "unmanaged-verify-wired", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_UNMANAGED,
-	        NM_SETTING_WIRED_SETTING_NAME,
-	        NM_SETTING_WIRED_MAC_ADDRESS);
-	ASSERT (array->len == ETH_ALEN,
-	        "unmanaged-verify-wired", "failed to verify %s: unexpected %s / %s key value length",
-	        TEST_IFCFG_UNMANAGED,
-	        NM_SETTING_WIRED_SETTING_NAME,
-	        NM_SETTING_WIRED_MAC_ADDRESS);
-	ASSERT (memcmp (array->data, &expected_mac_address[0], sizeof (expected_mac_address)) == 0,
-	        "unmanaged-verify-wired", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_UNMANAGED,
-	        NM_SETTING_WIRED_SETTING_NAME,
-	        NM_SETTING_WIRED_MAC_ADDRESS);
+static void
+test_read_unrecognized (void)
+{
+	NMConnection *connection;
+	NMSettingConnection *s_con;
+	char *unhandled_spec = NULL;
+	GError *error = NULL;
+	const char *expected_id = "U Can't Touch This";
+	guint64 expected_timestamp = 0;
+	gboolean success;
 
-	/* ===== IPv4 SETTING ===== */
+	connection = connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-unrecognized",
+	                                   NULL, NULL, NULL,
+	                                   &unhandled_spec,
+	                                   NULL, NULL, NULL, &error, NULL);
+	g_assert_no_error (error);
+	g_assert (connection);
+	success = nm_connection_verify (connection, &error);
+	g_assert_no_error (error);
+	g_assert (success);
+	g_assert_cmpstr (unhandled_spec, ==, "unrecognized:mac:00:11:22:33");
 
-	s_ip4 = nm_connection_get_setting_ip4_config (connection);
-	ASSERT (s_ip4 == NULL,
-	        "unmanaged-verify-ip4", "failed to verify %s: unexpected %s setting",
-	        TEST_IFCFG_UNMANAGED,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME);
+	/* ===== CONNECTION SETTING ===== */
+	s_con = nm_connection_get_setting_connection (connection);
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, expected_id);
+	g_assert_cmpint (nm_setting_connection_get_timestamp (s_con), ==, expected_timestamp);
 
-	g_free (unmanaged);
 	g_object_unref (connection);
 }
 
 static void
-test_read_wired_static (const char *file, const char *expected_id)
+test_read_wired_static (const char *file,
+                        const char *expected_id,
+                        gboolean expect_ip6)
 {
 	NMConnection *connection;
 	NMSettingConnection *s_con;
@@ -609,17 +397,12 @@ test_read_wired_static (const char *file, const char *expected_id)
 	NMSettingIP4Config *s_ip4;
 	NMSettingIP6Config *s_ip6;
 	char *unmanaged = NULL;
-	char *keyfile = NULL;
-	char *routefile = NULL;
-	char *route6file = NULL;
-	gboolean ignore_error = FALSE;
 	GError *error = NULL;
 	const GByteArray *array;
 	char expected_mac_address[ETH_ALEN] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0xee };
-	const char *tmp;
 	const char *expected_dns1 = "4.2.2.1";
 	const char *expected_dns2 = "4.2.2.2";
-	struct in_addr addr;
+	guint32 addr;
 	struct in6_addr addr6;
 	const char *expected_address1 = "192.168.1.5";
 	const char *expected_address1_gw = "192.168.1.1";
@@ -629,392 +412,134 @@ test_read_wired_static (const char *file, const char *expected_id)
 	const char *expected6_dns2 = "1:2:3:4::b";
 	NMIP4Address *ip4_addr;
 	NMIP6Address *ip6_addr;
+	gboolean success;
 
-	connection = connection_from_file (file,
-	                                   NULL,
-	                                   TYPE_ETHERNET,
-	                                   NULL,
-	                                   &unmanaged,
-	                                   &keyfile,
-	                                   &routefile,
-	                                   &route6file,
-	                                   &error,
-	                                   &ignore_error);
-	ASSERT (connection != NULL,
-	        "wired-static-read", "failed to read %s: %s", file, error->message);
-
-	ASSERT (nm_connection_verify (connection, &error),
-	        "wired-static-verify", "failed to verify %s: %s", file, error->message);
-
-	ASSERT (unmanaged == NULL,
-	        "wired-static-verify", "failed to verify %s: unexpected unmanaged value", file);
+	connection = connection_from_file (file, NULL, TYPE_ETHERNET, NULL,
+	                                   &unmanaged, NULL, NULL, NULL, &error, NULL);
+	g_assert_no_error (error);
+	g_assert (connection);
+	success = nm_connection_verify (connection, &error);
+	g_assert_no_error (error);
+	g_assert (success);
+	g_assert_cmpstr (unmanaged, ==, NULL);
 
 	/* ===== CONNECTION SETTING ===== */
-
 	s_con = nm_connection_get_setting_connection (connection);
-	ASSERT (s_con != NULL,
-	        "wired-static-verify-connection", "failed to verify %s: missing %s setting",
-	        file,
-	        NM_SETTING_CONNECTION_SETTING_NAME);
-
-	/* ID */
-	tmp = nm_setting_connection_get_id (s_con);
-	ASSERT (tmp != NULL,
-	        "wired-static-verify-connection", "failed to verify %s: missing %s / %s key",
-	        file,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-	ASSERT (strcmp (tmp, expected_id) == 0,
-	        "wired-static-verify-connection", "failed to verify %s: unexpected %s / %s key value",
-	        file,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-
-	/* Timestamp */
-	ASSERT (nm_setting_connection_get_timestamp (s_con) == 0,
-	        "wired-static-verify-connection", "failed to verify %s: unexpected %s /%s key value",
-	        file,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_TIMESTAMP);
-
-	/* Autoconnect */
-	ASSERT (nm_setting_connection_get_autoconnect (s_con) == TRUE,
-	        "wired-static-verify-connection", "failed to verify %s: unexpected %s /%s key value",
-	        file,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_AUTOCONNECT);
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, expected_id);
+	g_assert_cmpint (nm_setting_connection_get_timestamp (s_con), ==, 0);
+	g_assert (nm_setting_connection_get_autoconnect (s_con));
 
 	/* ===== WIRED SETTING ===== */
-
 	s_wired = nm_connection_get_setting_wired (connection);
-	ASSERT (s_wired != NULL,
-	        "wired-static-verify-wired", "failed to verify %s: missing %s setting",
-	        file,
-	        NM_SETTING_WIRED_SETTING_NAME);
+	g_assert (s_wired);
+	g_assert_cmpint (nm_setting_wired_get_mtu (s_wired), ==, 1492);
 
 	/* MAC address */
 	array = nm_setting_wired_get_mac_address (s_wired);
-	ASSERT (array != NULL,
-	        "wired-static-verify-wired", "failed to verify %s: missing %s / %s key",
-	        file,
-	        NM_SETTING_WIRED_SETTING_NAME,
-	        NM_SETTING_WIRED_MAC_ADDRESS);
-	ASSERT (array->len == ETH_ALEN,
-	        "wired-static-verify-wired", "failed to verify %s: unexpected %s / %s key value length",
-	        file,
-	        NM_SETTING_WIRED_SETTING_NAME,
-	        NM_SETTING_WIRED_MAC_ADDRESS);
-	ASSERT (memcmp (array->data, &expected_mac_address[0], sizeof (expected_mac_address)) == 0,
-	        "wired-static-verify-wired", "failed to verify %s: unexpected %s / %s key value",
-	        file,
-	        NM_SETTING_WIRED_SETTING_NAME,
-	        NM_SETTING_WIRED_MAC_ADDRESS);
-
-	ASSERT (nm_setting_wired_get_mtu (s_wired) == 1492,
-	        "wired-static-verify-wired", "failed to verify %s: unexpected %s / %s key value",
-	        file,
-	        NM_SETTING_WIRED_SETTING_NAME,
-	        NM_SETTING_WIRED_MTU);
+	g_assert (array);
+	g_assert_cmpint (array->len, ==, ETH_ALEN);
+	g_assert (memcmp (array->data, &expected_mac_address[0], ETH_ALEN) == 0);
 
 	/* ===== IPv4 SETTING ===== */
-
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
-	ASSERT (s_ip4 != NULL,
-	        "wired-static-verify-ip4", "failed to verify %s: missing %s setting",
-	        file,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME);
-
-	/* Method */
-	tmp = nm_setting_ip4_config_get_method (s_ip4);
-	ASSERT (strcmp (tmp, NM_SETTING_IP4_CONFIG_METHOD_MANUAL) == 0,
-	        "wired-static-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        file,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP4_CONFIG_METHOD);
-
-	/* Implicit may-fail */
-	ASSERT (nm_setting_ip4_config_get_may_fail (s_ip4) == TRUE,
-	        "wired-static-verify-ip6", "failed to verify %s: unexpected %s / %s key value",
-	        file,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP4_CONFIG_MAY_FAIL);
+	g_assert (s_ip4);
+	g_assert_cmpstr (nm_setting_ip4_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_MANUAL);
+	g_assert (nm_setting_ip4_config_get_may_fail (s_ip4));
 
 	/* DNS Addresses */
-	ASSERT (nm_setting_ip4_config_get_num_dns (s_ip4) == 2,
-	        "wired-static-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        file,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP4_CONFIG_DNS);
-
-	ASSERT (inet_pton (AF_INET, expected_dns1, &addr) > 0,
-	        "wired-static-verify-ip4", "failed to verify %s: couldn't convert DNS IP address #1",
-	        file,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP4_CONFIG_DNS);
-	ASSERT (nm_setting_ip4_config_get_dns (s_ip4, 0) == addr.s_addr,
-	        "wired-static-verify-ip4", "failed to verify %s: unexpected %s / %s key value #1",
-	        file,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP4_CONFIG_DNS);
-
-	ASSERT (inet_pton (AF_INET, expected_dns2, &addr) > 0,
-	        "wired-static-verify-ip4", "failed to verify %s: couldn't convert DNS IP address #2",
-	        file,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP4_CONFIG_DNS);
-	ASSERT (nm_setting_ip4_config_get_dns (s_ip4, 1) == addr.s_addr,
-	        "wired-static-verify-ip4", "failed to verify %s: unexpected %s / %s key value #2",
-	        file,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP4_CONFIG_DNS);
-
-	ASSERT (nm_setting_ip4_config_get_num_addresses (s_ip4) == 1,
-	        "wired-static-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        file,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP4_CONFIG_DNS);
+	g_assert_cmpint (nm_setting_ip4_config_get_num_dns (s_ip4), ==, 2);
+	g_assert_cmpint (inet_pton (AF_INET, expected_dns1, &addr), >, 0);
+	g_assert_cmpint (nm_setting_ip4_config_get_dns (s_ip4, 0), ==, addr);
+	g_assert_cmpint (inet_pton (AF_INET, expected_dns2, &addr), >, 0);
+	g_assert_cmpint (nm_setting_ip4_config_get_dns (s_ip4, 1), ==, addr);
 
-	/* Address #1 */
+	/* IP addresses */
+	g_assert_cmpint (nm_setting_ip4_config_get_num_addresses (s_ip4), ==, 1);
 	ip4_addr = nm_setting_ip4_config_get_address (s_ip4, 0);
-	ASSERT (ip4_addr,
-	        "wired-static-verify-ip4", "failed to verify %s: missing IP4 address #1",
-	        file,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP4_CONFIG_ADDRESSES);
+	g_assert (ip4_addr);
+	g_assert_cmpint (nm_ip4_address_get_prefix (ip4_addr), ==, 24);
+	g_assert_cmpint (inet_pton (AF_INET, expected_address1, &addr), >, 0);
+	g_assert_cmpint (nm_ip4_address_get_address (ip4_addr), ==, addr);
+	g_assert_cmpint (inet_pton (AF_INET, expected_address1_gw, &addr), >, 0);
+	g_assert_cmpint (nm_ip4_address_get_gateway (ip4_addr), ==, addr);
 
-	ASSERT (nm_ip4_address_get_prefix (ip4_addr) == 24,
-	        "wired-static-verify-ip4", "failed to verify %s: unexpected IP4 address #1 prefix",
-	        file,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP4_CONFIG_ADDRESSES);
-
-	ASSERT (inet_pton (AF_INET, expected_address1, &addr) > 0,
-	        "wired-static-verify-ip4", "failed to verify %s: couldn't convert IP address #1",
-	        file,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP4_CONFIG_DNS);
-	ASSERT (nm_ip4_address_get_address (ip4_addr) == addr.s_addr,
-	        "wired-static-verify-ip4", "failed to verify %s: unexpected IP4 address #1",
-	        file,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP4_CONFIG_ADDRESSES);
+	/* ===== IPv6 SETTING ===== */
+	s_ip6 = nm_connection_get_setting_ip6_config (connection);
+	g_assert (s_ip6);
+	if (expect_ip6) {
+		g_assert_cmpstr (nm_setting_ip6_config_get_method (s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_MANUAL);
+		g_assert (nm_setting_ip6_config_get_may_fail (s_ip6));
 
-	ASSERT (inet_pton (AF_INET, expected_address1_gw, &addr) > 0,
-	        "wired-static-verify-ip4", "failed to verify %s: couldn't convert IP address #1 gateway",
-	        file,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP4_CONFIG_ADDRESSES);
-	ASSERT (nm_ip4_address_get_gateway (ip4_addr) == addr.s_addr,
-	        "wired-static-verify-ip4", "failed to verify %s: unexpected IP4 address #1 gateway",
-	        file,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP4_CONFIG_ADDRESSES);
+		/* DNS Addresses */
+		g_assert_cmpint (nm_setting_ip6_config_get_num_dns (s_ip6), ==, 2);
+		g_assert_cmpint (inet_pton (AF_INET6, expected6_dns1, &addr6), >, 0);
+		g_assert (IN6_ARE_ADDR_EQUAL (nm_setting_ip6_config_get_dns (s_ip6, 0), &addr6));
+		g_assert_cmpint (inet_pton (AF_INET6, expected6_dns2, &addr6), >, 0);
+		g_assert (IN6_ARE_ADDR_EQUAL (nm_setting_ip6_config_get_dns (s_ip6, 1), &addr6));
 
-	if (!strcmp (expected_id, "System test-wired-static")) {
-		/* ===== IPv6 SETTING ===== */
-
-		s_ip6 = nm_connection_get_setting_ip6_config (connection);
-		ASSERT (s_ip6 != NULL,
-			"wired-static-verify-ip6", "failed to verify %s: missing %s setting",
-			file,
-			NM_SETTING_IP6_CONFIG_SETTING_NAME);
-
-		/* Method */
-		tmp = nm_setting_ip6_config_get_method (s_ip6);
-		ASSERT (strcmp (tmp, NM_SETTING_IP6_CONFIG_METHOD_MANUAL) == 0,
-			"wired-static-verify-ip6", "failed to verify %s: unexpected %s / %s key value",
-			file,
-			NM_SETTING_IP6_CONFIG_SETTING_NAME,
-			NM_SETTING_IP6_CONFIG_METHOD);
-
-		/* Implicit may-fail */
-		ASSERT (nm_setting_ip6_config_get_may_fail (s_ip6) == TRUE,
-		        "wired-static-verify-ip6", "failed to verify %s: unexpected %s / %s key value",
-		        file,
-		        NM_SETTING_IP6_CONFIG_SETTING_NAME,
-		        NM_SETTING_IP6_CONFIG_MAY_FAIL);
+		/* IP addresses */
+		g_assert_cmpint (nm_setting_ip6_config_get_num_addresses (s_ip6), ==, 2);
 
-		/* DNS Addresses */
-		ASSERT (nm_setting_ip6_config_get_num_dns (s_ip6) == 2,
-			"wired-static-verify-ip6", "failed to verify %s: unexpected %s / %s key value",
-			file,
-			NM_SETTING_IP6_CONFIG_SETTING_NAME,
-			NM_SETTING_IP6_CONFIG_DNS);
-
-		ASSERT (inet_pton (AF_INET6, expected6_dns1, &addr6) > 0,
-			"wired-static-verify-ip6", "failed to verify %s: couldn't convert DNS IP address #1",
-			file);
-		ASSERT (IN6_ARE_ADDR_EQUAL (nm_setting_ip6_config_get_dns (s_ip6, 0), &addr6),
-			"wired-static-verify-ip6", "failed to verify %s: unexpected %s / %s key value #1",
-			file,
-			NM_SETTING_IP6_CONFIG_SETTING_NAME,
-			NM_SETTING_IP6_CONFIG_DNS);
-
-		ASSERT (inet_pton (AF_INET6, expected6_dns2, &addr6) > 0,
-			"wired-static-verify-ip6", "failed to verify %s: couldn't convert DNS IP address #2",
-			file);
-		ASSERT (IN6_ARE_ADDR_EQUAL (nm_setting_ip6_config_get_dns (s_ip6, 1), &addr6),
-			"wired-static-verify-ip6", "failed to verify %s: unexpected %s / %s key value #2",
-			file,
-			NM_SETTING_IP6_CONFIG_SETTING_NAME,
-			NM_SETTING_IP6_CONFIG_DNS);
-
-		ASSERT (nm_setting_ip6_config_get_num_addresses (s_ip6) == 2,
-			"wired-static-verify-ip6", "failed to verify %s: unexpected %s / %s key value",
-			file,
-			NM_SETTING_IP6_CONFIG_SETTING_NAME,
-			NM_SETTING_IP6_CONFIG_ADDRESSES);
-
-		/* Address #1 */
 		ip6_addr = nm_setting_ip6_config_get_address (s_ip6, 0);
-		ASSERT (ip6_addr,
-			"wired-static-verify-ip6", "failed to verify %s: missing IP6 address #1",
-			file);
-
-		ASSERT (nm_ip6_address_get_prefix (ip6_addr) == 64,
-			"wired-static-verify-ip6", "failed to verify %s: unexpected IP6 address #1 prefix",
-			file);
-
-		ASSERT (inet_pton (AF_INET6, expected6_address1, &addr6) > 0,
-			"wired-static-verify-ip6", "failed to verify %s: couldn't convert IP address #1",
-			file);
-		ASSERT (IN6_ARE_ADDR_EQUAL (nm_ip6_address_get_address (ip6_addr), &addr6),
-			"wired-static-verify-ip6", "failed to verify %s: unexpected IP6 address #1",
-			file);
-
-		/* Address #2 */
+		g_assert (ip6_addr);
+		g_assert_cmpint (nm_ip6_address_get_prefix (ip6_addr), ==, 64);
+		g_assert_cmpint (inet_pton (AF_INET6, expected6_address1, &addr6), >, 0);
+		g_assert (IN6_ARE_ADDR_EQUAL (nm_ip6_address_get_address (ip6_addr), &addr6));
+
 		ip6_addr = nm_setting_ip6_config_get_address (s_ip6, 1);
-		ASSERT (ip6_addr,
-			"wired-static-verify-ip6", "failed to verify %s: missing IP6 address #2",
-			file);
-
-		ASSERT (nm_ip6_address_get_prefix (ip6_addr) == 56,
-			"wired-static-verify-ip6", "failed to verify %s: unexpected IP6 address #2 prefix",
-			file);
-
-		ASSERT (inet_pton (AF_INET6, expected6_address2, &addr6) > 0,
-			"wired-static-verify-ip6", "failed to verify %s: couldn't convert IP address #2",
-			file);
-		ASSERT (IN6_ARE_ADDR_EQUAL (nm_ip6_address_get_address (ip6_addr), &addr6),
-			"wired-static-verify-ip6", "failed to verify %s: unexpected IP6 address #2",
-			file);
+		g_assert (ip6_addr);
+		g_assert_cmpint (nm_ip6_address_get_prefix (ip6_addr), ==, 56);
+		g_assert_cmpint (inet_pton (AF_INET6, expected6_address2, &addr6), >, 0);
+		g_assert (IN6_ARE_ADDR_EQUAL (nm_ip6_address_get_address (ip6_addr), &addr6));
+	} else {
+		g_assert_cmpstr (nm_setting_ip6_config_get_method (s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_IGNORE);
 	}
 
 	g_free (unmanaged);
-	g_free (keyfile);
-	g_free (routefile);
-	g_free (route6file);
 	g_object_unref (connection);
 }
 
-#define TEST_IFCFG_STATIC_NO_PREFIX TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-static-no-prefix"
-
 static void
-test_read_wired_static_no_prefix (guint32 expected_prefix)
+test_read_wired_static_no_prefix (gconstpointer user_data)
 {
+	guint32 expected_prefix = GPOINTER_TO_UINT (user_data);
 	NMConnection *connection;
 	NMSettingConnection *s_con;
 	NMSettingIP4Config *s_ip4;
-	char *unmanaged = NULL;
-	char *keyfile = NULL;
-	char *routefile = NULL;
-	char *route6file = NULL;
-	gboolean ignore_error = FALSE;
 	GError *error = NULL;
 	NMIP4Address *ip4_addr;
 	char *file, *expected_id;
-	const char *tmp;
-
-	file = g_strdup_printf (TEST_IFCFG_STATIC_NO_PREFIX "-%u", expected_prefix);
-	ASSERT (file != NULL,
-	        "wired-static-no-prefix-read", "failed to create path to file");
 
+	file = g_strdup_printf (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-wired-static-no-prefix-%u", expected_prefix);
 	expected_id = g_strdup_printf ("System test-wired-static-no-prefix-%u", expected_prefix);
-	ASSERT (expected_id != NULL,
-	        "wired-static-no-prefix-read", "failed to expected connection ID");
 
-	connection = connection_from_file (file,
-	                                   NULL,
-	                                   TYPE_ETHERNET,
-	                                   NULL,
-	                                   &unmanaged,
-	                                   &keyfile,
-	                                   &routefile,
-	                                   &route6file,
-	                                   &error,
-	                                   &ignore_error);
-	ASSERT (connection != NULL,
-	        "wired-static-no-prefix-read", "failed to read %s: %s", file, error->message);
-
-	ASSERT (nm_connection_verify (connection, &error),
-	        "wired-static-no-prefix-verify", "failed to verify %s: %s", file, error->message);
-
-	ASSERT (unmanaged == NULL,
-	        "wired-static-no-prefix-verify", "failed to verify %s: unexpected unmanaged value", file);
+	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
+	                       "*missing PREFIX, assuming*");
+	connection = connection_from_file (file, NULL, TYPE_ETHERNET, NULL, NULL,
+	                                   NULL, NULL, NULL, &error, NULL);
+	g_test_assert_expected_messages ();
+	g_assert_no_error (error);
+	g_assert (connection);
+	g_assert (nm_connection_verify (connection, &error));
 
 	/* ===== CONNECTION SETTING ===== */
-
 	s_con = nm_connection_get_setting_connection (connection);
-	ASSERT (s_con != NULL,
-	        "wired-static-no-prefix-verify-connection", "failed to verify %s: missing %s setting",
-	        file,
-	        NM_SETTING_CONNECTION_SETTING_NAME);
-
-	/* ID */
-	tmp = nm_setting_connection_get_id (s_con);
-	ASSERT (tmp != NULL,
-	        "wired-static-no-prefix-verify-connection", "failed to verify %s: missing %s / %s key",
-	        file,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-	ASSERT (strcmp (tmp, expected_id) == 0,
-	        "wired-static-no-prefix-verify-connection", "failed to verify %s: unexpected %s / %s key value",
-	        file,
-	        NM_SETTING_CONNECTION_SETTING_NAME,
-	        NM_SETTING_CONNECTION_ID);
-	g_free (expected_id);
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, expected_id);
 
 	/* ===== IPv4 SETTING ===== */
-
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
-	ASSERT (s_ip4 != NULL,
-	        "wired-static-no-prefix-verify-ip4", "failed to verify %s: missing %s setting",
-	        file,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME);
-
-	/* Method */
-	tmp = nm_setting_ip4_config_get_method (s_ip4);
-	ASSERT (strcmp (tmp, NM_SETTING_IP4_CONFIG_METHOD_MANUAL) == 0,
-	        "wired-static-no-prefix-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        file,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP4_CONFIG_METHOD);
-
-	ASSERT (nm_setting_ip4_config_get_num_addresses (s_ip4) == 1,
-	        "wired-static-no-prefix-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
-	        file,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP4_CONFIG_DNS);
+	g_assert (s_ip4);
+	g_assert_cmpstr (nm_setting_ip4_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_MANUAL);
 
-	/* Address #1 */
+	g_assert_cmpint (nm_setting_ip4_config_get_num_addresses (s_ip4), ==, 1);
 	ip4_addr = nm_setting_ip4_config_get_address (s_ip4, 0);
-	ASSERT (ip4_addr,
-	        "wired-static-no-prefix-verify-ip4", "failed to verify %s: missing IP4 address #1",
-	        file,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP4_CONFIG_ADDRESSES);
-
-	ASSERT (nm_ip4_address_get_prefix (ip4_addr) == expected_prefix,
-	        "wired-static-no-prefix-verify-ip4", "failed to verify %s: unexpected IP4 address #1 prefix",
-	        file,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP4_CONFIG_ADDRESSES);
+	g_assert (ip4_addr);
+	g_assert_cmpint (nm_ip4_address_get_prefix (ip4_addr), ==, expected_prefix);
 
 	g_free (file);
-	g_free (unmanaged);
-	g_free (keyfile);
-	g_free (routefile);
-	g_free (route6file);
+	g_free (expected_id);
 	g_object_unref (connection);
 }
 
@@ -1039,7 +564,7 @@ test_read_wired_dhcp (void)
 	const char *expected_id = "System test-wired-dhcp";
 	const char *expected_dns1 = "4.2.2.1";
 	const char *expected_dns2 = "4.2.2.2";
-	struct in_addr addr;
+	guint32 addr;
 	const char *expected_dhcp_hostname = "foobar";
 
 	connection = connection_from_file (TEST_IFCFG_WIRED_DHCP,
@@ -1168,7 +693,7 @@ test_read_wired_dhcp (void)
 	        TEST_IFCFG_WIRED_DHCP,
 	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
 	        NM_SETTING_IP4_CONFIG_DNS);
-	ASSERT (nm_setting_ip4_config_get_dns (s_ip4, 0) == addr.s_addr,
+	ASSERT (nm_setting_ip4_config_get_dns (s_ip4, 0) == addr,
 	        "wired-dhcp-verify-ip4", "failed to verify %s: unexpected %s / %s key value #1",
 	        TEST_IFCFG_WIRED_DHCP,
 	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
@@ -1179,7 +704,7 @@ test_read_wired_dhcp (void)
 	        TEST_IFCFG_WIRED_DHCP,
 	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
 	        NM_SETTING_IP4_CONFIG_DNS);
-	ASSERT (nm_setting_ip4_config_get_dns (s_ip4, 1) == addr.s_addr,
+	ASSERT (nm_setting_ip4_config_get_dns (s_ip4, 1) == addr,
 	        "wired-dhcp-verify-ip4", "failed to verify %s: unexpected %s / %s key value #2",
 	        TEST_IFCFG_WIRED_DHCP,
 	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
@@ -1192,6 +717,93 @@ test_read_wired_dhcp (void)
 	g_object_unref (connection);
 }
 
+static void
+test_read_wired_dhcp_plus_ip (void)
+{
+	NMConnection *connection;
+	NMSettingIP4Config *s_ip4;
+	NMSettingIP6Config *s_ip6;
+	GError *error = NULL;
+	guint32 addr4;
+	struct in6_addr addr6;
+	NMIP4Address *ip4_addr;
+	NMIP6Address *ip6_addr;
+	gboolean success;
+
+	connection = connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-dhcp-plus-ip",
+	                                   NULL, TYPE_ETHERNET, NULL, NULL,
+	                                   NULL, NULL, NULL, &error, NULL);
+	g_assert_no_error (error);
+	g_assert (connection);
+	success = nm_connection_verify (connection, &error);
+	g_assert_no_error (error);
+	g_assert (success);
+
+	/* ===== IPv4 SETTING ===== */
+	s_ip4 = nm_connection_get_setting_ip4_config (connection);
+	g_assert (s_ip4);
+	g_assert_cmpstr (nm_setting_ip4_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO);
+	g_assert (nm_setting_ip4_config_get_may_fail (s_ip4));
+
+	/* DNS Addresses */
+	g_assert_cmpint (nm_setting_ip4_config_get_num_dns (s_ip4), ==, 2);
+	g_assert_cmpint (inet_pton (AF_INET, "4.2.2.1", &addr4), >, 0);
+	g_assert_cmpint (nm_setting_ip4_config_get_dns (s_ip4, 0), ==, addr4);
+	g_assert_cmpint (inet_pton (AF_INET, "4.2.2.2", &addr4), >, 0);
+	g_assert_cmpint (nm_setting_ip4_config_get_dns (s_ip4, 1), ==, addr4);
+
+	/* IP addresses */
+	g_assert_cmpint (nm_setting_ip4_config_get_num_addresses (s_ip4), ==, 2);
+	ip4_addr = nm_setting_ip4_config_get_address (s_ip4, 0);
+	g_assert (ip4_addr);
+	g_assert_cmpint (nm_ip4_address_get_prefix (ip4_addr), ==, 24);
+	g_assert_cmpint (inet_pton (AF_INET, "1.2.3.4", &addr4), >, 0);
+	g_assert_cmpint (nm_ip4_address_get_address (ip4_addr), ==, addr4);
+	g_assert_cmpint (inet_pton (AF_INET, "1.1.1.1", &addr4), >, 0);
+	g_assert_cmpint (nm_ip4_address_get_gateway (ip4_addr), ==, addr4);
+
+	ip4_addr = nm_setting_ip4_config_get_address (s_ip4, 1);
+	g_assert (ip4_addr);
+	g_assert_cmpint (nm_ip4_address_get_prefix (ip4_addr), ==, 16);
+	g_assert_cmpint (inet_pton (AF_INET, "9.8.7.6", &addr4), >, 0);
+	g_assert_cmpint (nm_ip4_address_get_address (ip4_addr), ==, addr4);
+
+	/* ===== IPv6 SETTING ===== */
+	s_ip6 = nm_connection_get_setting_ip6_config (connection);
+	g_assert (s_ip6);
+	g_assert_cmpstr (nm_setting_ip6_config_get_method (s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_AUTO);
+	g_assert (nm_setting_ip6_config_get_may_fail (s_ip6));
+
+	/* DNS Addresses */
+	g_assert_cmpint (nm_setting_ip6_config_get_num_dns (s_ip6), ==, 2);
+	g_assert_cmpint (inet_pton (AF_INET6, "1:2:3:4::a", &addr6), >, 0);
+	g_assert (IN6_ARE_ADDR_EQUAL (nm_setting_ip6_config_get_dns (s_ip6, 0), &addr6));
+	g_assert_cmpint (inet_pton (AF_INET6, "1:2:3:4::b", &addr6), >, 0);
+	g_assert (IN6_ARE_ADDR_EQUAL (nm_setting_ip6_config_get_dns (s_ip6, 1), &addr6));
+
+	/* IP addresses */
+	g_assert_cmpint (nm_setting_ip6_config_get_num_addresses (s_ip6), ==, 3);
+	ip6_addr = nm_setting_ip6_config_get_address (s_ip6, 0);
+	g_assert (ip6_addr);
+	g_assert_cmpint (nm_ip6_address_get_prefix (ip6_addr), ==, 56);
+	g_assert_cmpint (inet_pton (AF_INET6, "1001:abba::1234", &addr6), >, 0);
+	g_assert (IN6_ARE_ADDR_EQUAL (nm_ip6_address_get_address (ip6_addr), &addr6));
+
+	ip6_addr = nm_setting_ip6_config_get_address (s_ip6, 1);
+	g_assert (ip6_addr);
+	g_assert_cmpint (nm_ip6_address_get_prefix (ip6_addr), ==, 64);
+	g_assert_cmpint (inet_pton (AF_INET6, "2001:abba::2234", &addr6), >, 0);
+	g_assert (IN6_ARE_ADDR_EQUAL (nm_ip6_address_get_address (ip6_addr), &addr6));
+
+	ip6_addr = nm_setting_ip6_config_get_address (s_ip6, 2);
+	g_assert (ip6_addr);
+	g_assert_cmpint (nm_ip6_address_get_prefix (ip6_addr), ==, 96);
+	g_assert_cmpint (inet_pton (AF_INET6, "3001:abba::3234", &addr6), >, 0);
+	g_assert (IN6_ARE_ADDR_EQUAL (nm_ip6_address_get_address (ip6_addr), &addr6));
+
+	g_object_unref (connection);
+}
+
 #define TEST_IFCFG_WIRED_GLOBAL_GATEWAY TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-global-gateway"
 #define TEST_NETWORK_WIRED_GLOBAL_GATEWAY TEST_IFCFG_DIR"/network-scripts/network-test-wired-global-gateway"
 
@@ -1210,7 +822,7 @@ test_read_wired_global_gateway (void)
 	GError *error = NULL;
 	const char *tmp;
 	const char *expected_id = "System test-wired-global-gateway";
-	struct in_addr addr;
+	guint32 addr;
 	const char *expected_address1 = "192.168.1.5";
 	const char *expected_address1_gw = "192.168.1.2";
 	NMIP4Address *ip4_addr;
@@ -1298,7 +910,7 @@ test_read_wired_global_gateway (void)
 	        TEST_IFCFG_WIRED_GLOBAL_GATEWAY,
 	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
 	        NM_SETTING_IP4_CONFIG_DNS);
-	ASSERT (nm_ip4_address_get_address (ip4_addr) == addr.s_addr,
+	ASSERT (nm_ip4_address_get_address (ip4_addr) == addr,
 	        "wired-global-gateway-verify-ip4", "failed to verify %s: unexpected IP4 address #1",
 	        TEST_IFCFG_WIRED_GLOBAL_GATEWAY,
 	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
@@ -1309,7 +921,7 @@ test_read_wired_global_gateway (void)
 	        TEST_IFCFG_WIRED_GLOBAL_GATEWAY,
 	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
 	        NM_SETTING_IP4_CONFIG_ADDRESSES);
-	ASSERT (nm_ip4_address_get_gateway (ip4_addr) == addr.s_addr,
+	ASSERT (nm_ip4_address_get_gateway (ip4_addr) == addr,
 	        "wired-global-gateway-verify-ip4", "failed to verify %s: unexpected IP4 address #1 gateway",
 	        TEST_IFCFG_WIRED_GLOBAL_GATEWAY,
 	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
@@ -1710,7 +1322,7 @@ test_read_wired_static_routes (void)
 	GError *error = NULL;
 	const char *tmp;
 	NMIP4Route *ip4_route;
-	struct in_addr addr;
+	guint32 addr;
 	const char *expected_id = "System test-wired-static-routes";
 	const char *expected_dst1 = "11.22.33.0";
 	const char *expected_dst2 = "44.55.66.77";
@@ -1802,7 +1414,7 @@ test_read_wired_static_routes (void)
 	ASSERT (inet_pton (AF_INET, expected_dst1, &addr) > 0,
 	        "wired-static-routes-verify-ip4", "failed to verify %s: couldn't convert destination IP address #1",
 	        TEST_IFCFG_WIRED_STATIC_ROUTES);
-	ASSERT (nm_ip4_route_get_dest (ip4_route) == addr.s_addr,
+	ASSERT (nm_ip4_route_get_dest (ip4_route) == addr,
 	        "wired-static-routes-verify-ip4", "failed to verify %s: unexpected %s / %s key value #1",
 	        TEST_IFCFG_WIRED_STATIC_ROUTES,
 	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
@@ -1815,7 +1427,7 @@ test_read_wired_static_routes (void)
 	ASSERT (inet_pton (AF_INET, expected_gw1, &addr) > 0,
 	        "wired-static-routes-verify-ip4", "failed to verify %s: couldn't convert next hop IP address #1",
 	        TEST_IFCFG_WIRED_STATIC_ROUTES);
-	ASSERT (nm_ip4_route_get_next_hop (ip4_route) == addr.s_addr,
+	ASSERT (nm_ip4_route_get_next_hop (ip4_route) == addr,
 	        "wired-static-routes-verify-ip4", "failed to verify %s: unexpected %s / %s key value #1",
 	        TEST_IFCFG_WIRED_STATIC_ROUTES,
 	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
@@ -1829,7 +1441,7 @@ test_read_wired_static_routes (void)
 	ASSERT (inet_pton (AF_INET, expected_dst2, &addr) > 0,
 	        "wired-static-routes-verify-ip4", "failed to verify %s: couldn't convert destination IP address #2",
 	        TEST_IFCFG_WIRED_STATIC_ROUTES);
-	ASSERT (nm_ip4_route_get_dest (ip4_route) == addr.s_addr,
+	ASSERT (nm_ip4_route_get_dest (ip4_route) == addr,
 	        "wired-static-routes-verify-ip4", "failed to verify %s: unexpected %s / %s key value #2",
 	        TEST_IFCFG_WIRED_STATIC_ROUTES,
 	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
@@ -1842,7 +1454,7 @@ test_read_wired_static_routes (void)
 	ASSERT (inet_pton (AF_INET, expected_gw2, &addr) > 0,
 	        "wired-static-routes-verify-ip4", "failed to verify %s: couldn't convert next hop IP address #2",
 	        TEST_IFCFG_WIRED_STATIC_ROUTES);
-	ASSERT (nm_ip4_route_get_next_hop (ip4_route) == addr.s_addr,
+	ASSERT (nm_ip4_route_get_next_hop (ip4_route) == addr,
 	        "wired-static-routes-verify-ip4", "failed to verify %s: unexpected %s / %s key value #2",
 	        TEST_IFCFG_WIRED_STATIC_ROUTES,
 	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
@@ -1875,7 +1487,7 @@ test_read_wired_static_routes_legacy (void)
 	GError *error = NULL;
 	const char *tmp;
 	NMIP4Route *ip4_route;
-	struct in_addr addr;
+	guint32 addr;
 	const char *expected_id = "System test-wired-static-routes-legacy";
 	const char *expected_dst1 = "21.31.41.0";
 	const char *expected_dst2 = "32.42.52.62";
@@ -1970,7 +1582,7 @@ test_read_wired_static_routes_legacy (void)
 	ASSERT (inet_pton (AF_INET, expected_dst1, &addr) > 0,
 	        "wired-static-routes-legacy-verify-ip4", "failed to verify %s: couldn't convert destination IP address #1",
 	        TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY);
-	ASSERT (nm_ip4_route_get_dest (ip4_route) == addr.s_addr,
+	ASSERT (nm_ip4_route_get_dest (ip4_route) == addr,
 	        "wired-static-routes-legacy-verify-ip4", "failed to verify %s: unexpected %s / %s key value #1",
 	        TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY,
 	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
@@ -1983,7 +1595,7 @@ test_read_wired_static_routes_legacy (void)
 	ASSERT (inet_pton (AF_INET, expected_gw1, &addr) > 0,
 	        "wired-static-routes-legacy-verify-ip4", "failed to verify %s: couldn't convert next hop IP address #1",
 	        TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY);
-	ASSERT (nm_ip4_route_get_next_hop (ip4_route) == addr.s_addr,
+	ASSERT (nm_ip4_route_get_next_hop (ip4_route) == addr,
 	        "wired-static-routes-legacy-verify-ip4", "failed to verify %s: unexpected %s / %s key value #1",
 	        TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY,
 	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
@@ -2002,7 +1614,7 @@ test_read_wired_static_routes_legacy (void)
 	ASSERT (inet_pton (AF_INET, expected_dst2, &addr) > 0,
 	        "wired-static-routes-legacy-verify-ip4", "failed to verify %s: couldn't convert destination IP address #2",
 	        TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY);
-	ASSERT (nm_ip4_route_get_dest (ip4_route) == addr.s_addr,
+	ASSERT (nm_ip4_route_get_dest (ip4_route) == addr,
 	        "wired-static-routes-legacy-verify-ip4", "failed to verify %s: unexpected %s / %s key value #2",
 	        TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY,
 	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
@@ -2015,7 +1627,7 @@ test_read_wired_static_routes_legacy (void)
 	ASSERT (inet_pton (AF_INET, expected_gw2, &addr) > 0,
 	        "wired-static-routes-legacy-verify-ip4", "failed to verify %s: couldn't convert next hop IP address #2",
 	        TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY);
-	ASSERT (nm_ip4_route_get_next_hop (ip4_route) == addr.s_addr,
+	ASSERT (nm_ip4_route_get_next_hop (ip4_route) == addr,
 	        "wired-static-routes-legacy-verify-ip4", "failed to verify %s: unexpected %s / %s key value #2",
 	        TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY,
 	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
@@ -2034,7 +1646,7 @@ test_read_wired_static_routes_legacy (void)
 	ASSERT (inet_pton (AF_INET, expected_dst3, &addr) > 0,
 	        "wired-static-routes-legacy-verify-ip4", "failed to verify %s: couldn't convert destination IP address #3",
 	        TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY);
-	ASSERT (nm_ip4_route_get_dest (ip4_route) == addr.s_addr,
+	ASSERT (nm_ip4_route_get_dest (ip4_route) == addr,
 	        "wired-static-routes-legacy-verify-ip4", "failed to verify %s: unexpected %s / %s key value #3",
 	        TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY,
 	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
@@ -2047,7 +1659,7 @@ test_read_wired_static_routes_legacy (void)
 	ASSERT (inet_pton (AF_INET, expected_gw3, &addr) > 0,
 	        "wired-static-routes-legacy-verify-ip4", "failed to verify %s: couldn't convert next hop IP address #3",
 	        TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY);
-	ASSERT (nm_ip4_route_get_next_hop (ip4_route) == addr.s_addr,
+	ASSERT (nm_ip4_route_get_next_hop (ip4_route) == addr,
 	        "wired-static-routes-legacy-verify-ip4", "failed to verify %s: unexpected %s / %s key value #3",
 	        TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY,
 	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
@@ -2085,7 +1697,7 @@ test_read_wired_ipv4_manual (const char *file, const char *expected_id)
 	guint32 expected_prefix2 = 16;
 	guint32 expected_prefix3 = 8;
 	NMIP4Address *ip4_addr;
-	struct in_addr addr;
+	guint32 addr;
 
 	connection = connection_from_file (file,
 	                                   NULL,
@@ -2171,7 +1783,7 @@ test_read_wired_ipv4_manual (const char *file, const char *expected_id)
 	ASSERT (inet_pton (AF_INET, expected_address1, &addr) > 0,
 		"wired-ipv4-manual-verify-ip4", "failed to verify %s: couldn't convert IP address #1",
 		file);
-	ASSERT (nm_ip4_address_get_address (ip4_addr) == addr.s_addr,
+	ASSERT (nm_ip4_address_get_address (ip4_addr) == addr,
 		"wired-ipv4-manual-verify-ip4", "failed to verify %s: unexpected IP4 address #1",
 		file);
 
@@ -2188,7 +1800,7 @@ test_read_wired_ipv4_manual (const char *file, const char *expected_id)
 	ASSERT (inet_pton (AF_INET, expected_address2, &addr) > 0,
 		"wired-ipv4-manual-verify-ip4", "failed to verify %s: couldn't convert IP address #2",
 		file);
-	ASSERT (nm_ip4_address_get_address (ip4_addr) == addr.s_addr,
+	ASSERT (nm_ip4_address_get_address (ip4_addr) == addr,
 		"wired-ipv4-manual-verify-ip4", "failed to verify %s: unexpected IP4 address #2",
 		file);
 
@@ -2205,7 +1817,7 @@ test_read_wired_ipv4_manual (const char *file, const char *expected_id)
 	ASSERT (inet_pton (AF_INET, expected_address3, &addr) > 0,
 		"wired-ipv4-manual-verify-ip4", "failed to verify %s: couldn't convert IP address #3",
 		file);
-	ASSERT (nm_ip4_address_get_address (ip4_addr) == addr.s_addr,
+	ASSERT (nm_ip4_address_get_address (ip4_addr) == addr,
 		"wired-ipv4-manual-verify-ip4", "failed to verify %s: unexpected IP4 address #3",
 		file);
 
@@ -2240,16 +1852,14 @@ test_read_wired_ipv6_manual (void)
 	guint32 expected_prefix1 = 56;
 	guint32 expected_prefix2 = 64;
 	guint32 expected_prefix3 = 96;
-	const char *expected_route1_dest = "9876::1234";
-	guint32 expected_route1_prefix = 96;
-	const char *expected_route1_nexthop = "9876::7777";
-	guint32 expected_route1_metric = 2;
 	const char *expected_dns1 = "1:2:3:4::a";
 	const char *expected_dns2 = "1:2:3:4::b";
 	NMIP6Address *ip6_addr;
 	NMIP6Route *ip6_route;
 	struct in6_addr addr;
 
+	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
+	                       "*ignoring manual default route*");
 	connection = connection_from_file (TEST_IFCFG_WIRED_IPV6_MANUAL,
 	                                   NULL,
 	                                   TYPE_ETHERNET,
@@ -2260,6 +1870,8 @@ test_read_wired_ipv6_manual (void)
 	                                   &route6file,
 	                                   &error,
 	                                   &ignore_error);
+	g_test_assert_expected_messages ();
+
 	ASSERT (connection != NULL,
 	        "wired-ipv6-manual-read", "failed to read %s: %s", TEST_IFCFG_WIRED_IPV6_MANUAL, error->message);
 
@@ -2443,39 +2055,25 @@ test_read_wired_ipv6_manual (void)
 		TEST_IFCFG_WIRED_IPV6_MANUAL);
 
 	/* Routes */
-	ASSERT (nm_setting_ip6_config_get_num_routes (s_ip6) == 1,
-		"wired-ipv6-manual-verify-ip6", "failed to verify %s: unexpected %s / %s key value",
-		TEST_IFCFG_WIRED_IPV6_MANUAL,
-		NM_SETTING_IP6_CONFIG_SETTING_NAME,
-		NM_SETTING_IP6_CONFIG_ROUTES);
-
+	g_assert_cmpint (nm_setting_ip6_config_get_num_routes (s_ip6), ==, 2);
 	/* Route #1 */
 	ip6_route = nm_setting_ip6_config_get_route (s_ip6, 0);
-	ASSERT (ip6_route,
-		"wired-ipv6-manual-verify-ip6", "failed to verify %s: missing IP6 route #1",
-		TEST_IFCFG_WIRED_IPV6_MANUAL);
-
-	ASSERT (inet_pton (AF_INET6, expected_route1_dest, &addr) > 0,
-		"wired-ipv6-manual-verify-ip6", "failed to verify %s: couldn't convert IP route dest #1",
-		TEST_IFCFG_WIRED_IPV6_MANUAL);
-	ASSERT (IN6_ARE_ADDR_EQUAL (nm_ip6_route_get_dest (ip6_route), &addr),
-		"wired-ipv6-manual-verify-ip6", "failed to verify %s: unexpected IP6 route dest #1",
-		TEST_IFCFG_WIRED_IPV6_MANUAL);
-
-	ASSERT (nm_ip6_route_get_prefix (ip6_route) == expected_route1_prefix,
-		"wired-ipv6-manual-verify-ip6", "failed to verify %s: unexpected IP6 route #1 prefix",
-		TEST_IFCFG_WIRED_IPV6_MANUAL);
-
-	ASSERT (inet_pton (AF_INET6, expected_route1_nexthop, &addr) > 0,
-		"wired-ipv6-manual-verify-ip6", "failed to verify %s: couldn't convert IP route next_hop #1",
-		TEST_IFCFG_WIRED_IPV6_MANUAL);
-	ASSERT (IN6_ARE_ADDR_EQUAL (nm_ip6_route_get_next_hop (ip6_route), &addr),
-		"wired-ipv6-manual-verify-ip6", "failed to verify %s: unexpected IP6 route next hop #1",
-		TEST_IFCFG_WIRED_IPV6_MANUAL);
-
-	ASSERT (nm_ip6_route_get_metric (ip6_route) == expected_route1_metric,
-		"wired-ipv6-manual-verify-ip6", "failed to verify %s: unexpected IP6 route #1 metric",
-		TEST_IFCFG_WIRED_IPV6_MANUAL);
+	g_assert (ip6_route);
+	g_assert_cmpint (inet_pton (AF_INET6, "9876::1234", &addr), >, 0);
+	g_assert_cmpint (memcmp (nm_ip6_route_get_dest (ip6_route), &addr, sizeof (struct in6_addr)), ==, 0);
+	g_assert_cmpint (nm_ip6_route_get_prefix (ip6_route), ==, 96);
+	g_assert_cmpint (inet_pton (AF_INET6, "9876::7777", &addr), >, 0);
+	g_assert_cmpint (memcmp (nm_ip6_route_get_next_hop (ip6_route), &addr, sizeof (struct in6_addr)), ==, 0);
+	g_assert_cmpint (nm_ip6_route_get_metric (ip6_route), ==, 2);
+	/* Route #2 */
+	ip6_route = nm_setting_ip6_config_get_route (s_ip6, 1);
+	g_assert (ip6_route);
+	g_assert_cmpint (inet_pton (AF_INET6, "abbe::cafe", &addr), >, 0);
+	g_assert_cmpint (memcmp (nm_ip6_route_get_dest (ip6_route), &addr, sizeof (struct in6_addr)), ==, 0);
+	g_assert_cmpint (nm_ip6_route_get_prefix (ip6_route), ==, 64);
+	g_assert_cmpint (inet_pton (AF_INET6, "::", &addr), >, 0);
+	g_assert_cmpint (memcmp (nm_ip6_route_get_next_hop (ip6_route), &addr, sizeof (struct in6_addr)), ==, 0);
+	g_assert_cmpint (nm_ip6_route_get_metric (ip6_route), ==, 777);
 
 	/* DNS Addresses */
 	ASSERT (nm_setting_ip6_config_get_num_dns (s_ip6) == 2,
@@ -2507,7 +2105,7 @@ test_read_wired_ipv6_manual (void)
 	        "wired-ipv6-manual-verify-ip6", "failed to verify %s: unexpected %s / %s key value",
 	        TEST_IFCFG_WIRED_IPV6_MANUAL,
 	        NM_SETTING_IP6_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP6_CONFIG_DNS);
+	        NM_SETTING_IP6_CONFIG_DNS_SEARCH);
 
 	g_free (unmanaged);
 	g_free (keyfile);
@@ -2660,12 +2258,11 @@ test_read_wired_ipv6_only (void)
 		NM_SETTING_IP6_CONFIG_SETTING_NAME,
 		NM_SETTING_IP6_CONFIG_DNS);
 
-	/* DNS domains - none as domains are stuffed to 'ipv4' setting */
-	ASSERT (nm_setting_ip6_config_get_num_dns_searches (s_ip6) == 0,
-	        "wired-ipv6-only-verify-ip6", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIRED_IPV6_MANUAL,
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP6_CONFIG_DNS);
+	/* DNS domains should be in IPv6, because IPv4 is disabled */
+	g_assert_cmpint (nm_setting_ip6_config_get_num_dns_searches (s_ip6), ==, 3);
+	g_assert_cmpstr (nm_setting_ip6_config_get_dns_search (s_ip6, 0), ==, "lorem.com");
+	g_assert_cmpstr (nm_setting_ip6_config_get_dns_search (s_ip6, 1), ==, "ipsum.org");
+	g_assert_cmpstr (nm_setting_ip6_config_get_dns_search (s_ip6, 2), ==, "dolor.edu");
 
 	g_free (unmanaged);
 	g_free (keyfile);
@@ -2835,6 +2432,52 @@ test_read_onboot_no (void)
 	g_object_unref (connection);
 }
 
+#define TEST_IFCFG_NOIP TEST_IFCFG_DIR"/network-scripts/ifcfg-test-noip"
+
+static void
+test_read_noip (void)
+{
+	NMConnection *connection;
+	NMSettingIP4Config *s_ip4;
+	NMSettingIP6Config *s_ip6;
+	char *unmanaged = NULL;
+	char *keyfile = NULL;
+	char *routefile = NULL;
+	char *route6file = NULL;
+	gboolean ignore_error = FALSE;
+	GError *error = NULL;
+
+	connection = connection_from_file (TEST_IFCFG_NOIP,
+	                                   NULL,
+	                                   TYPE_ETHERNET,
+	                                   NULL,
+	                                   &unmanaged,
+	                                   &keyfile,
+	                                   &routefile,
+	                                   &route6file,
+	                                   &error,
+	                                   &ignore_error);
+	g_assert (connection);
+	g_assert (nm_connection_verify (connection, &error));
+	g_assert_no_error (error);
+
+	s_ip4 = nm_connection_get_setting_ip4_config (connection);
+	g_assert (s_ip4);
+	g_assert_cmpstr (nm_setting_ip4_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_DISABLED);
+	g_assert (nm_setting_ip4_config_get_never_default (s_ip4) == FALSE);
+
+	s_ip6 = nm_connection_get_setting_ip6_config (connection);
+	g_assert (s_ip6);
+	g_assert_cmpstr (nm_setting_ip6_config_get_method (s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_IGNORE);
+	g_assert (nm_setting_ip6_config_get_never_default (s_ip6) == FALSE);
+
+	g_free (unmanaged);
+	g_free (keyfile);
+	g_free (routefile);
+	g_free (route6file);
+	g_object_unref (connection);
+}
+
 #define TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2 TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-8021x-peap-mschapv2"
 #define TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2_CA_CERT TEST_IFCFG_DIR"/network-scripts/test_ca_cert.pem"
 
@@ -2995,10 +2638,6 @@ test_read_wired_8021x_peap_mschapv2 (void)
 
 	/* CA Cert */
 	tmp_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
-	ASSERT (tmp_8021x != NULL,
-	        "wired-8021x-peap-mschapv2-verify-8021x", "failed to verify %s: could not create temp 802.1x setting",
-	        TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2,
-	        NM_SETTING_802_1X_SETTING_NAME);
 
 	success = nm_setting_802_1x_set_ca_cert (tmp_8021x,
 	                                         TEST_IFCFG_WIRED_8021x_PEAP_MSCHAPV2_CA_CERT,
@@ -3106,6 +2745,406 @@ test_read_wired_8021x_tls_secret_flags (const char *ifcfg, NMSettingSecretFlags
 	g_object_unref (connection);
 }
 
+static void
+test_read_write_802_1X_subj_matches (void)
+{
+	NMConnection *connection, *reread;
+	NMSetting8021x *s_8021x;
+	char *written = NULL;
+	GError *error = NULL;
+	gboolean success = FALSE;
+
+	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
+	                       "*missing IEEE_8021X_CA_CERT*peap*");
+	connection = connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-802-1X-subj-matches",
+	                                   NULL, TYPE_ETHERNET, NULL, NULL,
+	                                   NULL, NULL, NULL, &error, NULL);
+	g_test_assert_expected_messages ();
+	g_assert_no_error (error);
+	g_assert (connection != NULL);
+
+	/* ===== 802.1x SETTING ===== */
+	s_8021x = nm_connection_get_setting_802_1x (connection);
+	g_assert (s_8021x);
+	g_assert_cmpint (nm_setting_802_1x_get_num_eap_methods (s_8021x), ==, 1);
+	g_assert_cmpstr (nm_setting_802_1x_get_eap_method (s_8021x, 0), ==, "peap");
+	g_assert_cmpstr (nm_setting_802_1x_get_identity (s_8021x), ==, "Jara Cimrman");
+	g_assert_cmpstr (nm_setting_802_1x_get_subject_match (s_8021x), ==, "server1.yourdomain.tld");
+	g_assert_cmpstr (nm_setting_802_1x_get_phase2_subject_match (s_8021x), ==, "server2.yourdomain.tld");
+	g_assert_cmpint (nm_setting_802_1x_get_num_altsubject_matches (s_8021x), ==, 3);
+	g_assert_cmpstr (nm_setting_802_1x_get_altsubject_match (s_8021x, 0), ==, "a.yourdomain.tld");
+	g_assert_cmpstr (nm_setting_802_1x_get_altsubject_match (s_8021x, 1), ==, "b.yourdomain.tld");
+	g_assert_cmpstr (nm_setting_802_1x_get_altsubject_match (s_8021x, 2), ==, "c.yourdomain.tld");
+	g_assert_cmpint (nm_setting_802_1x_get_num_phase2_altsubject_matches (s_8021x), ==, 2);
+	g_assert_cmpstr (nm_setting_802_1x_get_phase2_altsubject_match (s_8021x, 0), ==, "x.yourdomain.tld");
+	g_assert_cmpstr (nm_setting_802_1x_get_phase2_altsubject_match (s_8021x, 1), ==, "y.yourdomain.tld");
+
+	success = writer_new_connection (connection,
+	                                 TEST_SCRATCH_DIR "/network-scripts/",
+	                                 &written,
+	                                 &error);
+	g_assert (success);
+
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_utils_normalize_connection (connection, TRUE);
+
+	/* re-read the connection for comparison */
+	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
+	                       "*missing IEEE_8021X_CA_CERT*peap*");
+	reread = connection_from_file (written, NULL, TYPE_ETHERNET, NULL, NULL,
+	                               NULL, NULL, NULL, &error, NULL);
+	g_test_assert_expected_messages ();
+	unlink (written);
+	g_free (written);
+
+	g_assert_no_error (error);
+	g_assert (reread != NULL);
+
+	success = nm_connection_verify (reread, &error);
+	g_assert_no_error (error);
+	g_assert (success);
+
+	success = nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT);
+	g_assert (success);
+
+	/* Check 802.1X stuff of the re-read connection. */
+	s_8021x = nm_connection_get_setting_802_1x (reread);
+	g_assert (s_8021x);
+	g_assert_cmpint (nm_setting_802_1x_get_num_eap_methods (s_8021x), ==, 1);
+	g_assert_cmpstr (nm_setting_802_1x_get_eap_method (s_8021x, 0), ==, "peap");
+	g_assert_cmpstr (nm_setting_802_1x_get_identity (s_8021x), ==, "Jara Cimrman");
+	g_assert_cmpstr (nm_setting_802_1x_get_subject_match (s_8021x), ==, "server1.yourdomain.tld");
+	g_assert_cmpstr (nm_setting_802_1x_get_phase2_subject_match (s_8021x), ==, "server2.yourdomain.tld");
+	g_assert_cmpint (nm_setting_802_1x_get_num_altsubject_matches (s_8021x), ==, 3);
+	g_assert_cmpstr (nm_setting_802_1x_get_altsubject_match (s_8021x, 0), ==, "a.yourdomain.tld");
+	g_assert_cmpstr (nm_setting_802_1x_get_altsubject_match (s_8021x, 1), ==, "b.yourdomain.tld");
+	g_assert_cmpstr (nm_setting_802_1x_get_altsubject_match (s_8021x, 2), ==, "c.yourdomain.tld");
+	g_assert_cmpint (nm_setting_802_1x_get_num_phase2_altsubject_matches (s_8021x), ==, 2);
+	g_assert_cmpstr (nm_setting_802_1x_get_phase2_altsubject_match (s_8021x, 0), ==, "x.yourdomain.tld");
+	g_assert_cmpstr (nm_setting_802_1x_get_phase2_altsubject_match (s_8021x, 1), ==, "y.yourdomain.tld");
+
+	g_object_unref (connection);
+	g_object_unref (reread);
+}
+
+static void
+test_read_802_1x_ttls_eapgtc (void)
+{
+	NMConnection *connection;
+	NMSetting8021x *s_8021x;
+	GError *error = NULL;
+	gboolean success;
+
+	/* Test that EAP-* inner methods are correctly read into the
+	 * NMSetting8021x::autheap property.
+	 */
+
+	connection = connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-802-1x-ttls-eapgtc",
+	                                   NULL, TYPE_WIRELESS, NULL, NULL, NULL, NULL, NULL, &error, NULL);
+	g_assert_no_error (error);
+	g_assert (connection);
+	success = nm_connection_verify (connection, &error);
+	g_assert_no_error (error);
+	g_assert (success);
+
+	/* ===== 802.1x SETTING ===== */
+	s_8021x = nm_connection_get_setting_802_1x (connection);
+	g_assert (s_8021x);
+
+	/* EAP methods */
+	g_assert_cmpint (nm_setting_802_1x_get_num_eap_methods (s_8021x), ==, 1);
+	g_assert_cmpstr (nm_setting_802_1x_get_eap_method (s_8021x, 0), ==, "ttls");
+
+	/* Auth methods */
+	g_assert_cmpstr (nm_setting_802_1x_get_phase2_auth (s_8021x), ==, NULL);
+	g_assert_cmpstr (nm_setting_802_1x_get_phase2_autheap (s_8021x), ==, "gtc");
+
+	g_object_unref (connection);
+}
+
+#define TEST_IFCFG_ALIASES_GOOD TEST_IFCFG_DIR"/network-scripts/ifcfg-aliasem0"
+
+static void
+test_read_wired_aliases_good (void)
+{
+	NMConnection *connection;
+	NMSettingConnection *s_con;
+	NMSettingIP4Config *s_ip4;
+	char *unmanaged = NULL;
+	char *keyfile = NULL;
+	char *routefile = NULL;
+	char *route6file = NULL;
+	gboolean ignore_error = FALSE;
+	GError *error = NULL;
+	const char *tmp;
+	const char *expected_id = "System aliasem0";
+	int expected_num_addresses = 4, expected_prefix = 24;
+	const char *expected_address[4] = { "192.168.1.5", "192.168.1.6", "192.168.1.9", "192.168.1.99" };
+	const char *expected_label[4] = { NULL, "aliasem0:1", "aliasem0:2", "aliasem0:99" };
+	const char *expected_gateway[4] = { "192.168.1.1", "192.168.1.1", "192.168.1.1", "192.168.1.1" };
+	int i, j;
+
+	connection = connection_from_file (TEST_IFCFG_ALIASES_GOOD,
+	                                   NULL,
+	                                   TYPE_ETHERNET,
+	                                   NULL,
+	                                   &unmanaged,
+	                                   &keyfile,
+	                                   &routefile,
+	                                   &route6file,
+	                                   &error,
+	                                   &ignore_error);
+	ASSERT (connection != NULL,
+	        "aliases-good-read", "failed to read %s: %s", TEST_IFCFG_ALIASES_GOOD, error->message);
+
+	ASSERT (nm_connection_verify (connection, &error),
+	        "aliases-good-verify", "failed to verify %s: %s", TEST_IFCFG_ALIASES_GOOD, error->message);
+
+	/* ===== CONNECTION SETTING ===== */
+
+	s_con = nm_connection_get_setting_connection (connection);
+	ASSERT (s_con != NULL,
+	        "aliases-good-verify-connection", "failed to verify %s: missing %s setting",
+	        TEST_IFCFG_ALIASES_GOOD,
+	        NM_SETTING_CONNECTION_SETTING_NAME);
+
+	/* ID */
+	tmp = nm_setting_connection_get_id (s_con);
+	ASSERT (tmp != NULL,
+	        "aliases-good-verify-connection", "failed to verify %s: missing %s / %s key",
+	        TEST_IFCFG_ALIASES_GOOD,
+	        NM_SETTING_CONNECTION_SETTING_NAME,
+	        NM_SETTING_CONNECTION_ID);
+	ASSERT (strcmp (tmp, expected_id) == 0,
+	        "aliases-good-verify-connection", "failed to verify %s: unexpected %s / %s key value",
+	        TEST_IFCFG_ALIASES_GOOD,
+	        NM_SETTING_CONNECTION_SETTING_NAME,
+	        NM_SETTING_CONNECTION_ID);
+
+	/* ===== IPv4 SETTING ===== */
+
+	s_ip4 = nm_connection_get_setting_ip4_config (connection);
+	ASSERT (s_ip4 != NULL,
+	        "aliases-good-verify-ip4", "failed to verify %s: missing %s setting",
+	        TEST_IFCFG_ALIASES_GOOD,
+	        NM_SETTING_IP4_CONFIG_SETTING_NAME);
+
+	/* Method */
+	tmp = nm_setting_ip4_config_get_method (s_ip4);
+	ASSERT (strcmp (tmp, NM_SETTING_IP4_CONFIG_METHOD_MANUAL) == 0,
+	        "aliases-good-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
+	        TEST_IFCFG_ALIASES_GOOD,
+	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
+	        NM_SETTING_IP4_CONFIG_METHOD);
+
+	ASSERT (nm_setting_ip4_config_get_num_addresses (s_ip4) == expected_num_addresses,
+	        "aliases-good-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
+	        TEST_IFCFG_ALIASES_GOOD,
+	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
+	        NM_SETTING_IP4_CONFIG_ADDRESSES);
+
+	/* Addresses */
+	for (i = 0; i < expected_num_addresses; i++) {
+		NMIP4Address *ip4_addr;
+		char buf[INET_ADDRSTRLEN];
+		struct in_addr addr;
+
+		ip4_addr = nm_setting_ip4_config_get_address (s_ip4, i);
+		ASSERT (ip4_addr,
+		        "aliases-good-verify-ip4", "failed to verify %s: missing IP4 address #%d",
+		        TEST_IFCFG_ALIASES_GOOD,
+		        i);
+
+		addr.s_addr = nm_ip4_address_get_address (ip4_addr);
+		ASSERT (inet_ntop (AF_INET, &addr, buf, sizeof (buf)) > 0,
+		        "aliases-good-verify-ip4", "failed to verify %s: couldn't convert IP address #%d",
+		        TEST_IFCFG_ALIASES_GOOD,
+		        i);
+
+		for (j = 0; j < expected_num_addresses; j++) {
+			if (!g_strcmp0 (buf, expected_address[j]))
+				break;
+		}
+
+		ASSERT (j < expected_num_addresses,
+		        "aliases-good-verify-ip4", "failed to verify %s: unexpected IP4 address #%d",
+		        TEST_IFCFG_ALIASES_GOOD,
+		        i);
+
+		ASSERT (nm_ip4_address_get_prefix (ip4_addr) == expected_prefix,
+		        "aliases-good-verify-ip4", "failed to verify %s: unexpected IP4 address prefix #%d",
+		        TEST_IFCFG_ALIASES_GOOD,
+		        i);
+
+		if (expected_gateway[j]) {
+			ASSERT (inet_pton (AF_INET, expected_gateway[j], &addr) > 0,
+			        "aliases-good-verify-ip4", "failed to verify %s: couldn't convert IP address gateway #%d",
+			        TEST_IFCFG_ALIASES_GOOD,
+			        i);
+		} else
+			addr.s_addr = 0;
+		ASSERT (nm_ip4_address_get_gateway (ip4_addr) == addr.s_addr,
+		        "aliases-good-verify-ip4", "failed to verify %s: unexpected IP4 address gateway #%d",
+		        TEST_IFCFG_ALIASES_GOOD,
+		        i);
+
+		ASSERT (g_strcmp0 (NM_UTILS_PRIVATE_CALL (nm_setting_ip4_config_get_address_label (s_ip4, i)), expected_label[j]) == 0,
+		        "aliases-good-verify-ip4", "failed to verify %s: unexpected IP4 address label #%d",
+		        TEST_IFCFG_ALIASES_GOOD,
+		        i);
+
+		expected_address[j] = NULL;
+		expected_gateway[j] = NULL;
+		expected_label[j] = NULL;
+	}
+
+	for (i = 0; i < expected_num_addresses; i++) {
+		ASSERT (expected_address[i] == NULL,
+		        "aliases-good-verify-ip4", "failed to verify %s: did not find IP4 address %s",
+		        TEST_IFCFG_ALIASES_GOOD,
+		        expected_address[i]);
+	}
+
+	g_free (keyfile);
+	g_free (routefile);
+	g_free (route6file);
+	g_object_unref (connection);
+}
+
+static void
+test_read_wired_aliases_bad (const char *base, const char *expected_id)
+{
+	NMConnection *connection;
+	NMSettingConnection *s_con;
+	NMSettingIP4Config *s_ip4;
+	char *unmanaged = NULL;
+	char *keyfile = NULL;
+	char *routefile = NULL;
+	char *route6file = NULL;
+	gboolean ignore_error = FALSE;
+	GError *error = NULL;
+	const char *tmp;
+	int expected_num_addresses = 1, expected_prefix = 24;
+	const char *expected_address = "192.168.1.5";
+	const char *expected_label = NULL;
+	const char *expected_gateway = "192.168.1.1";
+	NMIP4Address *ip4_addr;
+	struct in_addr addr;
+
+	connection = connection_from_file (base,
+	                                   NULL,
+	                                   TYPE_ETHERNET,
+	                                   NULL,
+	                                   &unmanaged,
+	                                   &keyfile,
+	                                   &routefile,
+	                                   &route6file,
+	                                   &error,
+	                                   &ignore_error);
+	g_test_assert_expected_messages ();
+	ASSERT (connection != NULL,
+	        "aliases-bad-read", "failed to read %s: %s", base, error->message);
+
+	ASSERT (nm_connection_verify (connection, &error),
+	        "aliases-bad-verify", "failed to verify %s: %s", base, error->message);
+
+	/* ===== CONNECTION SETTING ===== */
+
+	s_con = nm_connection_get_setting_connection (connection);
+	ASSERT (s_con != NULL,
+	        "aliases-bad-verify-connection", "failed to verify %s: missing %s setting",
+	        base,
+	        NM_SETTING_CONNECTION_SETTING_NAME);
+
+	/* ID */
+	tmp = nm_setting_connection_get_id (s_con);
+	ASSERT (tmp != NULL,
+	        "aliases-bad-verify-connection", "failed to verify %s: missing %s / %s key",
+	        base,
+	        NM_SETTING_CONNECTION_SETTING_NAME,
+	        NM_SETTING_CONNECTION_ID);
+	ASSERT (strcmp (tmp, expected_id) == 0,
+	        "aliases-bad-verify-connection", "failed to verify %s: unexpected %s / %s key value",
+	        base,
+	        NM_SETTING_CONNECTION_SETTING_NAME,
+	        NM_SETTING_CONNECTION_ID);
+
+	/* ===== IPv4 SETTING ===== */
+
+	s_ip4 = nm_connection_get_setting_ip4_config (connection);
+	ASSERT (s_ip4 != NULL,
+	        "aliases-bad-verify-ip4", "failed to verify %s: missing %s setting",
+	        base,
+	        NM_SETTING_IP4_CONFIG_SETTING_NAME);
+
+	/* Method */
+	tmp = nm_setting_ip4_config_get_method (s_ip4);
+	ASSERT (strcmp (tmp, NM_SETTING_IP4_CONFIG_METHOD_MANUAL) == 0,
+	        "aliases-bad-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
+	        base,
+	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
+	        NM_SETTING_IP4_CONFIG_METHOD);
+
+	ASSERT (nm_setting_ip4_config_get_num_addresses (s_ip4) == expected_num_addresses,
+	        "aliases-bad-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
+	        base,
+	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
+	        NM_SETTING_IP4_CONFIG_ADDRESSES);
+
+	/* Addresses */
+	ip4_addr = nm_setting_ip4_config_get_address (s_ip4, 0);
+	ASSERT (ip4_addr,
+			"aliases-bad-verify-ip4", "failed to verify %s: missing IP4 address",
+			base);
+
+	ASSERT (inet_pton (AF_INET, expected_address, &addr) > 0,
+			"aliases-bad-verify-ip4", "failed to verify %s: couldn't convert IP address",
+			base);
+	ASSERT (nm_ip4_address_get_address (ip4_addr) == addr.s_addr,
+			"aliases-bad-verify-ip4", "failed to verify %s: unexpected IP4 address",
+			base);
+
+	ASSERT (nm_ip4_address_get_prefix (ip4_addr) == expected_prefix,
+			"aliases-bad-verify-ip4", "failed to verify %s: unexpected IP4 address prefix",
+			base);
+
+	ASSERT (inet_pton (AF_INET, expected_gateway, &addr) > 0,
+			"aliases-bad-verify-ip4", "failed to verify %s: couldn't convert IP address gateway",
+			base);
+	ASSERT (nm_ip4_address_get_gateway (ip4_addr) == addr.s_addr,
+			"aliases-bad-verify-ip4", "failed to verify %s: unexpected IP4 address gateway",
+			base);
+
+	ASSERT (g_strcmp0 (NM_UTILS_PRIVATE_CALL (nm_setting_ip4_config_get_address_label (s_ip4, 0)), expected_label) == 0,
+			"aliases-bad-verify-ip4", "failed to verify %s: unexpected IP4 address label",
+			base);
+
+	g_free (keyfile);
+	g_free (routefile);
+	g_free (route6file);
+	g_object_unref (connection);
+}
+
+#define TEST_IFCFG_ALIASES_BAD_1  TEST_IFCFG_DIR"/network-scripts/ifcfg-aliasem1"
+
+static void
+test_read_wired_aliases_bad_1 (void)
+{
+	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
+	                       "*aliasem1:1*has no DEVICE*");
+	test_read_wired_aliases_bad (TEST_IFCFG_ALIASES_BAD_1, "System aliasem1");
+}
+
+#define TEST_IFCFG_ALIASES_BAD_2  TEST_IFCFG_DIR"/network-scripts/ifcfg-aliasem2"
+
+static void
+test_read_wired_aliases_bad_2 (void)
+{
+	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
+	                       "*aliasem2:1*has invalid DEVICE*");
+	test_read_wired_aliases_bad (TEST_IFCFG_ALIASES_BAD_2, "System aliasem2");
+}
+
 #define TEST_IFCFG_WIFI_OPEN TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-open"
 
 static void
@@ -3114,6 +3153,7 @@ test_read_wifi_open (void)
 	NMConnection *connection;
 	NMSettingConnection *s_con;
 	NMSettingWireless *s_wireless;
+	NMSettingWirelessSecurity *s_wsec;
 	NMSettingIP4Config *s_ip4;
 	char *unmanaged = NULL;
 	char *keyfile = NULL;
@@ -3253,18 +3293,16 @@ test_read_wifi_open (void)
 	        NM_SETTING_WIRELESS_SETTING_NAME,
 	        NM_SETTING_WIRELESS_MODE);
 
-	ASSERT (nm_setting_wireless_get_security (s_wireless) == NULL,
-	        "wifi-open-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_OPEN,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SEC);
-
 	ASSERT (nm_setting_wireless_get_channel (s_wireless) == expected_channel,
 	        "wifi-open-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
 	        TEST_IFCFG_WIFI_OPEN,
 	        NM_SETTING_WIRELESS_SETTING_NAME,
 	        NM_SETTING_WIRELESS_CHANNEL);
 
+	/* ===== WiFi SECURITY SETTING ===== */
+	s_wsec = nm_connection_get_setting_wireless_security (connection);
+	g_assert (s_wsec == NULL);
+
 	/* ===== IPv4 SETTING ===== */
 
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
@@ -3739,20 +3777,6 @@ test_read_wifi_wep (void)
 	        NM_SETTING_WIRELESS_SETTING_NAME,
 	        NM_SETTING_WIRELESS_CHANNEL);
 
-	/* Security */
-	tmp = nm_setting_wireless_get_security (s_wireless);
-	ASSERT (tmp != NULL,
-	        "wifi-wep-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WEP,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SEC);
-	ASSERT (strcmp (tmp, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME) == 0,
-	        "wifi-wep-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WEP,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SEC);
-
-
 	/* ===== WIRELESS SECURITY SETTING ===== */
 
 	s_wsec = nm_connection_get_setting_wireless_security (connection);
@@ -3877,7 +3901,7 @@ test_read_wifi_wep_adhoc (void)
 	const char *expected_ssid = "blahblah";
 	const char *expected_mode = "adhoc";
 	const char *expected_wep_key0 = "0123456789abcdef0123456789";
-	struct in_addr addr;
+	guint32 addr;
 	const char *expected_dns1 = "4.2.2.1";
 	const char *expected_dns2 = "4.2.2.2";
 
@@ -3983,20 +4007,6 @@ test_read_wifi_wep_adhoc (void)
 	        NM_SETTING_WIRELESS_SETTING_NAME,
 	        NM_SETTING_WIRELESS_CHANNEL);
 
-	/* Security */
-	tmp = nm_setting_wireless_get_security (s_wireless);
-	ASSERT (tmp != NULL,
-	        "wifi-wep-adhoc-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WEP_ADHOC,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SEC);
-	ASSERT (strcmp (tmp, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME) == 0,
-	        "wifi-wep-adhoc-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WEP_ADHOC,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SEC);
-
-
 	/* ===== WIRELESS SECURITY SETTING ===== */
 
 	s_wsec = nm_connection_get_setting_wireless_security (connection);
@@ -4099,7 +4109,7 @@ test_read_wifi_wep_adhoc (void)
 	        TEST_IFCFG_WIFI_WEP_ADHOC,
 	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
 	        NM_SETTING_IP4_CONFIG_DNS);
-	ASSERT (nm_setting_ip4_config_get_dns (s_ip4, 0) == addr.s_addr,
+	ASSERT (nm_setting_ip4_config_get_dns (s_ip4, 0) == addr,
 	        "wifi-wep-adhoc-verify-ip4", "failed to verify %s: unexpected %s / %s key value #1",
 	        TEST_IFCFG_WIFI_WEP_ADHOC,
 	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
@@ -4110,7 +4120,7 @@ test_read_wifi_wep_adhoc (void)
 	        TEST_IFCFG_WIFI_WEP_ADHOC,
 	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
 	        NM_SETTING_IP4_CONFIG_DNS);
-	ASSERT (nm_setting_ip4_config_get_dns (s_ip4, 1) == addr.s_addr,
+	ASSERT (nm_setting_ip4_config_get_dns (s_ip4, 1) == addr,
 	        "wifi-wep-adhoc-verify-ip4", "failed to verify %s: unexpected %s / %s key value #2",
 	        TEST_IFCFG_WIFI_WEP_ADHOC,
 	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
@@ -4176,20 +4186,6 @@ test_read_wifi_wep_passphrase (void)
 	        TEST_IFCFG_WIFI_WEP_PASSPHRASE,
 	        NM_SETTING_WIRELESS_SETTING_NAME);
 
-	/* Security */
-	tmp = nm_setting_wireless_get_security (s_wireless);
-	ASSERT (tmp != NULL,
-	        "wifi-wep-passphrase-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WEP_PASSPHRASE,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SEC);
-	ASSERT (strcmp (tmp, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME) == 0,
-	        "wifi-wep-passphrase-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WEP_PASSPHRASE,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SEC);
-
-
 	/* ===== WIRELESS SECURITY SETTING ===== */
 
 	s_wsec = nm_connection_get_setting_wireless_security (connection);
@@ -4314,19 +4310,6 @@ test_read_wifi_wep_40_ascii (void)
 	        TEST_IFCFG_WIFI_WEP_40_ASCII,
 	        NM_SETTING_WIRELESS_SETTING_NAME);
 
-	/* Security */
-	tmp = nm_setting_wireless_get_security (s_wireless);
-	ASSERT (tmp != NULL,
-	        "wifi-wep-40-ascii-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WEP_40_ASCII,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SEC);
-	ASSERT (strcmp (tmp, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME) == 0,
-	        "wifi-wep-40-ascii-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WEP_40_ASCII,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SEC);
-
 	/* ===== WIRELESS SECURITY SETTING ===== */
 
 	s_wsec = nm_connection_get_setting_wireless_security (connection);
@@ -4451,19 +4434,6 @@ test_read_wifi_wep_104_ascii (void)
 	        TEST_IFCFG_WIFI_WEP_104_ASCII,
 	        NM_SETTING_WIRELESS_SETTING_NAME);
 
-	/* Security */
-	tmp = nm_setting_wireless_get_security (s_wireless);
-	ASSERT (tmp != NULL,
-	        "wifi-wep-104-ascii-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WEP_104_ASCII,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SEC);
-	ASSERT (strcmp (tmp, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME) == 0,
-	        "wifi-wep-104-ascii-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WEP_104_ASCII,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SEC);
-
 	/* ===== WIRELESS SECURITY SETTING ===== */
 
 	s_wsec = nm_connection_get_setting_wireless_security (connection);
@@ -4602,20 +4572,6 @@ test_read_wifi_leap (void)
 	        TEST_IFCFG_WIFI_LEAP,
 	        NM_SETTING_WIRELESS_SETTING_NAME);
 
-	/* Security */
-	tmp = nm_setting_wireless_get_security (s_wireless);
-	ASSERT (tmp != NULL,
-	        "wifi-leap-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_LEAP,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SEC);
-	ASSERT (strcmp (tmp, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME) == 0,
-	        "wifi-leap-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_LEAP,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SEC);
-
-
 	/* ===== WIRELESS SECURITY SETTING ===== */
 
 	s_wsec = nm_connection_get_setting_wireless_security (connection);
@@ -4716,8 +4672,6 @@ test_read_wifi_leap_secret_flags (const char *file, NMSettingSecretFlags expecte
 	s_wifi = nm_connection_get_setting_wireless (connection);
 	g_assert (s_wifi);
 
-	g_assert (g_strcmp0 (nm_setting_wireless_get_security (s_wifi), NM_SETTING_WIRELESS_SECURITY_SETTING_NAME) == 0);
-
 	/* ===== WIRELESS SECURITY SETTING ===== */
 	s_wsec = nm_connection_get_setting_wireless_security (connection);
 	g_assert (s_wsec);
@@ -4906,19 +4860,6 @@ test_read_wifi_wpa_psk (void)
 	        NM_SETTING_WIRELESS_SETTING_NAME,
 	        NM_SETTING_WIRELESS_CHANNEL);
 
-	/* Security */
-	tmp = nm_setting_wireless_get_security (s_wireless);
-	ASSERT (tmp != NULL,
-	        "wifi-wpa-psk-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WPA_PSK,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SEC);
-	ASSERT (strcmp (tmp, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME) == 0,
-	        "wifi-wpa-psk-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_PSK,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SEC);
-
 	/* ===== WIRELESS SECURITY SETTING ===== */
 
 	s_wsec = nm_connection_get_setting_wireless_security (connection);
@@ -5119,19 +5060,6 @@ test_read_wifi_wpa_psk_2 (void)
 	        TEST_IFCFG_WIFI_WPA_PSK_2,
 	        NM_SETTING_WIRELESS_SETTING_NAME);
 
-	/* Security */
-	tmp = nm_setting_wireless_get_security (s_wireless);
-	ASSERT (tmp != NULL,
-	        "wifi-wpa-psk-2-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WPA_PSK_2,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SEC);
-	ASSERT (strcmp (tmp, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME) == 0,
-	        "wifi-wpa-psk-2-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_PSK_2,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SEC);
-
 	/* ===== WIRELESS SECURITY SETTING ===== */
 
 	s_wsec = nm_connection_get_setting_wireless_security (connection);
@@ -5224,19 +5152,6 @@ test_read_wifi_wpa_psk_unquoted (void)
 	        TEST_IFCFG_WIFI_WPA_PSK_UNQUOTED,
 	        NM_SETTING_WIRELESS_SETTING_NAME);
 
-	/* Security */
-	tmp = nm_setting_wireless_get_security (s_wireless);
-	ASSERT (tmp != NULL,
-	        "wifi-wpa-psk-unquoted-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WPA_PSK_UNQUOTED,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SEC);
-	ASSERT (strcmp (tmp, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME) == 0,
-	        "wifi-wpa-psk-unquoted-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_PSK_UNQUOTED,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SEC);
-
 	/* ===== WIRELESS SECURITY SETTING ===== */
 
 	s_wsec = nm_connection_get_setting_wireless_security (connection);
@@ -5384,19 +5299,6 @@ test_read_wifi_wpa_psk_adhoc (void)
 	        NM_SETTING_WIRELESS_SETTING_NAME,
 	        NM_SETTING_WIRELESS_MODE);
 
-	/* Security */
-	tmp = nm_setting_wireless_get_security (s_wireless);
-	ASSERT (tmp != NULL,
-	        "wifi-wpa-psk-adhoc-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WPA_PSK_ADHOC,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SEC);
-	ASSERT (strcmp (tmp, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME) == 0,
-	        "wifi-wpa-psk-adhoc-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_PSK_ADHOC,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SEC);
-
 	/* ===== WIRELESS SECURITY SETTING ===== */
 
 	s_wsec = nm_connection_get_setting_wireless_security (connection);
@@ -5580,19 +5482,6 @@ test_read_wifi_wpa_psk_hex (void)
 	        NM_SETTING_WIRELESS_SETTING_NAME,
 	        NM_SETTING_WIRELESS_SSID);
 
-	/* Security */
-	tmp = nm_setting_wireless_get_security (s_wireless);
-	ASSERT (tmp != NULL,
-	        "wifi-wpa-psk-hex-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WPA_PSK_HEX,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SEC);
-	ASSERT (strcmp (tmp, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME) == 0,
-	        "wifi-wpa-psk-hex-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WPA_PSK_HEX,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SEC);
-
 	/* ===== WIRELESS SECURITY SETTING ===== */
 
 	s_wsec = nm_connection_get_setting_wireless_security (connection);
@@ -5754,21 +5643,15 @@ test_read_wifi_wpa_eap_tls (void)
 	        NM_SETTING_802_1X_IDENTITY);
 
 	/* CA Cert */
-	verify_cert_or_key (CK_CA_CERT,
-	                    s_8021x,
+	verify_cert_or_key (s_8021x,
 	                    TEST_IFCFG_WIFI_WPA_EAP_TLS_CA_CERT,
 	                    NULL,
-	                    TEST_IFCFG_WIFI_WPA_EAP_TLS,
-	                    "wifi-wpa-eap-tls-verify-8021x",
 	                    NM_SETTING_802_1X_CA_CERT);
 
 	/* Client Cert */
-	verify_cert_or_key (CK_CLIENT_CERT,
-	                    s_8021x,
+	verify_cert_or_key (s_8021x,
 	                    TEST_IFCFG_WIFI_WPA_EAP_TLS_CLIENT_CERT,
 	                    NULL,
-	                    TEST_IFCFG_WIFI_WPA_EAP_TLS,
-	                    "wifi-wpa-eap-tls-verify-8021x",
 	                    NM_SETTING_802_1X_CLIENT_CERT);
 
 	/* Private Key Password */
@@ -5786,12 +5669,9 @@ test_read_wifi_wpa_eap_tls (void)
 	        NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD);
 
 	/* Private key */
-	verify_cert_or_key (CK_PRIV_KEY,
-	                    s_8021x,
+	verify_cert_or_key (s_8021x,
 	                    TEST_IFCFG_WIFI_WPA_EAP_TLS_PRIVATE_KEY,
 	                    expected_privkey_password,
-	                    TEST_IFCFG_WIFI_WPA_EAP_TLS,
-	                    "wifi-wpa-eap-tls-verify-8021x",
 	                    NM_SETTING_802_1X_PRIVATE_KEY);
 
 	g_free (unmanaged);
@@ -5891,12 +5771,9 @@ test_read_wifi_wpa_eap_ttls_tls (void)
 	        NM_SETTING_802_1X_EAP);
 
 	/* CA Cert */
-	verify_cert_or_key (CK_CA_CERT,
-	                    s_8021x,
+	verify_cert_or_key (s_8021x,
 	                    TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS_CA_CERT,
 	                    NULL,
-	                    TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS,
-	                    "wifi-wpa-eap-ttls-tls-verify-8021x",
 	                    NM_SETTING_802_1X_CA_CERT);
 
 	/* Inner auth method */
@@ -5913,21 +5790,15 @@ test_read_wifi_wpa_eap_ttls_tls (void)
 	        NM_SETTING_802_1X_PHASE2_AUTHEAP);
 
 	/* Inner CA Cert */
-	verify_cert_or_key (CK_CA_CERT,
-	                    s_8021x,
+	verify_cert_or_key (s_8021x,
 	                    TEST_IFCFG_WIFI_WPA_EAP_TLS_CA_CERT,
 	                    NULL,
-	                    TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS,
-	                    "wifi-wpa-eap-ttls-tls-verify-8021x",
 	                    NM_SETTING_802_1X_PHASE2_CA_CERT);
 
 	/* Inner Client Cert */
-	verify_cert_or_key (CK_CLIENT_CERT,
-	                    s_8021x,
+	verify_cert_or_key (s_8021x,
 	                    TEST_IFCFG_WIFI_WPA_EAP_TLS_CLIENT_CERT,
 	                    NULL,
-	                    TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS,
-	                    "wifi-wpa-eap-ttls-tls-verify-8021x",
 	                    NM_SETTING_802_1X_PHASE2_CLIENT_CERT);
 
 	/* Inner Private Key Password */
@@ -5945,12 +5816,9 @@ test_read_wifi_wpa_eap_ttls_tls (void)
 	        NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD);
 
 	/* Inner private key */
-	verify_cert_or_key (CK_PRIV_KEY,
-	                    s_8021x,
+	verify_cert_or_key (s_8021x,
 	                    TEST_IFCFG_WIFI_WPA_EAP_TLS_PRIVATE_KEY,
 	                    expected_privkey_password,
-	                    TEST_IFCFG_WIFI_WPA_EAP_TTLS_TLS,
-	                    "wifi-wpa-eap-ttls-tls-verify-8021x",
 	                    NM_SETTING_802_1X_PHASE2_PRIVATE_KEY);
 
 	/* Identity */
@@ -6011,8 +5879,6 @@ test_read_wifi_dynamic_wep_leap (void)
 	s_wifi = nm_connection_get_setting_wireless (connection);
 	g_assert (s_wifi);
 
-	g_assert_cmpstr (nm_setting_wireless_get_security (s_wifi), ==, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME);
-
 	/* ===== WiFi SECURITY SETTING ===== */
 	s_wsec = nm_connection_get_setting_wireless_security (connection);
 	g_assert (s_wsec);
@@ -6159,12 +6025,9 @@ test_read_wifi_wep_eap_ttls_chap (void)
 	        NM_SETTING_802_1X_EAP);
 
 	/* CA Cert */
-	verify_cert_or_key (CK_CA_CERT,
-	                    s_8021x,
+	verify_cert_or_key (s_8021x,
 	                    TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP_CA_CERT,
 	                    NULL,
-	                    TEST_IFCFG_WIFI_WEP_EAP_TTLS_CHAP,
-	                    "wifi-wep-eap-ttls-chap-verify-8021x",
 	                    NM_SETTING_802_1X_CA_CERT);
 
 	/* Inner auth method */
@@ -6213,6 +6076,121 @@ test_read_wifi_wep_eap_ttls_chap (void)
 	g_object_unref (connection);
 }
 
+static void
+test_read_wifi_hidden (void)
+{
+	NMConnection *connection;
+	NMSettingConnection *s_con;
+	NMSettingWireless *s_wifi;
+	gboolean success;
+	GError *error = NULL;
+
+	connection = connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-hidden",
+	                                   NULL, TYPE_WIRELESS, NULL, NULL, NULL, NULL, NULL, &error, NULL);
+	g_assert_no_error (error);
+	g_assert (connection);
+
+	success = nm_connection_verify (connection, &error);
+	g_assert_no_error (error);
+	g_assert (success);
+
+	s_con = nm_connection_get_setting_connection (connection);
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_connection_type (s_con), ==, NM_SETTING_WIRELESS_SETTING_NAME);
+
+	s_wifi = nm_connection_get_setting_wireless (connection);
+	g_assert (s_wifi);
+	g_assert (nm_setting_wireless_get_hidden (s_wifi) == TRUE);
+
+	g_object_unref (connection);
+}
+
+static void
+test_write_wifi_hidden (void)
+{
+	NMConnection *connection, *reread;
+	NMSettingConnection *s_con;
+	NMSettingWireless *s_wifi;
+	char *uuid, *testfile = NULL, *val;
+	gboolean success;
+	GError *error = NULL;
+	shvarFile *f;
+	GByteArray *ssid;
+	const unsigned char ssid_data[] = { 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x53, 0x49, 0x44 };
+
+	connection = nm_connection_new ();
+
+	/* Connection setting */
+	s_con = (NMSettingConnection *) nm_setting_connection_new ();
+	nm_connection_add_setting (connection, NM_SETTING (s_con));
+
+	uuid = nm_utils_uuid_generate ();
+	g_object_set (s_con,
+	              NM_SETTING_CONNECTION_ID, "Test Write WiFi Hidden",
+	              NM_SETTING_CONNECTION_UUID, uuid,
+	              NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME,
+	              NULL);
+	g_free (uuid);
+
+	/* Wifi setting */
+	s_wifi = (NMSettingWireless *) nm_setting_wireless_new ();
+	nm_connection_add_setting (connection, NM_SETTING (s_wifi));
+
+	ssid = g_byte_array_sized_new (sizeof (ssid_data));
+	g_byte_array_append (ssid, ssid_data, sizeof (ssid_data));
+
+	g_object_set (s_wifi,
+	              NM_SETTING_WIRELESS_SSID, ssid,
+	              NM_SETTING_WIRELESS_MODE, "infrastructure",
+	              NM_SETTING_WIRELESS_HIDDEN, TRUE,
+	              NULL);
+
+	g_byte_array_free (ssid, TRUE);
+
+	success = nm_connection_verify (connection, &error);
+	g_assert_no_error (error);
+	g_assert (success);
+
+	/* Save the ifcfg */
+	success = writer_new_connection (connection,
+	                                 TEST_SCRATCH_DIR "/network-scripts/",
+	                                 &testfile,
+	                                 &error);
+	g_assert_no_error (error);
+	g_assert (success);
+
+	f = svOpenFile (testfile, &error);
+	g_assert_no_error (error);
+	g_assert (f);
+
+	/* re-read the file to check that what key was written. */
+	val = svGetValue (f, "SSID_HIDDEN", FALSE);
+	g_assert (val);
+	g_assert_cmpstr (val, ==, "yes");
+	g_free (val);
+	svCloseFile (f);
+
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_utils_normalize_connection (connection, TRUE);
+
+	/* re-read the connection for comparison */
+	reread = connection_from_file (testfile, NULL, TYPE_WIRELESS, NULL,
+	                               NULL, NULL, NULL, NULL, &error, NULL);
+	unlink (testfile);
+	g_assert_no_error (error);
+	g_assert (reread);
+
+	success = nm_connection_verify (reread, &error);
+	g_assert_no_error (error);
+	g_assert (success);
+
+	g_assert (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT));
+
+	g_free (testfile);
+	g_object_unref (connection);
+	g_object_unref (reread);
+}
+
 #define TEST_IFCFG_WIRED_QETH_STATIC TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-qeth-static"
 
 static void
@@ -6531,20 +6509,6 @@ test_read_wifi_wep_no_keys (void)
 	        TEST_IFCFG_WIFI_WEP_NO_KEYS,
 	        NM_SETTING_WIRELESS_SETTING_NAME);
 
-	/* Security */
-	tmp = nm_setting_wireless_get_security (s_wireless);
-	ASSERT (tmp != NULL,
-	        "wifi-wep-no-keys-verify-wireless", "failed to verify %s: missing %s / %s key",
-	        TEST_IFCFG_WIFI_WEP_NO_KEYS,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SEC);
-	ASSERT (strcmp (tmp, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME) == 0,
-	        "wifi-wep-no-keys-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
-	        TEST_IFCFG_WIFI_WEP_NO_KEYS,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_SEC);
-
-
 	/* ===== WIRELESS SECURITY SETTING ===== */
 
 	s_wsec = nm_connection_get_setting_wireless_security (connection);
@@ -6677,7 +6641,6 @@ test_read_wifi_wep_agent_keys (void)
 	char *route6file = NULL;
 	gboolean ignore_error = FALSE;
 	GError *error = NULL;
-	const char *tmp;
 	NMWepKeyType key_type;
 	gboolean success;
 	NMSettingSecretFlags flags;
@@ -6705,8 +6668,6 @@ test_read_wifi_wep_agent_keys (void)
 	/* ===== WIRELESS SETTING ===== */
 	s_wifi = nm_connection_get_setting_wireless (connection);
 	g_assert (s_wifi);
-	tmp = nm_setting_wireless_get_security (s_wifi);
-	g_assert (g_strcmp0 (tmp, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME) == 0);
 
 	/* ===== WIRELESS SECURITY SETTING ===== */
 	s_wsec = nm_connection_get_setting_wireless_security (connection);
@@ -6782,14 +6743,9 @@ test_write_wired_static (void)
 	inet_pton (AF_INET6, "cafe:ffff:eeee:dddd:cccc:bbbb:aaaa:feed", &dns6_2);
 
 	connection = nm_connection_new ();
-	ASSERT (connection != NULL,
-	        "wired-static-write", "failed to allocate new connection");
 
 	/* Connection setting */
 	s_con = (NMSettingConnection *) nm_setting_connection_new ();
-	ASSERT (s_con != NULL,
-	        "wired-static-write", "failed to allocate new %s setting",
-	        NM_SETTING_CONNECTION_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_con));
 
 	uuid = nm_utils_uuid_generate ();
@@ -6803,9 +6759,6 @@ test_write_wired_static (void)
 
 	/* Wired setting */
 	s_wired = (NMSettingWired *) nm_setting_wired_new ();
-	ASSERT (s_wired != NULL,
-	        "wired-static-write", "failed to allocate new %s setting",
-	        NM_SETTING_WIRED_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_wired));
 
 	mac = g_byte_array_sized_new (sizeof (tmpmac));
@@ -6819,9 +6772,6 @@ test_write_wired_static (void)
 
 	/* IP4 setting */
 	s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
-	ASSERT (s_ip4 != NULL,
-			"wired-static-write", "failed to allocate new %s setting",
-			NM_SETTING_IP4_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip4));
 
 	g_object_set (s_ip4,
@@ -6851,9 +6801,6 @@ test_write_wired_static (void)
 
 	/* IP6 setting */
 	s_ip6 = (NMSettingIP6Config *) nm_setting_ip6_config_new ();
-	ASSERT (s_ip6 != NULL,
-	        "wired-static-write", "failed to allocate new %s setting",
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
 
 	g_object_set (s_ip6,
@@ -6921,6 +6868,9 @@ test_write_wired_static (void)
 	ASSERT (testfile != NULL,
 	        "wired-static-write", "didn't get ifcfg file path back after writing connection");
 
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_utils_normalize_connection (connection, TRUE);
+
 	/* re-read the connection for comparison */
 	reread = connection_from_file (testfile,
 	                               NULL,
@@ -6986,14 +6936,9 @@ test_write_wired_dhcp (void)
 	gboolean ignore_error = FALSE;
 
 	connection = nm_connection_new ();
-	ASSERT (connection != NULL,
-	        "wired-dhcp-write", "failed to allocate new connection");
 
 	/* Connection setting */
 	s_con = (NMSettingConnection *) nm_setting_connection_new ();
-	ASSERT (s_con != NULL,
-	        "wired-dhcp-write", "failed to allocate new %s setting",
-	        NM_SETTING_CONNECTION_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_con));
 
 	uuid = nm_utils_uuid_generate ();
@@ -7007,16 +6952,10 @@ test_write_wired_dhcp (void)
 
 	/* Wired setting */
 	s_wired = (NMSettingWired *) nm_setting_wired_new ();
-	ASSERT (s_wired != NULL,
-	        "wired-dhcp-write", "failed to allocate new %s setting",
-	        NM_SETTING_WIRED_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_wired));
 
 	/* IP4 setting */
 	s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
-	ASSERT (s_ip4 != NULL,
-			"wired-dhcp-write", "failed to allocate new %s setting",
-			NM_SETTING_IP4_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip4));
 
 	g_object_set (s_ip4,
@@ -7033,9 +6972,6 @@ test_write_wired_dhcp (void)
 
 	/* IP6 setting */
 	s_ip6 = (NMSettingIP6Config *) nm_setting_ip6_config_new ();
-	ASSERT (s_ip6 != NULL,
-	        "wired-dhcp-write", "failed to allocate new %s setting",
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
 
 	g_object_set (s_ip6,
@@ -7055,6 +6991,9 @@ test_write_wired_dhcp (void)
 	ASSERT (testfile != NULL,
 	        "wired-dhcp-write", "didn't get ifcfg file path back after writing connection");
 
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_utils_normalize_connection (connection, TRUE);
+
 	/* re-read the connection for comparison */
 	reread = connection_from_file (testfile,
 	                               NULL,
@@ -7087,6 +7026,118 @@ test_write_wired_dhcp (void)
 }
 
 static void
+test_write_wired_dhcp_plus_ip (void)
+{
+	NMConnection *connection, *reread;
+	char *written = NULL;
+	GError *error = NULL;
+	gboolean success = FALSE;
+
+	connection = connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-dhcp-plus-ip",
+	                                   NULL, TYPE_ETHERNET, NULL, NULL,
+	                                   NULL, NULL, NULL, &error, NULL);
+	g_assert_no_error (error);
+	g_assert (connection != NULL);
+
+	success = writer_new_connection (connection,
+	                                 TEST_SCRATCH_DIR "/network-scripts/",
+	                                 &written,
+	                                 &error);
+	g_assert (success);
+
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_utils_normalize_connection (connection, TRUE);
+
+	/* re-read the connection for comparison */
+	reread = connection_from_file (written, NULL, TYPE_ETHERNET, NULL, NULL,
+	                               NULL, NULL, NULL, &error, NULL);
+	unlink (written);
+	g_free (written);
+
+	g_assert_no_error (error);
+	g_assert (reread != NULL);
+
+	success = nm_connection_verify (reread, &error);
+	g_assert_no_error (error);
+	g_assert (success);
+
+	success = nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT);
+	g_assert (success);
+
+	g_object_unref (connection);
+	g_object_unref (reread);
+}
+
+static void
+test_read_write_wired_dhcp_send_hostname (void)
+{
+	NMConnection *connection, *reread;
+	NMSettingIP4Config *s_ip4;
+	NMSettingIP6Config *s_ip6;
+	const char * dhcp_hostname = "kamil-patka";
+	char *written = NULL;
+	GError *error = NULL;
+	gboolean success = FALSE;
+
+	connection = connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-dhcp-send-hostname",
+	                                   NULL, TYPE_ETHERNET, NULL, NULL,
+	                                   NULL, NULL, NULL, &error, NULL);
+	g_assert_no_error (error);
+	g_assert (connection != NULL);
+
+	/* Check dhcp-hostname and dhcp-send-hostname */
+	s_ip4 = nm_connection_get_setting_ip4_config (connection);
+	s_ip6 = nm_connection_get_setting_ip6_config (connection);
+	g_assert (s_ip4);
+	g_assert (s_ip6);
+	g_assert (nm_setting_ip4_config_get_dhcp_send_hostname (s_ip4) == TRUE);
+	g_assert_cmpstr (nm_setting_ip4_config_get_dhcp_hostname (s_ip4), ==, "svata-pulec");
+	g_assert_cmpstr (nm_setting_ip6_config_get_dhcp_hostname (s_ip6), ==, "svata-pulec");
+
+	/* Set dhcp-send-hostname=false dhcp-hostname="kamil-patka" and write the connection. */
+	g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_DHCP_SEND_HOSTNAME, FALSE, NULL);
+	g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_DHCP_HOSTNAME, dhcp_hostname, NULL);
+	g_object_set (s_ip6, NM_SETTING_IP4_CONFIG_DHCP_HOSTNAME, dhcp_hostname, NULL);
+
+	success = writer_new_connection (connection,
+	                                 TEST_SCRATCH_DIR "/network-scripts/",
+	                                 &written,
+	                                 &error);
+	g_assert (success);
+
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_utils_normalize_connection (connection, TRUE);
+
+	/* re-read the connection for comparison */
+	reread = connection_from_file (written, NULL, TYPE_ETHERNET, NULL, NULL,
+	                               NULL, NULL, NULL, &error, NULL);
+	unlink (written);
+	g_free (written);
+
+	g_assert_no_error (error);
+	g_assert (reread != NULL);
+
+	success = nm_connection_verify (reread, &error);
+	g_assert_no_error (error);
+	g_assert (success);
+
+	success = nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT);
+	g_assert (success);
+
+	/* Check dhcp-hostname and dhcp-send-hostname from the re-read connection. */
+	s_ip4 = nm_connection_get_setting_ip4_config (reread);
+	s_ip6 = nm_connection_get_setting_ip6_config (reread);
+	g_assert (s_ip4);
+	g_assert (s_ip6);
+	g_assert (nm_setting_ip4_config_get_dhcp_send_hostname (s_ip4) == FALSE);
+	g_assert_cmpstr (nm_setting_ip4_config_get_dhcp_hostname (s_ip4), ==, dhcp_hostname);
+	g_assert_cmpstr (nm_setting_ip6_config_get_dhcp_hostname (s_ip6), ==, dhcp_hostname);
+
+	g_object_unref (connection);
+	g_object_unref (reread);
+}
+
+static void
 test_write_wired_static_ip6_only (void)
 {
 	NMConnection *connection;
@@ -7114,14 +7165,9 @@ test_write_wired_static_ip6_only (void)
 	inet_pton (AF_INET6, "fade:0102:0103::face", &dns6);
 
 	connection = nm_connection_new ();
-	ASSERT (connection != NULL,
-	        "wired-static-ip6-only-write", "failed to allocate new connection");
 
 	/* Connection setting */
 	s_con = (NMSettingConnection *) nm_setting_connection_new ();
-	ASSERT (s_con != NULL,
-	        "wired-static-ip6-only-write", "failed to allocate new %s setting",
-	        NM_SETTING_CONNECTION_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_con));
 
 	uuid = nm_utils_uuid_generate ();
@@ -7135,9 +7181,6 @@ test_write_wired_static_ip6_only (void)
 
 	/* Wired setting */
 	s_wired = (NMSettingWired *) nm_setting_wired_new ();
-	ASSERT (s_wired != NULL,
-	        "wired-static-ip6-only-write", "failed to allocate new %s setting",
-	        NM_SETTING_WIRED_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_wired));
 
 	mac = g_byte_array_sized_new (sizeof (tmpmac));
@@ -7147,9 +7190,6 @@ test_write_wired_static_ip6_only (void)
 
 	/* IP4 setting */
 	s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
-	ASSERT (s_ip4 != NULL,
-	        "wired-static-ip6-only-write", "failed to allocate new %s setting",
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip4));
 
 	g_object_set (s_ip4,
@@ -7158,9 +7198,6 @@ test_write_wired_static_ip6_only (void)
 
 	/* IP6 setting */
 	s_ip6 = (NMSettingIP6Config *) nm_setting_ip6_config_new ();
-	ASSERT (s_ip6 != NULL,
-	        "wired-static-ip6-only-write", "failed to allocate new %s setting",
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
 
 	g_object_set (s_ip6,
@@ -7193,6 +7230,9 @@ test_write_wired_static_ip6_only (void)
 	ASSERT (testfile != NULL,
 	        "wired-static-ip6-only-write", "didn't get ifcfg file path back after writing connection");
 
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_utils_normalize_connection (connection, TRUE);
+
 	/* re-read the connection for comparison */
 	reread = connection_from_file (testfile,
 	                               NULL,
@@ -7236,7 +7276,7 @@ test_write_wired_static_ip6_only (void)
  * That way, the gateway actually defaults to "::".
  */
 static void
-test_write_wired_static_ip6_only_gw (const char *gateway_addr)
+test_write_wired_static_ip6_only_gw (gconstpointer user_data)
 {
 	NMConnection *connection;
 	NMConnection *reread;
@@ -7259,12 +7299,11 @@ test_write_wired_static_ip6_only_gw (const char *gateway_addr)
 	char s_gateway6[INET6_ADDRSTRLEN] = { 0 };
 	struct in6_addr gateway6_autovar;
 	const struct in6_addr *gateway6 = NULL;
-	char *unmanaged = NULL, *keyfile = NULL, *routefile = NULL, *route6file = NULL;
 
 	/* parsing the input argument and set the struct in6_addr "gateway6" to
 	 * the gateway address. NULL means "do not set the gateway explicitly". */
-	if (gateway_addr) {
-		g_assert_cmpint (inet_pton (AF_INET6, gateway_addr, &gateway6_autovar), ==, 1);
+	if (user_data) {
+		g_assert_cmpint (inet_pton (AF_INET6, user_data, &gateway6_autovar), ==, 1);
 		gateway6 = &gateway6_autovar;
 	}
 
@@ -7338,22 +7377,27 @@ test_write_wired_static_ip6_only_gw (const char *gateway_addr)
 	g_assert (success);
 	g_assert (testfile);
 
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_utils_normalize_connection (connection, TRUE);
+
 	/* re-read the connection for comparison */
 	reread = connection_from_file (testfile,
 	                               NULL,
 	                               TYPE_ETHERNET,
-	                               NULL,
-	                               &unmanaged,
-	                               &keyfile,
-	                               &routefile,
-	                               &route6file,
+	                               NULL, NULL, NULL,
+	                               NULL, NULL,
 	                               &error,
 	                               &ignore_error);
+	g_assert_no_error (error);
+	g_assert (reread);
+	g_assert (nm_connection_verify (reread, &error));
+	g_assert (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT));
 
 	{
 		/* re-read the file to check that what key was written. */
-		shvarFile *ifcfg = svNewFile (testfile);
+		shvarFile *ifcfg = svOpenFile (testfile, &error);
 
+		g_assert_no_error (error);
 		g_assert (ifcfg);
 		written_ifcfg_gateway = svGetValue (ifcfg, "IPV6_DEFAULTGW", FALSE);
 		svCloseFile (ifcfg);
@@ -7361,17 +7405,6 @@ test_write_wired_static_ip6_only_gw (const char *gateway_addr)
 
 	unlink (testfile);
 
-	g_assert_no_error (error);
-	g_assert (reread);
-
-	g_free (unmanaged);
-	g_free (keyfile);
-	g_free (routefile);
-	g_free (route6file);
-
-	g_assert (nm_connection_verify (reread, &error));
-	g_assert (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT));
-
 	/* access the gateway from the loaded connection. */
 	s_ip6 = nm_connection_get_setting_ip6_config (reread);
 	g_assert (s_ip6 && nm_setting_ip6_config_get_num_addresses (s_ip6)==1);
@@ -7502,6 +7535,9 @@ test_read_write_static_routes_legacy (void)
 	ASSERT (testfile != NULL,
 	        "read-write-static-routes-legacy-write", "didn't get ifcfg file path back after writing connection");
 
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_utils_normalize_connection (connection, TRUE);
+
 	/* re-read the connection for comparison */
 	reread = connection_from_file (testfile,
 	                               NULL,
@@ -7578,14 +7614,9 @@ test_write_wired_static_routes (void)
 	gboolean ignore_error = FALSE;
 
 	connection = nm_connection_new ();
-	ASSERT (connection != NULL,
-	        "wired-static-routes-write", "failed to allocate new connection");
 
 	/* Connection setting */
 	s_con = (NMSettingConnection *) nm_setting_connection_new ();
-	ASSERT (s_con != NULL,
-	        "wired-static-routes-write", "failed to allocate new %s setting",
-	        NM_SETTING_CONNECTION_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_con));
 
 	uuid = nm_utils_uuid_generate ();
@@ -7599,9 +7630,6 @@ test_write_wired_static_routes (void)
 
 	/* Wired setting */
 	s_wired = (NMSettingWired *) nm_setting_wired_new ();
-	ASSERT (s_wired != NULL,
-	        "wired-static-routes-write", "failed to allocate new %s setting",
-	        NM_SETTING_WIRED_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_wired));
 
 	mac = g_byte_array_sized_new (sizeof (tmpmac));
@@ -7615,9 +7643,6 @@ test_write_wired_static_routes (void)
 
 	/* IP4 setting */
 	s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
-	ASSERT (s_ip4 != NULL,
-			"wired-static-routes-write", "failed to allocate new %s setting",
-			NM_SETTING_IP4_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip4));
 
 	g_object_set (s_ip4,
@@ -7662,9 +7687,6 @@ test_write_wired_static_routes (void)
 
 	/* IP6 setting */
 	s_ip6 = (NMSettingIP6Config *) nm_setting_ip6_config_new ();
-	ASSERT (s_ip6 != NULL,
-	        "wired-dhcp-8021x-peap-mschapv2write", "failed to allocate new %s setting",
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
 
 	g_object_set (s_ip6,
@@ -7688,6 +7710,9 @@ test_write_wired_static_routes (void)
 	ASSERT (testfile != NULL,
 	        "wired-static-routes-write", "didn't get ifcfg file path back after writing connection");
 
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_utils_normalize_connection (connection, TRUE);
+
 	/* re-read the connection for comparison */
 	reread = connection_from_file (testfile,
 	                               NULL,
@@ -7744,14 +7769,9 @@ test_write_wired_dhcp_8021x_peap_mschapv2 (void)
 	gboolean ignore_error = FALSE;
 
 	connection = nm_connection_new ();
-	ASSERT (connection != NULL,
-	        "wired-dhcp-8021x-peap-mschapv2write", "failed to allocate new connection");
 
 	/* Connection setting */
 	s_con = (NMSettingConnection *) nm_setting_connection_new ();
-	ASSERT (s_con != NULL,
-	        "wired-dhcp-8021x-peap-mschapv2write", "failed to allocate new %s setting",
-	        NM_SETTING_CONNECTION_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_con));
 
 	uuid = nm_utils_uuid_generate ();
@@ -7765,25 +7785,16 @@ test_write_wired_dhcp_8021x_peap_mschapv2 (void)
 
 	/* Wired setting */
 	s_wired = (NMSettingWired *) nm_setting_wired_new ();
-	ASSERT (s_wired != NULL,
-	        "wired-dhcp-8021x-peap-mschapv2write", "failed to allocate new %s setting",
-	        NM_SETTING_WIRED_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_wired));
 
 	/* IP4 setting */
 	s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
-	ASSERT (s_ip4 != NULL,
-			"wired-dhcp-8021x-peap-mschapv2write", "failed to allocate new %s setting",
-			NM_SETTING_IP4_CONFIG_SETTING_NAME);
 	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);
 
 	/* IP6 setting */
 	s_ip6 = (NMSettingIP6Config *) nm_setting_ip6_config_new ();
-	ASSERT (s_ip6 != NULL,
-	        "wired-dhcp-8021x-peap-mschapv2write", "failed to allocate new %s setting",
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
 
 	g_object_set (s_ip6,
@@ -7793,9 +7804,6 @@ test_write_wired_dhcp_8021x_peap_mschapv2 (void)
 
 	/* 802.1x setting */
 	s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
-	ASSERT (s_8021x != NULL,
-			"wired-dhcp-8021x-peap-mschapv2write", "failed to allocate new %s setting",
-			NM_SETTING_802_1X_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_8021x));
 
 	g_object_set (s_8021x,
@@ -7834,6 +7842,9 @@ test_write_wired_dhcp_8021x_peap_mschapv2 (void)
 	ASSERT (testfile != NULL,
 	        "wired-dhcp-8021x-peap-mschapv2write", "didn't get ifcfg file path back after writing connection");
 
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_utils_normalize_connection (connection, TRUE);
+
 	/* re-read the connection for comparison */
 	reread = connection_from_file (testfile,
 	                               NULL,
@@ -7879,10 +7890,8 @@ file_to_byte_array (const char *filename)
 
 	if (g_file_get_contents (filename, &contents, &length, NULL)) {
 		array = g_byte_array_sized_new (length);
-		if (array) {
-			g_byte_array_append (array, (guint8 *) contents, length);
-			g_assert (array->len == length);
-		}
+		g_byte_array_append (array, (guint8 *) contents, length);
+		g_assert (array->len == length);
 		g_free (contents);
 	}
 	return array;
@@ -8018,6 +8027,9 @@ test_write_wired_8021x_tls (NMSetting8021xCKScheme scheme,
 	g_assert (success);
 	g_assert (testfile != NULL);
 
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_utils_normalize_connection (connection, TRUE);
+
 	/* re-read the connection for comparison */
 	reread = connection_from_file (testfile,
 	                               NULL,
@@ -8104,6 +8116,354 @@ test_write_wired_8021x_tls (NMSetting8021xCKScheme scheme,
 	g_object_unref (reread);
 }
 
+#define TEST_SCRATCH_ALIAS_BASE TEST_SCRATCH_DIR "/network-scripts/ifcfg-alias0"
+
+static void
+test_write_wired_aliases (void)
+{
+	NMConnection *connection;
+	NMConnection *reread;
+	NMSettingConnection *s_con;
+	NMSettingWired *s_wired;
+	NMSettingIP4Config *s_ip4;
+	char *uuid;
+	int num_addresses = 4;
+	guint32 ip[] = { 0x01010101, 0x01010102, 0x01010103, 0x01010104 };
+	const char *label[] = { NULL, "alias0:2", NULL, "alias0:3" };
+	const guint32 gw = htonl (0x01010101);
+	const guint32 prefix = 24;
+	NMIP4Address *addr;
+	gboolean success;
+	GError *error = NULL;
+	char *testfile = NULL;
+	char *unmanaged = NULL;
+	char *keyfile = NULL;
+	char *routefile = NULL;
+	char *route6file = NULL;
+	gboolean ignore_error = FALSE;
+	shvarFile *ifcfg;
+	int i, j;
+
+	connection = nm_connection_new ();
+	ASSERT (connection != NULL,
+	        "wired-aliases-write", "failed to allocate new connection");
+
+	/* Connection setting */
+	s_con = (NMSettingConnection *) nm_setting_connection_new ();
+	ASSERT (s_con != NULL,
+	        "wired-aliases-write", "failed to allocate new %s setting",
+	        NM_SETTING_CONNECTION_SETTING_NAME);
+	nm_connection_add_setting (connection, NM_SETTING (s_con));
+
+	uuid = nm_utils_uuid_generate ();
+	g_object_set (s_con,
+	              NM_SETTING_CONNECTION_ID, "alias0",
+	              NM_SETTING_CONNECTION_UUID, uuid,
+	              NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME,
+	              NULL);
+	g_free (uuid);
+
+	/* Wired setting */
+	s_wired = (NMSettingWired *) nm_setting_wired_new ();
+	ASSERT (s_wired != NULL,
+	        "wired-aliases-write", "failed to allocate new %s setting",
+	        NM_SETTING_WIRED_SETTING_NAME);
+	nm_connection_add_setting (connection, NM_SETTING (s_wired));
+
+	/* IP4 setting */
+	s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
+	ASSERT (s_ip4 != NULL,
+	        "wired-aliases-write", "failed to allocate new %s setting",
+	        NM_SETTING_IP4_CONFIG_SETTING_NAME);
+	nm_connection_add_setting (connection, NM_SETTING (s_ip4));
+
+	g_object_set (s_ip4,
+	              NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL,
+	              NM_SETTING_IP4_CONFIG_MAY_FAIL, TRUE,
+	              NULL);
+
+	for (i = 0; i < num_addresses; i++) {
+		addr = nm_ip4_address_new ();
+		nm_ip4_address_set_address (addr, ip[i]);
+		nm_ip4_address_set_prefix (addr, prefix);
+		nm_ip4_address_set_gateway (addr, gw);
+		NM_UTILS_PRIVATE_CALL (nm_setting_ip4_config_add_address_with_label (s_ip4, addr, label[i]));
+		nm_ip4_address_unref (addr);
+	}
+
+	ASSERT (nm_connection_verify (connection, &error) == TRUE,
+	        "wired-aliases-write", "failed to verify connection: %s",
+	        (error && error->message) ? error->message : "(unknown)");
+
+	/* Create some pre-existing alias files, to make sure they get overwritten / deleted. */
+	ifcfg = svCreateFile (TEST_SCRATCH_ALIAS_BASE ":2");
+	svSetValue (ifcfg, "DEVICE", "alias0:2", FALSE);
+	svSetValue (ifcfg, "IPADDR", "192.168.1.2", FALSE);
+	svWriteFile (ifcfg, 0644, NULL);
+	svCloseFile (ifcfg);
+	ASSERT (g_file_test (TEST_SCRATCH_ALIAS_BASE ":2", G_FILE_TEST_EXISTS),
+	        "wired-aliases-write", "failed to write extra alias file");
+
+	ifcfg = svCreateFile (TEST_SCRATCH_ALIAS_BASE ":5");
+	svSetValue (ifcfg, "DEVICE", "alias0:5", FALSE);
+	svSetValue (ifcfg, "IPADDR", "192.168.1.5", FALSE);
+	svWriteFile (ifcfg, 0644, NULL);
+	svCloseFile (ifcfg);
+	ASSERT (g_file_test (TEST_SCRATCH_ALIAS_BASE ":5", G_FILE_TEST_EXISTS),
+	        "wired-aliases-write", "failed to write extra alias file");
+
+	/* Save the ifcfg */
+	success = writer_new_connection (connection,
+	                                 TEST_SCRATCH_DIR "/network-scripts/",
+	                                 &testfile,
+	                                 &error);
+	ASSERT (success == TRUE,
+	        "wired-aliases-write", "failed to write connection to disk: %s",
+	        (error && error->message) ? error->message : "(unknown)");
+
+	ASSERT (testfile != NULL,
+	        "wired-aliases-write", "didn't get ifcfg file path back after writing connection");
+
+	/* Re-check the alias files */
+	ASSERT (g_file_test (TEST_SCRATCH_ALIAS_BASE ":2", G_FILE_TEST_EXISTS),
+	        "wired-aliases-write", "saving failed to write ifcfg-alias0:2");
+	ASSERT (g_file_test (TEST_SCRATCH_ALIAS_BASE ":3", G_FILE_TEST_EXISTS),
+	        "wired-aliases-write", "saving failed to write ifcfg-alias0:3");
+	ASSERT (!g_file_test (TEST_SCRATCH_ALIAS_BASE ":5", G_FILE_TEST_EXISTS),
+	        "wired-aliases-write", "saving failed to delete unused ifcfg-alias0:5");
+
+	/* re-read the connection for comparison */
+	reread = connection_from_file (testfile,
+	                               NULL,
+	                               TYPE_ETHERNET,
+	                               NULL,
+	                               &unmanaged,
+	                               &keyfile,
+	                               &routefile,
+	                               &route6file,
+	                               &error,
+	                               &ignore_error);
+	unlink (testfile);
+	unlink (TEST_SCRATCH_ALIAS_BASE ":2");
+	unlink (TEST_SCRATCH_ALIAS_BASE ":3");
+
+	ASSERT (reread != NULL,
+	        "wired-aliases-write-reread", "failed to read %s: %s", testfile, error->message);
+
+	ASSERT (nm_connection_verify (reread, &error),
+	        "wired-aliases-write-reread-verify", "failed to verify %s: %s", testfile, error->message);
+
+	/* nm_connection_compare() is not guaranteed to succeed, because the
+	 * aliases get read back in essentially random order. So just
+	 * verify the aliases manually.
+	 */
+	s_ip4 = nm_connection_get_setting_ip4_config (connection);
+	ASSERT (nm_setting_ip4_config_get_num_addresses (s_ip4) == num_addresses,
+	        "wired-aliases-write-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
+	        testfile,
+	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
+	        NM_SETTING_IP4_CONFIG_ADDRESSES);
+
+	/* Addresses */
+	for (i = 0; i < num_addresses; i++) {
+		guint32 addrbytes;
+
+		addr = nm_setting_ip4_config_get_address (s_ip4, i);
+		ASSERT (addr,
+		        "wired-aliases-write-verify-ip4", "failed to verify %s: missing IP4 address #%d",
+		        testfile,
+		        i);
+
+		addrbytes = nm_ip4_address_get_address (addr);
+		for (j = 0; j < num_addresses; j++) {
+			if (addrbytes == ip[j])
+				break;
+		}
+
+		ASSERT (j < num_addresses,
+		        "wired-aliases-write-verify-ip4", "failed to verify %s: unexpected IP4 address #%d",
+		        testfile,
+		        i);
+
+		ASSERT (nm_ip4_address_get_prefix (addr) == prefix,
+		        "wired-aliases-write-verify-ip4", "failed to verify %s: unexpected IP4 address prefix #%d",
+		        testfile,
+		        i);
+
+		ASSERT (nm_ip4_address_get_gateway (addr) == gw,
+		        "wired-aliases-write-verify-ip4", "failed to verify %s: unexpected IP4 address gateway #%d",
+		        testfile,
+		        i);
+
+		ASSERT (g_strcmp0 (NM_UTILS_PRIVATE_CALL (nm_setting_ip4_config_get_address_label (s_ip4, i)), label[j]) == 0,
+		        "wired-aliases-write-verify-ip4", "failed to verify %s: unexpected IP4 address label #%d",
+		        testfile,
+		        i);
+
+		ip[j] = 0;
+	}
+
+	for (i = 0; i < num_addresses; i++) {
+		ASSERT (ip[i] == 0,
+		        "wired-aliases-write-verify-ip4", "failed to verify %s: did not find IP4 address 0x%08x",
+		        testfile,
+		        ip[i]);
+	}
+
+	g_free (testfile);
+	g_free (keyfile);
+	g_free (routefile);
+	g_free (route6file);
+	g_object_unref (connection);
+	g_object_unref (reread);
+}
+
+static void
+test_write_gateway (void)
+{
+	NMConnection *connection, *reread;
+	NMSettingConnection *s_con;
+	NMSettingWired *s_wired;
+	NMSettingIP4Config *s_ip4;
+	char *uuid, *testfile = NULL, *val;
+	gboolean success;
+	GError *error = NULL;
+	shvarFile *f;
+	NMIP4Address *addr;
+	const char *ip1_str = "1.1.1.3";
+	const char *ip2_str = "2.2.2.5";
+	const char *gw1_str = "1.1.1.254";
+	const char *gw2_str = "2.2.2.254";
+	struct in_addr ip1, ip2, gw1, gw2;
+	const guint32 prefix = 24;
+
+	connection = nm_connection_new ();
+
+	/* Connection setting */
+	s_con = (NMSettingConnection *) nm_setting_connection_new ();
+	nm_connection_add_setting (connection, NM_SETTING (s_con));
+
+	uuid = nm_utils_uuid_generate ();
+	g_object_set (s_con,
+	              NM_SETTING_CONNECTION_ID, "Test Write Static Addresses Gateway",
+	              NM_SETTING_CONNECTION_UUID, uuid,
+	              NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME,
+	              NULL);
+	g_free (uuid);
+
+	/* Wired setting */
+	s_wired = (NMSettingWired *) nm_setting_wired_new ();
+	nm_connection_add_setting (connection, NM_SETTING (s_wired));
+
+	/* IP4 setting */
+	s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
+	nm_connection_add_setting (connection, NM_SETTING (s_ip4));
+
+	g_object_set (s_ip4,
+	              NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL,
+	              NM_SETTING_IP4_CONFIG_MAY_FAIL, TRUE,
+	              NULL);
+
+	inet_pton (AF_INET, ip1_str, &ip1);
+	inet_pton (AF_INET, ip2_str, &ip2);
+	inet_pton (AF_INET, gw1_str, &gw1);
+	inet_pton (AF_INET, gw2_str, &gw2);
+
+	addr = nm_ip4_address_new ();
+	nm_ip4_address_set_address (addr, ip1.s_addr);
+	nm_ip4_address_set_prefix (addr, prefix);
+	nm_ip4_address_set_gateway (addr, gw1.s_addr);
+	nm_setting_ip4_config_add_address (s_ip4, addr);
+	nm_ip4_address_unref (addr);
+
+	addr = nm_ip4_address_new ();
+	nm_ip4_address_set_address (addr, ip2.s_addr);
+	nm_ip4_address_set_prefix (addr, prefix);
+	nm_ip4_address_set_gateway (addr, gw2.s_addr);
+	nm_setting_ip4_config_add_address (s_ip4, addr);
+	nm_ip4_address_unref (addr);
+
+	success = nm_connection_verify (connection, &error);
+	g_assert_no_error (error);
+	g_assert (success);
+
+	/* Save the ifcfg */
+	success = writer_new_connection (connection,
+	                                 TEST_SCRATCH_DIR "/network-scripts/",
+	                                 &testfile,
+	                                 &error);
+	g_assert_no_error (error);
+	g_assert (success);
+
+	f = svOpenFile (testfile, &error);
+	g_assert_no_error (error);
+	g_assert (f);
+
+	/* re-read the file to check that the keys was written as IPADDR, GATEWAY and IPADDR1, GATEWAY1 */
+	val = svGetValue (f, "IPADDR", FALSE);
+	g_assert (val);
+	g_assert_cmpstr (val, ==, ip1_str);
+	g_free (val);
+
+	val = svGetValue (f, "IPADDR1", FALSE);
+	g_assert (val);
+	g_assert_cmpstr (val, ==, ip2_str);
+	g_free (val);
+
+	val = svGetValue (f, "IPADDR0", FALSE);
+	g_assert (val == NULL);
+
+	val = svGetValue (f, "PREFIX", FALSE);
+	g_assert (val);
+	g_assert_cmpstr (val, ==, "24");
+	g_free (val);
+
+	val = svGetValue (f, "PREFIX1", FALSE);
+	g_assert (val);
+	g_assert_cmpstr (val, ==, "24");
+	g_free (val);
+
+	val = svGetValue (f, "PREFIX0", FALSE);
+	g_assert (val == NULL);
+
+	val = svGetValue (f, "GATEWAY", FALSE);
+	g_assert (val);
+	g_assert_cmpstr (val, ==, gw1_str);
+	g_free (val);
+
+	val = svGetValue (f, "GATEWAY1", FALSE);
+	g_assert (val);
+	g_assert_cmpstr (val, ==, gw2_str);
+	g_free (val);
+
+	val = svGetValue (f, "GATEWAY0", FALSE);
+	g_assert (val == NULL);
+
+
+	svCloseFile (f);
+
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_utils_normalize_connection (connection, TRUE);
+
+	/* re-read the connection for comparison */
+	reread = connection_from_file (testfile, NULL, TYPE_WIRELESS, NULL,
+	                               NULL, NULL, NULL, NULL, &error, NULL);
+	unlink (testfile);
+	g_assert_no_error (error);
+	g_assert (reread);
+
+	success = nm_connection_verify (reread, &error);
+	g_assert_no_error (error);
+	g_assert (success);
+
+	g_assert (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT));
+
+	g_free (testfile);
+	g_object_unref (connection);
+	g_object_unref (reread);
+}
+
+
 static void
 test_write_wifi_open (void)
 {
@@ -8133,14 +8493,9 @@ test_write_wifi_open (void)
 	char *tmp;
 
 	connection = nm_connection_new ();
-	ASSERT (connection != NULL,
-	        "wifi-open-write", "failed to allocate new connection");
 
 	/* Connection setting */
 	s_con = (NMSettingConnection *) nm_setting_connection_new ();
-	ASSERT (s_con != NULL,
-	        "wifi-open-write", "failed to allocate new %s setting",
-	        NM_SETTING_CONNECTION_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_con));
 
 	uuid = nm_utils_uuid_generate ();
@@ -8154,9 +8509,6 @@ test_write_wifi_open (void)
 
 	/* Wifi setting */
 	s_wifi = (NMSettingWireless *) nm_setting_wireless_new ();
-	ASSERT (s_wifi != NULL,
-	        "wifi-open-write", "failed to allocate new %s setting",
-	        NM_SETTING_WIRELESS_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_wifi));
 
 	ssid = g_byte_array_sized_new (sizeof (ssid_data));
@@ -8182,18 +8534,12 @@ test_write_wifi_open (void)
 
 	/* IP4 setting */
 	s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
-	ASSERT (s_ip4 != NULL,
-			"wifi-open-write", "failed to allocate new %s setting",
-			NM_SETTING_IP4_CONFIG_SETTING_NAME);
 	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);
 
 	/* IP6 setting */
 	s_ip6 = (NMSettingIP6Config *) nm_setting_ip6_config_new ();
-	ASSERT (s_ip6 != NULL,
-	        "wifi-open-write", "failed to allocate new %s setting",
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
 
 	g_object_set (s_ip6,
@@ -8217,6 +8563,9 @@ test_write_wifi_open (void)
 	ASSERT (testfile != NULL,
 	        "wifi-open-write", "didn't get ifcfg file path back after writing connection");
 
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_utils_normalize_connection (connection, TRUE);
+
 	/* re-read the connection for comparison */
 	reread = connection_from_file (testfile,
 	                               NULL,
@@ -8228,11 +8577,12 @@ test_write_wifi_open (void)
 	                               &route6file,
 	                               &error,
 	                               &ignore_error);
+	g_assert_no_error (error);
 
 	/* Now make sure that the ESSID item isn't double-quoted (rh #606518) */
-	ifcfg = svNewFile (testfile);
-	ASSERT (ifcfg != NULL,
-	        "wifi-open-write-reread", "failed to load %s as shvarfile", testfile);
+	ifcfg = svOpenFile (testfile, &error);
+	g_assert_no_error (error);
+	g_assert (ifcfg != NULL);
 
 	tmp = svGetValue (ifcfg, "ESSID", TRUE);
 	ASSERT (tmp != NULL,
@@ -8286,14 +8636,9 @@ test_write_wifi_open_hex_ssid (void)
 	const unsigned char ssid_data[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd };
 
 	connection = nm_connection_new ();
-	ASSERT (connection != NULL,
-	        "wifi-open-hex-ssid-write", "failed to allocate new connection");
 
 	/* Connection setting */
 	s_con = (NMSettingConnection *) nm_setting_connection_new ();
-	ASSERT (s_con != NULL,
-	        "wifi-open-hex-ssid-write", "failed to allocate new %s setting",
-	        NM_SETTING_CONNECTION_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_con));
 
 	uuid = nm_utils_uuid_generate ();
@@ -8307,9 +8652,6 @@ test_write_wifi_open_hex_ssid (void)
 
 	/* Wifi setting */
 	s_wifi = (NMSettingWireless *) nm_setting_wireless_new ();
-	ASSERT (s_wifi != NULL,
-	        "wifi-open-hex-ssid-write", "failed to allocate new %s setting",
-	        NM_SETTING_WIRELESS_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_wifi));
 
 	ssid = g_byte_array_sized_new (sizeof (ssid_data));
@@ -8324,18 +8666,12 @@ test_write_wifi_open_hex_ssid (void)
 
 	/* IP4 setting */
 	s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
-	ASSERT (s_ip4 != NULL,
-			"wifi-open-hex-ssid-write", "failed to allocate new %s setting",
-			NM_SETTING_IP4_CONFIG_SETTING_NAME);
 	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);
 
 	/* IP6 setting */
 	s_ip6 = (NMSettingIP6Config *) nm_setting_ip6_config_new ();
-	ASSERT (s_ip6 != NULL,
-	        "wifi-open-hex-ssid-write", "failed to allocate new %s setting",
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
 
 	g_object_set (s_ip6,
@@ -8359,6 +8695,9 @@ test_write_wifi_open_hex_ssid (void)
 	ASSERT (testfile != NULL,
 	        "wifi-open-hex-ssid-write", "didn't get ifcfg file path back after writing connection");
 
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_utils_normalize_connection (connection, TRUE);
+
 	/* re-read the connection for comparison */
 	reread = connection_from_file (testfile,
 	                               NULL,
@@ -8414,14 +8753,9 @@ test_write_wifi_wep (void)
 	struct stat statbuf;
 
 	connection = nm_connection_new ();
-	ASSERT (connection != NULL,
-	        "wifi-wep-write", "failed to allocate new connection");
 
 	/* Connection setting */
 	s_con = (NMSettingConnection *) nm_setting_connection_new ();
-	ASSERT (s_con != NULL,
-	        "wifi-wep-write", "failed to allocate new %s setting",
-	        NM_SETTING_CONNECTION_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_con));
 
 	uuid = nm_utils_uuid_generate ();
@@ -8435,9 +8769,6 @@ test_write_wifi_wep (void)
 
 	/* Wifi setting */
 	s_wifi = (NMSettingWireless *) nm_setting_wireless_new ();
-	ASSERT (s_wifi != NULL,
-	        "wifi-wep-write", "failed to allocate new %s setting",
-	        NM_SETTING_WIRELESS_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_wifi));
 
 	ssid = g_byte_array_sized_new (sizeof (ssid_data));
@@ -8446,16 +8777,12 @@ test_write_wifi_wep (void)
 	g_object_set (s_wifi,
 	              NM_SETTING_WIRELESS_SSID, ssid,
 	              NM_SETTING_WIRELESS_MODE, "infrastructure",
-	              NM_SETTING_WIRELESS_SEC, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
 	              NULL);
 
 	g_byte_array_free (ssid, TRUE);
 
 	/* Wireless security setting */
 	s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
-	ASSERT (s_wsec != NULL,
-			"wifi-wep-write", "failed to allocate new %s setting",
-			NM_SETTING_WIRELESS_SECURITY_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_wsec));
 
 	g_object_set (s_wsec,
@@ -8470,18 +8797,12 @@ test_write_wifi_wep (void)
 
 	/* IP4 setting */
 	s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
-	ASSERT (s_ip4 != NULL,
-			"wifi-wep-write", "failed to allocate new %s setting",
-			NM_SETTING_IP4_CONFIG_SETTING_NAME);
 	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);
 
 	/* IP6 setting */
 	s_ip6 = (NMSettingIP6Config *) nm_setting_ip6_config_new ();
-	ASSERT (s_ip6 != NULL,
-	        "wifi-wep-write", "failed to allocate new %s setting",
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
 
 	g_object_set (s_ip6,
@@ -8505,6 +8826,9 @@ test_write_wifi_wep (void)
 	ASSERT (testfile != NULL,
 	        "wifi-wep-write", "didn't get ifcfg file path back after writing connection");
 
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_utils_normalize_connection (connection, TRUE);
+
 	/* re-read the connection for comparison */
 	reread = connection_from_file (testfile,
 	                               NULL,
@@ -8577,14 +8901,9 @@ test_write_wifi_wep_adhoc (void)
 	const guint32 prefix = 24;
 
 	connection = nm_connection_new ();
-	ASSERT (connection != NULL,
-	        "wifi-wep-adhoc-write", "failed to allocate new connection");
 
 	/* Connection setting */
 	s_con = (NMSettingConnection *) nm_setting_connection_new ();
-	ASSERT (s_con != NULL,
-	        "wifi-wep-adhoc-write", "failed to allocate new %s setting",
-	        NM_SETTING_CONNECTION_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_con));
 
 	uuid = nm_utils_uuid_generate ();
@@ -8598,9 +8917,6 @@ test_write_wifi_wep_adhoc (void)
 
 	/* Wifi setting */
 	s_wifi = (NMSettingWireless *) nm_setting_wireless_new ();
-	ASSERT (s_wifi != NULL,
-	        "wifi-wep-adhoc-write", "failed to allocate new %s setting",
-	        NM_SETTING_WIRELESS_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_wifi));
 
 	ssid = g_byte_array_sized_new (sizeof (ssid_data));
@@ -8609,16 +8925,12 @@ test_write_wifi_wep_adhoc (void)
 	g_object_set (s_wifi,
 	              NM_SETTING_WIRELESS_SSID, ssid,
 	              NM_SETTING_WIRELESS_MODE, "adhoc",
-	              NM_SETTING_WIRELESS_SEC, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
 	              NULL);
 
 	g_byte_array_free (ssid, TRUE);
 
 	/* Wireless security setting */
 	s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
-	ASSERT (s_wsec != NULL,
-			"wifi-wep-adhoc-write", "failed to allocate new %s setting",
-			NM_SETTING_WIRELESS_SECURITY_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_wsec));
 
 	g_object_set (s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "none", NULL);
@@ -8626,9 +8938,6 @@ test_write_wifi_wep_adhoc (void)
 
 	/* IP4 setting */
 	s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
-	ASSERT (s_ip4 != NULL,
-			"wifi-wep-adhoc-write", "failed to allocate new %s setting",
-			NM_SETTING_IP4_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip4));
 
 	g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, NULL);
@@ -8645,9 +8954,6 @@ test_write_wifi_wep_adhoc (void)
 
 	/* IP6 setting */
 	s_ip6 = (NMSettingIP6Config *) nm_setting_ip6_config_new ();
-	ASSERT (s_ip6 != NULL,
-	        "wifi-wep-adhoc-write", "failed to allocate new %s setting",
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
 
 	g_object_set (s_ip6,
@@ -8671,6 +8977,9 @@ test_write_wifi_wep_adhoc (void)
 	ASSERT (testfile != NULL,
 	        "wifi-wep-adhoc-write", "didn't get ifcfg file path back after writing connection");
 
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_utils_normalize_connection (connection, TRUE);
+
 	/* re-read the connection for comparison */
 	reread = connection_from_file (testfile,
 	                               NULL,
@@ -8738,14 +9047,9 @@ test_write_wifi_wep_passphrase (void)
 	struct stat statbuf;
 
 	connection = nm_connection_new ();
-	ASSERT (connection != NULL,
-	        "wifi-wep-passphrase-write", "failed to allocate new connection");
 
 	/* Connection setting */
 	s_con = (NMSettingConnection *) nm_setting_connection_new ();
-	ASSERT (s_con != NULL,
-	        "wifi-wep-passphrase-write", "failed to allocate new %s setting",
-	        NM_SETTING_CONNECTION_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_con));
 
 	uuid = nm_utils_uuid_generate ();
@@ -8759,9 +9063,6 @@ test_write_wifi_wep_passphrase (void)
 
 	/* Wifi setting */
 	s_wifi = (NMSettingWireless *) nm_setting_wireless_new ();
-	ASSERT (s_wifi != NULL,
-	        "wifi-wep-passphrase-write", "failed to allocate new %s setting",
-	        NM_SETTING_WIRELESS_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_wifi));
 
 	ssid = g_byte_array_sized_new (sizeof (ssid_data));
@@ -8770,16 +9071,12 @@ test_write_wifi_wep_passphrase (void)
 	g_object_set (s_wifi,
 	              NM_SETTING_WIRELESS_SSID, ssid,
 	              NM_SETTING_WIRELESS_MODE, "infrastructure",
-	              NM_SETTING_WIRELESS_SEC, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
 	              NULL);
 
 	g_byte_array_free (ssid, TRUE);
 
 	/* Wireless security setting */
 	s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
-	ASSERT (s_wsec != NULL,
-			"wifi-wep-passphrase-write", "failed to allocate new %s setting",
-			NM_SETTING_WIRELESS_SECURITY_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_wsec));
 
 	g_object_set (s_wsec,
@@ -8792,18 +9089,12 @@ test_write_wifi_wep_passphrase (void)
 
 	/* IP4 setting */
 	s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
-	ASSERT (s_ip4 != NULL,
-			"wifi-wep-passphrase-write", "failed to allocate new %s setting",
-			NM_SETTING_IP4_CONFIG_SETTING_NAME);
 	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);
 
 	/* IP6 setting */
 	s_ip6 = (NMSettingIP6Config *) nm_setting_ip6_config_new ();
-	ASSERT (s_ip6 != NULL,
-	        "wifi-wep-adhoc-write", "failed to allocate new %s setting",
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
 
 	g_object_set (s_ip6,
@@ -8827,6 +9118,9 @@ test_write_wifi_wep_passphrase (void)
 	ASSERT (testfile != NULL,
 	        "wifi-wep-passphrase-write", "didn't get ifcfg file path back after writing connection");
 
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_utils_normalize_connection (connection, TRUE);
+
 	/* re-read the connection for comparison */
 	reread = connection_from_file (testfile,
 	                               NULL,
@@ -8894,14 +9188,9 @@ test_write_wifi_wep_40_ascii (void)
 	struct stat statbuf;
 
 	connection = nm_connection_new ();
-	ASSERT (connection != NULL,
-	        "wifi-wep-40-ascii-write", "failed to allocate new connection");
 
 	/* Connection setting */
 	s_con = (NMSettingConnection *) nm_setting_connection_new ();
-	ASSERT (s_con != NULL,
-	        "wifi-wep-40-ascii-write", "failed to allocate new %s setting",
-	        NM_SETTING_CONNECTION_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_con));
 
 	uuid = nm_utils_uuid_generate ();
@@ -8915,9 +9204,6 @@ test_write_wifi_wep_40_ascii (void)
 
 	/* Wifi setting */
 	s_wifi = (NMSettingWireless *) nm_setting_wireless_new ();
-	ASSERT (s_wifi != NULL,
-	        "wifi-wep-40-ascii-write", "failed to allocate new %s setting",
-	        NM_SETTING_WIRELESS_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_wifi));
 
 	ssid = g_byte_array_sized_new (sizeof (ssid_data));
@@ -8926,16 +9212,12 @@ test_write_wifi_wep_40_ascii (void)
 	g_object_set (s_wifi,
 	              NM_SETTING_WIRELESS_SSID, ssid,
 	              NM_SETTING_WIRELESS_MODE, "infrastructure",
-	              NM_SETTING_WIRELESS_SEC, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
 	              NULL);
 
 	g_byte_array_free (ssid, TRUE);
 
 	/* Wireless security setting */
 	s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
-	ASSERT (s_wsec != NULL,
-			"wifi-wep-40-ascii-write", "failed to allocate new %s setting",
-			NM_SETTING_WIRELESS_SECURITY_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_wsec));
 
 	g_object_set (s_wsec,
@@ -8950,18 +9232,12 @@ test_write_wifi_wep_40_ascii (void)
 
 	/* IP4 setting */
 	s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
-	ASSERT (s_ip4 != NULL,
-			"wifi-wep-40-ascii-write", "failed to allocate new %s setting",
-			NM_SETTING_IP4_CONFIG_SETTING_NAME);
 	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);
 
 	/* IP6 setting */
 	s_ip6 = (NMSettingIP6Config *) nm_setting_ip6_config_new ();
-	ASSERT (s_ip6 != NULL,
-	        "wifi-wep-40-ascii-write", "failed to allocate new %s setting",
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
 
 	g_object_set (s_ip6,
@@ -8985,6 +9261,9 @@ test_write_wifi_wep_40_ascii (void)
 	ASSERT (testfile != NULL,
 	        "wifi-wep-40-ascii-write", "didn't get ifcfg file path back after writing connection");
 
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_utils_normalize_connection (connection, TRUE);
+
 	/* re-read the connection for comparison */
 	reread = connection_from_file (testfile,
 	                               NULL,
@@ -9052,14 +9331,9 @@ test_write_wifi_wep_104_ascii (void)
 	struct stat statbuf;
 
 	connection = nm_connection_new ();
-	ASSERT (connection != NULL,
-	        "wifi-wep-104-ascii-write", "failed to allocate new connection");
 
 	/* Connection setting */
 	s_con = (NMSettingConnection *) nm_setting_connection_new ();
-	ASSERT (s_con != NULL,
-	        "wifi-wep-104-ascii-write", "failed to allocate new %s setting",
-	        NM_SETTING_CONNECTION_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_con));
 
 	uuid = nm_utils_uuid_generate ();
@@ -9073,9 +9347,6 @@ test_write_wifi_wep_104_ascii (void)
 
 	/* Wifi setting */
 	s_wifi = (NMSettingWireless *) nm_setting_wireless_new ();
-	ASSERT (s_wifi != NULL,
-	        "wifi-wep-104-ascii-write", "failed to allocate new %s setting",
-	        NM_SETTING_WIRELESS_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_wifi));
 
 	ssid = g_byte_array_sized_new (sizeof (ssid_data));
@@ -9084,16 +9355,12 @@ test_write_wifi_wep_104_ascii (void)
 	g_object_set (s_wifi,
 	              NM_SETTING_WIRELESS_SSID, ssid,
 	              NM_SETTING_WIRELESS_MODE, "infrastructure",
-	              NM_SETTING_WIRELESS_SEC, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
 	              NULL);
 
 	g_byte_array_free (ssid, TRUE);
 
 	/* Wireless security setting */
 	s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
-	ASSERT (s_wsec != NULL,
-			"wifi-wep-104-ascii-write", "failed to allocate new %s setting",
-			NM_SETTING_WIRELESS_SECURITY_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_wsec));
 
 	g_object_set (s_wsec,
@@ -9108,18 +9375,12 @@ test_write_wifi_wep_104_ascii (void)
 
 	/* IP4 setting */
 	s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
-	ASSERT (s_ip4 != NULL,
-			"wifi-wep-104-ascii-write", "failed to allocate new %s setting",
-			NM_SETTING_IP4_CONFIG_SETTING_NAME);
 	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);
 
 	/* IP6 setting */
 	s_ip6 = (NMSettingIP6Config *) nm_setting_ip6_config_new ();
-	ASSERT (s_ip6 != NULL,
-	        "wifi-wep-104-ascii-write", "failed to allocate new %s setting",
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
 
 	g_object_set (s_ip6,
@@ -9143,6 +9404,9 @@ test_write_wifi_wep_104_ascii (void)
 	ASSERT (testfile != NULL,
 	        "wifi-wep-104-ascii-write", "didn't get ifcfg file path back after writing connection");
 
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_utils_normalize_connection (connection, TRUE);
+
 	/* re-read the connection for comparison */
 	reread = connection_from_file (testfile,
 	                               NULL,
@@ -9210,14 +9474,9 @@ test_write_wifi_leap (void)
 	struct stat statbuf;
 
 	connection = nm_connection_new ();
-	ASSERT (connection != NULL,
-	        "wifi-leap-write", "failed to allocate new connection");
 
 	/* Connection setting */
 	s_con = (NMSettingConnection *) nm_setting_connection_new ();
-	ASSERT (s_con != NULL,
-	        "wifi-leap-write", "failed to allocate new %s setting",
-	        NM_SETTING_CONNECTION_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_con));
 
 	uuid = nm_utils_uuid_generate ();
@@ -9231,9 +9490,6 @@ test_write_wifi_leap (void)
 
 	/* Wifi setting */
 	s_wifi = (NMSettingWireless *) nm_setting_wireless_new ();
-	ASSERT (s_wifi != NULL,
-	        "wifi-leap-write", "failed to allocate new %s setting",
-	        NM_SETTING_WIRELESS_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_wifi));
 
 	ssid = g_byte_array_sized_new (sizeof (ssid_data));
@@ -9242,16 +9498,12 @@ test_write_wifi_leap (void)
 	g_object_set (s_wifi,
 	              NM_SETTING_WIRELESS_SSID, ssid,
 	              NM_SETTING_WIRELESS_MODE, "infrastructure",
-	              NM_SETTING_WIRELESS_SEC, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
 	              NULL);
 
 	g_byte_array_free (ssid, TRUE);
 
 	/* Wireless security setting */
 	s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
-	ASSERT (s_wsec != NULL,
-			"wifi-leap-write", "failed to allocate new %s setting",
-			NM_SETTING_WIRELESS_SECURITY_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_wsec));
 
 	g_object_set (s_wsec,
@@ -9263,18 +9515,12 @@ test_write_wifi_leap (void)
 
 	/* IP4 setting */
 	s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
-	ASSERT (s_ip4 != NULL,
-			"wifi-leap-write", "failed to allocate new %s setting",
-			NM_SETTING_IP4_CONFIG_SETTING_NAME);
 	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);
 
 	/* IP6 setting */
 	s_ip6 = (NMSettingIP6Config *) nm_setting_ip6_config_new ();
-	ASSERT (s_ip6 != NULL,
-	        "wifi-leap-write", "failed to allocate new %s setting",
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
 
 	g_object_set (s_ip6,
@@ -9298,6 +9544,9 @@ test_write_wifi_leap (void)
 	ASSERT (testfile != NULL,
 	        "wifi-leap-write", "didn't get ifcfg file path back after writing connection");
 
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_utils_normalize_connection (connection, TRUE);
+
 	/* re-read the connection for comparison */
 	reread = connection_from_file (testfile,
 	                               NULL,
@@ -9389,7 +9638,6 @@ test_write_wifi_leap_secret_flags (NMSettingSecretFlags flags)
 	g_object_set (s_wifi,
 	              NM_SETTING_WIRELESS_SSID, ssid,
 	              NM_SETTING_WIRELESS_MODE, "infrastructure",
-	              NM_SETTING_WIRELESS_SEC, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
 	              NULL);
 	g_byte_array_free (ssid, TRUE);
 
@@ -9435,6 +9683,9 @@ test_write_wifi_leap_secret_flags (NMSettingSecretFlags flags)
 	g_assert (success);
 	g_assert (testfile);
 
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_utils_normalize_connection (connection, TRUE);
+
 	/* re-read the connection for comparison */
 	reread = connection_from_file (testfile,
 	                               NULL,
@@ -9505,14 +9756,9 @@ test_write_wifi_wpa_psk (const char *name,
 	g_return_if_fail (psk != NULL);
 
 	connection = nm_connection_new ();
-	ASSERT (connection != NULL,
-	        test_name, "failed to allocate new connection");
 
 	/* Connection setting */
 	s_con = (NMSettingConnection *) nm_setting_connection_new ();
-	ASSERT (s_con != NULL,
-	        test_name, "failed to allocate new %s setting",
-	        NM_SETTING_CONNECTION_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_con));
 
 	uuid = nm_utils_uuid_generate ();
@@ -9526,9 +9772,6 @@ test_write_wifi_wpa_psk (const char *name,
 
 	/* Wifi setting */
 	s_wifi = (NMSettingWireless *) nm_setting_wireless_new ();
-	ASSERT (s_wifi != NULL,
-	        test_name, "failed to allocate new %s setting",
-	        NM_SETTING_WIRELESS_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_wifi));
 
 	ssid = g_byte_array_sized_new (sizeof (ssid_data));
@@ -9537,16 +9780,12 @@ test_write_wifi_wpa_psk (const char *name,
 	g_object_set (s_wifi,
 	              NM_SETTING_WIRELESS_SSID, ssid,
 	              NM_SETTING_WIRELESS_MODE, "infrastructure",
-	              NM_SETTING_WIRELESS_SEC, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
 	              NULL);
 
 	g_byte_array_free (ssid, TRUE);
 
 	/* Wireless security setting */
 	s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
-	ASSERT (s_wsec != NULL,
-			test_name, "failed to allocate new %s setting",
-			NM_SETTING_WIRELESS_SECURITY_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_wsec));
 
 	g_object_set (s_wsec,
@@ -9571,18 +9810,12 @@ test_write_wifi_wpa_psk (const char *name,
 
 	/* IP4 setting */
 	s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
-	ASSERT (s_ip4 != NULL,
-			test_name, "failed to allocate new %s setting",
-			NM_SETTING_IP4_CONFIG_SETTING_NAME);
 	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);
 
 	/* IP6 setting */
 	s_ip6 = (NMSettingIP6Config *) nm_setting_ip6_config_new ();
-	ASSERT (s_ip6 != NULL,
-	        test_name, "failed to allocate new %s setting",
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
 
 	g_object_set (s_ip6,
@@ -9606,6 +9839,9 @@ test_write_wifi_wpa_psk (const char *name,
 	ASSERT (testfile != NULL,
 	        test_name, "didn't get ifcfg file path back after writing connection");
 
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_utils_normalize_connection (connection, TRUE);
+
 	/* re-read the connection for comparison */
 	reread = connection_from_file (testfile,
 	                               NULL,
@@ -9671,14 +9907,9 @@ test_write_wifi_wpa_psk_adhoc (void)
 	const guint32 prefix = 24;
 
 	connection = nm_connection_new ();
-	ASSERT (connection != NULL,
-	        "wifi-wpa-psk-adhoc-write", "failed to allocate new connection");
 
 	/* Connection setting */
 	s_con = (NMSettingConnection *) nm_setting_connection_new ();
-	ASSERT (s_con != NULL,
-	        "wifi-wpa-psk-adhoc-write", "failed to allocate new %s setting",
-	        NM_SETTING_CONNECTION_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_con));
 
 	uuid = nm_utils_uuid_generate ();
@@ -9692,9 +9923,6 @@ test_write_wifi_wpa_psk_adhoc (void)
 
 	/* Wifi setting */
 	s_wifi = (NMSettingWireless *) nm_setting_wireless_new ();
-	ASSERT (s_wifi != NULL,
-	        "wifi-wpa-psk-adhoc-write", "failed to allocate new %s setting",
-	        NM_SETTING_WIRELESS_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_wifi));
 
 	ssid = g_byte_array_sized_new (sizeof (ssid_data));
@@ -9703,7 +9931,6 @@ test_write_wifi_wpa_psk_adhoc (void)
 	g_object_set (s_wifi,
 	              NM_SETTING_WIRELESS_SSID, ssid,
 	              NM_SETTING_WIRELESS_MODE, "adhoc",
-	              NM_SETTING_WIRELESS_SEC, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
 	              NM_SETTING_WIRELESS_CHANNEL, 11,
 	              NM_SETTING_WIRELESS_BAND, "bg",
 	              NULL);
@@ -9712,9 +9939,6 @@ test_write_wifi_wpa_psk_adhoc (void)
 
 	/* Wireless security setting */
 	s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
-	ASSERT (s_wsec != NULL,
-			"wifi-wpa-psk-adhoc-write", "failed to allocate new %s setting",
-			NM_SETTING_WIRELESS_SECURITY_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_wsec));
 
 	g_object_set (s_wsec,
@@ -9727,9 +9951,6 @@ test_write_wifi_wpa_psk_adhoc (void)
 
 	/* IP4 setting */
 	s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
-	ASSERT (s_ip4 != NULL,
-			"wifi-wpa-psk-adhoc-write", "failed to allocate new %s setting",
-			NM_SETTING_IP4_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip4));
 
 	g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, NULL);
@@ -9746,9 +9967,6 @@ test_write_wifi_wpa_psk_adhoc (void)
 
 	/* IP6 setting */
 	s_ip6 = (NMSettingIP6Config *) nm_setting_ip6_config_new ();
-	ASSERT (s_ip6 != NULL,
-	        "wifi-wpa-psk-adhoc-write", "failed to allocate new %s setting",
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
 
 	g_object_set (s_ip6,
@@ -9772,6 +9990,9 @@ test_write_wifi_wpa_psk_adhoc (void)
 	ASSERT (testfile != NULL,
 	        "wifi-wpa-psk-adhoc-write", "didn't get ifcfg file path back after writing connection");
 
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_utils_normalize_connection (connection, TRUE);
+
 	/* re-read the connection for comparison */
 	reread = connection_from_file (testfile,
 	                               NULL,
@@ -9831,14 +10052,9 @@ test_write_wifi_wpa_eap_tls (void)
 	const char *ssid_data = "blahblah";
 
 	connection = nm_connection_new ();
-	ASSERT (connection != NULL,
-	        "wifi-wpa-eap-tls-write", "failed to allocate new connection");
 
 	/* Connection setting */
 	s_con = (NMSettingConnection *) nm_setting_connection_new ();
-	ASSERT (s_con != NULL,
-	        "wifi-wpa-eap-tls-write", "failed to allocate new %s setting",
-	        NM_SETTING_CONNECTION_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_con));
 
 	uuid = nm_utils_uuid_generate ();
@@ -9852,9 +10068,6 @@ test_write_wifi_wpa_eap_tls (void)
 
 	/* Wifi setting */
 	s_wifi = (NMSettingWireless *) nm_setting_wireless_new ();
-	ASSERT (s_wifi != NULL,
-	        "wifi-wpa-eap-tls-write", "failed to allocate new %s setting",
-	        NM_SETTING_WIRELESS_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_wifi));
 
 	ssid = g_byte_array_sized_new (strlen (ssid_data));
@@ -9863,16 +10076,12 @@ test_write_wifi_wpa_eap_tls (void)
 	g_object_set (s_wifi,
 	              NM_SETTING_WIRELESS_SSID, ssid,
 	              NM_SETTING_WIRELESS_MODE, "infrastructure",
-	              NM_SETTING_WIRELESS_SEC, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
 	              NULL);
 
 	g_byte_array_free (ssid, TRUE);
 
 	/* Wireless security setting */
 	s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
-	ASSERT (s_wsec != NULL,
-	        "wifi-wpa-eap-tls-write", "failed to allocate new %s setting",
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_wsec));
 
 	g_object_set (s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-eap", NULL);
@@ -9882,9 +10091,6 @@ test_write_wifi_wpa_eap_tls (void)
 
 	/* Wireless security setting */
 	s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
-	ASSERT (s_8021x != NULL,
-	        "wifi-wpa-eap-tls-write", "failed to allocate new %s setting",
-	        NM_SETTING_802_1X_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_8021x));
 
 	g_object_set (s_8021x, NM_SETTING_802_1X_IDENTITY, "Bill Smith", NULL);
@@ -9921,18 +10127,12 @@ test_write_wifi_wpa_eap_tls (void)
 
 	/* IP4 setting */
 	s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
-	ASSERT (s_ip4 != NULL,
-			"wifi-wpa-eap-tls-write", "failed to allocate new %s setting",
-			NM_SETTING_IP4_CONFIG_SETTING_NAME);
 	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);
 
 	/* IP6 setting */
 	s_ip6 = (NMSettingIP6Config *) nm_setting_ip6_config_new ();
-	ASSERT (s_ip6 != NULL,
-	        "wifi-wpa-eap-tls-write", "failed to allocate new %s setting",
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
 
 	g_object_set (s_ip6,
@@ -9956,6 +10156,9 @@ test_write_wifi_wpa_eap_tls (void)
 	ASSERT (testfile != NULL,
 	        "wifi-wpa-eap-tls-write", "didn't get ifcfg file path back after writing connection");
 
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_utils_normalize_connection (connection, TRUE);
+
 	/* re-read the connection for comparison */
 	reread = connection_from_file (testfile,
 	                               NULL,
@@ -10015,14 +10218,9 @@ test_write_wifi_wpa_eap_ttls_tls (void)
 	const char *ssid_data = "blahblah";
 
 	connection = nm_connection_new ();
-	ASSERT (connection != NULL,
-	        "wifi-wpa-eap-ttls-tls-write", "failed to allocate new connection");
 
 	/* Connection setting */
 	s_con = (NMSettingConnection *) nm_setting_connection_new ();
-	ASSERT (s_con != NULL,
-	        "wifi-wpa-eap-ttls-tls-write", "failed to allocate new %s setting",
-	        NM_SETTING_CONNECTION_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_con));
 
 	uuid = nm_utils_uuid_generate ();
@@ -10036,9 +10234,6 @@ test_write_wifi_wpa_eap_ttls_tls (void)
 
 	/* Wifi setting */
 	s_wifi = (NMSettingWireless *) nm_setting_wireless_new ();
-	ASSERT (s_wifi != NULL,
-	        "wifi-wpa-eap-ttls-tls-write", "failed to allocate new %s setting",
-	        NM_SETTING_WIRELESS_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_wifi));
 
 	ssid = g_byte_array_sized_new (strlen (ssid_data));
@@ -10047,16 +10242,12 @@ test_write_wifi_wpa_eap_ttls_tls (void)
 	g_object_set (s_wifi,
 	              NM_SETTING_WIRELESS_SSID, ssid,
 	              NM_SETTING_WIRELESS_MODE, "infrastructure",
-	              NM_SETTING_WIRELESS_SEC, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
 	              NULL);
 
 	g_byte_array_free (ssid, TRUE);
 
 	/* Wireless security setting */
 	s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
-	ASSERT (s_wsec != NULL,
-	        "wifi-wpa-eap-ttls-tls-write", "failed to allocate new %s setting",
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_wsec));
 
 	g_object_set (s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-eap", NULL);
@@ -10066,9 +10257,6 @@ test_write_wifi_wpa_eap_ttls_tls (void)
 
 	/* Wireless security setting */
 	s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
-	ASSERT (s_8021x != NULL,
-	        "wifi-wpa-eap-ttls-tls-write", "failed to allocate new %s setting",
-	        NM_SETTING_802_1X_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_8021x));
 
 	nm_setting_802_1x_add_eap_method (s_8021x, "ttls");
@@ -10123,18 +10311,12 @@ test_write_wifi_wpa_eap_ttls_tls (void)
 
 	/* IP4 setting */
 	s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
-	ASSERT (s_ip4 != NULL,
-			"wifi-wpa-eap-ttls-tls-write", "failed to allocate new %s setting",
-			NM_SETTING_IP4_CONFIG_SETTING_NAME);
 	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);
 
 	/* IP6 setting */
 	s_ip6 = (NMSettingIP6Config *) nm_setting_ip6_config_new ();
-	ASSERT (s_ip6 != NULL,
-	        "wifi-wpa-eap-ttls-tls-write", "failed to allocate new %s setting",
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
 
 	g_object_set (s_ip6,
@@ -10158,6 +10340,9 @@ test_write_wifi_wpa_eap_ttls_tls (void)
 	ASSERT (testfile != NULL,
 	        "wifi-wpa-eap-ttls-tls-write", "didn't get ifcfg file path back after writing connection");
 
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_utils_normalize_connection (connection, TRUE);
+
 	/* re-read the connection for comparison */
 	reread = connection_from_file (testfile,
 	                               NULL,
@@ -10217,14 +10402,9 @@ test_write_wifi_wpa_eap_ttls_mschapv2 (void)
 	const char *ssid_data = "blahblah";
 
 	connection = nm_connection_new ();
-	ASSERT (connection != NULL,
-	        "wifi-wpa-eap-ttls-mschapv2-write", "failed to allocate new connection");
 
 	/* Connection setting */
 	s_con = (NMSettingConnection *) nm_setting_connection_new ();
-	ASSERT (s_con != NULL,
-	        "wifi-wpa-eap-ttls-mschapv2-write", "failed to allocate new %s setting",
-	        NM_SETTING_CONNECTION_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_con));
 
 	uuid = nm_utils_uuid_generate ();
@@ -10238,9 +10418,6 @@ test_write_wifi_wpa_eap_ttls_mschapv2 (void)
 
 	/* Wifi setting */
 	s_wifi = (NMSettingWireless *) nm_setting_wireless_new ();
-	ASSERT (s_wifi != NULL,
-	        "wifi-wpa-eap-ttls-mschapv2-write", "failed to allocate new %s setting",
-	        NM_SETTING_WIRELESS_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_wifi));
 
 	ssid = g_byte_array_sized_new (strlen (ssid_data));
@@ -10249,16 +10426,12 @@ test_write_wifi_wpa_eap_ttls_mschapv2 (void)
 	g_object_set (s_wifi,
 	              NM_SETTING_WIRELESS_SSID, ssid,
 	              NM_SETTING_WIRELESS_MODE, "infrastructure",
-	              NM_SETTING_WIRELESS_SEC, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
 	              NULL);
 
 	g_byte_array_free (ssid, TRUE);
 
 	/* Wireless security setting */
 	s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
-	ASSERT (s_wsec != NULL,
-	        "wifi-wpa-eap-ttls-mschapv2-write", "failed to allocate new %s setting",
-	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_wsec));
 
 	g_object_set (s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-eap", NULL);
@@ -10271,9 +10444,6 @@ test_write_wifi_wpa_eap_ttls_mschapv2 (void)
 
 	/* Wireless security setting */
 	s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
-	ASSERT (s_8021x != NULL,
-	        "wifi-wpa-eap-ttls-mschapv2-write", "failed to allocate new %s setting",
-	        NM_SETTING_802_1X_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_8021x));
 
 	nm_setting_802_1x_add_eap_method (s_8021x, "ttls");
@@ -10297,18 +10467,12 @@ test_write_wifi_wpa_eap_ttls_mschapv2 (void)
 
 	/* IP4 setting */
 	s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
-	ASSERT (s_ip4 != NULL,
-			"wifi-wpa-eap-ttls-mschapv2-write", "failed to allocate new %s setting",
-			NM_SETTING_IP4_CONFIG_SETTING_NAME);
 	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);
 
 	/* IP6 setting */
 	s_ip6 = (NMSettingIP6Config *) nm_setting_ip6_config_new ();
-	ASSERT (s_ip6 != NULL,
-	        "wifi-wpa-eap-ttls-mschapv2-write", "failed to allocate new %s setting",
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
 
 	g_object_set (s_ip6,
@@ -10332,6 +10496,9 @@ test_write_wifi_wpa_eap_ttls_mschapv2 (void)
 	ASSERT (testfile != NULL,
 	        "wifi-wpa-eap-ttls-mschapv2-write", "didn't get ifcfg file path back after writing connection");
 
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_utils_normalize_connection (connection, TRUE);
+
 	/* re-read the connection for comparison */
 	reread = connection_from_file (testfile,
 	                               NULL,
@@ -10421,7 +10588,6 @@ test_write_wifi_wpa_then_open (void)
 	g_object_set (s_wifi,
 	              NM_SETTING_WIRELESS_SSID, ssid,
 	              NM_SETTING_WIRELESS_MODE, "infrastructure",
-	              NM_SETTING_WIRELESS_SEC, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
 	              NULL);
 
 	g_byte_array_free (ssid, TRUE);
@@ -10474,6 +10640,9 @@ test_write_wifi_wpa_then_open (void)
 	g_assert (success);
 	g_assert (testfile);
 
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_utils_normalize_connection (connection, TRUE);
+
 	/* re-read the connection for comparison */
 	reread = connection_from_file (testfile,
 	                               NULL,
@@ -10503,9 +10672,6 @@ test_write_wifi_wpa_then_open (void)
 	g_object_unref (reread);
 
 	/* Now change the connection to open and recheck */
-	s_wifi = nm_connection_get_setting_wireless (connection);
-	g_assert (s_wifi);
-	g_object_set (s_wifi, NM_SETTING_WIRELESS_SEC, NULL, NULL);
 	nm_connection_remove_setting (connection, NM_TYPE_SETTING_WIRELESS_SECURITY);
 
 	/* Write it back out */
@@ -10521,6 +10687,9 @@ test_write_wifi_wpa_then_open (void)
 	g_free (keyfile);
 	keyfile = NULL;
 
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_utils_normalize_connection (connection, TRUE);
+
 	/* re-read it for comparison */
 	reread = connection_from_file (testfile,
 	                               NULL,
@@ -10618,7 +10787,6 @@ test_write_wifi_wpa_then_wep_with_perms (void)
 	g_object_set (s_wifi,
 	              NM_SETTING_WIRELESS_SSID, ssid,
 	              NM_SETTING_WIRELESS_MODE, "infrastructure",
-	              NM_SETTING_WIRELESS_SEC, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
 	              NULL);
 
 	g_byte_array_free (ssid, TRUE);
@@ -10671,6 +10839,9 @@ test_write_wifi_wpa_then_wep_with_perms (void)
 	g_assert (success);
 	g_assert (testfile);
 
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_utils_normalize_connection (connection, TRUE);
+
 	/* re-read the connection for comparison */
 	reread = connection_from_file (testfile,
 	                               NULL,
@@ -10721,6 +10892,9 @@ test_write_wifi_wpa_then_wep_with_perms (void)
 	g_free (keyfile);
 	keyfile = NULL;
 
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_utils_normalize_connection (connection, TRUE);
+
 	/* re-read it for comparison */
 	reread = connection_from_file (testfile,
 	                               NULL,
@@ -10811,7 +10985,6 @@ test_write_wifi_dynamic_wep_leap (void)
 	g_object_set (s_wifi,
 	              NM_SETTING_WIRELESS_SSID, ssid,
 	              NM_SETTING_WIRELESS_MODE, "infrastructure",
-	              NM_SETTING_WIRELESS_SEC, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
 	              NULL);
 
 	g_byte_array_free (ssid, TRUE);
@@ -10864,6 +11037,9 @@ test_write_wifi_dynamic_wep_leap (void)
 	g_assert (success);
 	g_assert (testfile);
 
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_utils_normalize_connection (connection, TRUE);
+
 	/* re-read the connection for comparison */
 	reread = connection_from_file (testfile,
 	                               NULL,
@@ -10891,7 +11067,8 @@ test_write_wifi_dynamic_wep_leap (void)
 	 * did not get written.  Check first that the auth alg is not set to "LEAP"
 	 * and next that the only IEEE 802.1x EAP method is "LEAP".
 	 */
-	ifcfg = svNewFile (testfile);
+	ifcfg = svOpenFile (testfile, &error);
+	g_assert_no_error (error);
 	g_assert (ifcfg);
 	tmp = svGetValue (ifcfg, "SECURITYMODE", FALSE);
 	g_assert_cmpstr (tmp, ==, NULL);
@@ -11074,7 +11251,7 @@ test_read_ibft_static (void)
 	guint64 expected_timestamp = 0;
 	const char *expected_dns1 = "10.16.255.2";
 	const char *expected_dns2 = "10.16.255.3";
-	struct in_addr addr;
+	guint32 addr;
 	const char *expected_address1 = "192.168.32.72";
 	const char *expected_address1_gw = "192.168.35.254";
 	NMIP4Address *ip4_addr;
@@ -11202,7 +11379,7 @@ test_read_ibft_static (void)
 	        TEST_IFCFG_IBFT_STATIC,
 	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
 	        NM_SETTING_IP4_CONFIG_DNS);
-	ASSERT (nm_setting_ip4_config_get_dns (s_ip4, 0) == addr.s_addr,
+	ASSERT (nm_setting_ip4_config_get_dns (s_ip4, 0) == addr,
 	        "ibft-static-verify-ip4", "failed to verify %s: unexpected %s / %s key value #1",
 	        TEST_IFCFG_IBFT_STATIC,
 	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
@@ -11213,7 +11390,7 @@ test_read_ibft_static (void)
 	        TEST_IFCFG_IBFT_STATIC,
 	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
 	        NM_SETTING_IP4_CONFIG_DNS);
-	ASSERT (nm_setting_ip4_config_get_dns (s_ip4, 1) == addr.s_addr,
+	ASSERT (nm_setting_ip4_config_get_dns (s_ip4, 1) == addr,
 	        "ibft-static-verify-ip4", "failed to verify %s: unexpected %s / %s key value #2",
 	        TEST_IFCFG_IBFT_STATIC,
 	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
@@ -11244,7 +11421,7 @@ test_read_ibft_static (void)
 	        TEST_IFCFG_IBFT_STATIC,
 	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
 	        NM_SETTING_IP4_CONFIG_DNS);
-	ASSERT (nm_ip4_address_get_address (ip4_addr) == addr.s_addr,
+	ASSERT (nm_ip4_address_get_address (ip4_addr) == addr,
 	        "ibft-static-verify-ip4", "failed to verify %s: unexpected IP4 address #1",
 	        TEST_IFCFG_IBFT_STATIC,
 	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
@@ -11255,7 +11432,7 @@ test_read_ibft_static (void)
 	        TEST_IFCFG_IBFT_STATIC,
 	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
 	        NM_SETTING_IP4_CONFIG_ADDRESSES);
-	ASSERT (nm_ip4_address_get_gateway (ip4_addr) == addr.s_addr,
+	ASSERT (nm_ip4_address_get_gateway (ip4_addr) == addr,
 	        "ibft-static-verify-ip4", "failed to verify %s: unexpected IP4 address #1 gateway",
 	        TEST_IFCFG_IBFT_STATIC,
 	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
@@ -11269,7 +11446,7 @@ test_read_ibft_static (void)
 }
 
 static void
-test_read_ibft_malformed (const char *name, const char *iscsiadm_path)
+test_read_ibft_malformed (const char *name, const char *iscsiadm_path, gboolean expect_warning)
 {
 	NMConnection *connection;
 	char *unmanaged = NULL;
@@ -11281,6 +11458,10 @@ test_read_ibft_malformed (const char *name, const char *iscsiadm_path)
 
 	g_assert (g_file_test (iscsiadm_path, G_FILE_TEST_EXISTS));
 
+	if (expect_warning) {
+		g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
+		                       "*malformed iscsiadm record*");
+	}
 	connection = connection_from_file (TEST_IFCFG_IBFT_STATIC,
 	                                   NULL,
 	                                   TYPE_ETHERNET,
@@ -11291,6 +11472,8 @@ test_read_ibft_malformed (const char *name, const char *iscsiadm_path)
 	                                   &route6file,
 	                                   &error,
 	                                   &ignore_error);
+	if (expect_warning)
+		g_test_assert_expected_messages ();
 	ASSERT (connection == NULL,
 	        name, "unexpectedly able to read %s", TEST_IFCFG_IBFT_STATIC);
 
@@ -11321,14 +11504,9 @@ test_write_wired_qeth_dhcp (void)
 	gboolean ignore_error = FALSE;
 
 	connection = nm_connection_new ();
-	ASSERT (connection != NULL,
-	        "wired-qeth-dhcp-write", "failed to allocate new connection");
 
 	/* Connection setting */
 	s_con = (NMSettingConnection *) nm_setting_connection_new ();
-	ASSERT (s_con != NULL,
-	        "wired-qeth-dhcp-write", "failed to allocate new %s setting",
-	        NM_SETTING_CONNECTION_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_con));
 
 	uuid = nm_utils_uuid_generate ();
@@ -11342,9 +11520,6 @@ test_write_wired_qeth_dhcp (void)
 
 	/* Wired setting */
 	s_wired = (NMSettingWired *) nm_setting_wired_new ();
-	ASSERT (s_wired != NULL,
-	        "wired-qeth-dhcp-write", "failed to allocate new %s setting",
-	        NM_SETTING_WIRED_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_wired));
 
 	subchans = g_ptr_array_sized_new (3);
@@ -11364,9 +11539,6 @@ test_write_wired_qeth_dhcp (void)
 
 	/* IP4 setting */
 	s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
-	ASSERT (s_ip4 != NULL,
-			"wired-qeth-dhcp-write", "failed to allocate new %s setting",
-			NM_SETTING_IP4_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip4));
 
 	g_object_set (s_ip4,
@@ -11375,9 +11547,6 @@ test_write_wired_qeth_dhcp (void)
 
 	/* IP6 setting */
 	s_ip6 = (NMSettingIP6Config *) nm_setting_ip6_config_new ();
-	ASSERT (s_ip6 != NULL,
-			"wired-qeth-dhcp-write", "failed to allocate new %s setting",
-			NM_SETTING_IP6_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
 
 	g_object_set (s_ip6,
@@ -11402,6 +11571,9 @@ test_write_wired_qeth_dhcp (void)
 	ASSERT (testfile != NULL,
 	        "wired-qeth-dhcp-write", "didn't get ifcfg file path back after writing connection");
 
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_utils_normalize_connection (connection, TRUE);
+
 	/* re-read the connection for comparison */
 	reread = connection_from_file (testfile,
 	                               NULL,
@@ -11520,7 +11692,8 @@ test_write_wired_ctc_dhcp (void)
 	g_assert (testfile != NULL);
 
 	/* Ensure the CTCPROT item gets written out as it's own option */
-	ifcfg = svNewFile (testfile);
+	ifcfg = svOpenFile (testfile, &error);
+	g_assert_no_error (error);
 	g_assert (ifcfg);
 
 	tmp = svGetValue (ifcfg, "CTCPROT", TRUE);
@@ -11535,6 +11708,9 @@ test_write_wired_ctc_dhcp (void)
 
 	svCloseFile (ifcfg);
 
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_utils_normalize_connection (connection, TRUE);
+
 	/* re-read the connection for comparison */
 	reread = connection_from_file (testfile,
 	                               NULL,
@@ -11588,14 +11764,9 @@ test_write_permissions (void)
 	gboolean ignore_error = FALSE;
 
 	connection = nm_connection_new ();
-	ASSERT (connection != NULL,
-	        "permissions-write", "failed to allocate new connection");
 
 	/* Connection setting */
 	s_con = (NMSettingConnection *) nm_setting_connection_new ();
-	ASSERT (s_con != NULL,
-	        "permissions-write", "failed to allocate new %s setting",
-	        NM_SETTING_CONNECTION_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_con));
 
 	uuid = nm_utils_uuid_generate ();
@@ -11613,16 +11784,10 @@ test_write_permissions (void)
 
 	/* Wired setting */
 	s_wired = (NMSettingWired *) nm_setting_wired_new ();
-	ASSERT (s_wired != NULL,
-	        "permissions-write", "failed to allocate new %s setting",
-	        NM_SETTING_WIRED_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_wired));
 
 	/* IP4 setting */
 	s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
-	ASSERT (s_ip4 != NULL,
-			"permissions-write", "failed to allocate new %s setting",
-			NM_SETTING_IP4_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip4));
 
 	g_object_set (s_ip4,
@@ -11631,9 +11796,6 @@ test_write_permissions (void)
 
 	/* IP6 setting */
 	s_ip6 = (NMSettingIP6Config *) nm_setting_ip6_config_new ();
-	ASSERT (s_ip6 != NULL,
-			"wired-qeth-dhcp-write", "failed to allocate new %s setting",
-			NM_SETTING_IP6_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
 
 	g_object_set (s_ip6,
@@ -11658,6 +11820,9 @@ test_write_permissions (void)
 	ASSERT (testfile != NULL,
 	        "permissions-write", "didn't get ifcfg file path back after writing connection");
 
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_utils_normalize_connection (connection, TRUE);
+
 	/* re-read the connection for comparison */
 	reread = connection_from_file (testfile,
 	                               NULL,
@@ -11755,7 +11920,6 @@ test_write_wifi_wep_agent_keys (void)
 	g_byte_array_append (ssid, (guint8 *) str_ssid, strlen (str_ssid));
 	g_object_set (s_wifi,
 	              NM_SETTING_WIRELESS_SSID, ssid,
-	              NM_SETTING_WIRELESS_SEC, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
 	              NM_SETTING_WIRELESS_MODE, "infrastructure",
 	              NULL);
 	g_byte_array_free (ssid, TRUE);
@@ -11786,6 +11950,9 @@ test_write_wifi_wep_agent_keys (void)
 	g_assert (success);
 	g_assert (testfile != NULL);
 
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_utils_normalize_connection (connection, TRUE);
+
 	/* re-read the connection for comparison */
 	reread = connection_from_file (testfile,
 	                               NULL,
@@ -11847,14 +12014,9 @@ test_write_wired_pppoe (void)
 	char *testfile = NULL;
 
 	connection = nm_connection_new ();
-	ASSERT (connection != NULL,
-	        "wired-pppoe-write", "failed to allocate new connection");
 
 	/* Connection setting */
 	s_con = (NMSettingConnection *) nm_setting_connection_new ();
-	ASSERT (s_con != NULL,
-	        "wired-pppoe-write", "failed to allocate new %s setting",
-	        NM_SETTING_CONNECTION_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_con));
 
 	uuid = nm_utils_uuid_generate ();
@@ -11868,16 +12030,10 @@ test_write_wired_pppoe (void)
 
 	/* Wired setting */
 	s_wired = (NMSettingWired *) nm_setting_wired_new ();
-	ASSERT (s_wired != NULL,
-	        "wired-pppoe-write", "failed to allocate new %s setting",
-	        NM_SETTING_WIRED_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_wired));
 
 	/* IP4 setting */
 	s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
-	ASSERT (s_ip4 != NULL,
-			"wired-pppoe-write", "failed to allocate new %s setting",
-			NM_SETTING_IP4_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip4));
 
 	g_object_set (s_ip4,
@@ -11886,9 +12042,6 @@ test_write_wired_pppoe (void)
 
 	/* PPPoE setting */
 	s_pppoe = (NMSettingPPPOE *) nm_setting_pppoe_new ();
-	ASSERT (s_pppoe != NULL,
-			"wired-pppoe-write", "failed to allocate new %s setting",
-			NM_SETTING_PPPOE_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_pppoe));
 
 	g_object_set (G_OBJECT (s_pppoe),
@@ -11899,9 +12052,6 @@ test_write_wired_pppoe (void)
 
 	/* PPP setting */
 	s_ppp = (NMSettingPPP *) nm_setting_ppp_new ();
-	ASSERT (s_ppp != NULL,
-			"wired-pppoe-write", "failed to allocate new %s setting",
-			NM_SETTING_PPP_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ppp));
 
 	ASSERT (nm_connection_verify (connection, &error) == TRUE,
@@ -11932,14 +12082,9 @@ test_write_vpn (void)
 	char *testfile = NULL;
 
 	connection = nm_connection_new ();
-	ASSERT (connection != NULL,
-	        "vpn-write", "failed to allocate new connection");
 
 	/* Connection setting */
 	s_con = (NMSettingConnection *) nm_setting_connection_new ();
-	ASSERT (s_con != NULL,
-	        "vpn-write", "failed to allocate new %s setting",
-	        NM_SETTING_CONNECTION_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_con));
 
 	uuid = nm_utils_uuid_generate ();
@@ -11953,9 +12098,6 @@ test_write_vpn (void)
 
 	/* VPN setting */
 	s_vpn = (NMSettingVPN *) nm_setting_vpn_new ();
-	ASSERT (s_vpn != NULL,
-	        "vpn-write", "failed to allocate new %s setting",
-	        NM_SETTING_VPN_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_vpn));
 
 	g_object_set (s_vpn,
@@ -11968,9 +12110,6 @@ test_write_vpn (void)
 
 	/* IP4 setting */
 	s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
-	ASSERT (s_ip4 != NULL,
-			"vpn-write", "failed to allocate new %s setting",
-			NM_SETTING_IP4_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip4));
 
 	g_object_set (s_ip4,
@@ -12008,14 +12147,9 @@ test_write_mobile_broadband (gboolean gsm)
 	char *testfile = NULL;
 
 	connection = nm_connection_new ();
-	ASSERT (connection != NULL,
-	        "mobile-broadband-write", "failed to allocate new connection");
 
 	/* Connection setting */
 	s_con = (NMSettingConnection *) nm_setting_connection_new ();
-	ASSERT (s_con != NULL,
-	        "mobile-broadband-write", "failed to allocate new %s setting",
-	        NM_SETTING_CONNECTION_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_con));
 
 	uuid = nm_utils_uuid_generate ();
@@ -12030,18 +12164,12 @@ test_write_mobile_broadband (gboolean gsm)
 	if (gsm) {
 		/* GSM setting */
 		s_gsm = (NMSettingGsm *) nm_setting_gsm_new ();
-		ASSERT (s_gsm != NULL,
-		        "mobile-broadband-write", "failed to allocate new %s setting",
-		        NM_SETTING_GSM_SETTING_NAME);
 		nm_connection_add_setting (connection, NM_SETTING (s_gsm));
 
 		g_object_set (s_gsm, NM_SETTING_GSM_NUMBER, "*99#", NULL);
 	} else {
 		/* CDMA setting */
 		s_cdma = (NMSettingCdma *) nm_setting_cdma_new ();
-		ASSERT (s_cdma != NULL,
-		        "mobile-broadband-write", "failed to allocate new %s setting",
-		        NM_SETTING_CDMA_SETTING_NAME);
 		nm_connection_add_setting (connection, NM_SETTING (s_cdma));
 
 		g_object_set (s_cdma, NM_SETTING_CDMA_NUMBER, "#777", NULL);
@@ -12049,9 +12177,6 @@ test_write_mobile_broadband (gboolean gsm)
 
 	/* Serial setting */
 	s_serial = (NMSettingSerial *) nm_setting_serial_new ();
-	ASSERT (s_serial != NULL,
-	        "mobile-broadband-write", "failed to allocate new %s setting",
-	        NM_SETTING_SERIAL_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_serial));
 
 	g_object_set (s_serial,
@@ -12063,9 +12188,6 @@ test_write_mobile_broadband (gboolean gsm)
 
 	/* IP4 setting */
 	s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
-	ASSERT (s_ip4 != NULL,
-			"mobile-broadband-write", "failed to allocate new %s setting",
-			NM_SETTING_IP4_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip4));
 
 	g_object_set (s_ip4,
@@ -12074,9 +12196,6 @@ test_write_mobile_broadband (gboolean gsm)
 
 	/* PPP setting */
 	s_ppp = (NMSettingPPP *) nm_setting_ppp_new ();
-	ASSERT (s_ppp != NULL,
-			"mobile-broadband-write", "failed to allocate new %s setting",
-			NM_SETTING_PPP_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ppp));
 
 	ASSERT (nm_connection_verify (connection, &error) == TRUE,
@@ -12101,6 +12220,8 @@ test_read_bridge_main (void)
 {
 	NMConnection *connection;
 	NMSettingBridge *s_bridge;
+	const GByteArray *array;
+	char expected_mac_address[ETH_ALEN] = { 0x00, 0x16, 0x41, 0x11, 0x22, 0x33 };
 	char *unmanaged = NULL;
 	char *keyfile = NULL;
 	char *routefile = NULL;
@@ -12128,11 +12249,16 @@ test_read_bridge_main (void)
 	g_assert (s_bridge);
 	g_assert_cmpstr (nm_setting_bridge_get_interface_name (s_bridge), ==, "br0");
 	g_assert_cmpuint (nm_setting_bridge_get_forward_delay (s_bridge), ==, 0);
-	g_assert_cmpuint (nm_setting_bridge_get_stp (s_bridge), ==, TRUE);
+	g_assert (nm_setting_bridge_get_stp (s_bridge));
 	g_assert_cmpuint (nm_setting_bridge_get_priority (s_bridge), ==, 32744);
 	g_assert_cmpuint (nm_setting_bridge_get_hello_time (s_bridge), ==, 7);
 	g_assert_cmpuint (nm_setting_bridge_get_max_age (s_bridge), ==, 39);
 	g_assert_cmpuint (nm_setting_bridge_get_ageing_time (s_bridge), ==, 235352);
+	/* MAC address */
+	array = nm_setting_bridge_get_mac_address (s_bridge);
+	g_assert (array);
+	g_assert_cmpint (array->len, ==, ETH_ALEN);
+	g_assert (memcmp (array->data, &expected_mac_address[0], ETH_ALEN) == 0);
 
 	g_free (unmanaged);
 	g_free (keyfile);
@@ -12155,6 +12281,8 @@ test_write_bridge_main (void)
 	const guint32 gw = htonl (0x01010101);
 	const guint32 prefix = 24;
 	NMIP4Address *addr;
+	static unsigned char bridge_mac[] = { 0x31, 0x33, 0x33, 0x37, 0xbe, 0xcd };
+	GByteArray *mac_array;
 	gboolean success;
 	GError *error = NULL;
 	char *testfile = NULL;
@@ -12186,9 +12314,13 @@ test_write_bridge_main (void)
 	g_assert (s_bridge);
 	nm_connection_add_setting (connection, NM_SETTING (s_bridge));
 
+	mac_array = g_byte_array_sized_new (sizeof (bridge_mac));
+	g_byte_array_append (mac_array, bridge_mac, sizeof (bridge_mac));
 	g_object_set (s_bridge,
 	              NM_SETTING_BRIDGE_INTERFACE_NAME, "br0",
+	              NM_SETTING_BRIDGE_MAC_ADDRESS, mac_array,
 	              NULL);
+	g_byte_array_free (mac_array, TRUE);
 
 	/* IP4 setting */
 	s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
@@ -12227,6 +12359,9 @@ test_write_bridge_main (void)
 	g_assert (success);
 	g_assert_cmpstr (testfile, !=, NULL);
 
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_utils_normalize_connection (connection, TRUE);
+
 	/* re-read the connection for comparison */
 	reread = connection_from_file (testfile,
 	                               NULL,
@@ -12379,6 +12514,9 @@ test_write_bridge_component (void)
 	g_assert (success);
 	g_assert (testfile);
 
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_utils_normalize_connection (connection, TRUE);
+
 	/* re-read the connection for comparison */
 	reread = connection_from_file (testfile,
 	                               NULL,
@@ -12442,7 +12580,7 @@ test_read_bridge_missing_stp (void)
 	s_bridge = nm_connection_get_setting_bridge (connection);
 	g_assert (s_bridge);
 	g_assert_cmpstr (nm_setting_bridge_get_interface_name (s_bridge), ==, "br0");
-	g_assert_cmpuint (nm_setting_bridge_get_stp (s_bridge), ==, FALSE);
+	g_assert (nm_setting_bridge_get_stp (s_bridge) == FALSE);
 
 	g_free (unmanaged);
 	g_free (keyfile);
@@ -12612,15 +12750,10 @@ test_read_vlan_physdev (void)
 	NMConnection *connection;
 	GError *error = NULL;
 	NMSettingVlan *s_vlan;
-	char *unmanaged = NULL, *keyfile = NULL, *routefile = NULL, *route6file = NULL;
 
 	connection = connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-vlan-physdev",
-	                                   NULL, TYPE_ETHERNET, NULL,
-	                                   &unmanaged,
-	                                   &keyfile,
-	                                   &routefile,
-	                                   &route6file,
-	                                   &error, NULL);
+	                                   NULL, TYPE_ETHERNET, NULL, NULL,
+	                                   NULL, NULL, NULL, &error, NULL);
 	g_assert_no_error (error);
 	g_assert (connection);
 	g_assert (nm_connection_verify (connection, &error));
@@ -12633,11 +12766,6 @@ test_read_vlan_physdev (void)
 	g_assert_cmpint (nm_setting_vlan_get_id (s_vlan), ==, 3);
 
 	g_object_unref (connection);
-
-	g_free (unmanaged);
-	g_free (keyfile);
-	g_free (routefile);
-	g_free (route6file);
 }
 
 static void
@@ -12721,6 +12849,9 @@ test_write_vlan_only_vlanid (void)
 	                                 &error);
 	g_assert (success);
 
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_utils_normalize_connection (connection, TRUE);
+
 	/* re-read the connection for comparison */
 	reread = connection_from_file (written,
 	                               NULL,
@@ -12827,6 +12958,9 @@ test_write_ethernet_missing_ipv6 (void)
 	ASSERT (testfile != NULL,
 	        "ethernet-missing-ipv6", "didn't get ifcfg file path back after writing connection");
 
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_utils_normalize_connection (connection, TRUE);
+
 	/* re-read the connection for comparison */
 	reread = connection_from_file (testfile,
 	                               NULL,
@@ -12949,14 +13083,9 @@ test_write_bond_main (void)
 	gboolean ignore_error = FALSE;
 
 	connection = nm_connection_new ();
-	ASSERT (connection != NULL,
-	        "bond-main-write", "failed to allocate new connection");
 
 	/* Connection setting */
 	s_con = (NMSettingConnection *) nm_setting_connection_new ();
-	ASSERT (s_con != NULL,
-	        "bond-main-write", "failed to allocate new %s setting",
-	        NM_SETTING_CONNECTION_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_con));
 
 	uuid = nm_utils_uuid_generate ();
@@ -12970,16 +13099,10 @@ test_write_bond_main (void)
 
 	/* Wired setting */
 	s_wired = (NMSettingWired *) nm_setting_wired_new ();
-	ASSERT (s_wired != NULL,
-	        "bond-main-write", "failed to allocate new %s setting",
-	        NM_SETTING_WIRED_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_wired));
 
 	/* bond setting */
 	s_bond = (NMSettingBond *) nm_setting_bond_new ();
-	ASSERT (s_bond != NULL,
-	        "bond-main-write", "failed to allocate new %s setting",
-	        NM_SETTING_BOND_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_bond));
 
 	g_object_set (s_bond,
@@ -12988,9 +13111,6 @@ test_write_bond_main (void)
 
 	/* IP4 setting */
 	s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
-	ASSERT (s_ip4 != NULL,
-			"bond-main-write", "failed to allocate new %s setting",
-			NM_SETTING_IP4_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip4));
 
 	g_object_set (s_ip4,
@@ -13007,9 +13127,6 @@ test_write_bond_main (void)
 
 	/* IP6 setting */
 	s_ip6 = (NMSettingIP6Config *) nm_setting_ip6_config_new ();
-	ASSERT (s_ip6 != NULL,
-	        "bond-main-write", "failed to allocate new %s setting",
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
 
 	g_object_set (s_ip6,
@@ -13032,6 +13149,9 @@ test_write_bond_main (void)
 	ASSERT (testfile != NULL,
 	        "bond-main-write", "didn't get ifcfg file path back after writing connection");
 
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_utils_normalize_connection (connection, TRUE);
+
 	/* re-read the connection for comparison */
 	reread = connection_from_file (testfile,
 	                               NULL,
@@ -13077,6 +13197,8 @@ test_read_bond_slave (void)
 	gboolean ignore_error = FALSE;
 	GError *error = NULL;
 
+	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
+	                       "*ignoring IP4 config on slave*");
 	connection = connection_from_file (TEST_IFCFG_BOND_SLAVE,
 	                                   NULL,
 	                                   TYPE_ETHERNET,
@@ -13087,6 +13209,8 @@ test_read_bond_slave (void)
 	                                   &route6file,
 	                                   &error,
 	                                   &ignore_error);
+	g_test_assert_expected_messages ();
+
 	ASSERT (connection != NULL,
 	        "bond-slave-read", "unexpected failure reading %s", TEST_IFCFG_BOND_SLAVE);
 
@@ -13134,14 +13258,9 @@ test_write_bond_slave (void)
 	gboolean ignore_error = FALSE;
 
 	connection = nm_connection_new ();
-	ASSERT (connection != NULL,
-	        "bond-slave-write", "failed to allocate new connection");
 
 	/* Connection setting */
 	s_con = (NMSettingConnection *) nm_setting_connection_new ();
-	ASSERT (s_con != NULL,
-	        "bond-slave-write", "failed to allocate new %s setting",
-	        NM_SETTING_CONNECTION_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_con));
 
 	uuid = nm_utils_uuid_generate ();
@@ -13157,9 +13276,6 @@ test_write_bond_slave (void)
 
 	/* Wired setting */
 	s_wired = (NMSettingWired *) nm_setting_wired_new ();
-	ASSERT (s_wired != NULL,
-	        "bond-main-write", "failed to allocate new %s setting",
-	        NM_SETTING_WIRED_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_wired));
 
 	mac = g_byte_array_sized_new (sizeof (tmpmac));
@@ -13187,6 +13303,9 @@ test_write_bond_slave (void)
 	ASSERT (testfile != NULL,
 	        "bond-slave-write", "didn't get ifcfg file path back after writing connection");
 
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_utils_normalize_connection (connection, TRUE);
+
 	/* re-read the connection for comparison */
 	reread = connection_from_file (testfile,
 	                               NULL,
@@ -13330,14 +13449,9 @@ test_write_infiniband (void)
 	gboolean ignore_error = FALSE;
 
 	connection = nm_connection_new ();
-	ASSERT (connection != NULL,
-	        "infiniband-write", "failed to allocate new connection");
 
 	/* Connection setting */
 	s_con = (NMSettingConnection *) nm_setting_connection_new ();
-	ASSERT (s_con != NULL,
-	        "infiniband-write", "failed to allocate new %s setting",
-	        NM_SETTING_CONNECTION_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_con));
 
 	uuid = nm_utils_uuid_generate ();
@@ -13351,9 +13465,6 @@ test_write_infiniband (void)
 
 	/* InfiniBand setting */
 	s_infiniband = (NMSettingInfiniband *) nm_setting_infiniband_new ();
-	ASSERT (s_infiniband != NULL,
-	        "infiniband-write", "failed to allocate new %s setting",
-	        NM_SETTING_INFINIBAND_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_infiniband));
 
 	mac = g_byte_array_sized_new (sizeof (tmpmac));
@@ -13368,9 +13479,6 @@ test_write_infiniband (void)
 
 	/* IP4 setting */
 	s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
-	ASSERT (s_ip4 != NULL,
-			"infiniband-write", "failed to allocate new %s setting",
-			NM_SETTING_IP4_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip4));
 
 	g_object_set (s_ip4,
@@ -13387,9 +13495,6 @@ test_write_infiniband (void)
 
 	/* IP6 setting */
 	s_ip6 = (NMSettingIP6Config *) nm_setting_ip6_config_new ();
-	ASSERT (s_ip6 != NULL,
-	        "wired-static-write", "failed to allocate new %s setting",
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
 
 	g_object_set (s_ip6,
@@ -13412,6 +13517,9 @@ test_write_infiniband (void)
 	ASSERT (testfile != NULL,
 	        "infiniband-write", "didn't get ifcfg file path back after writing connection");
 
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_utils_normalize_connection (connection, TRUE);
+
 	/* re-read the connection for comparison */
 	reread = connection_from_file (testfile,
 	                               NULL,
@@ -13457,6 +13565,8 @@ test_read_bond_slave_ib (void)
 	gboolean ignore_error = FALSE;
 	GError *error = NULL;
 
+	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
+	                       "*ignoring IP4 config on slave*");
 	connection = connection_from_file (TEST_IFCFG_BOND_SLAVE_IB,
 	                                   NULL,
 	                                   NULL,
@@ -13467,6 +13577,8 @@ test_read_bond_slave_ib (void)
 	                                   &route6file,
 	                                   &error,
 	                                   &ignore_error);
+	g_test_assert_expected_messages();
+
 	ASSERT (connection != NULL,
 	        "bond-slave-read-ib", "unexpected failure reading %s", TEST_IFCFG_BOND_SLAVE_IB);
 
@@ -13516,14 +13628,9 @@ test_write_bond_slave_ib (void)
 	gboolean ignore_error = FALSE;
 
 	connection = nm_connection_new ();
-	ASSERT (connection != NULL,
-	        "bond-slave-write-ib", "failed to allocate new connection");
 
 	/* Connection setting */
 	s_con = (NMSettingConnection *) nm_setting_connection_new ();
-	ASSERT (s_con != NULL,
-	        "bond-slave-write-ib", "failed to allocate new %s setting",
-	        NM_SETTING_CONNECTION_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_con));
 
 	uuid = nm_utils_uuid_generate ();
@@ -13539,9 +13646,6 @@ test_write_bond_slave_ib (void)
 
 	/* InfiniBand setting */
 	s_infiniband = (NMSettingInfiniband *) nm_setting_infiniband_new ();
-	ASSERT (s_infiniband != NULL,
-	        "bond-main-write", "failed to allocate new %s setting",
-	        NM_SETTING_INFINIBAND_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_infiniband));
 
 	mac = g_byte_array_sized_new (sizeof (tmpmac));
@@ -13570,6 +13674,9 @@ test_write_bond_slave_ib (void)
 	ASSERT (testfile != NULL,
 	        "bond-slave-write-ib", "didn't get ifcfg file path back after writing connection");
 
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_utils_normalize_connection (connection, TRUE);
+
 	/* re-read the connection for comparison */
 	reread = connection_from_file (testfile,
 	                               NULL,
@@ -13604,6 +13711,819 @@ test_write_bond_slave_ib (void)
 	g_object_unref (reread);
 }
 
+#define DCB_ALL_FLAGS (NM_SETTING_DCB_FLAG_ENABLE | \
+                       NM_SETTING_DCB_FLAG_ADVERTISE | \
+                       NM_SETTING_DCB_FLAG_WILLING)
+
+static void
+test_read_dcb_basic (void)
+{
+	NMConnection *connection;
+	GError *error = NULL;
+	NMSettingDcb *s_dcb;
+	gboolean success;
+	guint i;
+	guint expected_group_ids[8] = { 0, 0, 0, 0, 1, 1, 1, 0xF };
+	guint expected_group_bandwidths[8] = { 25, 0, 0, 75, 0, 0, 0, 0 };
+	guint expected_bandwidths[8] = { 5, 10, 30, 25, 10, 50, 5, 0 };
+	gboolean expected_strict[8] = { FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE };
+	guint expected_traffic_classes[8] = { 7, 6, 5, 4, 3, 2, 1, 0 };
+	gboolean expected_pfcs[8] = { TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE };
+
+	connection = connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-dcb",
+	                                   NULL, TYPE_ETHERNET, NULL, NULL, NULL, NULL, NULL, &error, NULL);
+	g_assert_no_error (error);
+	g_assert (connection);
+	success = nm_connection_verify (connection, &error);
+	g_assert_no_error (error);
+	g_assert (success);
+
+	s_dcb = nm_connection_get_setting_dcb (connection);
+	g_assert (s_dcb);
+
+	g_assert_cmpint (nm_setting_dcb_get_app_fcoe_flags (s_dcb), ==, DCB_ALL_FLAGS);
+	g_assert_cmpint (nm_setting_dcb_get_app_fcoe_priority (s_dcb), ==, 7);
+
+	g_assert_cmpint (nm_setting_dcb_get_app_iscsi_flags (s_dcb), ==, DCB_ALL_FLAGS);
+		g_assert_cmpint (nm_setting_dcb_get_app_iscsi_priority (s_dcb), ==, 6);
+
+	g_assert_cmpint (nm_setting_dcb_get_app_fip_flags (s_dcb), ==, DCB_ALL_FLAGS);
+	g_assert_cmpint (nm_setting_dcb_get_app_fip_priority (s_dcb), ==, 2);
+
+	g_assert_cmpint (nm_setting_dcb_get_priority_flow_control_flags (s_dcb), ==, (NM_SETTING_DCB_FLAG_ENABLE | NM_SETTING_DCB_FLAG_ADVERTISE));
+	for (i = 0; i < 8; i++)
+		g_assert_cmpint (nm_setting_dcb_get_priority_flow_control (s_dcb, i), ==, expected_pfcs[i]);
+
+	g_assert_cmpint (nm_setting_dcb_get_priority_group_flags (s_dcb), ==, DCB_ALL_FLAGS);
+
+	/* Group IDs */
+	for (i = 0; i < 8; i++)
+		g_assert_cmpint (nm_setting_dcb_get_priority_group_id (s_dcb, i), ==, expected_group_ids[i]);
+
+	/* Group bandwidth */
+	for (i = 0; i < 8; i++)
+		g_assert_cmpint (nm_setting_dcb_get_priority_group_bandwidth (s_dcb, i), ==, expected_group_bandwidths[i]);
+
+	/* User priority bandwidth */
+	for (i = 0; i < 8; i++)
+		g_assert_cmpint (nm_setting_dcb_get_priority_bandwidth (s_dcb, i), ==, expected_bandwidths[i]);
+
+	/* Strict bandwidth */
+	for (i = 0; i < 8; i++)
+		g_assert_cmpint (nm_setting_dcb_get_priority_strict_bandwidth (s_dcb, i), ==, expected_strict[i]);
+
+	/* Traffic class */
+	for (i = 0; i < 8; i++)
+		g_assert_cmpint (nm_setting_dcb_get_priority_traffic_class (s_dcb, i), ==, expected_traffic_classes[i]);
+
+	g_object_unref (connection);
+}
+
+static void
+test_write_dcb_basic (void)
+{
+	NMConnection *connection, *reread;
+	GError *error = NULL;
+	NMSettingConnection *s_con;
+	NMSettingWired *s_wired;
+	NMSettingDcb *s_dcb;
+	NMSettingIP4Config *s_ip4;
+	NMSettingIP6Config *s_ip6;
+	gboolean success, ignore_error;
+	guint i;
+	char *uuid, *testfile;
+	const guint group_ids[8] = { 4, 0xF, 6, 0xF, 1, 7, 3, 0xF };
+	const guint group_bandwidths[8] = { 10, 20, 15, 10, 2, 3, 35, 5 };
+	const guint bandwidths[8] = { 10, 20, 30, 40, 50, 10, 0, 25 };
+	const gboolean strict[8] = { TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE };
+	const guint traffic_classes[8] = { 3, 4, 7, 2, 1, 0, 5, 6 };
+	const gboolean pfcs[8] = { TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE };
+
+	connection = nm_connection_new ();
+
+	s_con = (NMSettingConnection *) nm_setting_connection_new ();
+	nm_connection_add_setting (connection, NM_SETTING (s_con));
+	uuid = nm_utils_uuid_generate ();
+	g_object_set (G_OBJECT (s_con),
+	              NM_SETTING_CONNECTION_ID, "dcb-test",
+	              NM_SETTING_CONNECTION_UUID, uuid,
+	              NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME,
+	              NM_SETTING_CONNECTION_INTERFACE_NAME, "eth0",
+	              NULL);
+	g_free (uuid);
+
+	/* Wired setting */
+	s_wired = (NMSettingWired *) nm_setting_wired_new ();
+	nm_connection_add_setting (connection, NM_SETTING (s_wired));
+
+	/* IP stuff */
+	s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
+	g_object_set (G_OBJECT (s_ip4), NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL);
+	nm_connection_add_setting (connection, NM_SETTING (s_ip4));
+
+	s_ip6 = (NMSettingIP6Config *) nm_setting_ip6_config_new ();
+	g_object_set (G_OBJECT (s_ip6), NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, NULL);
+	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
+
+	/* DCB */
+	s_dcb = (NMSettingDcb *) nm_setting_dcb_new ();
+	nm_connection_add_setting (connection, NM_SETTING (s_dcb));
+
+	g_object_set (G_OBJECT (s_dcb),
+	              NM_SETTING_DCB_APP_FCOE_FLAGS, DCB_ALL_FLAGS,
+	              NM_SETTING_DCB_APP_FCOE_PRIORITY, 5,
+	              NM_SETTING_DCB_APP_ISCSI_FLAGS, DCB_ALL_FLAGS,
+	              NM_SETTING_DCB_APP_ISCSI_PRIORITY, 1,
+	              NM_SETTING_DCB_APP_FIP_FLAGS, DCB_ALL_FLAGS,
+	              NM_SETTING_DCB_APP_FIP_PRIORITY, 3,
+	              NM_SETTING_DCB_PRIORITY_FLOW_CONTROL_FLAGS, DCB_ALL_FLAGS,
+	              NM_SETTING_DCB_PRIORITY_GROUP_FLAGS, DCB_ALL_FLAGS,
+	              NULL);
+
+	for (i = 0; i < 8; i++) {
+		nm_setting_dcb_set_priority_flow_control (s_dcb, i, pfcs[i]);
+		nm_setting_dcb_set_priority_group_id (s_dcb, i, group_ids[i]);
+		nm_setting_dcb_set_priority_group_bandwidth (s_dcb, i, group_bandwidths[i]);
+		nm_setting_dcb_set_priority_bandwidth (s_dcb, i, bandwidths[i]);
+		nm_setting_dcb_set_priority_strict_bandwidth (s_dcb, i, strict[i]);
+		nm_setting_dcb_set_priority_traffic_class (s_dcb, i, traffic_classes[i]);
+	}
+
+	g_assert (nm_connection_verify (connection, &error));
+
+	/* Save the ifcfg */
+	success = writer_new_connection (connection,
+	                                 TEST_SCRATCH_DIR "/network-scripts/",
+	                                 &testfile,
+	                                 &error);
+	g_assert_no_error (error);
+	g_assert (success);
+	g_assert (testfile);
+
+	/* re-read the connection for comparison */
+	reread = connection_from_file (testfile,
+	                               NULL,
+	                               TYPE_ETHERNET,
+	                               NULL, NULL, NULL,
+	                               NULL, NULL,
+	                               &error,
+	                               &ignore_error);
+	unlink (testfile);
+
+	g_assert_no_error (error);
+	g_assert (reread);
+	g_assert (nm_connection_verify (reread, &error));
+	g_assert (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT));
+
+	g_object_unref (connection);
+	g_object_unref (reread);
+	g_free (testfile);
+}
+
+static void
+test_read_dcb_default_app_priorities (void)
+{
+	NMConnection *connection;
+	GError *error = NULL;
+	NMSettingDcb *s_dcb;
+	gboolean success;
+
+	connection = connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-dcb-default-app-priorities",
+	                                   NULL, TYPE_ETHERNET, NULL, NULL, NULL, NULL, NULL, &error, NULL);
+	g_assert_no_error (error);
+	g_assert (connection);
+	success = nm_connection_verify (connection, &error);
+	g_assert_no_error (error);
+	g_assert (success);
+
+	s_dcb = nm_connection_get_setting_dcb (connection);
+	g_assert (s_dcb);
+
+	g_assert_cmpint (nm_setting_dcb_get_app_fcoe_flags (s_dcb), ==, NM_SETTING_DCB_FLAG_ENABLE);
+	g_assert_cmpint (nm_setting_dcb_get_app_fcoe_priority (s_dcb), ==, -1);
+
+	g_assert_cmpint (nm_setting_dcb_get_app_iscsi_flags (s_dcb), ==, NM_SETTING_DCB_FLAG_ENABLE);
+	g_assert_cmpint (nm_setting_dcb_get_app_iscsi_priority (s_dcb), ==, -1);
+
+	g_assert_cmpint (nm_setting_dcb_get_app_fip_flags (s_dcb), ==, NM_SETTING_DCB_FLAG_ENABLE);
+	g_assert_cmpint (nm_setting_dcb_get_app_fip_priority (s_dcb), ==, -1);
+
+	g_object_unref (connection);
+}
+
+static void
+test_read_dcb_bad_booleans (void)
+{
+	NMConnection *connection;
+	GError *error = NULL;
+
+	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
+	                       "*invalid DCB_PG_STRICT value*not all 0s and 1s*");
+	connection = connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-dcb-bad-booleans",
+	                                   NULL, TYPE_ETHERNET, NULL, NULL, NULL, NULL, NULL, &error, NULL);
+	g_test_assert_expected_messages ();
+
+	g_assert_error (error, IFCFG_PLUGIN_ERROR, 0);
+	g_assert (strstr (error->message, "invalid boolean digit"));
+	g_assert (connection == NULL);
+}
+
+static void
+test_read_dcb_short_booleans (void)
+{
+	NMConnection *connection;
+	GError *error = NULL;
+
+	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
+	                       "*DCB_PG_STRICT value*8 characters*");
+	connection = connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-dcb-short-booleans",
+	                                   NULL, TYPE_ETHERNET, NULL, NULL, NULL, NULL, NULL, &error, NULL);
+	g_test_assert_expected_messages ();
+
+	g_assert_error (error, IFCFG_PLUGIN_ERROR, 0);
+	g_assert (strstr (error->message, "boolean array must be 8 characters"));
+	g_assert (connection == NULL);
+}
+
+static void
+test_read_dcb_bad_uints (void)
+{
+	NMConnection *connection;
+	GError *error = NULL;
+
+	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
+	                       "*invalid DCB_PG_UP2TC value*not 0 - 7*");
+	connection = connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-dcb-bad-uints",
+	                                   NULL, TYPE_ETHERNET, NULL, NULL, NULL, NULL, NULL, &error, NULL);
+	g_test_assert_expected_messages ();
+
+	g_assert_error (error, IFCFG_PLUGIN_ERROR, 0);
+	g_assert (strstr (error->message, "invalid uint digit"));
+	g_assert (connection == NULL);
+}
+
+static void
+test_read_dcb_short_uints (void)
+{
+	NMConnection *connection;
+	GError *error = NULL;
+
+	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
+	                       "*DCB_PG_UP2TC value*8 characters*");
+	connection = connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-dcb-short-uints",
+	                                   NULL, TYPE_ETHERNET, NULL, NULL, NULL, NULL, NULL, &error, NULL);
+	g_test_assert_expected_messages ();
+
+	g_assert_error (error, IFCFG_PLUGIN_ERROR, 0);
+	g_assert (strstr (error->message, "uint array must be 8 characters"));
+	g_assert (connection == NULL);
+}
+
+static void
+test_read_dcb_bad_percent (void)
+{
+	NMConnection *connection;
+	GError *error = NULL;
+
+	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
+	                       "*invalid DCB_PG_PCT percentage value*");
+	connection = connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-dcb-bad-percent",
+	                                   NULL, TYPE_ETHERNET, NULL, NULL, NULL, NULL, NULL, &error, NULL);
+	g_test_assert_expected_messages ();
+
+	g_assert_error (error, IFCFG_PLUGIN_ERROR, 0);
+	g_assert (strstr (error->message, "invalid percent element"));
+	g_assert (connection == NULL);
+}
+
+static void
+test_read_dcb_short_percent (void)
+{
+	NMConnection *connection;
+	GError *error = NULL;
+
+	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
+	                       "*invalid DCB_PG_PCT percentage list value*");
+	connection = connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-dcb-short-percent",
+	                                   NULL, TYPE_ETHERNET, NULL, NULL, NULL, NULL, NULL, &error, NULL);
+	g_test_assert_expected_messages ();
+
+	g_assert_error (error, IFCFG_PLUGIN_ERROR, 0);
+	g_assert (strstr (error->message, "percent array must be 8 elements"));
+	g_assert (connection == NULL);
+}
+
+static void
+test_read_dcb_pgpct_not_100 (void)
+{
+	NMConnection *connection;
+	GError *error = NULL;
+
+	g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING,
+	                       "*DCB_PG_PCT percentages do not equal 100*");
+	connection = connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-dcb-pgpct-not-100",
+	                                   NULL, TYPE_ETHERNET, NULL, NULL, NULL, NULL, NULL, &error, NULL);
+	g_test_assert_expected_messages ();
+
+	g_assert_error (error, IFCFG_PLUGIN_ERROR, 0);
+	g_assert (strstr (error->message, "invalid percentage sum"));
+	g_assert (connection == NULL);
+}
+
+static void
+test_read_fcoe_mode (gconstpointer user_data)
+{
+	const char *expected_mode = user_data;
+	NMConnection *connection;
+	GError *error = NULL;
+	NMSettingDcb *s_dcb;
+	gboolean success;
+	char *file;
+
+	file = g_strdup_printf (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-fcoe-%s", expected_mode);
+	connection = connection_from_file (file, NULL, TYPE_ETHERNET, NULL, NULL, NULL, NULL, NULL, &error, NULL);
+	g_free (file);
+	g_assert_no_error (error);
+	g_assert (connection);
+	success = nm_connection_verify (connection, &error);
+	g_assert_no_error (error);
+	g_assert (success);
+
+	s_dcb = nm_connection_get_setting_dcb (connection);
+	g_assert (s_dcb);
+
+	g_assert_cmpint (nm_setting_dcb_get_app_fcoe_flags (s_dcb), ==, NM_SETTING_DCB_FLAG_ENABLE);
+	g_assert_cmpstr (nm_setting_dcb_get_app_fcoe_mode (s_dcb), ==, expected_mode);
+
+	g_object_unref (connection);
+}
+
+static void
+test_write_fcoe_mode (gconstpointer user_data)
+{
+	const char *expected_mode = user_data;
+	NMConnection *connection, *reread;
+	GError *error = NULL;
+	NMSettingConnection *s_con;
+	NMSettingWired *s_wired;
+	NMSettingDcb *s_dcb;
+	NMSettingIP4Config *s_ip4;
+	NMSettingIP6Config *s_ip6;
+	gboolean success, ignore_error;
+	char *uuid, *testfile;
+
+	connection = nm_connection_new ();
+
+	s_con = (NMSettingConnection *) nm_setting_connection_new ();
+	nm_connection_add_setting (connection, NM_SETTING (s_con));
+	uuid = nm_utils_uuid_generate ();
+	g_object_set (G_OBJECT (s_con),
+	              NM_SETTING_CONNECTION_ID, "fcoe-test",
+	              NM_SETTING_CONNECTION_UUID, uuid,
+	              NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME,
+	              NM_SETTING_CONNECTION_INTERFACE_NAME, "eth0",
+	              NULL);
+	g_free (uuid);
+
+	/* Wired setting */
+	s_wired = (NMSettingWired *) nm_setting_wired_new ();
+	nm_connection_add_setting (connection, NM_SETTING (s_wired));
+
+	/* IP stuff */
+	s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
+	g_object_set (G_OBJECT (s_ip4), NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL);
+	nm_connection_add_setting (connection, NM_SETTING (s_ip4));
+
+	s_ip6 = (NMSettingIP6Config *) nm_setting_ip6_config_new ();
+	g_object_set (G_OBJECT (s_ip6), NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, NULL);
+	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
+
+	/* DCB */
+	s_dcb = (NMSettingDcb *) nm_setting_dcb_new ();
+	nm_connection_add_setting (connection, NM_SETTING (s_dcb));
+
+	g_object_set (G_OBJECT (s_dcb),
+	              NM_SETTING_DCB_APP_FCOE_FLAGS, NM_SETTING_DCB_FLAG_ENABLE,
+	              NM_SETTING_DCB_APP_FCOE_MODE, expected_mode,
+	              NULL);
+
+	g_assert (nm_connection_verify (connection, &error));
+
+	/* Save the ifcfg */
+	success = writer_new_connection (connection,
+	                                 TEST_SCRATCH_DIR "/network-scripts/",
+	                                 &testfile,
+	                                 &error);
+	g_assert_no_error (error);
+	g_assert (success);
+	g_assert (testfile);
+
+	{
+		shvarFile *ifcfg = svOpenFile (testfile, &error);
+		char *written_mode;
+
+		g_assert_no_error (error);
+		g_assert (ifcfg);
+		written_mode = svGetValue (ifcfg, "DCB_APP_FCOE_MODE", FALSE);
+		svCloseFile (ifcfg);
+		g_assert_cmpstr (written_mode, ==, expected_mode);
+		g_free (written_mode);
+	}
+
+	/* re-read the connection for comparison */
+	reread = connection_from_file (testfile,
+	                               NULL,
+	                               TYPE_ETHERNET,
+	                               NULL, NULL, NULL,
+	                               NULL, NULL,
+	                               &error,
+	                               &ignore_error);
+	unlink (testfile);
+
+	g_assert_no_error (error);
+	g_assert (reread);
+	g_assert (nm_connection_verify (reread, &error));
+	g_assert (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT));
+
+	g_object_unref (connection);
+	g_object_unref (reread);
+	g_free (testfile);
+}
+
+static void
+test_read_team_master (void)
+{
+	NMConnection *connection;
+	NMSettingConnection *s_con;
+	NMSettingTeam *s_team;
+	gboolean success;
+	GError *error = NULL;
+	const char *expected_config = "{ \"device\": \"team0\", \"link_watch\": { \"name\": \"ethtool\" } }";
+
+	connection = connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-team-master",
+	                                   NULL, TYPE_ETHERNET, NULL, NULL, NULL, NULL, NULL, &error, NULL);
+	g_assert_no_error (error);
+	g_assert (connection);
+
+	success = nm_connection_verify (connection, &error);
+	g_assert_no_error (error);
+	g_assert (success);
+
+	s_con = nm_connection_get_setting_connection (connection);
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_connection_type (s_con), ==, NM_SETTING_TEAM_SETTING_NAME);
+
+	s_team = nm_connection_get_setting_team (connection);
+	g_assert (s_team);
+	g_assert_cmpstr (nm_setting_team_get_interface_name (s_team), ==, "team0");
+	g_assert_cmpstr (nm_setting_team_get_config (s_team), ==, expected_config);
+
+	g_object_unref (connection);
+}
+
+static void
+test_write_team_master (void)
+{
+	NMConnection *connection, *reread;
+	NMSettingConnection *s_con;
+	NMSettingTeam *s_team;
+	NMSettingWired *s_wired;
+	char *uuid, *testfile = NULL, *val;
+	gboolean success;
+	GError *error = NULL;
+	const char *expected_config = "{ \"device\": \"team0\", \"link_watch\": { \"name\": \"ethtool\" } }";
+	const char *escaped_expected_config = "\"{ \\\"device\\\": \\\"team0\\\", \\\"link_watch\\\": { \\\"name\\\": \\\"ethtool\\\" } }\"";
+	shvarFile *f;
+
+	connection = nm_connection_new ();
+
+	/* Connection setting */
+	s_con = (NMSettingConnection *) nm_setting_connection_new ();
+	nm_connection_add_setting (connection, NM_SETTING (s_con));
+
+	uuid = nm_utils_uuid_generate ();
+	g_object_set (s_con,
+	              NM_SETTING_CONNECTION_ID, "Test Write Team Master",
+	              NM_SETTING_CONNECTION_UUID, uuid,
+	              NM_SETTING_CONNECTION_TYPE, NM_SETTING_TEAM_SETTING_NAME,
+	              NULL);
+	g_free (uuid);
+
+	/* Team setting */
+	s_team = (NMSettingTeam *) nm_setting_team_new ();
+	nm_connection_add_setting (connection, NM_SETTING (s_team));
+
+	g_object_set (s_team,
+	              NM_SETTING_TEAM_INTERFACE_NAME, "team0",
+	              NM_SETTING_TEAM_CONFIG, expected_config,
+	              NULL);
+
+	/* Wired setting */
+	s_wired = (NMSettingWired *) nm_setting_wired_new ();
+	nm_connection_add_setting (connection, NM_SETTING (s_wired));
+
+	success = nm_connection_verify (connection, &error);
+	g_assert_no_error (error);
+	g_assert (success);
+
+	/* Save the ifcfg */
+	success = writer_new_connection (connection,
+	                                 TEST_SCRATCH_DIR "/network-scripts/",
+	                                 &testfile,
+	                                 &error);
+	g_assert_no_error (error);
+	g_assert (success);
+
+	f = svOpenFile (testfile, &error);
+	g_assert_no_error (error);
+	g_assert (f);
+
+	/* re-read the file to check that what key was written. */
+	val = svGetValue (f, "DEVICETYPE", FALSE);
+	g_assert (val);
+	g_assert_cmpstr (val, ==, "Team");
+	g_free (val);
+	val = svGetValue (f, "TEAM_CONFIG", TRUE);
+	g_assert (val);
+	g_assert_cmpstr (val, ==, escaped_expected_config);
+	g_free (val);
+	svCloseFile (f);
+
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_utils_normalize_connection (connection, TRUE);
+
+	/* re-read the connection for comparison */
+	reread = connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL,
+	                               NULL, NULL, NULL, NULL, &error, NULL);
+	unlink (testfile);
+	g_assert_no_error (error);
+	g_assert (reread);
+
+	success = nm_connection_verify (reread, &error);
+	g_assert_no_error (error);
+	g_assert (success);
+
+	g_assert (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT));
+
+	g_free (testfile);
+	g_object_unref (connection);
+	g_object_unref (reread);
+}
+
+static void
+test_read_team_port (void)
+{
+	NMConnection *connection;
+	NMSettingConnection *s_con;
+	NMSettingTeamPort *s_team_port;
+	gboolean success;
+	GError *error = NULL;
+	const char *expected_config = "{ \"p4p1\": { \"prio\": -10, \"sticky\": true } }";
+
+	connection = connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-team-port",
+	                                   NULL, TYPE_ETHERNET, NULL, NULL, NULL, NULL, NULL, &error, NULL);
+	g_assert_no_error (error);
+	g_assert (connection);
+
+	success = nm_connection_verify (connection, &error);
+	g_assert_no_error (error);
+	g_assert (success);
+
+	s_con = nm_connection_get_setting_connection (connection);
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_connection_type (s_con), ==, NM_SETTING_WIRED_SETTING_NAME);
+	g_assert_cmpstr (nm_setting_connection_get_master (s_con), ==, "team0");
+
+	s_team_port = nm_connection_get_setting_team_port (connection);
+	g_assert (s_team_port);
+	g_assert_cmpstr (nm_setting_team_port_get_config (s_team_port), ==, expected_config);
+
+	g_object_unref (connection);
+}
+
+static void
+test_write_team_port (void)
+{
+	NMConnection *connection, *reread;
+	NMSettingConnection *s_con;
+	NMSettingTeamPort *s_team_port;
+	NMSettingWired *s_wired;
+	char *uuid, *testfile = NULL, *val;
+	gboolean success;
+	GError *error = NULL;
+	const char *expected_config = "{ \"p4p1\": { \"prio\": -10, \"sticky\": true } }";
+	const char *escaped_expected_config = "\"{ \\\"p4p1\\\": { \\\"prio\\\": -10, \\\"sticky\\\": true } }\"";
+	shvarFile *f;
+
+	connection = nm_connection_new ();
+
+	/* Connection setting */
+	s_con = (NMSettingConnection *) nm_setting_connection_new ();
+	nm_connection_add_setting (connection, NM_SETTING (s_con));
+
+	uuid = nm_utils_uuid_generate ();
+	g_object_set (s_con,
+	              NM_SETTING_CONNECTION_ID, "Test Write Team Port",
+	              NM_SETTING_CONNECTION_UUID, uuid,
+	              NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME,
+	              NM_SETTING_CONNECTION_MASTER, "team0",
+	              NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_TEAM_SETTING_NAME,
+	              NULL);
+	g_free (uuid);
+
+	/* Team setting */
+	s_team_port = (NMSettingTeamPort *) nm_setting_team_port_new ();
+	nm_connection_add_setting (connection, NM_SETTING (s_team_port));
+	g_object_set (s_team_port, NM_SETTING_TEAM_PORT_CONFIG, expected_config, NULL);
+
+	/* Wired setting */
+	s_wired = (NMSettingWired *) nm_setting_wired_new ();
+	nm_connection_add_setting (connection, NM_SETTING (s_wired));
+
+	success = nm_connection_verify (connection, &error);
+	g_assert_no_error (error);
+	g_assert (success);
+
+	/* Save the ifcfg */
+	success = writer_new_connection (connection,
+	                                 TEST_SCRATCH_DIR "/network-scripts/",
+	                                 &testfile,
+	                                 &error);
+	g_assert_no_error (error);
+	g_assert (success);
+
+	f = svOpenFile (testfile, &error);
+	g_assert_no_error (error);
+	g_assert (f);
+
+	/* re-read the file to check that what key was written. */
+	val = svGetValue (f, "TYPE", FALSE);
+	g_assert (!val);
+	val = svGetValue (f, "DEVICETYPE", FALSE);
+	g_assert (val);
+	g_assert_cmpstr (val, ==, "TeamPort");
+	g_free (val);
+	val = svGetValue (f, "TEAM_PORT_CONFIG", TRUE);
+	g_assert (val);
+	g_assert_cmpstr (val, ==, escaped_expected_config);
+	val = svGetValue (f, "TEAM_MASTER", TRUE);
+	g_assert (val);
+	g_assert_cmpstr (val, ==, "team0");
+	g_free (val);
+	svCloseFile (f);
+
+	/* reread will be normalized, so we must normalize connection too. */
+	nm_utils_normalize_connection (connection, TRUE);
+
+	/* re-read the connection for comparison */
+	reread = connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL,
+	                               NULL, NULL, NULL, NULL, &error, NULL);
+	unlink (testfile);
+	g_assert_no_error (error);
+	g_assert (reread);
+
+	success = nm_connection_verify (reread, &error);
+	g_assert_no_error (error);
+	g_assert (success);
+
+	g_assert (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT));
+
+	g_free (testfile);
+	g_object_unref (connection);
+	g_object_unref (reread);
+}
+
+static void
+test_read_team_port_empty_config (void)
+{
+	NMConnection *connection;
+	NMSettingConnection *s_con;
+	gboolean success;
+	GError *error = NULL;
+
+	connection = connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-team-port-empty-config",
+	                                   NULL, TYPE_ETHERNET, NULL, NULL, NULL, NULL, NULL, &error, NULL);
+	g_assert_no_error (error);
+	g_assert (connection);
+
+	success = nm_connection_verify (connection, &error);
+	g_assert_no_error (error);
+	g_assert (success);
+
+	s_con = nm_connection_get_setting_connection (connection);
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_connection_type (s_con), ==, NM_SETTING_WIRED_SETTING_NAME);
+	g_assert_cmpstr (nm_setting_connection_get_master (s_con), ==, "team0");
+
+	/* Empty TEAM_PORT_CONFIG means no team-port setting */
+	g_assert (nm_connection_get_setting_team_port (connection) == NULL);
+
+	g_object_unref (connection);
+}
+
+/* Old algorithm for "remove escaped characters in place".
+ *
+ * This function is obsolete because it has O(n^2) runtime
+ * complexity and got replaced. Keep it here for testing,
+ * that both functions behave identical.
+ **/
+static void
+svUnescape_On2 (char *s)
+{
+	int len, i;
+
+	len = strlen(s);
+	if (len >= 2 && (s[0] == '"' || s[0] == '\'') && s[0] == s[len-1]) {
+		i = len - 2;
+		if (i == 0)
+			s[0] = '\0';
+		else {
+			memmove(s, s+1, i);
+			s[i+1] = '\0';
+			len = i;
+		}
+	}
+	for (i = 0; i < len; i++) {
+		if (s[i] == '\\') {
+			memmove(s+i, s+i+1, len-(i+1));
+			len--;
+		}
+		s[len] = '\0';
+	}
+}
+
+static void
+test_svUnescape_assert (const char *str)
+{
+	char *s1 = g_strdup (str);
+	char *s2 = g_strdup (str);
+
+	svUnescape (s1);
+	svUnescape_On2 (s2);
+
+	g_assert_cmpstr (s1, ==, s2);
+
+	g_free (s1);
+	g_free (s2);
+}
+
+static void
+test_svUnescape ()
+{
+	int len, repeat, i, k;
+	GRand *rand = g_rand_new ();
+	guint32 seed = g_random_int ();
+
+	g_rand_set_seed (rand, seed);
+
+	test_svUnescape_assert ("");
+	test_svUnescape_assert ("'");
+	test_svUnescape_assert ("\"");
+	test_svUnescape_assert ("\\");
+	test_svUnescape_assert ("x");
+	test_svUnescape_assert (" ");
+	test_svUnescape_assert ("'  '");
+	test_svUnescape_assert ("'x'");
+	test_svUnescape_assert ("\'some string\'");
+	test_svUnescape_assert ("Bob outside LAN");
+	test_svUnescape_assert ("{ \"device\": \"team0\", \"link_watch\": { \"name\": \"ethtool\" } }");
+
+	for (len = 1; len < 25; len++) {
+		char *s = g_new0 (char, len+1);
+
+		for (repeat = 0; repeat < MAX (4*len, 20); repeat++) {
+
+			/* fill the entire string with random. */
+			for (i = 0; i < len; i++)
+				s[i] = g_rand_int (rand);
+
+			/* randomly place escape characters into the string */
+			k = g_rand_int (rand) % (len);
+			while (k-- > 0)
+				s[g_rand_int (rand) % len] = '\\';
+
+			if (len > 1) {
+				/* quote the string. */
+				k = g_rand_int (rand) % (10);
+				if (k < 4) {
+					char quote = k < 2 ? '"' : '\'';
+
+					s[0] = quote;
+					s[len-1] = quote;
+				}
+			}
+
+			/*g_message (">>%s<<", s);*/
+			test_svUnescape_assert (s);
+		}
+
+		g_free (s);
+	}
+
+	g_rand_free (rand);
+}
+
+
 #define TEST_IFCFG_WIFI_OPEN_SSID_BAD_HEX TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-open-ssid-bad-hex"
 #define TEST_IFCFG_WIFI_OPEN_SSID_LONG_QUOTED TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-open-ssid-long-quoted"
 #define TEST_IFCFG_WIFI_OPEN_SSID_LONG_HEX TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-open-ssid-long-hex"
@@ -13619,34 +14539,34 @@ test_write_bond_slave_ib (void)
 
 #define DEFAULT_HEX_PSK "7d308b11df1b4243b0f78e5f3fc68cdbb9a264ed0edf4c188edf329ff5b467f0"
 
-#define TEST_IFCFG_VARIABLES_CORNER_CASES_1 TEST_IFCFG_DIR"/network-scripts/ifcfg-test-variables-corner-cases-1"
+#define TPATH "/settings/plugins/ifcfg-rh/"
+
+NMTST_DEFINE ();
 
 int main (int argc, char **argv)
 {
-	GError *error = NULL;
-	char *base;
-
-	g_type_init ();
-
-	if (!nm_utils_init (&error))
-		FAIL ("nm-utils-init", "failed to initialize libnm-util: %s", error->message);
-
-	/* The tests */
-	test_read_unmanaged ();
-	test_read_minimal ();
-	test_read_variables_corner_cases (TEST_IFCFG_VARIABLES_CORNER_CASES_1, "\"");
-	test_read_wired_static (TEST_IFCFG_WIRED_STATIC, "System test-wired-static");
-	test_read_wired_static (TEST_IFCFG_WIRED_STATIC_BOOTPROTO, "System test-wired-static-bootproto");
-	test_read_wired_static_no_prefix (8);
-	test_read_wired_static_no_prefix (16);
-	test_read_wired_static_no_prefix (24);
-
-	test_write_wired_static_ip6_only_gw (NULL);
-	test_write_wired_static_ip6_only_gw ("::");
-	test_write_wired_static_ip6_only_gw ("2001:db8:8:4::2");
-	test_write_wired_static_ip6_only_gw ("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255");
-
+	nmtst_init_assert_logging (&argc, &argv);
+
+	g_test_add_func (TPATH "svUnescape", test_svUnescape);
+
+	g_test_add_func (TPATH "unmanaged", test_read_unmanaged);
+	g_test_add_func (TPATH "unmanaged-unrecognized", test_read_unmanaged_unrecognized);
+	g_test_add_func (TPATH "unrecognized", test_read_unrecognized);
+	g_test_add_func (TPATH "basic", test_read_basic);
+	g_test_add_func (TPATH "variables-corner-cases", test_read_variables_corner_cases);
+	g_test_add_data_func (TPATH "no-prefix/8", GUINT_TO_POINTER (8), test_read_wired_static_no_prefix);
+	g_test_add_data_func (TPATH "no-prefix/16", GUINT_TO_POINTER (16), test_read_wired_static_no_prefix);
+	g_test_add_data_func (TPATH "no-prefix/24", GUINT_TO_POINTER (24), test_read_wired_static_no_prefix);
+	g_test_add_data_func (TPATH "static-ip6-only-gw/_NULL_", NULL, test_write_wired_static_ip6_only_gw);
+	g_test_add_data_func (TPATH "static-ip6-only-gw/::", "::", test_write_wired_static_ip6_only_gw);
+	g_test_add_data_func (TPATH "static-ip6-only-gw/2001:db8:8:4::2", "2001:db8:8:4::2", test_write_wired_static_ip6_only_gw);
+	g_test_add_data_func (TPATH "static-ip6-only-gw/ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255", "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255", test_write_wired_static_ip6_only_gw);
+
+	test_read_wired_static (TEST_IFCFG_WIRED_STATIC, "System test-wired-static", TRUE);
+	test_read_wired_static (TEST_IFCFG_WIRED_STATIC_BOOTPROTO, "System test-wired-static-bootproto", FALSE);
 	test_read_wired_dhcp ();
+	g_test_add_func (TPATH "dhcp-plus-ip", test_read_wired_dhcp_plus_ip);
+	g_test_add_func (TPATH "dhcp-send-hostname", test_read_write_wired_dhcp_send_hostname);
 	test_read_wired_global_gateway ();
 	test_read_wired_never_default ();
 	test_read_wired_defroute_no ();
@@ -13661,10 +14581,16 @@ int main (int argc, char **argv)
 	test_read_wired_ipv6_only ();
 	test_read_wired_dhcp6_only ();
 	test_read_onboot_no ();
+	test_read_noip ();
 	test_read_wired_8021x_peap_mschapv2 ();
 	test_read_wired_8021x_tls_secret_flags (TEST_IFCFG_WIRED_8021X_TLS_AGENT, NM_SETTING_SECRET_FLAG_AGENT_OWNED);
 	test_read_wired_8021x_tls_secret_flags (TEST_IFCFG_WIRED_8021X_TLS_ALWAYS,
 	                                        NM_SETTING_SECRET_FLAG_AGENT_OWNED | NM_SETTING_SECRET_FLAG_NOT_SAVED);
+	g_test_add_func (TPATH "802-1x/subj-matches", test_read_write_802_1X_subj_matches);
+	g_test_add_func (TPATH "802-1x/ttls-eapgtc", test_read_802_1x_ttls_eapgtc);
+	test_read_wired_aliases_good ();
+	test_read_wired_aliases_bad_1 ();
+	test_read_wired_aliases_bad_2 ();
 	test_read_wifi_open ();
 	test_read_wifi_open_auto ();
 	test_read_wifi_open_ssid_hex ();
@@ -13691,6 +14617,7 @@ int main (int argc, char **argv)
 	test_read_wifi_wpa_eap_tls ();
 	test_read_wifi_wpa_eap_ttls_tls ();
 	test_read_wifi_wep_eap_ttls_chap ();
+	g_test_add_func (TPATH "wifi/read-hidden", test_read_wifi_hidden);
 	test_read_wired_qeth_static ();
 	test_read_wired_ctc_static ();
 	test_read_wifi_wep_no_keys ();
@@ -13700,18 +14627,21 @@ int main (int argc, char **argv)
 	test_read_vlan_interface ();
 	test_read_vlan_only_vlan_id ();
 	test_read_vlan_only_device ();
-	test_read_vlan_physdev ();
+	g_test_add_func (TPATH "vlan/physdev", test_read_vlan_physdev);
 
 	test_write_wired_static ();
 	test_write_wired_static_ip6_only ();
 	test_write_wired_static_routes ();
 	test_read_write_static_routes_legacy ();
 	test_write_wired_dhcp ();
+	g_test_add_func (TPATH "dhcp-plus-ip", test_write_wired_dhcp_plus_ip);
 	test_write_wired_dhcp_8021x_peap_mschapv2 ();
 	test_write_wired_8021x_tls (NM_SETTING_802_1X_CK_SCHEME_PATH, NM_SETTING_SECRET_FLAG_AGENT_OWNED);
 	test_write_wired_8021x_tls (NM_SETTING_802_1X_CK_SCHEME_PATH, NM_SETTING_SECRET_FLAG_NOT_SAVED);
 	test_write_wired_8021x_tls (NM_SETTING_802_1X_CK_SCHEME_PATH, NM_SETTING_SECRET_FLAG_AGENT_OWNED | NM_SETTING_SECRET_FLAG_NOT_SAVED);
 	test_write_wired_8021x_tls (NM_SETTING_802_1X_CK_SCHEME_BLOB, NM_SETTING_SECRET_FLAG_NONE);
+	test_write_wired_aliases ();
+	g_test_add_func (TPATH "ipv4/write-static-addresses-GATEWAY", test_write_gateway);
 	test_write_wifi_open ();
 	test_write_wifi_open_hex_ssid ();
 	test_write_wifi_wep ();
@@ -13766,6 +14696,7 @@ int main (int argc, char **argv)
 	test_write_wifi_dynamic_wep_leap ();
 	test_write_wifi_wpa_then_open ();
 	test_write_wifi_wpa_then_wep_with_perms ();
+	g_test_add_func (TPATH "wifi/write-hidden", test_write_wifi_hidden);
 	test_write_wired_qeth_dhcp ();
 	test_write_wired_ctc_dhcp ();
 	test_write_permissions ();
@@ -13778,12 +14709,26 @@ int main (int argc, char **argv)
 	/* iSCSI / ibft */
 	test_read_ibft_dhcp ();
 	test_read_ibft_static ();
-	test_read_ibft_malformed ("ibft-bad-record-read", TEST_IFCFG_DIR "/iscsiadm-test-bad-record");
-	test_read_ibft_malformed ("ibft-bad-entry-read", TEST_IFCFG_DIR "/iscsiadm-test-bad-entry");
-	test_read_ibft_malformed ("ibft-bad-ipaddr-read", TEST_IFCFG_DIR "/iscsiadm-test-bad-ipaddr");
-	test_read_ibft_malformed ("ibft-bad-gateway-read", TEST_IFCFG_DIR "/iscsiadm-test-bad-gateway");
-	test_read_ibft_malformed ("ibft-bad-dns1-read", TEST_IFCFG_DIR "/iscsiadm-test-bad-dns1");
-	test_read_ibft_malformed ("ibft-bad-dns2-read", TEST_IFCFG_DIR "/iscsiadm-test-bad-dns2");
+	test_read_ibft_malformed ("ibft-bad-record-read", TEST_IFCFG_DIR "/iscsiadm-test-bad-record", FALSE);
+	test_read_ibft_malformed ("ibft-bad-entry-read", TEST_IFCFG_DIR "/iscsiadm-test-bad-entry", TRUE);
+	test_read_ibft_malformed ("ibft-bad-ipaddr-read", TEST_IFCFG_DIR "/iscsiadm-test-bad-ipaddr", TRUE);
+	test_read_ibft_malformed ("ibft-bad-gateway-read", TEST_IFCFG_DIR "/iscsiadm-test-bad-gateway", TRUE);
+	test_read_ibft_malformed ("ibft-bad-dns1-read", TEST_IFCFG_DIR "/iscsiadm-test-bad-dns1", TRUE);
+	test_read_ibft_malformed ("ibft-bad-dns2-read", TEST_IFCFG_DIR "/iscsiadm-test-bad-dns2", TRUE);
+	g_test_add_func (TPATH "dcb/read-basic", test_read_dcb_basic);
+	g_test_add_func (TPATH "dcb/write-basic", test_write_dcb_basic);
+	g_test_add_func (TPATH "dcb/default-app-priorities", test_read_dcb_default_app_priorities);
+	g_test_add_func (TPATH "dcb/bad-booleans", test_read_dcb_bad_booleans);
+	g_test_add_func (TPATH "dcb/short-booleans", test_read_dcb_short_booleans);
+	g_test_add_func (TPATH "dcb/bad-uints", test_read_dcb_bad_uints);
+	g_test_add_func (TPATH "dcb/short-uints", test_read_dcb_short_uints);
+	g_test_add_func (TPATH "dcb/bad-percent", test_read_dcb_bad_percent);
+	g_test_add_func (TPATH "dcb/short-percent", test_read_dcb_short_percent);
+	g_test_add_func (TPATH "dcb/pgpct-not-100", test_read_dcb_pgpct_not_100);
+	g_test_add_data_func (TPATH "fcoe/fabric", (gpointer) NM_SETTING_DCB_FCOE_MODE_FABRIC, test_read_fcoe_mode);
+	g_test_add_data_func (TPATH "fcoe/vn2vn", (gpointer) NM_SETTING_DCB_FCOE_MODE_VN2VN, test_read_fcoe_mode);
+	g_test_add_data_func (TPATH "fcoe/write-fabric", (gpointer) NM_SETTING_DCB_FCOE_MODE_FABRIC, test_write_fcoe_mode);
+	g_test_add_data_func (TPATH "fcoe/write-vn2vn", (gpointer) NM_SETTING_DCB_FCOE_MODE_VN2VN, test_write_fcoe_mode);
 
 	/* bonding */
 	test_read_bond_main ();
@@ -13800,15 +14745,19 @@ int main (int argc, char **argv)
 	test_write_bridge_component ();
 	test_read_bridge_missing_stp ();
 
+	/* Team */
+	g_test_add_func (TPATH "team/read-master", test_read_team_master);
+	g_test_add_func (TPATH "team/write-master", test_write_team_master);
+	g_test_add_func (TPATH "team/read-port", test_read_team_port);
+	g_test_add_func (TPATH "team/write-port", test_write_team_port);
+	g_test_add_func (TPATH "team/read-port-empty-config", test_read_team_port_empty_config);
+
 	/* Stuff we expect to fail for now */
 	test_write_wired_pppoe ();
 	test_write_vpn ();
 	test_write_mobile_broadband (TRUE);
 	test_write_mobile_broadband (FALSE);
 
-	base = g_path_get_basename (argv[0]);
-	fprintf (stdout, "%s: SUCCESS\n", base);
-	g_free (base);
-	return 0;
+	return g_test_run ();
 }
 
diff --git a/src/settings/plugins/ifcfg-rh/utils.c b/src/settings/plugins/ifcfg-rh/utils.c
index 04df6671..8318a65d 100644
--- a/src/settings/plugins/ifcfg-rh/utils.c
+++ b/src/settings/plugins/ifcfg-rh/utils.c
@@ -25,97 +25,6 @@
 #include "shvar.h"
 
 /*
- * utils_bin2hexstr
- *
- * Convert a byte-array into a hexadecimal string.
- *
- * Code originally by Alex Larsson <alexl@redhat.com> and
- *  copyright Red Hat, Inc. under terms of the LGPL.
- *
- */
-char *
-utils_bin2hexstr (const char *bytes, int len, int final_len)
-{
-	static char hex_digits[] = "0123456789abcdef";
-	char *result;
-	int i;
-	gsize buflen = (len * 2) + 1;
-
-	g_return_val_if_fail (bytes != NULL, NULL);
-	g_return_val_if_fail (len > 0, NULL);
-	g_return_val_if_fail (len < 4096, NULL);   /* Arbitrary limit */
-	if (final_len > -1)
-		g_return_val_if_fail (final_len < buflen, NULL);
-
-	result = g_malloc0 (buflen);
-	for (i = 0; i < len; i++)
-	{
-		result[2*i] = hex_digits[(bytes[i] >> 4) & 0xf];
-		result[2*i+1] = hex_digits[bytes[i] & 0xf];
-	}
-	/* Cut converted key off at the correct length for this cipher type */
-	if (final_len > -1)
-		result[final_len] = '\0';
-	else
-		result[buflen - 1] = '\0';
-
-	return result;
-}
-
-/* From hostap, Copyright (c) 2002-2005, Jouni Malinen <jkmaline@cc.hut.fi> */
-
-static int hex2num (char c)
-{
-	if (c >= '0' && c <= '9')
-		return c - '0';
-	if (c >= 'a' && c <= 'f')
-		return c - 'a' + 10;
-	if (c >= 'A' && c <= 'F')
-		return c - 'A' + 10;
-	return -1;
-}
-
-static int hex2byte (const char *hex)
-{
-	int a, b;
-	a = hex2num(*hex++);
-	if (a < 0)
-		return -1;
-	b = hex2num(*hex++);
-	if (b < 0)
-		return -1;
-	return (a << 4) | b;
-}
-
-char *
-utils_hexstr2bin (const char *hex, size_t len)
-{
-	size_t       i;
-	int          a;
-	const char * ipos = hex;
-	char *       buf = NULL;
-	char *       opos;
-
-	/* Length must be a multiple of 2 */
-	if ((len % 2) != 0)
-		return NULL;
-
-	opos = buf = g_malloc0 ((len / 2) + 1);
-	for (i = 0; i < len; i += 2) {
-		a = hex2byte (ipos);
-		if (a < 0) {
-			g_free (buf);
-			return NULL;
-		}
-		*opos++ = a;
-		ipos += 2;
-	}
-	return buf;
-}
-
-/* End from hostap */
-
-/*
  * utils_single_quote_string
  *
  * Put string inside single quotes and remove CR, LF characters. If single quote
@@ -143,7 +52,6 @@ utils_single_quote_string (const char *str)
 			drop++;
 	}
 	new_str = g_malloc0 (slen + extra - drop + 4); /* 4 is for $''\0*/
-	if (!new_str) return NULL;
 
 	if (extra > 0)
 		new_str[j++] = '$';
@@ -179,7 +87,6 @@ utils_single_unquote_string (const char *str)
 
 	slen = strlen (str);
 	new_str = g_malloc0 (slen + 1);
-	if (!new_str) return NULL;
 
 	if (   (slen >= 2 && (str[0] == dq_char || str[0] == q_char) && str[0] == str[slen-1])
 	    || (slen >= 3 && str[0] == '$' && str[1] == q_char && str[1] == str[slen-1])) {
@@ -389,7 +296,7 @@ utils_get_extra_ifcfg (const char *parent, const char *tag, gboolean should_crea
 		ifcfg = svCreateFile (path);
 
 	if (!ifcfg)
-		ifcfg = svNewFile (path);
+		ifcfg = svOpenFile (path, NULL);
 
 	g_free (path);
 	return ifcfg;
@@ -455,8 +362,55 @@ utils_ignore_ip_config (NMConnection *connection)
 	 * scripts just ignore it if it's there.
 	 */
 	if (   nm_setting_connection_is_slave_type (s_con, NM_SETTING_BOND_SETTING_NAME)
-	    || nm_setting_connection_is_slave_type (s_con, NM_SETTING_BRIDGE_SETTING_NAME))
+	    || nm_setting_connection_is_slave_type (s_con, NM_SETTING_BRIDGE_SETTING_NAME)
+	    || nm_setting_connection_is_slave_type (s_con, NM_SETTING_TEAM_SETTING_NAME))
 		return TRUE;
 
 	return FALSE;
 }
+
+/* Find out if the 'alias' file name might be an alias file for 'ifcfg' file name,
+ * or any alias when 'ifcfg' is NULL. Does not check that it's actually a valid
+ * alias name; that happens in reader.c
+ */
+gboolean
+utils_is_ifcfg_alias_file (const char *alias, const char *ifcfg)
+{
+	g_return_val_if_fail (alias != NULL, FALSE);
+
+	if (strncmp (alias, IFCFG_TAG, strlen (IFCFG_TAG)))
+		return FALSE;
+
+	if (ifcfg) {
+		size_t len = strlen (ifcfg);
+
+		return (strncmp (alias, ifcfg, len) == 0 && alias[len] == ':');
+	} else {
+		return (strchr (alias, ':') != NULL);
+	}
+}
+
+char *
+utils_get_ifcfg_from_alias (const char *alias)
+{
+	char *base, *ptr, *ifcfg = NULL;
+
+	g_return_val_if_fail (alias != NULL, NULL);
+
+	base = g_path_get_basename (alias);
+	g_return_val_if_fail (base != NULL, NULL);
+
+	if (utils_is_ifcfg_alias_file (base, NULL)) {
+		ifcfg = g_strdup (alias);
+		ptr = strrchr (ifcfg, ':');
+		if (ptr)
+			*ptr = '\0';
+		else {
+			g_free (ifcfg);
+			ifcfg = NULL;
+		}
+	}
+
+	g_free (base);
+	return ifcfg;
+}
diff --git a/src/settings/plugins/ifcfg-rh/utils.h b/src/settings/plugins/ifcfg-rh/utils.h
index 9262ef72..95af828b 100644
--- a/src/settings/plugins/ifcfg-rh/utils.h
+++ b/src/settings/plugins/ifcfg-rh/utils.h
@@ -26,10 +26,6 @@
 #include "shvar.h"
 #include "common.h"
 
-char *utils_bin2hexstr (const char *bytes, int len, int final_len);
-
-char *utils_hexstr2bin (const char *hex, size_t len);
-
 char *utils_single_quote_string (const char *str);
 
 char *utils_single_unquote_string (const char *str);
@@ -54,5 +50,8 @@ gboolean utils_has_route_file_new_syntax (const char *filename);
 
 gboolean utils_ignore_ip_config (NMConnection *connection);
 
+gboolean utils_is_ifcfg_alias_file (const char *alias, const char *ifcfg);
+char *utils_get_ifcfg_from_alias (const char *alias);
+
 #endif  /* _UTILS_H_ */
 
diff --git a/src/settings/plugins/ifcfg-rh/writer.c b/src/settings/plugins/ifcfg-rh/writer.c
index 8ecbf2bd..60af599b 100644
--- a/src/settings/plugins/ifcfg-rh/writer.c
+++ b/src/settings/plugins/ifcfg-rh/writer.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) 2009 - 2012 Red Hat, Inc.
+ * Copyright (C) 2009 - 2013 Red Hat, Inc.
  */
 
 #include <string.h>
@@ -37,8 +37,12 @@
 #include <nm-setting-ip6-config.h>
 #include <nm-setting-pppoe.h>
 #include <nm-setting-vlan.h>
+#include <nm-setting-team.h>
+#include <nm-setting-team-port.h>
+#include <nm-utils-private.h>
 #include <nm-utils.h>
 
+#include "nm-logging.h"
 #include "common.h"
 #include "shvar.h"
 #include "reader.h"
@@ -46,8 +50,13 @@
 #include "utils.h"
 #include "crypto.h"
 
-#define PLUGIN_WARN(pname, fmt, args...) \
-	{ g_warning ("   " pname ": " fmt, ##args); }
+
+static void
+svSetValue_free (shvarFile *s, const char *key, char *value, gboolean verbatim)
+{
+	svSetValue (s, key, value, verbatim);
+	g_free (value);
+}
 
 static void
 save_secret_flags (shvarFile *ifcfg,
@@ -94,6 +103,7 @@ set_secret (shvarFile *ifcfg,
             gboolean verbatim)
 {
 	shvarFile *keyfile;
+	GError *error = NULL;
 	
 	/* Clear the secret from the ifcfg and the associated "keys" file */
 	svSetValue (ifcfg, key, NULL, FALSE);
@@ -103,8 +113,7 @@ set_secret (shvarFile *ifcfg,
 
 	keyfile = utils_get_keys_ifcfg (ifcfg->fileName, TRUE);
 	if (!keyfile) {
-		PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: could not create key file for '%s'",
-		             ifcfg->fileName);
+		nm_log_warn (LOGD_SETTINGS, "    could not create ifcfg file for '%s'", ifcfg->fileName);
 		goto error;
 	}
 
@@ -115,9 +124,10 @@ set_secret (shvarFile *ifcfg,
 	if (flags == NM_SETTING_SECRET_FLAG_NONE)
 		svSetValue (keyfile, key, value, verbatim);
 
-	if (svWriteFile (keyfile, 0600)) {
-		PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    warning: could not update key file '%s'",
-		             keyfile->fileName);
+	if (!svWriteFile (keyfile, 0600, &error)) {
+		nm_log_warn (LOGD_SETTINGS, "    could not update ifcfg file '%s': %s",
+		             keyfile->fileName, error->message);
+		g_clear_error (&error);
 		svCloseFile (keyfile);
 		goto error;
 	}
@@ -140,13 +150,6 @@ write_secret_file (const char *path,
 	gboolean success = FALSE;
 
 	tmppath = g_malloc0 (strlen (path) + 10);
-	if (!tmppath) {
-		g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
-		             "Could not allocate memory for temporary file for '%s'",
-		             path);
-		return FALSE;
-	}
-
 	memcpy (tmppath, path, strlen (path));
 	strcat (tmppath, ".XXXXXX");
 
@@ -452,10 +455,12 @@ write_8021x_setting (NMConnection *connection,
                      GError **error)
 {
 	NMSetting8021x *s_8021x;
-	const char *value;
+	const char *value, *match;
 	char *tmp = NULL;
 	gboolean success = FALSE;
 	GString *phase2_auth;
+	GString *str;
+	guint32 i, num;
 
 	s_8021x = nm_connection_get_setting_802_1x (connection);
 	if (!s_8021x) {
@@ -550,6 +555,40 @@ write_8021x_setting (NMConnection *connection,
 
 	g_string_free (phase2_auth, TRUE);
 
+	svSetValue (ifcfg, "IEEE_8021X_SUBJECT_MATCH",
+	            nm_setting_802_1x_get_subject_match (s_8021x),
+	            FALSE);
+
+	svSetValue (ifcfg, "IEEE_8021X_PHASE2_SUBJECT_MATCH",
+	            nm_setting_802_1x_get_phase2_subject_match (s_8021x),
+	            FALSE);
+
+	svSetValue (ifcfg, "IEEE_8021X_ALTSUBJECT_MATCHES", NULL, FALSE);
+	str = g_string_new (NULL);
+	num = nm_setting_802_1x_get_num_altsubject_matches (s_8021x);
+	for (i = 0; i < num; i++) {
+		if (i > 0)
+			g_string_append_c (str, ' ');
+		match = nm_setting_802_1x_get_altsubject_match (s_8021x, i);
+		g_string_append (str, match);
+	}
+	if (str->len > 0)
+		svSetValue (ifcfg, "IEEE_8021X_ALTSUBJECT_MATCHES", str->str, FALSE);
+	g_string_free (str, TRUE);
+
+	svSetValue (ifcfg, "IEEE_8021X_PHASE2_ALTSUBJECT_MATCHES", NULL, FALSE);
+	str = g_string_new (NULL);
+	num = nm_setting_802_1x_get_num_phase2_altsubject_matches (s_8021x);
+	for (i = 0; i < num; i++) {
+		if (i > 0)
+			g_string_append_c (str, ' ');
+		match = nm_setting_802_1x_get_phase2_altsubject_match (s_8021x, i);
+		g_string_append (str, match);
+	}
+	if (str->len > 0)
+		svSetValue (ifcfg, "IEEE_8021X_PHASE2_ALTSUBJECT_MATCHES", str->str, FALSE);
+	g_string_free (str, TRUE);
+
 	success = write_8021x_certs (s_8021x, FALSE, ifcfg, error);
 	if (success) {
 		/* phase2/inner certs */
@@ -786,21 +825,15 @@ write_wireless_setting (NMConnection *connection,
 	svSetValue (ifcfg, "HWADDR", NULL, FALSE);
 	device_mac = nm_setting_wireless_get_mac_address (s_wireless);
 	if (device_mac) {
-		tmp = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X",
-		                       device_mac->data[0], device_mac->data[1], device_mac->data[2],
-		                       device_mac->data[3], device_mac->data[4], device_mac->data[5]);
-		svSetValue (ifcfg, "HWADDR", tmp, FALSE);
-		g_free (tmp);
+		svSetValue_free (ifcfg, "HWADDR",
+		                 nm_utils_hwaddr_ntoa_len (device_mac->data, device_mac->len), FALSE);
 	}
 
 	svSetValue (ifcfg, "MACADDR", NULL, FALSE);
 	cloned_mac = nm_setting_wireless_get_cloned_mac_address (s_wireless);
 	if (cloned_mac) {
-		tmp = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X",
-		                       cloned_mac->data[0], cloned_mac->data[1], cloned_mac->data[2],
-		                       cloned_mac->data[3], cloned_mac->data[4], cloned_mac->data[5]);
-		svSetValue (ifcfg, "MACADDR", tmp, FALSE);
-		g_free (tmp);
+		svSetValue_free (ifcfg, "MACADDR",
+		                 nm_utils_hwaddr_ntoa_len (cloned_mac->data, cloned_mac->len), FALSE);
 	}
 
 	svSetValue (ifcfg, "HWADDR_BLACKLIST", NULL, FALSE);
@@ -902,11 +935,8 @@ write_wireless_setting (NMConnection *connection,
 	svSetValue (ifcfg, "BSSID", NULL, FALSE);
 	bssid = nm_setting_wireless_get_bssid (s_wireless);
 	if (bssid) {
-		tmp = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X",
-		                       bssid->data[0], bssid->data[1], bssid->data[2],
-		                       bssid->data[3], bssid->data[4], bssid->data[5]);
-		svSetValue (ifcfg, "BSSID", tmp, FALSE);
-		g_free (tmp);
+		svSetValue_free (ifcfg, "BSSID",
+		                 nm_utils_hwaddr_ntoa_len (bssid->data, bssid->len), FALSE);
 	}
 
 	/* Ensure DEFAULTKEY and SECURITYMODE are cleared unless there's security;
@@ -916,7 +946,7 @@ write_wireless_setting (NMConnection *connection,
 	svSetValue (ifcfg, "DEFAULTKEY", NULL, FALSE);
 	svSetValue (ifcfg, "SECURITYMODE", NULL, FALSE);
 
-	if (nm_setting_wireless_get_security (s_wireless)) {
+	if (nm_connection_get_setting_wireless_security (connection)) {
 		if (!write_wireless_security_setting (connection, ifcfg, adhoc, no_8021x, error))
 			return FALSE;
 	} else {
@@ -953,6 +983,8 @@ write_wireless_setting (NMConnection *connection,
 		g_free (keys_path);
 	}
 
+	svSetValue (ifcfg, "SSID_HIDDEN", nm_setting_wireless_get_hidden (s_wireless) ? "yes" : NULL, TRUE);
+
 	svSetValue (ifcfg, "TYPE", TYPE_WIRELESS, FALSE);
 
 	return TRUE;
@@ -964,8 +996,9 @@ write_infiniband_setting (NMConnection *connection, shvarFile *ifcfg, GError **e
 	NMSettingInfiniband *s_infiniband;
 	const GByteArray *mac;
 	char *tmp;
-	const char *transport_mode;
+	const char *transport_mode, *parent;
 	guint32 mtu;
+	int p_key;
 
 	s_infiniband = nm_connection_get_setting_infiniband (connection);
 	if (!s_infiniband) {
@@ -995,6 +1028,18 @@ write_infiniband_setting (NMConnection *connection, shvarFile *ifcfg, GError **e
 	            strcmp (transport_mode, "connected") == 0 ? "yes" : "no",
 	            FALSE);
 
+	p_key = nm_setting_infiniband_get_p_key (s_infiniband);
+	if (p_key != -1) {
+		svSetValue (ifcfg, "PKEY", "yes", FALSE);
+		tmp = g_strdup_printf ("%u", p_key);
+		svSetValue (ifcfg, "PKEY_ID", tmp, FALSE);
+		g_free (tmp);
+
+		parent = nm_setting_infiniband_get_parent (s_infiniband);
+		if (parent)
+			svSetValue (ifcfg, "PHYSDEV", parent, FALSE);
+	}
+
 	svSetValue (ifcfg, "TYPE", TYPE_INFINIBAND, FALSE);
 
 	return TRUE;
@@ -1022,21 +1067,15 @@ write_wired_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
 	svSetValue (ifcfg, "HWADDR", NULL, FALSE);
 	device_mac = nm_setting_wired_get_mac_address (s_wired);
 	if (device_mac) {
-		tmp = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X",
-		                       device_mac->data[0], device_mac->data[1], device_mac->data[2],
-		                       device_mac->data[3], device_mac->data[4], device_mac->data[5]);
-		svSetValue (ifcfg, "HWADDR", tmp, FALSE);
-		g_free (tmp);
+		svSetValue_free (ifcfg, "HWADDR",
+		                 nm_utils_hwaddr_ntoa_len (device_mac->data, device_mac->len), FALSE);
 	}
 
 	svSetValue (ifcfg, "MACADDR", NULL, FALSE);
 	cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired);
 	if (cloned_mac) {
-		tmp = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X",
-		                       cloned_mac->data[0], cloned_mac->data[1], cloned_mac->data[2],
-		                       cloned_mac->data[3], cloned_mac->data[4], cloned_mac->data[5]);
-		svSetValue (ifcfg, "MACADDR", tmp, FALSE);
-		g_free (tmp);
+		svSetValue_free (ifcfg, "MACADDR",
+		                 nm_utils_hwaddr_ntoa_len (cloned_mac->data, cloned_mac->len), FALSE);
 	}
 
 	svSetValue (ifcfg, "HWADDR_BLACKLIST", NULL, FALSE);
@@ -1139,7 +1178,7 @@ vlan_priority_maplist_to_stringlist (NMSettingVlan *s_vlan, NMVlanPriorityMap ma
 	for (iter = strlist; iter; iter = g_slist_next (iter))
 		g_string_append_printf (value, "%s%s", value->len ? "," : "", (const char *) iter->data);
 
-	nm_utils_slist_free (strlist, g_free);
+	g_slist_free_full (strlist, g_free);
 
 	return value;
 }
@@ -1288,11 +1327,39 @@ write_bonding_setting (NMConnection *connection, shvarFile *ifcfg, GError **erro
 	return TRUE;
 }
 
+static gboolean
+write_team_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
+{
+	NMSettingTeam *s_team;
+	const char *iface;
+	const char *config;
+
+	s_team = nm_connection_get_setting_team (connection);
+	if (!s_team) {
+		g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
+		             "Missing '%s' setting", NM_SETTING_TEAM_SETTING_NAME);
+		return FALSE;
+	}
+
+	iface = nm_setting_team_get_interface_name (s_team);
+	if (!iface) {
+		g_set_error (error, IFCFG_PLUGIN_ERROR, 0, "Missing interface name");
+		return FALSE;
+	}
+
+	svSetValue (ifcfg, "DEVICE", iface, FALSE);
+	config = nm_setting_team_get_config (s_team);
+	svSetValue (ifcfg, "TEAM_CONFIG", config, FALSE);
+	svSetValue (ifcfg, "DEVICETYPE", TYPE_TEAM, FALSE);
+
+	return TRUE;
+}
+
 static guint32
 get_setting_default (NMSetting *setting, const char *prop)
 {
 	GParamSpec *pspec;
-	GValue val = { 0 };
+	GValue val = G_VALUE_INIT;
 	guint32 ret = 0;
 
 	pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (setting), prop);
@@ -1312,6 +1379,7 @@ write_bridge_setting (NMConnection *connection, shvarFile *ifcfg, GError **error
 	const char *iface;
 	guint32 i;
 	GString *opts;
+	const GByteArray *mac;
 	char *s;
 
 	s_bridge = nm_connection_get_setting_bridge (connection);
@@ -1331,6 +1399,11 @@ write_bridge_setting (NMConnection *connection, shvarFile *ifcfg, GError **error
 	svSetValue (ifcfg, "BRIDGING_OPTS", NULL, FALSE);
 	svSetValue (ifcfg, "STP", "no", FALSE);
 	svSetValue (ifcfg, "DELAY", NULL, FALSE);
+	svSetValue (ifcfg, "MACADDR", NULL, FALSE);
+
+	mac = nm_setting_bridge_get_mac_address (s_bridge);
+	if (mac)
+		svSetValue_free (ifcfg, "MACADDR", nm_utils_hwaddr_ntoa_len (mac->data, mac->len), FALSE);
 
 	/* Bridge options */
 	opts = g_string_sized_new (32);
@@ -1339,7 +1412,7 @@ write_bridge_setting (NMConnection *connection, shvarFile *ifcfg, GError **error
 		svSetValue (ifcfg, "STP", "yes", FALSE);
 
 		i = nm_setting_bridge_get_forward_delay (s_bridge);
-		if (i && i != get_setting_default (NM_SETTING (s_bridge), NM_SETTING_BRIDGE_FORWARD_DELAY)) {
+		if (i != get_setting_default (NM_SETTING (s_bridge), NM_SETTING_BRIDGE_FORWARD_DELAY)) {
 			s = g_strdup_printf ("%u", i);
 			svSetValue (ifcfg, "DELAY", s, FALSE);
 			g_free (s);
@@ -1348,14 +1421,14 @@ write_bridge_setting (NMConnection *connection, shvarFile *ifcfg, GError **error
 		g_string_append_printf (opts, "priority=%u", nm_setting_bridge_get_priority (s_bridge));
 
 		i = nm_setting_bridge_get_hello_time (s_bridge);
-		if (i && i != get_setting_default (NM_SETTING (s_bridge), NM_SETTING_BRIDGE_HELLO_TIME)) {
+		if (i != get_setting_default (NM_SETTING (s_bridge), NM_SETTING_BRIDGE_HELLO_TIME)) {
 			if (opts->len)
 				g_string_append_c (opts, ' ');
 			g_string_append_printf (opts, "hello_time=%u", i);
 		}
 
 		i = nm_setting_bridge_get_max_age (s_bridge);
-		if (i && i != get_setting_default (NM_SETTING (s_bridge), NM_SETTING_BRIDGE_MAX_AGE)) {
+		if (i != get_setting_default (NM_SETTING (s_bridge), NM_SETTING_BRIDGE_MAX_AGE)) {
 			if (opts->len)
 				g_string_append_c (opts, ' ');
 			g_string_append_printf (opts, "max_age=%u", i);
@@ -1395,11 +1468,11 @@ write_bridge_port_setting (NMConnection *connection, shvarFile *ifcfg, GError **
 	opts = g_string_sized_new (32);
 
 	i = nm_setting_bridge_port_get_priority (s_port);
-	if (i && i != get_setting_default (NM_SETTING (s_port), NM_SETTING_BRIDGE_PORT_PRIORITY))
+	if (i != get_setting_default (NM_SETTING (s_port), NM_SETTING_BRIDGE_PORT_PRIORITY))
 		g_string_append_printf (opts, "priority=%u", i);
 
 	i = nm_setting_bridge_port_get_path_cost (s_port);
-	if (i && i != get_setting_default (NM_SETTING (s_port), NM_SETTING_BRIDGE_PORT_PATH_COST)) {
+	if (i != get_setting_default (NM_SETTING (s_port), NM_SETTING_BRIDGE_PORT_PATH_COST)) {
 		if (opts->len)
 			g_string_append_c (opts, ' ');
 		g_string_append_printf (opts, "path_cost=%u", i);
@@ -1418,15 +1491,220 @@ write_bridge_port_setting (NMConnection *connection, shvarFile *ifcfg, GError **
 	return TRUE;
 }
 
+static gboolean
+write_team_port_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
+{
+	NMSettingTeamPort *s_port;
+	const char *config;
+
+	s_port = nm_connection_get_setting_team_port (connection);
+	if (!s_port)
+		return TRUE;
+
+	config = nm_setting_team_port_get_config (s_port);
+	svSetValue (ifcfg, "TEAM_PORT_CONFIG", config, FALSE);
+
+	return TRUE;
+}
+
+static void
+write_dcb_flags (shvarFile *ifcfg, const char *tag, NMSettingDcbFlags flags)
+{
+	char *prop;
+
+	prop = g_strdup_printf ("DCB_%s_ENABLE", tag);
+	svSetValue (ifcfg, prop, (flags & NM_SETTING_DCB_FLAG_ENABLE) ? "yes" : NULL, FALSE);
+	g_free (prop);
+
+	prop = g_strdup_printf ("DCB_%s_ADVERTISE", tag);
+	svSetValue (ifcfg, prop, (flags & NM_SETTING_DCB_FLAG_ADVERTISE) ? "yes" : NULL, FALSE);
+	g_free (prop);
+
+	prop = g_strdup_printf ("DCB_%s_WILLING", tag);
+	svSetValue (ifcfg, prop, (flags & NM_SETTING_DCB_FLAG_WILLING) ? "yes" : NULL, FALSE);
+	g_free (prop);
+}
+
+static void
+write_dcb_app (shvarFile *ifcfg,
+               const char *tag,
+               NMSettingDcbFlags flags,
+               gint priority)
+{
+	char *prop, *tmp = NULL;
+
+	write_dcb_flags (ifcfg, tag, flags);
+
+	if ((flags & NM_SETTING_DCB_FLAG_ENABLE) && (priority >= 0))
+		tmp = g_strdup_printf ("%d", priority);
+	prop = g_strdup_printf ("DCB_%s_PRIORITY", tag);
+	svSetValue (ifcfg, prop, tmp, FALSE);
+	g_free (prop);
+	g_free (tmp);
+}
+
+typedef gboolean (*DcbGetBoolFunc) (NMSettingDcb *, guint);
+
+static void
+write_dcb_bool_array (shvarFile *ifcfg,
+                      const char *key,
+                      NMSettingDcb *s_dcb,
+                      NMSettingDcbFlags flags,
+                      DcbGetBoolFunc get_func)
+{
+	char str[9];
+	guint i;
+
+	if (!(flags & NM_SETTING_DCB_FLAG_ENABLE)) {
+		svSetValue (ifcfg, key, NULL, FALSE);
+		return;
+	}
+
+	str[8] = 0;
+	for (i = 0; i < 8; i++)
+		str[i] = get_func (s_dcb, i) ? '1' : '0';
+	svSetValue (ifcfg, key, str, FALSE);
+}
+
+typedef guint (*DcbGetUintFunc) (NMSettingDcb *, guint);
+
+static void
+write_dcb_uint_array (shvarFile *ifcfg,
+                      const char *key,
+                      NMSettingDcb *s_dcb,
+                      NMSettingDcbFlags flags,
+                      DcbGetUintFunc get_func)
+{
+	char str[9];
+	guint i, num;
+
+	if (!(flags & NM_SETTING_DCB_FLAG_ENABLE)) {
+		svSetValue (ifcfg, key, NULL, FALSE);
+		return;
+	}
+
+	str[8] = 0;
+	for (i = 0; i < 8; i++) {
+		num = get_func (s_dcb, i);
+		if (num < 10)
+			str[i] = '0' + num;
+		else if (num == 15)
+			str[i] = 'f';
+		else
+			g_assert_not_reached ();
+	}
+	svSetValue (ifcfg, key, str, FALSE);
+}
+
+static void
+write_dcb_percent_array (shvarFile *ifcfg,
+                         const char *key,
+                         NMSettingDcb *s_dcb,
+                         NMSettingDcbFlags flags,
+                         DcbGetUintFunc get_func)
+{
+	GString *str;
+	guint i;
+
+	if (!(flags & NM_SETTING_DCB_FLAG_ENABLE)) {
+		svSetValue (ifcfg, key, NULL, FALSE);
+		return;
+	}
+
+	str = g_string_sized_new (30);
+	for (i = 0; i < 8; i++) {
+		if (str->len)
+			g_string_append_c (str, ',');
+		g_string_append_printf (str, "%d", get_func (s_dcb, i));
+	}
+	svSetValue (ifcfg, key, str->str, FALSE);
+	g_string_free (str, TRUE);
+}
+
+static gboolean
+write_dcb_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
+{
+	NMSettingDcb *s_dcb;
+	NMSettingDcbFlags flags;
+
+	s_dcb = nm_connection_get_setting_dcb (connection);
+	if (!s_dcb) {
+		static const char *clear_keys[] = {
+		    "DCB",
+		    KEY_DCB_APP_FCOE_ENABLE,
+		    KEY_DCB_APP_FCOE_ADVERTISE,
+		    KEY_DCB_APP_FCOE_WILLING,
+		    KEY_DCB_APP_FCOE_MODE,
+		    KEY_DCB_APP_ISCSI_ENABLE,
+		    KEY_DCB_APP_ISCSI_ADVERTISE,
+		    KEY_DCB_APP_ISCSI_WILLING,
+		    KEY_DCB_APP_FIP_ENABLE,
+		    KEY_DCB_APP_FIP_ADVERTISE,
+		    KEY_DCB_APP_FIP_WILLING,
+		    KEY_DCB_PFC_ENABLE,
+		    KEY_DCB_PFC_ADVERTISE,
+		    KEY_DCB_PFC_WILLING,
+		    KEY_DCB_PFC_UP,
+		    KEY_DCB_PG_ENABLE,
+		    KEY_DCB_PG_ADVERTISE,
+		    KEY_DCB_PG_WILLING,
+		    KEY_DCB_PG_ID,
+		    KEY_DCB_PG_PCT,
+		    KEY_DCB_PG_UPPCT,
+		    KEY_DCB_PG_STRICT,
+		    KEY_DCB_PG_UP2TC,
+		    NULL };
+		const char **iter;
+
+		for (iter = clear_keys; *iter; iter++)
+			svSetValue (ifcfg, *iter, NULL, FALSE);
+		return TRUE;
+	}
+
+	svSetValue (ifcfg, "DCB", "yes", FALSE);
+
+	write_dcb_app (ifcfg, "APP_FCOE",
+	               nm_setting_dcb_get_app_fcoe_flags (s_dcb),
+	               nm_setting_dcb_get_app_fcoe_priority (s_dcb));
+	if (nm_setting_dcb_get_app_fcoe_flags (s_dcb) & NM_SETTING_DCB_FLAG_ENABLE)
+		svSetValue (ifcfg, KEY_DCB_APP_FCOE_MODE, nm_setting_dcb_get_app_fcoe_mode (s_dcb), FALSE);
+	else
+		svSetValue (ifcfg, KEY_DCB_APP_FCOE_MODE, NULL, FALSE);
+
+	write_dcb_app (ifcfg, "APP_ISCSI",
+	               nm_setting_dcb_get_app_iscsi_flags (s_dcb),
+	               nm_setting_dcb_get_app_iscsi_priority (s_dcb));
+	write_dcb_app (ifcfg, "APP_FIP",
+	               nm_setting_dcb_get_app_fip_flags (s_dcb),
+	               nm_setting_dcb_get_app_fip_priority (s_dcb));
+
+	write_dcb_flags (ifcfg, "PFC", nm_setting_dcb_get_priority_flow_control_flags (s_dcb));
+	write_dcb_bool_array (ifcfg, KEY_DCB_PFC_UP, s_dcb,
+	                      nm_setting_dcb_get_priority_flow_control_flags (s_dcb),
+	                      nm_setting_dcb_get_priority_flow_control);
+
+	flags = nm_setting_dcb_get_priority_group_flags (s_dcb);
+	write_dcb_flags (ifcfg, "PG", flags);
+	write_dcb_uint_array (ifcfg, KEY_DCB_PG_ID, s_dcb, flags, nm_setting_dcb_get_priority_group_id);
+	write_dcb_percent_array (ifcfg, KEY_DCB_PG_PCT, s_dcb, flags, nm_setting_dcb_get_priority_group_bandwidth);
+	write_dcb_percent_array (ifcfg, KEY_DCB_PG_UPPCT, s_dcb, flags, nm_setting_dcb_get_priority_bandwidth);
+	write_dcb_bool_array (ifcfg, KEY_DCB_PG_STRICT, s_dcb, flags, nm_setting_dcb_get_priority_strict_bandwidth);
+	write_dcb_uint_array (ifcfg, KEY_DCB_PG_UP2TC, s_dcb, flags, nm_setting_dcb_get_priority_traffic_class);
+
+	return TRUE;
+}
+
 static void
 write_connection_setting (NMSettingConnection *s_con, shvarFile *ifcfg)
 {
 	guint32 n, i;
 	GString *str;
 	const char *master;
+	char *tmp;
 
 	svSetValue (ifcfg, "NAME", nm_setting_connection_get_id (s_con), FALSE);
 	svSetValue (ifcfg, "UUID", nm_setting_connection_get_uuid (s_con), FALSE);
+	svSetValue (ifcfg, "DEVICE", nm_setting_connection_get_interface_name (s_con), FALSE);
 	svSetValue (ifcfg, "ONBOOT",
 	            nm_setting_connection_get_autoconnect (s_con) ? "yes" : "no",
 	            FALSE);
@@ -1457,10 +1735,16 @@ write_connection_setting (NMSettingConnection *s_con, shvarFile *ifcfg)
 
 	master = nm_setting_connection_get_master (s_con);
 	if (master) {
-		if (nm_setting_connection_is_slave_type (s_con, NM_SETTING_BOND_SETTING_NAME))
+		if (nm_setting_connection_is_slave_type (s_con, NM_SETTING_BOND_SETTING_NAME)) {
 			svSetValue (ifcfg, "MASTER", master, FALSE);
-		else if (nm_setting_connection_is_slave_type (s_con, NM_SETTING_BRIDGE_SETTING_NAME))
+			svSetValue (ifcfg, "SLAVE", "yes", FALSE);
+		} else if (nm_setting_connection_is_slave_type (s_con, NM_SETTING_BRIDGE_SETTING_NAME))
 			svSetValue (ifcfg, "BRIDGE", master, FALSE);
+		else if (nm_setting_connection_is_slave_type (s_con, NM_SETTING_TEAM_SETTING_NAME)) {
+			svSetValue (ifcfg, "TEAM_MASTER", master, FALSE);
+			svSetValue (ifcfg, "DEVICETYPE", TYPE_TEAM_PORT, FALSE);
+			svSetValue (ifcfg, "TYPE", NULL, FALSE);
+		}
 	}
 
 	/* secondary connection UUIDs */
@@ -1484,6 +1768,13 @@ write_connection_setting (NMSettingConnection *s_con, shvarFile *ifcfg)
 		svSetValue (ifcfg, "SECONDARY_UUIDS", str->str, FALSE);
 		g_string_free (str, TRUE);
 	}
+
+	svSetValue (ifcfg, "GATEWAY_PING_TIMEOUT", NULL, FALSE);
+	if (nm_setting_connection_get_gateway_ping_timeout (s_con)) {
+		tmp = g_strdup_printf ("%" G_GUINT32_FORMAT, nm_setting_connection_get_gateway_ping_timeout (s_con));
+		svSetValue (ifcfg, "GATEWAY_PING_TIMEOUT", tmp, FALSE);
+		g_free (tmp);
+	}
 }
 
 static gboolean
@@ -1553,7 +1844,7 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
 	char *addr_key, *prefix_key, *netmask_key, *gw_key, *metric_key, *tmp;
 	char *route_path = NULL;
 	gint32 j;
-	guint32 i, num;
+	guint32 i, n, num;
 	GString *searches;
 	gboolean success = FALSE;
 	gboolean fake_ip4 = FALSE;
@@ -1617,48 +1908,85 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
 	else if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED))
 		svSetValue (ifcfg, "BOOTPROTO", "shared", FALSE);
 
-	/* Write out IPADDR0 .. IPADDR255, PREFIX0 .. PREFIX255, GATEWAY0 .. GATEWAY255
-	 * Possible NETMASK<n> is removed only (it's obsolete) */
-	num = nm_setting_ip4_config_get_num_addresses (s_ip4);
+	/* Clear out un-numbered IP address fields */
 	svSetValue (ifcfg, "IPADDR", NULL, FALSE);
 	svSetValue (ifcfg, "PREFIX", NULL, FALSE);
 	svSetValue (ifcfg, "NETMASK", NULL, FALSE);
 	svSetValue (ifcfg, "GATEWAY", NULL, FALSE);
-	for (i = 0; i < 256; i++) {
+	/* Clear out zero-indexed IP address fields */
+	svSetValue (ifcfg, "IPADDR0", NULL, FALSE);
+	svSetValue (ifcfg, "PREFIX0", NULL, FALSE);
+	svSetValue (ifcfg, "NETMASK0", NULL, FALSE);
+	svSetValue (ifcfg, "GATEWAY0", NULL, FALSE);
+
+	/* Write out IPADDR<n>, PREFIX<n>, GATEWAY<n> for current IP addresses
+	 * without labels. Unset obsolete NETMASK<n>.
+	 */
+	num = nm_setting_ip4_config_get_num_addresses (s_ip4);
+	for (i = n = 0; i < num; i++) {
 		char buf[INET_ADDRSTRLEN];
 		NMIP4Address *addr;
 		guint32 ip;
 
-		addr_key = g_strdup_printf ("IPADDR%d", i);
-		prefix_key = g_strdup_printf ("PREFIX%d", i);
-		netmask_key = g_strdup_printf ("NETMASK%d", i);
-		gw_key = g_strdup_printf ("GATEWAY%d", i);
+		if (i > 0 && NM_UTILS_PRIVATE_CALL (nm_setting_ip4_config_get_address_label (s_ip4, i)))
+			continue;
 
-		if (i >= num) {
-			svSetValue (ifcfg, addr_key, NULL, FALSE);
-			svSetValue (ifcfg, prefix_key, NULL, FALSE);
-			svSetValue (ifcfg, netmask_key, NULL, FALSE);
-			svSetValue (ifcfg, gw_key, NULL, FALSE);
+		if (n == 0) {
+			/* Instead of index 0 use un-numbered variables.
+			 * It's needed for compatibility with ifup that only recognizes 'GATEAWAY'
+			 * See https://bugzilla.redhat.com/show_bug.cgi?id=771673
+			 * and https://bugzilla.redhat.com/show_bug.cgi?id=1105770
+			 */
+			addr_key = g_strdup ("IPADDR");
+			prefix_key = g_strdup ("PREFIX");
+			netmask_key = g_strdup ("NETMASK");
+			gw_key = g_strdup ("GATEWAY");
 		} else {
-			addr = nm_setting_ip4_config_get_address (s_ip4, i);
+			addr_key = g_strdup_printf ("IPADDR%d", n);
+			prefix_key = g_strdup_printf ("PREFIX%d", n);
+			netmask_key = g_strdup_printf ("NETMASK%d", n);
+			gw_key = g_strdup_printf ("GATEWAY%d", n);
+		}
 
+		addr = nm_setting_ip4_config_get_address (s_ip4, i);
+
+		memset (buf, 0, sizeof (buf));
+		ip = nm_ip4_address_get_address (addr);
+		inet_ntop (AF_INET, (const void *) &ip, &buf[0], sizeof (buf));
+		svSetValue (ifcfg, addr_key, &buf[0], FALSE);
+
+		tmp = g_strdup_printf ("%u", nm_ip4_address_get_prefix (addr));
+		svSetValue (ifcfg, prefix_key, tmp, FALSE);
+		g_free (tmp);
+
+		svSetValue (ifcfg, netmask_key, NULL, FALSE);
+
+		if (nm_ip4_address_get_gateway (addr)) {
 			memset (buf, 0, sizeof (buf));
-			ip = nm_ip4_address_get_address (addr);
+			ip = nm_ip4_address_get_gateway (addr);
 			inet_ntop (AF_INET, (const void *) &ip, &buf[0], sizeof (buf));
-			svSetValue (ifcfg, addr_key, &buf[0], FALSE);
+			svSetValue (ifcfg, gw_key, &buf[0], FALSE);
+		} else
+			svSetValue (ifcfg, gw_key, NULL, FALSE);
 
-			tmp = g_strdup_printf ("%u", nm_ip4_address_get_prefix (addr));
-			svSetValue (ifcfg, prefix_key, tmp, FALSE);
-			g_free (tmp);
+		g_free (addr_key);
+		g_free (prefix_key);
+		g_free (netmask_key);
+		g_free (gw_key);
+		n++;
+	}
 
-			if (nm_ip4_address_get_gateway (addr)) {
-				memset (buf, 0, sizeof (buf));
-				ip = nm_ip4_address_get_gateway (addr);
-				inet_ntop (AF_INET, (const void *) &ip, &buf[0], sizeof (buf));
-				svSetValue (ifcfg, gw_key, &buf[0], FALSE);
-			} else
-				svSetValue (ifcfg, gw_key, NULL, FALSE);
-		}
+	/* Clear remaining IPADDR<n..255>, etc */
+	for (; n < 256; n++) {
+		addr_key = g_strdup_printf ("IPADDR%d", n);
+		prefix_key = g_strdup_printf ("PREFIX%d", n);
+		netmask_key = g_strdup_printf ("NETMASK%d", n);
+		gw_key = g_strdup_printf ("GATEWAY%d", n);
+
+		svSetValue (ifcfg, addr_key, NULL, FALSE);
+		svSetValue (ifcfg, prefix_key, NULL, FALSE);
+		svSetValue (ifcfg, netmask_key, NULL, FALSE);
+		svSetValue (ifcfg, gw_key, NULL, FALSE);
 
 		g_free (addr_key);
 		g_free (prefix_key);
@@ -1719,6 +2047,13 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
 		if (value)
 			svSetValue (ifcfg, "DHCP_HOSTNAME", value, FALSE);
 
+		/* Missing DHCP_SEND_HOSTNAME means TRUE, and we prefer not write it explicitly
+		 * in that case, because it is NM-specific variable
+		 */
+		svSetValue (ifcfg, "DHCP_SEND_HOSTNAME",
+		            nm_setting_ip4_config_get_dhcp_send_hostname (s_ip4) ? NULL : "no",
+		            FALSE);
+
 		value = nm_setting_ip4_config_get_dhcp_client_id (s_ip4);
 		if (value)
 			svSetValue (ifcfg, "DHCP_CLIENT_ID", value, FALSE);
@@ -1798,9 +2133,7 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
 			g_free (gw_key);
 			g_free (metric_key);
 		}
-		if (svWriteFile (routefile, 0644)) {
-			g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
-			             "Could not update route file '%s'", routefile->fileName);
+		if (!svWriteFile (routefile, 0644, error)) {
 			svCloseFile (routefile);
 			goto out;
 		}
@@ -1821,6 +2154,101 @@ out:
 	return success;
 }
 
+static void
+write_ip4_aliases (NMConnection *connection, char *base_ifcfg_path)
+{
+	NMSettingIP4Config *s_ip4;
+	char *base_ifcfg_dir, *base_ifcfg_name, *base_name;
+	int i, num, base_ifcfg_name_len, base_name_len;
+	GDir *dir;
+
+	base_ifcfg_dir = g_path_get_dirname (base_ifcfg_path);
+	base_ifcfg_name = g_path_get_basename (base_ifcfg_path);
+	base_ifcfg_name_len = strlen (base_ifcfg_name);
+	base_name = base_ifcfg_name + strlen (IFCFG_TAG);
+	base_name_len = strlen (base_name);
+
+	/* Remove all existing aliases for this file first */
+	dir = g_dir_open (base_ifcfg_dir, 0, NULL);
+	if (dir) {
+		const char *item;
+
+		while ((item = g_dir_read_name (dir))) {
+			char *full_path;
+
+			if (   strncmp (item, base_ifcfg_name, base_ifcfg_name_len) != 0
+			    || item[base_ifcfg_name_len] != ':')
+				continue;
+
+			full_path = g_build_filename (base_ifcfg_dir, item, NULL);
+			unlink (full_path);
+			g_free (full_path);
+		}
+
+		g_dir_close (dir);
+	}
+
+	if (utils_ignore_ip_config (connection))
+		return;
+
+	s_ip4 = nm_connection_get_setting_ip4_config (connection);
+	if (!s_ip4)
+		return;
+
+	num = nm_setting_ip4_config_get_num_addresses (s_ip4);
+	for (i = 0; i < num; i++) {
+		const char *label, *p;
+		char buf[INET_ADDRSTRLEN], *path, *tmp;
+		NMIP4Address *addr;
+		guint32 ip;
+		shvarFile *ifcfg;
+
+		label = NM_UTILS_PRIVATE_CALL (nm_setting_ip4_config_get_address_label (s_ip4, i));
+		if (!label)
+			continue;
+		if (   strncmp (label, base_name, base_name_len) != 0
+		    || label[base_name_len] != ':')
+			continue;
+
+		for (p = label; *p; p++) {
+			if (!g_ascii_isalnum (*p) && *p != '_' && *p != ':')
+				break;
+		}
+		if (*p)
+			continue;
+
+		path = g_strdup_printf ("%s%s", base_ifcfg_path, label + base_name_len);
+		ifcfg = svCreateFile (path);
+		g_free (path);
+
+		svSetValue (ifcfg, "DEVICE", label, FALSE);
+
+		addr = nm_setting_ip4_config_get_address (s_ip4, i);
+
+		memset (buf, 0, sizeof (buf));
+		ip = nm_ip4_address_get_address (addr);
+		inet_ntop (AF_INET, (const void *) &ip, &buf[0], sizeof (buf));
+		svSetValue (ifcfg, "IPADDR", &buf[0], FALSE);
+
+		tmp = g_strdup_printf ("%u", nm_ip4_address_get_prefix (addr));
+		svSetValue (ifcfg, "PREFIX", tmp, FALSE);
+		g_free (tmp);
+
+		if (nm_ip4_address_get_gateway (addr)) {
+			memset (buf, 0, sizeof (buf));
+			ip = nm_ip4_address_get_gateway (addr);
+			inet_ntop (AF_INET, (const void *) &ip, &buf[0], sizeof (buf));
+			svSetValue (ifcfg, "GATEWAY", &buf[0], FALSE);
+		}
+
+		svWriteFile (ifcfg, 0644, NULL);
+		svCloseFile (ifcfg);
+	}
+
+	g_free (base_ifcfg_name);
+	g_free (base_ifcfg_dir);
+}
+
 static gboolean
 write_route6_file (const char *filename, NMSettingIP6Config *s_ip6, GError **error)
 {
@@ -1890,6 +2318,7 @@ write_ip6_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
 	guint32 i, num, num4;
 	GString *searches;
 	char buf[INET6_ADDRSTRLEN];
+	char ipv6_defaultgw[INET6_ADDRSTRLEN];
 	NMIP6Address *addr;
 	const struct in6_addr *ip;
 	GString *ip_str1, *ip_str2, *ip_ptr;
@@ -1940,51 +2369,41 @@ write_ip6_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
 		/* TODO */
 	}
 
-	if (!strcmp (value, NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) {
-		char ipv6_defaultgw[INET6_ADDRSTRLEN];
-
-		/* Write out IP addresses */
-		num = nm_setting_ip6_config_get_num_addresses (s_ip6);
+	/* Write out IP addresses */
+	num = nm_setting_ip6_config_get_num_addresses (s_ip6);
+	ip_str1 = g_string_new (NULL);
+	ip_str2 = g_string_new (NULL);
+	ipv6_defaultgw[0] = 0;
+	for (i = 0; i < num; i++) {
+		if (i == 0)
+			ip_ptr = ip_str1;
+		else
+			ip_ptr = ip_str2;
 
-		ip_str1 = g_string_new (NULL);
-		ip_str2 = g_string_new (NULL);
-		ipv6_defaultgw[0] = 0;
-		for (i = 0; i < num; i++) {
-			if (i == 0)
-				ip_ptr = ip_str1;
-			else
-				ip_ptr = ip_str2;
-
-			addr = nm_setting_ip6_config_get_address (s_ip6, i);
-			ip = nm_ip6_address_get_address (addr);
-			prefix = g_strdup_printf ("%u", nm_ip6_address_get_prefix (addr));
-			memset (buf, 0, sizeof (buf));
-			inet_ntop (AF_INET6, (const void *) ip, buf, sizeof (buf));
-			if (i > 1)
-				g_string_append_c (ip_ptr, ' ');  /* separate addresses in IPV6ADDR_SECONDARIES */
-			g_string_append (ip_ptr, buf);
-			g_string_append_c (ip_ptr, '/');
-			g_string_append (ip_ptr, prefix);
-			g_free (prefix);
-
-			/* We only support gateway for the first IP address for now */
-			if (i == 0) {
-				ip = nm_ip6_address_get_gateway (addr);
-				if (!IN6_IS_ADDR_UNSPECIFIED (ip))
-					inet_ntop (AF_INET6, ip, ipv6_defaultgw, sizeof (ipv6_defaultgw));
-			}
+		addr = nm_setting_ip6_config_get_address (s_ip6, i);
+		ip = nm_ip6_address_get_address (addr);
+		prefix = g_strdup_printf ("%u", nm_ip6_address_get_prefix (addr));
+		memset (buf, 0, sizeof (buf));
+		inet_ntop (AF_INET6, (const void *) ip, buf, sizeof (buf));
+		if (i > 1)
+			g_string_append_c (ip_ptr, ' ');  /* separate addresses in IPV6ADDR_SECONDARIES */
+		g_string_append (ip_ptr, buf);
+		g_string_append_c (ip_ptr, '/');
+		g_string_append (ip_ptr, prefix);
+		g_free (prefix);
+
+		/* We only support gateway for the first IP address for now */
+		if (i == 0) {
+			ip = nm_ip6_address_get_gateway (addr);
+			if (!IN6_IS_ADDR_UNSPECIFIED (ip))
+				inet_ntop (AF_INET6, ip, ipv6_defaultgw, sizeof (ipv6_defaultgw));
 		}
-
-		svSetValue (ifcfg, "IPV6ADDR", ip_str1->str, FALSE);
-		svSetValue (ifcfg, "IPV6ADDR_SECONDARIES", ip_str2->str, FALSE);
-		svSetValue (ifcfg, "IPV6_DEFAULTGW", ipv6_defaultgw, FALSE);
-		g_string_free (ip_str1, TRUE);
-		g_string_free (ip_str2, TRUE);
-	} else {
-		svSetValue (ifcfg, "IPV6ADDR", NULL, FALSE);
-		svSetValue (ifcfg, "IPV6ADDR_SECONDARIES", NULL, FALSE);
-		svSetValue (ifcfg, "IPV6_DEFAULTGW", NULL, FALSE);
 	}
+	svSetValue (ifcfg, "IPV6ADDR", ip_str1->str, FALSE);
+	svSetValue (ifcfg, "IPV6ADDR_SECONDARIES", ip_str2->str, FALSE);
+	svSetValue (ifcfg, "IPV6_DEFAULTGW", ipv6_defaultgw, FALSE);
+	g_string_free (ip_str1, TRUE);
+	g_string_free (ip_str2, TRUE);
 
 	/* Write out DNS - 'DNS' key is used both for IPv4 and IPv6 */
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
@@ -2115,16 +2534,18 @@ write_connection (NMConnection *connection,
 	gboolean no_8021x = FALSE;
 	gboolean wired = FALSE;
 
-	s_con = nm_connection_get_setting_connection (connection);
-	if (!s_con) {
-		g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
-		             "Missing '%s' setting", NM_SETTING_CONNECTION_SETTING_NAME);
+	if (!writer_can_write_connection (connection, error))
 		return FALSE;
-	}
+
+	s_con = nm_connection_get_setting_connection (connection);
+	g_assert (s_con);
 
 	if (filename) {
 		/* For existing connections, 'filename' should be full path to ifcfg file */
-		ifcfg = svNewFile (filename);
+		ifcfg = svOpenFile (filename, error);
+		if (!ifcfg)
+			return FALSE;
+
 		ifcfg_name = g_strdup (filename);
 	} else {
 		char *escaped;
@@ -2160,12 +2581,6 @@ write_connection (NMConnection *connection,
 		ifcfg = svCreateFile (ifcfg_name);
 	}
 
-	if (!ifcfg) {
-		g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
-		             "Failed to open/create ifcfg file '%s'", ifcfg_name);
-		goto out;
-	}
-
 	type = nm_setting_connection_get_connection_type (s_con);
 	if (!type) {
 		g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
@@ -2197,6 +2612,9 @@ write_connection (NMConnection *connection,
 	} else if (!strcmp (type, NM_SETTING_BOND_SETTING_NAME)) {
 		if (!write_bonding_setting (connection, ifcfg, error))
 			goto out;
+	} else if (!strcmp (type, NM_SETTING_TEAM_SETTING_NAME)) {
+		if (!write_team_setting (connection, ifcfg, error))
+			goto out;
 	} else if (!strcmp (type, NM_SETTING_BRIDGE_SETTING_NAME)) {
 		if (!write_bridge_setting (connection, ifcfg, error))
 			goto out;
@@ -2214,11 +2632,18 @@ write_connection (NMConnection *connection,
 	if (!write_bridge_port_setting (connection, ifcfg, error))
 		goto out;
 
+	if (!write_team_port_setting (connection, ifcfg, error))
+		goto out;
+
+	if (!write_dcb_setting (connection, ifcfg, error))
+		goto out;
+
 	if (!utils_ignore_ip_config (connection)) {
 		svSetValue (ifcfg, "DHCP_HOSTNAME", NULL, FALSE);
 
 		if (!write_ip4_setting (connection, ifcfg, error))
 			goto out;
+		write_ip4_aliases (connection, ifcfg_name);
 
 		if (!write_ip6_setting (connection, ifcfg, error))
 			goto out;
@@ -2226,11 +2651,8 @@ write_connection (NMConnection *connection,
 
 	write_connection_setting (s_con, ifcfg);
 
-	if (svWriteFile (ifcfg, 0644)) {
-		g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
-		             "Can't write connection '%s'", ifcfg->fileName);
+	if (!svWriteFile (ifcfg, 0644, error))
 		goto out;
-	}
 
 	/* Only return the filename if this was a newly written ifcfg */
 	if (out_filename && !filename)
@@ -2246,6 +2668,31 @@ out:
 }
 
 gboolean
+writer_can_write_connection (NMConnection *connection, GError **error)
+{
+	NMSettingConnection *s_con;
+
+	if (   (   nm_connection_is_type (connection, NM_SETTING_WIRED_SETTING_NAME)
+	        && !nm_connection_get_setting_pppoe (connection))
+	    || nm_connection_is_type (connection, NM_SETTING_VLAN_SETTING_NAME)
+	    || nm_connection_is_type (connection, NM_SETTING_WIRELESS_SETTING_NAME)
+	    || nm_connection_is_type (connection, NM_SETTING_INFINIBAND_SETTING_NAME)
+	    || nm_connection_is_type (connection, NM_SETTING_BOND_SETTING_NAME)
+	    || nm_connection_is_type (connection, NM_SETTING_TEAM_SETTING_NAME)
+	    || nm_connection_is_type (connection, NM_SETTING_BRIDGE_SETTING_NAME))
+		return TRUE;
+
+	s_con = nm_connection_get_setting_connection (connection);
+	g_assert (s_con);
+	g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
+	             "The ifcfg-rh plugin cannot write the connection '%s' (type '%s' pppoe %d)",
+	             nm_connection_get_id (connection),
+	             nm_setting_connection_get_connection_type (s_con),
+	             !!nm_connection_get_setting_pppoe (connection));
+	return FALSE;
+}
+
+gboolean
 writer_new_connection (NMConnection *connection,
                        const char *ifcfg_dir,
                        char **out_filename,
diff --git a/src/settings/plugins/ifcfg-rh/writer.h b/src/settings/plugins/ifcfg-rh/writer.h
index edeac0cc..894313dd 100644
--- a/src/settings/plugins/ifcfg-rh/writer.h
+++ b/src/settings/plugins/ifcfg-rh/writer.h
@@ -25,6 +25,9 @@
 #include <glib.h>
 #include <nm-connection.h>
 
+gboolean writer_can_write_connection (NMConnection *connection,
+                                      GError **error);
+
 gboolean writer_new_connection (NMConnection *connection,
                                 const char *ifcfg_dir,
                                 char **out_filename,