summary refs log tree commit diff
path: root/src/settings/plugins/keyfile
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2015-01-22 00:29:39 +0100
committerMichael Biebl <biebl@debian.org>2015-01-22 00:29:39 +0100
commit2c032d8f1c6292c1338a615e6ec40252889ba85c (patch)
tree1f77182220b2b0264288ba4a476ab47e5bc48716 /src/settings/plugins/keyfile
parent33491bc4279481db8ae47213e34a6d695a0e8830 (diff)
Imported Upstream version 1.0.0 upstream/1.0.0
Diffstat (limited to 'src/settings/plugins/keyfile')
-rw-r--r--src/settings/plugins/keyfile/Makefile.am17
-rw-r--r--src/settings/plugins/keyfile/Makefile.in35
-rw-r--r--src/settings/plugins/keyfile/common.h3
-rw-r--r--src/settings/plugins/keyfile/errors.c35
-rw-r--r--src/settings/plugins/keyfile/nm-keyfile-connection.c14
-rw-r--r--src/settings/plugins/keyfile/nm-keyfile-connection.h6
-rw-r--r--src/settings/plugins/keyfile/plugin.c18
-rw-r--r--src/settings/plugins/keyfile/plugin.h2
-rw-r--r--src/settings/plugins/keyfile/reader.c619
-rw-r--r--src/settings/plugins/keyfile/tests/Makefile.am12
-rw-r--r--src/settings/plugins/keyfile/tests/Makefile.in39
-rw-r--r--src/settings/plugins/keyfile/tests/keyfiles/ATT_Data_Connect_BT1
-rw-r--r--src/settings/plugins/keyfile/tests/keyfiles/ATT_Data_Connect_Plain1
-rw-r--r--src/settings/plugins/keyfile/tests/keyfiles/Makefile.am11
-rw-r--r--src/settings/plugins/keyfile/tests/keyfiles/Makefile.in17
-rw-r--r--src/settings/plugins/keyfile/tests/keyfiles/Test_Enum_Property8
-rw-r--r--src/settings/plugins/keyfile/tests/keyfiles/Test_Flags_Property11
-rw-r--r--src/settings/plugins/keyfile/tests/keyfiles/Test_Missing_ID_UUID9
-rw-r--r--src/settings/plugins/keyfile/tests/keyfiles/Test_minimal_12
-rw-r--r--src/settings/plugins/keyfile/tests/keyfiles/Test_minimal_21
-rw-r--r--src/settings/plugins/keyfile/tests/keyfiles/Test_minimal_slave_14
-rw-r--r--src/settings/plugins/keyfile/tests/keyfiles/Test_minimal_slave_27
-rw-r--r--src/settings/plugins/keyfile/tests/keyfiles/Test_minimal_slave_34
-rw-r--r--src/settings/plugins/keyfile/tests/keyfiles/Test_minimal_slave_44
-rw-r--r--src/settings/plugins/keyfile/tests/test-keyfile.c1276
-rw-r--r--src/settings/plugins/keyfile/utils.c3
-rw-r--r--src/settings/plugins/keyfile/utils.h1
-rw-r--r--src/settings/plugins/keyfile/writer.c515
28 files changed, 1317 insertions, 1358 deletions
diff --git a/src/settings/plugins/keyfile/Makefile.am b/src/settings/plugins/keyfile/Makefile.am
index cac97e7f..079c45c3 100644
--- a/src/settings/plugins/keyfile/Makefile.am
+++ b/src/settings/plugins/keyfile/Makefile.am
@@ -4,18 +4,15 @@ SUBDIRS = . tests
 
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src \
-	-I$(top_srcdir)/src/config \
-	-I$(top_srcdir)/src/logging \
 	-I$(top_srcdir)/src/settings \
 	-I$(top_srcdir)/include \
-	-I$(top_builddir)/include \
-	-I$(top_srcdir)/libnm-util \
-	-I$(top_builddir)/libnm-util \
+	-I$(top_srcdir)/libnm-core \
+	-I$(top_builddir)/libnm-core \
 	-DG_LOG_DOMAIN=\""NetworkManager-keyfile"\" \
+	-DNETWORKMANAGER_COMPILATION \
 	-DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \
 	$(GLIB_CFLAGS) \
 	$(DBUS_CFLAGS) \
-	$(POLKIT_CFLAGS) \
 	-DNMCONFDIR=\"$(nmconfdir)\"
 
 noinst_LTLIBRARIES = \
@@ -29,7 +26,6 @@ libkeyfile_io_la_SOURCES = \
 	reader.h \
 	writer.c \
 	writer.h \
-	errors.c \
 	utils.c \
 	utils.h \
 	common.h
@@ -45,12 +41,7 @@ libnm_settings_plugin_keyfile_la_SOURCES = \
 	plugin.h
 
 libnm_settings_plugin_keyfile_la_LIBADD = \
-	$(top_builddir)/libnm-util/libnm-util.la \
-	libkeyfile-io.la \
-	$(GLIB_LIBS) \
-	$(DBUS_LIBS)
-
-libnm_settings_plugin_keyfile_la_LDFLAGS = -rdynamic
+	libkeyfile-io.la
 
 keyfiledir=$(sysconfdir)/NetworkManager/system-connections
 
diff --git a/src/settings/plugins/keyfile/Makefile.in b/src/settings/plugins/keyfile/Makefile.in
index 8c4d6101..8c0d11af 100644
--- a/src/settings/plugins/keyfile/Makefile.in
+++ b/src/settings/plugins/keyfile/Makefile.in
@@ -104,23 +104,17 @@ CONFIG_CLEAN_VPATH_FILES =
 LTLIBRARIES = $(noinst_LTLIBRARIES)
 am__DEPENDENCIES_1 =
 libkeyfile_io_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
-am_libkeyfile_io_la_OBJECTS = reader.lo writer.lo errors.lo utils.lo
+am_libkeyfile_io_la_OBJECTS = reader.lo writer.lo utils.lo
 libkeyfile_io_la_OBJECTS = $(am_libkeyfile_io_la_OBJECTS)
 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 = 
-libnm_settings_plugin_keyfile_la_DEPENDENCIES =  \
-	$(top_builddir)/libnm-util/libnm-util.la libkeyfile-io.la \
-	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+libnm_settings_plugin_keyfile_la_DEPENDENCIES = libkeyfile-io.la
 am_libnm_settings_plugin_keyfile_la_OBJECTS =  \
 	nm-keyfile-connection.lo plugin.lo
 libnm_settings_plugin_keyfile_la_OBJECTS =  \
 	$(am_libnm_settings_plugin_keyfile_la_OBJECTS)
-libnm_settings_plugin_keyfile_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
-	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
-	$(AM_CFLAGS) $(CFLAGS) \
-	$(libnm_settings_plugin_keyfile_la_LDFLAGS) $(LDFLAGS) -o $@
 AM_V_P = $(am__v_P_@AM_V@)
 am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
 am__v_P_0 = false
@@ -235,6 +229,8 @@ AUTOCONF = @AUTOCONF@
 AUTOHEADER = @AUTOHEADER@
 AUTOMAKE = @AUTOMAKE@
 AWK = @AWK@
+BLUEZ5_CFLAGS = @BLUEZ5_CFLAGS@
+BLUEZ5_LIBS = @BLUEZ5_LIBS@
 CC = @CC@
 CCDEPMODE = @CCDEPMODE@
 CFLAGS = @CFLAGS@
@@ -358,6 +354,7 @@ NEWT_CFLAGS = @NEWT_CFLAGS@
 NEWT_LIBS = @NEWT_LIBS@
 NM = @NM@
 NMEDIT = @NMEDIT@
+NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@
 NM_MAJOR_VERSION = @NM_MAJOR_VERSION@
 NM_MICRO_VERSION = @NM_MICRO_VERSION@
 NM_MINOR_VERSION = @NM_MINOR_VERSION@
@@ -377,6 +374,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
 PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
 PKG_CONFIG = @PKG_CONFIG@
 PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
 PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
@@ -403,7 +401,7 @@ SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@
 SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@
 SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@
 SYSTEM_CA_PATH = @SYSTEM_CA_PATH@
-UDEV_BASE_DIR = @UDEV_BASE_DIR@
+UDEV_DIR = @UDEV_DIR@
 USE_NLS = @USE_NLS@
 UUID_CFLAGS = @UUID_CFLAGS@
 UUID_LIBS = @UUID_LIBS@
@@ -485,18 +483,15 @@ with_valgrind = @with_valgrind@
 SUBDIRS = . tests
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src \
-	-I$(top_srcdir)/src/config \
-	-I$(top_srcdir)/src/logging \
 	-I$(top_srcdir)/src/settings \
 	-I$(top_srcdir)/include \
-	-I$(top_builddir)/include \
-	-I$(top_srcdir)/libnm-util \
-	-I$(top_builddir)/libnm-util \
+	-I$(top_srcdir)/libnm-core \
+	-I$(top_builddir)/libnm-core \
 	-DG_LOG_DOMAIN=\""NetworkManager-keyfile"\" \
+	-DNETWORKMANAGER_COMPILATION \
 	-DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \
 	$(GLIB_CFLAGS) \
 	$(DBUS_CFLAGS) \
-	$(POLKIT_CFLAGS) \
 	-DNMCONFDIR=\"$(nmconfdir)\"
 
 noinst_LTLIBRARIES = \
@@ -510,7 +505,6 @@ libkeyfile_io_la_SOURCES = \
 	reader.h \
 	writer.c \
 	writer.h \
-	errors.c \
 	utils.c \
 	utils.h \
 	common.h
@@ -525,12 +519,8 @@ libnm_settings_plugin_keyfile_la_SOURCES = \
 	plugin.h
 
 libnm_settings_plugin_keyfile_la_LIBADD = \
-	$(top_builddir)/libnm-util/libnm-util.la \
-	libkeyfile-io.la \
-	$(GLIB_LIBS) \
-	$(DBUS_LIBS)
+	libkeyfile-io.la
 
-libnm_settings_plugin_keyfile_la_LDFLAGS = -rdynamic
 keyfiledir = $(sysconfdir)/NetworkManager/system-connections
 all: all-recursive
 
@@ -582,7 +572,7 @@ libkeyfile-io.la: $(libkeyfile_io_la_OBJECTS) $(libkeyfile_io_la_DEPENDENCIES) $
 	$(AM_V_CCLD)$(LINK)  $(libkeyfile_io_la_OBJECTS) $(libkeyfile_io_la_LIBADD) $(LIBS)
 
 libnm-settings-plugin-keyfile.la: $(libnm_settings_plugin_keyfile_la_OBJECTS) $(libnm_settings_plugin_keyfile_la_DEPENDENCIES) $(EXTRA_libnm_settings_plugin_keyfile_la_DEPENDENCIES) 
-	$(AM_V_CCLD)$(libnm_settings_plugin_keyfile_la_LINK)  $(libnm_settings_plugin_keyfile_la_OBJECTS) $(libnm_settings_plugin_keyfile_la_LIBADD) $(LIBS)
+	$(AM_V_CCLD)$(LINK)  $(libnm_settings_plugin_keyfile_la_OBJECTS) $(libnm_settings_plugin_keyfile_la_LIBADD) $(LIBS)
 
 mostlyclean-compile:
 	-rm -f *.$(OBJEXT)
@@ -590,7 +580,6 @@ mostlyclean-compile:
 distclean-compile:
 	-rm -f *.tab.c
 
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/errors.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-keyfile-connection.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/reader.Plo@am__quote@
diff --git a/src/settings/plugins/keyfile/common.h b/src/settings/plugins/keyfile/common.h
index 4faa5a84..db6569e5 100644
--- a/src/settings/plugins/keyfile/common.h
+++ b/src/settings/plugins/keyfile/common.h
@@ -30,8 +30,5 @@
 
 #define VPN_SECRETS_GROUP "vpn-secrets"
 
-#define KEYFILE_PLUGIN_ERROR (keyfile_plugin_error_quark ())
-GQuark keyfile_plugin_error_quark (void);
-
 #endif  /* __COMMON_H__ */
 
diff --git a/src/settings/plugins/keyfile/errors.c b/src/settings/plugins/keyfile/errors.c
deleted file mode 100644
index e2e97690..00000000
--- a/src/settings/plugins/keyfile/errors.c
+++ /dev/null
@@ -1,35 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-/* NetworkManager system settings service
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * 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 - 2010 Red Hat, Inc.
- */
-
-#include <glib.h>
-#include "common.h"
-
-GQuark
-keyfile_plugin_error_quark (void)
-{
-	static GQuark error_quark = 0;
-
-	if (G_UNLIKELY (error_quark == 0))
-		error_quark = g_quark_from_static_string ("keyfile-plugin-error-quark");
-
-	return error_quark;
-}
-
-
diff --git a/src/settings/plugins/keyfile/nm-keyfile-connection.c b/src/settings/plugins/keyfile/nm-keyfile-connection.c
index 4ef761c6..c852f028 100644
--- a/src/settings/plugins/keyfile/nm-keyfile-connection.c
+++ b/src/settings/plugins/keyfile/nm-keyfile-connection.c
@@ -19,9 +19,11 @@
  * Copyright (C) 2008 - 2012 Red Hat, Inc.
  */
 
+#include "config.h"
+
 #include <string.h>
 #include <glib/gstdio.h>
-#include <NetworkManager.h>
+#include <nm-dbus-interface.h>
 #include <nm-setting-connection.h>
 #include <nm-utils.h>
 
@@ -63,7 +65,7 @@ nm_keyfile_connection_new (NMConnection *source,
 
 		uuid = nm_connection_get_uuid (NM_CONNECTION (tmp));
 		if (!uuid) {
-			g_set_error (error, KEYFILE_PLUGIN_ERROR, 0,
+			g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
 			             "Connection in file %s had no UUID", full_path);
 			g_object_unref (tmp);
 			return NULL;
@@ -166,11 +168,7 @@ nm_keyfile_connection_init (NMKeyfileConnection *connection)
 static void
 finalize (GObject *object)
 {
-	NMKeyfileConnectionPrivate *priv = NM_KEYFILE_CONNECTION_GET_PRIVATE (object);
-
-	nm_connection_clear_secrets (NM_CONNECTION (object));
-
-	g_free (priv->path);
+	g_free (NM_KEYFILE_CONNECTION_GET_PRIVATE (object)->path);
 
 	G_OBJECT_CLASS (nm_keyfile_connection_parent_class)->finalize (object);
 }
@@ -184,7 +182,7 @@ nm_keyfile_connection_class_init (NMKeyfileConnectionClass *keyfile_connection_c
 	g_type_class_add_private (keyfile_connection_class, sizeof (NMKeyfileConnectionPrivate));
 
 	/* Virtual methods */
-	object_class->finalize     = finalize;
+	object_class->finalize = finalize;
 	settings_class->commit_changes = commit_changes;
 	settings_class->delete = do_delete;
 }
diff --git a/src/settings/plugins/keyfile/nm-keyfile-connection.h b/src/settings/plugins/keyfile/nm-keyfile-connection.h
index 07dcafcb..135bb49f 100644
--- a/src/settings/plugins/keyfile/nm-keyfile-connection.h
+++ b/src/settings/plugins/keyfile/nm-keyfile-connection.h
@@ -19,8 +19,8 @@
  * Copyright (C) 2008 - 2012 Red Hat, Inc.
  */
 
-#ifndef NM_KEYFILE_CONNECTION_H
-#define NM_KEYFILE_CONNECTION_H
+#ifndef __NETWORKMANAGER_KEYFILE_CONNECTION_H__
+#define __NETWORKMANAGER_KEYFILE_CONNECTION_H__
 
 #include <nm-settings-connection.h>
 
@@ -52,4 +52,4 @@ void        nm_keyfile_connection_set_path (NMKeyfileConnection *self, const cha
 
 G_END_DECLS
 
-#endif /* NM_KEYFILE_CONNECTION_H */
+#endif /* __NETWORKMANAGER_KEYFILE_CONNECTION_H__ */
diff --git a/src/settings/plugins/keyfile/plugin.c b/src/settings/plugins/keyfile/plugin.c
index 10c83971..371fa47a 100644
--- a/src/settings/plugins/keyfile/plugin.c
+++ b/src/settings/plugins/keyfile/plugin.c
@@ -19,11 +19,11 @@
  * Copyright (C) 2008 - 2013 Red Hat, Inc.
  */
 
-#include <config.h>
+#include "config.h"
+
 #include <sys/stat.h>
 #include <unistd.h>
 #include <sys/types.h>
-#include <netinet/ether.h>
 #include <string.h>
 
 #include <gmodule.h>
@@ -37,6 +37,7 @@
 #include <nm-utils.h>
 #include <nm-config.h>
 #include <nm-logging.h>
+#include "nm-core-internal.h"
 
 #include "plugin.h"
 #include "nm-system-config-interface.h"
@@ -373,20 +374,13 @@ static GSList *
 get_connections (NMSystemConfigInterface *config)
 {
 	SCPluginKeyfilePrivate *priv = SC_PLUGIN_KEYFILE_GET_PRIVATE (config);
-	GHashTableIter iter;
-	gpointer data = NULL;
-	GSList *list = NULL;
 
 	if (!priv->initialized) {
 		setup_monitoring (config);
 		read_connections (config);
 		priv->initialized = TRUE;
 	}
-
-	g_hash_table_iter_init (&iter, priv->connections);
-	while (g_hash_table_iter_next (&iter, NULL, &data))
-		list = g_slist_prepend (list, data);
-	return list;
+	return _nm_utils_hash_values_to_slist (priv->connections);
 }
 
 static gboolean
@@ -496,12 +490,12 @@ get_unmanaged_specs (NMSystemConfigInterface *config)
 		char **udis;
 		int i;
 
-		udis = g_strsplit (str, ";", -1);
+		udis = g_strsplit_set (str, ";,", -1);
 		g_free (str);
 
 		for (i = 0; udis[i] != NULL; i++) {
 			/* Verify unmanaged specification and add it to the list */
-			if (!strncmp (udis[i], "mac:", 4) && nm_utils_hwaddr_valid (udis[i] + 4)) {
+			if (!strncmp (udis[i], "mac:", 4) && nm_utils_hwaddr_valid (udis[i] + 4, -1)) {
 				specs = g_slist_append (specs, udis[i]);
 			} else if (!strncmp (udis[i], "interface-name:", 15) && nm_utils_iface_valid_name (udis[i] + 15)) {
 				specs = g_slist_append (specs, udis[i]);
diff --git a/src/settings/plugins/keyfile/plugin.h b/src/settings/plugins/keyfile/plugin.h
index 5f437390..48579785 100644
--- a/src/settings/plugins/keyfile/plugin.h
+++ b/src/settings/plugins/keyfile/plugin.h
@@ -41,8 +41,6 @@ typedef struct {
 
 GType sc_plugin_keyfile_get_type (void);
 
-GQuark keyfile_plugin_error_quark (void);
-
 GObject *nm_settings_keyfile_plugin_new (void);
 
 #endif	/* _PLUGIN_H_ */
diff --git a/src/settings/plugins/keyfile/reader.c b/src/settings/plugins/keyfile/reader.c
index 735f8c28..1d2ecdad 100644
--- a/src/settings/plugins/keyfile/reader.c
+++ b/src/settings/plugins/keyfile/reader.c
@@ -19,27 +19,17 @@
  * Copyright (C) 2008 - 2011 Red Hat, Inc.
  */
 
+#include "config.h"
+
 #include <errno.h>
 #include <stdlib.h>
 #include <sys/stat.h>
 #include <unistd.h>
 #include <sys/types.h>
-#include <dbus/dbus-glib.h>
-#include <nm-setting.h>
-#include <nm-setting-ip4-config.h>
-#include <nm-setting-ip6-config.h>
-#include <nm-setting-vpn.h>
-#include <nm-setting-connection.h>
-#include <nm-setting-wired.h>
-#include <nm-setting-wireless.h>
-#include <nm-setting-bluetooth.h>
-#include <nm-setting-8021x.h>
-#include <nm-utils.h>
 #include <arpa/inet.h>
-#include <netinet/ether.h>
-#include <linux/if_infiniband.h>
 #include <string.h>
 
+#include "nm-core-internal.h"
 #include "nm-dbus-glib-types.h"
 #include "nm-glib-compat.h"
 #include "nm-system-config-interface.h"
@@ -47,6 +37,8 @@
 #include "reader.h"
 #include "common.h"
 #include "utils.h"
+#include "nm-core-internal.h"
+#include "NetworkManagerUtils.h"
 
 /* Some setting properties also contain setting names, such as
  * NMSettingConnection's 'type' property (which specifies the base type of the
@@ -119,135 +111,77 @@ get_one_int (const char *str, guint32 max_val, const char *key_name, guint32 *ou
 }
 
 static gpointer
-build_ip4_address_or_route (const char *key_name, const char *address_str, guint32 plen, const char *gateway_str, const char *metric_str, gboolean route)
+build_address (int family, const char *address_str, guint32 plen)
 {
-	GArray *result;
-	guint32 addr;
-	guint32 address = 0;
-	guint32 gateway = 0;
-	guint32 metric = 0;
-	int err;
+	NMIPAddress *addr;
+	GError *error = NULL;
 
 	g_return_val_if_fail (address_str, NULL);
 
-	/* Address */
-	err = inet_pton (AF_INET, address_str, &addr);
-	if (err <= 0) {
-		nm_log_warn (LOGD_SETTINGS, "%s: ignoring invalid IPv4 address '%s'", __func__, address_str);
-		return NULL;
-	}
-	address = addr;
-
-	/* Gateway */
-	if (gateway_str && gateway_str[0]) {
-		err = inet_pton (AF_INET, gateway_str, &addr);
-		if (err <= 0) {
-			nm_log_warn (LOGD_SETTINGS, "%s: ignoring invalid IPv4 gateway '%s'", __func__, gateway_str);
-			return NULL;
-		}
-		gateway = addr;
-	}
-	else
-		gateway = 0;
-
-	/* parse metric, default to 0 */
-	if (metric_str) {
-		if (!get_one_int (metric_str, G_MAXUINT32, key_name, &metric))
-			return NULL;
+	addr = nm_ip_address_new (family, address_str, plen, &error);
+	if (!addr) {
+		nm_log_warn (LOGD_SETTINGS, "%s: ignoring invalid %s address: %s", __func__,
+		             family == AF_INET ? "IPv4" : "IPv6",
+		             error->message);
+		g_error_free (error);
 	}
 
-	result = g_array_sized_new (FALSE, TRUE, sizeof (guint32), 3 + !!route);
-	g_array_append_val (result, address);
-	g_array_append_val (result, plen);
-	g_array_append_val (result, gateway);
-	if (route)
-		g_array_append_val (result, metric);
-
-	return result;
+	return addr;
 }
 
 static gpointer
-build_ip6_address_or_route (const char *key_name, const char *address_str, guint32 plen, const char *gateway_str, const char *metric_str, gboolean route)
+build_route (int family,
+             const char *dest_str, guint32 plen,
+             const char *gateway_str, const char *metric_str,
+             const char *key_name)
 {
-	GValueArray *result;
-	struct in6_addr addr;
-	GByteArray *address;
-	GByteArray *gateway;
+	NMIPRoute *route;
 	guint32 metric = 0;
-	GValue value = G_VALUE_INIT;
-	int err;
-
-	g_return_val_if_fail (address_str, NULL);
+	GError *error = NULL;
 
-	result = g_value_array_new (3);
+	g_return_val_if_fail (plen, NULL);
+	g_return_val_if_fail (dest_str, NULL);
 
-	/* add address */
-	err = inet_pton (AF_INET6, address_str, &addr);
-	if (err <= 0) {
-		nm_log_warn (LOGD_SETTINGS, "%s: ignoring invalid IPv6 address '%s'", __func__, address_str);
-		goto error_out;
-	}
-	address = g_byte_array_new ();
-	g_byte_array_append (address, (guint8 *) addr.s6_addr, 16);
-	g_value_init (&value, DBUS_TYPE_G_UCHAR_ARRAY);
-	g_value_take_boxed (&value, address);
-	g_value_array_append (result, &value);
-	g_value_unset (&value);
-
-	/* add prefix length */
-	g_value_init (&value, G_TYPE_UINT);
-	g_value_set_uint (&value, plen);
-	g_value_array_append (result, &value);
-	g_value_unset (&value);
-
-	/* add gateway */
+	/* Next hop */
 	if (gateway_str && gateway_str[0]) {
-		err = inet_pton (AF_INET6, gateway_str, &addr);
-		if (err <= 0) {
+		if (!nm_utils_ipaddr_valid (family, gateway_str)) {
 			/* Try workaround for routes written by broken keyfile writer.
 			 * Due to bug bgo#719851, an older version of writer would have
 			 * written "a:b:c:d::/plen,metric" if the gateway was ::, instead
 			 * of "a:b:c:d::/plen,,metric" or "a:b:c:d::/plen,::,metric"
-			 * Try workaround by interepeting gateway_str as metric to accept such
+			 * Try workaround by interpreting gateway_str as metric to accept such
 			 * invalid routes. This broken syntax should not be not officially
 			 * supported.
 			 **/
-			if (route && !metric_str && get_one_int (gateway_str, G_MAXUINT32, NULL, &metric))
-				addr = in6addr_any;
+			if (   family == AF_INET6
+			    && !metric_str
+			    && get_one_int (gateway_str, G_MAXUINT32, NULL, &metric))
+				gateway_str = NULL;
 			else {
-				nm_log_warn (LOGD_SETTINGS, "%s: ignoring invalid IPv6 gateway '%s'", __func__, gateway_str);
-				goto error_out;
+				nm_log_warn (LOGD_SETTINGS, "%s: ignoring invalid gateway '%s'", __func__, gateway_str);
+				return NULL;
 			}
 		}
 	} else
-		addr = in6addr_any;
+		gateway_str = NULL;
 
 	/* parse metric, default to 0 */
 	if (metric_str) {
 		if (!get_one_int (metric_str, G_MAXUINT32, key_name, &metric))
-			goto error_out;
+			return NULL;
 	}
 
-	gateway = g_byte_array_new ();
-	g_byte_array_append (gateway, (guint8 *) addr.s6_addr, 16);
-	g_value_init (&value, DBUS_TYPE_G_UCHAR_ARRAY);
-	g_value_take_boxed (&value, gateway);
-	g_value_array_append (result, &value);
-	g_value_unset (&value);
-
-	/* add metric (for routing) */
-	if (route) {
-		g_value_init (&value, G_TYPE_UINT);
-		g_value_set_uint (&value, metric);
-		g_value_array_append (result, &value);
-		g_value_unset (&value);
+	route = nm_ip_route_new (family, dest_str, plen, gateway_str,
+	                         metric ? (gint64) metric : -1,
+	                         &error);
+	if (!route) {
+		nm_log_warn (LOGD_SETTINGS, "%s: ignoring invalid %s route: %s", __func__,
+		             family == AF_INET ? "IPv4" : "IPv6",
+		             error->message);
+		g_error_free (error);
 	}
 
-	return result;
-
-error_out:
-	g_value_array_free (result);
-	return NULL;
+	return route;
 }
 
 /* On success, returns pointer to the zero-terminated field (original @current).
@@ -334,17 +268,16 @@ read_field (char **current, char **error, const char *characters, const char *de
  * changed. The default for IPv4 is now 24, which is the closest
  * IPv4 equivalent. These defaults may just as well be changed to
  * match the iproute2 defaults (32 for IPv4 and 128 for IPv6).
- *
- * The returned result is GArray for IPv4 and GValueArray for IPv6.
  */
 static gpointer
 read_one_ip_address_or_route (GKeyFile *file,
-	const char *setting_name,
-	const char *key_name,
-	gboolean ipv6,
-	gboolean route)
+                              const char *setting_name,
+                              const char *key_name,
+                              gboolean ipv6,
+                              gboolean route,
+                              char **out_gateway)
 {
-	guint32 plen;
+	guint32 plen = G_MAXUINT32;
 	gpointer result;
 	char *address_str, *plen_str, *gateway_str, *metric_str, *value, *current, *error;
 
@@ -394,22 +327,33 @@ read_one_ip_address_or_route (GKeyFile *file,
 		}
 	}
 
+#define DEFAULT_PREFIX(for_route, for_ipv6) ( (for_route) ? ( (for_ipv6) ? 128 : 24 ) : ( (for_ipv6) ? 64 : 24 ) )
+
 	/* parse plen, fallback to defaults */
-	if (plen_str)
-		g_return_val_if_fail (get_one_int (plen_str, ipv6 ? 128 : 32,
-			key_name, &plen), NULL);
-	else {
-		if (route)
-			plen = ipv6 ? 128 : 24;
-		else
-			plen = ipv6 ? 64 : 24;
+	if (plen_str) {
+		if (!get_one_int (plen_str, ipv6 ? 128 : 32, key_name, &plen)
+		    || (route && plen == 0)) {
+			plen = DEFAULT_PREFIX (route, ipv6);
+			nm_log_warn (LOGD_SETTINGS, "keyfile: invalid prefix length '%s' in '%s.%s', defaulting to %d",
+			             plen_str, setting_name, key_name, plen);
+		}
+	} else {
+		plen = DEFAULT_PREFIX (route, ipv6);
 		nm_log_warn (LOGD_SETTINGS, "keyfile: Missing prefix length in '%s.%s', defaulting to %d",
 		             setting_name, key_name, plen);
 	}
 
 	/* build the appropriate data structure for NetworkManager settings */
-	result = (ipv6 ? build_ip6_address_or_route : build_ip4_address_or_route) (
-	    key_name, address_str, plen, gateway_str, metric_str, route);
+	if (route) {
+		result = build_route (ipv6 ? AF_INET6 : AF_INET,
+		                      address_str, plen, gateway_str, metric_str,
+		                      key_name);
+	} else {
+		result = build_address (ipv6 ? AF_INET6 : AF_INET,
+		                        address_str, plen);
+		if (out_gateway && gateway_str)
+			*out_gateway = g_strdup (gateway_str);
+	}
 
 	g_free (value);
 	return result;
@@ -427,13 +371,16 @@ ip_address_or_route_parser (NMSetting *setting, const char *key, GKeyFile *keyfi
 	static const char *key_names_routes[] = { "route", "routes", NULL };
 	static const char *key_names_addresses[] = { "address", "addresses", NULL };
 	const char **key_names = routes ? key_names_routes : key_names_addresses;
+	char *gateway = NULL;
 	GPtrArray *list;
+	GDestroyNotify free_func;
 	int i;
 
-	G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
-	list = g_ptr_array_new_with_free_func (
-		ipv6 ? (GDestroyNotify) g_value_array_free : (GDestroyNotify) g_array_unref);
-	G_GNUC_END_IGNORE_DEPRECATIONS;
+	if (routes)
+		free_func = (GDestroyNotify) nm_ip_route_unref;
+	else
+		free_func = (GDestroyNotify) nm_ip_address_unref;
+	list = g_ptr_array_new_with_free_func (free_func);
 
 	for (i = -1; i < 1000; i++) {
 		const char **key_basename;
@@ -448,8 +395,8 @@ ip_address_or_route_parser (NMSetting *setting, const char *key, GKeyFile *keyfi
 			else
 				key_name = g_strdup (*key_basename);
 
-			item = read_one_ip_address_or_route (keyfile, setting_name, key_name, ipv6, routes);
-
+			item = read_one_ip_address_or_route (keyfile, setting_name, key_name, ipv6, routes,
+			                                     gateway ? NULL : &gateway);
 			if (item)
 				g_ptr_array_add (list, item);
 
@@ -460,6 +407,11 @@ ip_address_or_route_parser (NMSetting *setting, const char *key, GKeyFile *keyfi
 	if (list->len >= 1)
 		g_object_set (setting, key, list, NULL);
 
+	if (gateway) {
+		g_object_set (setting, "gateway", gateway, NULL);
+		g_free (gateway);
+	}
+
 	g_ptr_array_unref (list);
 }
 
@@ -467,7 +419,7 @@ static void
 ip4_dns_parser (NMSetting *setting, const char *key, GKeyFile *keyfile, const char *keyfile_path)
 {
 	const char *setting_name = nm_setting_get_name (setting);
-	GArray *array = NULL;
+	GPtrArray *array;
 	gsize length;
 	char **list, **iter;
 	int ret;
@@ -476,7 +428,7 @@ ip4_dns_parser (NMSetting *setting, const char *key, GKeyFile *keyfile, const ch
 	if (!list || !g_strv_length (list))
 		return;
 
-	array = g_array_sized_new (FALSE, FALSE, sizeof (guint32), length);
+	array = g_ptr_array_sized_new (length + 1);
 	for (iter = list; *iter; iter++) {
 		guint32 addr;
 
@@ -486,14 +438,13 @@ ip4_dns_parser (NMSetting *setting, const char *key, GKeyFile *keyfile, const ch
 			continue;
 		}
 
-		g_array_append_val (array, addr);
+		g_ptr_array_add (array, *iter);
 	}
-	g_strfreev (list);
+	g_ptr_array_add (array, NULL);
 
-	if (array) {
-		g_object_set (setting, key, array, NULL);
-		g_array_unref (array);
-	}
+	g_object_set (setting, key, array->pdata, NULL);
+	g_ptr_array_unref (array);
+	g_strfreev (list);
 }
 
 static void
@@ -509,10 +460,9 @@ ip6_dns_parser (NMSetting *setting, const char *key, GKeyFile *keyfile, const ch
 	if (!list || !g_strv_length (list))
 		return;
 
-	array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_byte_array_unref);
+	array = g_ptr_array_sized_new (length + 1);
 
 	for (iter = list; *iter; iter++) {
-		GByteArray *byte_array;
 		struct in6_addr addr;
 
 		ret = inet_pton (AF_INET6, *iter, &addr);
@@ -520,24 +470,21 @@ ip6_dns_parser (NMSetting *setting, const char *key, GKeyFile *keyfile, const ch
 			nm_log_warn (LOGD_SETTINGS, "%s: ignoring invalid DNS server IPv6 address '%s'", __func__, *iter);
 			continue;
 		}
-		byte_array = g_byte_array_new ();
-		g_byte_array_append (byte_array, (guint8 *) addr.s6_addr, 16);
 
-		g_ptr_array_add (array, byte_array);
+		g_ptr_array_add (array, *iter);
 	}
-	g_strfreev (list);
+	g_ptr_array_add (array, NULL);
 
-	if (array) {
-		g_object_set (setting, key, array, NULL);
-		g_ptr_array_unref (array);
-	}
+	g_object_set (setting, key, array->pdata, NULL);
+	g_ptr_array_unref (array);
+	g_strfreev (list);
 }
 
 static void
 mac_address_parser (NMSetting *setting, const char *key, GKeyFile *keyfile, const char *keyfile_path, gsize enforce_length)
 {
 	const char *setting_name = nm_setting_get_name (setting);
-	char *tmp_string = NULL, *p;
+	char *tmp_string = NULL, *p, *mac_str;
 	gint *tmp_list;
 	GByteArray *array = NULL;
 	gsize length;
@@ -557,7 +504,7 @@ mac_address_parser (NMSetting *setting, const char *key, GKeyFile *keyfile, cons
 			/* If we found enough it's probably a string-format MAC address */
 			array = g_byte_array_sized_new (i+1);
 			g_byte_array_set_size (array, i+1);
-			if (!nm_utils_hwaddr_aton_len (tmp_string, array->data, array->len)) {
+			if (!nm_utils_hwaddr_aton (tmp_string, array->data, array->len)) {
 				g_byte_array_unref (array);
 				array = NULL;
 			}
@@ -590,13 +537,16 @@ mac_address_parser (NMSetting *setting, const char *key, GKeyFile *keyfile, cons
 		g_free (tmp_list);
 	}
 
-	if (array) {
-		g_object_set (setting, key, array, NULL);
-		g_byte_array_free (array, TRUE);
-	} else {
+	if (!array) {
 		nm_log_warn (LOGD_SETTINGS, "%s: ignoring invalid MAC address for %s / %s",
 		             __func__, setting_name, key);
+		return;
 	}
+
+	mac_str = nm_utils_hwaddr_ntoa (array->data, array->len);
+	g_object_set (setting, key, mac_str, NULL);
+	g_free (mac_str);
+	g_byte_array_free (array, TRUE);
 }
 
 static void
@@ -628,11 +578,12 @@ read_hash_of_string (GKeyFile *file, NMSetting *setting, const char *key)
 			continue;
 
 		if (NM_IS_SETTING_VPN (setting)) {
-			if (strcmp (*iter, NM_SETTING_VPN_SERVICE_TYPE) && strcmp (*iter, NM_SETTING_VPN_USER_NAME))
+			/* Add any item that's not a class property to the data hash */
+			if (!g_object_class_find_property (G_OBJECT_GET_CLASS (setting), *iter))
 				nm_setting_vpn_add_data_item (NM_SETTING_VPN (setting), *iter, value);
 		}
 		if (NM_IS_SETTING_BOND (setting)) {
-			if (strcmp (*iter, NM_SETTING_BOND_INTERFACE_NAME))
+			if (strcmp (*iter, "interface-name"))
 				nm_setting_bond_add_option (NM_SETTING_BOND (setting), *iter, value);
 		}
 		g_free (value);
@@ -655,12 +606,12 @@ unescape_semicolons (char *str)
 	}
 }
 
-static GByteArray *
-get_uchar_array (GKeyFile *keyfile,
-                 const char *setting_name,
-                 const char *key,
-                 gboolean zero_terminate,
-                 gboolean unescape_semicolon)
+static GBytes *
+get_bytes (GKeyFile *keyfile,
+           const char *setting_name,
+           const char *key,
+           gboolean zero_terminate,
+           gboolean unescape_semicolon)
 {
 	GByteArray *array = NULL;
 	char *tmp_string;
@@ -714,21 +665,21 @@ get_uchar_array (GKeyFile *keyfile,
 
 	if (array->len == 0) {
 		g_byte_array_free (array, TRUE);
-		array = NULL;
-	}
-	return array;
+		return NULL;
+	} else
+		return g_byte_array_free_to_bytes (array);
 }
 
 static void
 ssid_parser (NMSetting *setting, const char *key, GKeyFile *keyfile, const char *keyfile_path)
 {
 	const char *setting_name = nm_setting_get_name (setting);
-	GByteArray *array;
+	GBytes *bytes;
 
-	array = get_uchar_array (keyfile, setting_name, key, FALSE, TRUE);
-	if (array) {
-		g_object_set (setting, key, array, NULL);
-		g_byte_array_free (array, TRUE);
+	bytes = get_bytes (keyfile, setting_name, key, FALSE, TRUE);
+	if (bytes) {
+		g_object_set (setting, key, bytes, NULL);
+		g_bytes_unref (bytes);
 	} else {
 		nm_log_warn (LOGD_SETTINGS, "%s: ignoring invalid SSID for %s / %s",
 		             __func__, setting_name, key);
@@ -739,12 +690,12 @@ static void
 password_raw_parser (NMSetting *setting, const char *key, GKeyFile *keyfile, const char *keyfile_path)
 {
 	const char *setting_name = nm_setting_get_name (setting);
-	GByteArray *array;
+	GBytes *bytes;
 
-	array = get_uchar_array (keyfile, setting_name, key, FALSE, TRUE);
-	if (array) {
-		g_object_set (setting, key, array, NULL);
-		g_byte_array_free (array, TRUE);
+	bytes = get_bytes (keyfile, setting_name, key, FALSE, TRUE);
+	if (bytes) {
+		g_object_set (setting, key, bytes, NULL);
+		g_bytes_unref (bytes);
 	} else {
 		nm_log_warn (LOGD_SETTINGS, "%s: ignoring invalid raw password for %s / %s",
 		             __func__, setting_name, key);
@@ -752,7 +703,7 @@ password_raw_parser (NMSetting *setting, const char *key, GKeyFile *keyfile, con
 }
 
 static char *
-get_cert_path (const char *keyfile_path, GByteArray *cert_path)
+get_cert_path (const char *keyfile_path, const guint8 *cert_path, gsize cert_path_len)
 {
 	const char *base;
 	char *p = NULL, *path, *dirname, *tmp;
@@ -760,8 +711,8 @@ get_cert_path (const char *keyfile_path, GByteArray *cert_path)
 	g_return_val_if_fail (keyfile_path != NULL, NULL);
 	g_return_val_if_fail (cert_path != NULL, NULL);
 
-	base = path = g_malloc0 (cert_path->len + 1);
-	memcpy (path, cert_path->data, cert_path->len);
+	base = path = g_malloc0 (cert_path_len + 1);
+	memcpy (path, cert_path, cert_path_len);
 
 	if (path[0] == '/')
 		return path;
@@ -794,37 +745,46 @@ has_cert_ext (const char *path)
 }
 
 static gboolean
-handle_as_scheme (GByteArray *array, NMSetting *setting, const char *key)
+handle_as_scheme (GBytes *bytes, NMSetting *setting, const char *key)
 {
+	const guint8 *data;
+	gsize data_len;
+
+	data = g_bytes_get_data (bytes, &data_len);
+
 	/* It's the PATH scheme, can just set plain data */
-	if (   (array->len > strlen (SCHEME_PATH))
-	    && g_str_has_prefix ((const char *) array->data, SCHEME_PATH)
-	    && (array->data[array->len - 1] == '\0')) {
-		g_object_set (setting, key, array, NULL);
+	if (   (data_len > strlen (SCHEME_PATH))
+	    && g_str_has_prefix ((const char *) data, SCHEME_PATH)
+	    && (data[data_len - 1] == '\0')) {
+		g_object_set (setting, key, bytes, NULL);
 		return TRUE;
 	}
 	return FALSE;
 }
 
 static gboolean
-handle_as_path (GByteArray *array,
+handle_as_path (GBytes *bytes,
                 NMSetting *setting,
                 const char *key,
                 const char *keyfile_path)
 {
-	gsize validate_len = array->len;
-	GByteArray *val;
+	const guint8 *data;
+	gsize data_len;
+	gsize validate_len;
 	char *path;
 	gboolean exists, success = FALSE;
 
-	if (array->len > 500 || array->len < 1)
+	data = g_bytes_get_data (bytes, &data_len);
+	if (data_len > 500 || data_len < 1)
 		return FALSE;
 
 	/* If there's a trailing NULL tell g_utf8_validate() to to until the NULL */
-	if (array->data[array->len - 1] == '\0')
+	if (data[data_len - 1] == '\0')
 		validate_len = -1;
+	else
+		validate_len = data_len;
 
-	if (g_utf8_validate ((const char *) array->data, validate_len, NULL) == FALSE)
+	if (g_utf8_validate ((const char *) data, validate_len, NULL) == FALSE)
 		return FALSE;
 
 	/* Might be a bare path without the file:// prefix; in that case
@@ -832,18 +792,22 @@ handle_as_path (GByteArray *array,
 	 * relative path to the current directory.
 	 */
 
-	path = get_cert_path (keyfile_path, array);
+	path = get_cert_path (keyfile_path, data, data_len);
 	exists = g_file_test (path, G_FILE_TEST_EXISTS);
 	if (   exists
-	    || memchr (array->data, '/', array->len)
+	    || memchr (data, '/', data_len)
 	    || has_cert_ext (path)) {
+		GByteArray *tmp;
+		GBytes *val;
+
 		/* Construct the proper value as required for the PATH scheme */
-		val = g_byte_array_sized_new (strlen (SCHEME_PATH) + strlen (path) + 1);
-		g_byte_array_append (val, (const guint8 *) SCHEME_PATH, strlen (SCHEME_PATH));
-		g_byte_array_append (val, (const guint8 *) path, strlen (path));
-		g_byte_array_append (val, (const guint8 *) "\0", 1);
+		tmp = g_byte_array_sized_new (strlen (SCHEME_PATH) + strlen (path) + 1);
+		g_byte_array_append (tmp, (const guint8 *) SCHEME_PATH, strlen (SCHEME_PATH));
+		g_byte_array_append (tmp, (const guint8 *) path, strlen (path));
+		g_byte_array_append (tmp, (const guint8 *) "\0", 1);
+		val = g_byte_array_free_to_bytes (tmp);
 		g_object_set (setting, key, val, NULL);
-		g_byte_array_free (val, TRUE);
+		g_bytes_unref (val);
 		success = TRUE;
 
 		/* Warn if the certificate didn't exist */
@@ -859,28 +823,78 @@ static void
 cert_parser (NMSetting *setting, const char *key, GKeyFile *keyfile, const char *keyfile_path)
 {
 	const char *setting_name = nm_setting_get_name (setting);
-	GByteArray *array;
+	GBytes *bytes;
 	gboolean success = FALSE;
 
-	array = get_uchar_array (keyfile, setting_name, key, TRUE, FALSE);
-	if (array && array->len > 0) {
+	bytes = get_bytes (keyfile, setting_name, key, TRUE, FALSE);
+	if (bytes) {
 		/* Try as a path + scheme (ie, starts with "file://") */
-		success = handle_as_scheme (array, setting, key);
+		success = handle_as_scheme (bytes, setting, key);
 
 		/* If not, it might be a plain path */
 		if (success == FALSE)
-			success = handle_as_path (array, setting, key, keyfile_path);
+			success = handle_as_path (bytes, setting, key, keyfile_path);
 
 		/* If neither of those two, assume blob with certificate data */
 		if (success == FALSE)
-			g_object_set (setting, key, array, NULL);
+			g_object_set (setting, key, bytes, NULL);
 	} else {
 		nm_log_warn (LOGD_SETTINGS, "%s: ignoring invalid key/cert value for %s / %s",
 		             __func__, setting_name, key);
 	}
 
-	if (array)
-		g_byte_array_free (array, TRUE);
+	if (bytes)
+		g_bytes_unref (bytes);
+}
+
+static void
+parity_parser (NMSetting *setting, const char *key, GKeyFile *keyfile, const char *keyfile_path)
+{
+	const char *setting_name = nm_setting_get_name (setting);
+	NMSettingSerialParity parity;
+	int int_val;
+	char *str_val;
+
+	/* Keyfile traditionally stored this as the ASCII value for 'E', 'o', or 'n'.
+	 * We now accept either that or the (case-insensitive) character itself (but
+	 * still always write it the old way, for backward compatibility).
+	 */
+	int_val = nm_keyfile_plugin_kf_get_integer (keyfile, setting_name, key, NULL);
+	if (!int_val) {
+		str_val = nm_keyfile_plugin_kf_get_string (keyfile, setting_name, key, NULL);
+		if (str_val) {
+			if (str_val[0] && !str_val[1])
+				int_val = str_val[0];
+			else {
+				/* This will hit the warning below */
+				int_val = 'X';
+			}
+		}
+	}
+
+	if (!int_val)
+		return;
+
+	switch (int_val) {
+	case 'E':
+	case 'e':
+		parity = NM_SETTING_SERIAL_PARITY_EVEN;
+		break;
+	case 'O':
+	case 'o':
+		parity = NM_SETTING_SERIAL_PARITY_ODD;
+		break;
+	case 'N':
+	case 'n':
+		parity = NM_SETTING_SERIAL_PARITY_NONE;
+		break;
+	default:
+		nm_log_warn (LOGD_SETTINGS, "%s: ignoring invalid value for %s / %s",
+		             __func__, setting_name, key);
+		return;
+	}
+
+	g_object_set (setting, key, parity, NULL);
 }
 
 typedef struct {
@@ -906,27 +920,27 @@ static KeyParser key_parsers[] = {
 	  TRUE,
 	  mac_address_parser_ETHER },
 	{ NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	  NM_SETTING_IP4_CONFIG_ADDRESSES,
+	  NM_SETTING_IP_CONFIG_ADDRESSES,
 	  FALSE,
 	  ip_address_or_route_parser },
 	{ NM_SETTING_IP6_CONFIG_SETTING_NAME,
-	  NM_SETTING_IP6_CONFIG_ADDRESSES,
+	  NM_SETTING_IP_CONFIG_ADDRESSES,
 	  FALSE,
 	  ip_address_or_route_parser },
 	{ NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	  NM_SETTING_IP4_CONFIG_ROUTES,
+	  NM_SETTING_IP_CONFIG_ROUTES,
 	  FALSE,
 	  ip_address_or_route_parser },
 	{ NM_SETTING_IP6_CONFIG_SETTING_NAME,
-	  NM_SETTING_IP6_CONFIG_ROUTES,
+	  NM_SETTING_IP_CONFIG_ROUTES,
 	  FALSE,
 	  ip_address_or_route_parser },
 	{ NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	  NM_SETTING_IP4_CONFIG_DNS,
+	  NM_SETTING_IP_CONFIG_DNS,
 	  FALSE,
 	  ip4_dns_parser },
 	{ NM_SETTING_IP6_CONFIG_SETTING_NAME,
-	  NM_SETTING_IP6_CONFIG_DNS,
+	  NM_SETTING_IP_CONFIG_DNS,
 	  FALSE,
 	  ip6_dns_parser },
 	{ NM_SETTING_WIRED_SETTING_NAME,
@@ -993,6 +1007,10 @@ static KeyParser key_parsers[] = {
 	  NM_SETTING_802_1X_PHASE2_PRIVATE_KEY,
 	  TRUE,
 	  cert_parser },
+	{ NM_SETTING_SERIAL_SETTING_NAME,
+	  NM_SETTING_SERIAL_PARITY,
+	  TRUE,
+	  parity_parser },
 	{ NULL, NULL, FALSE }
 };
 
@@ -1010,6 +1028,7 @@ read_one_setting_value (NMSetting *setting,
 {
 	ReadInfo *info = user_data;
 	const char *setting_name;
+	int errsv;
 	GType type;
 	GError *err = NULL;
 	gboolean check_for_key = TRUE;
@@ -1110,9 +1129,22 @@ read_one_setting_value (NMSetting *setting,
 		uint_val = g_ascii_strtoull (tmp_str, NULL, 10);
 		g_free (tmp_str);
 		g_object_set (setting, key, uint_val, NULL);
- 	} else if (type == DBUS_TYPE_G_UCHAR_ARRAY) {
+	} else if (type == G_TYPE_INT64) {
+		char *tmp_str;
+		gint64 int_val;
+
+		tmp_str = nm_keyfile_plugin_kf_get_value (info->keyfile, setting_name, key, NULL);
+		int_val = nm_utils_ascii_str_to_int64 (tmp_str, 10, G_MININT64, G_MAXINT64, 0);
+		errsv = errno;
+		if (errsv)
+			nm_log_warn (LOGD_SETTINGS, "Invalid int64 value (%s)", tmp_str);
+		else
+			g_object_set (setting, key, int_val, NULL);
+		g_free (tmp_str);
+ 	} else if (type == G_TYPE_BYTES) {
 		gint *tmp;
 		GByteArray *array;
+		GBytes *bytes;
 		gsize length;
 		int i;
 
@@ -1131,31 +1163,45 @@ read_one_setting_value (NMSetting *setting,
 				g_byte_array_append (array, (const unsigned char *) &v, sizeof (v));
 		}
 
-		g_object_set (setting, key, array, NULL);
-		g_byte_array_free (array, TRUE);
+		bytes = g_byte_array_free_to_bytes (array);
+		g_object_set (setting, key, bytes, NULL);
+		g_bytes_unref (bytes);
 		g_free (tmp);
- 	} else if (type == DBUS_TYPE_G_LIST_OF_STRING) {
+	} else if (type == G_TYPE_STRV) {
 		gchar **sa;
 		gsize length;
-		int i;
-		GSList *list = NULL;
 
 		sa = nm_keyfile_plugin_kf_get_string_list (info->keyfile, setting_name, key, &length, NULL);
-		for (i = 0; i < length; i++)
-			list = g_slist_prepend (list, sa[i]);
-
-		list = g_slist_reverse (list);
-		g_object_set (setting, key, list, NULL);
-
-		g_slist_free (list);
+		g_object_set (setting, key, sa, NULL);
 		g_strfreev (sa);
-	} else if (type == DBUS_TYPE_G_MAP_OF_STRING) {
+	} else if (type == G_TYPE_HASH_TABLE) {
 		read_hash_of_string (info->keyfile, setting, key);
-	} else if (type == DBUS_TYPE_G_UINT_ARRAY) {
+	} else if (type == G_TYPE_ARRAY) {
 		if (!read_array_of_uint (info->keyfile, setting, key)) {
 			nm_log_warn (LOGD_SETTINGS, "Unhandled setting property type (read): '%s/%s' : '%s'",
 			             setting_name, key, G_VALUE_TYPE_NAME (value));
 		}
+	} else if (G_VALUE_HOLDS_FLAGS (value)) {
+		guint64 uint_val;
+
+		/* Flags are guint but GKeyFile has no uint reader, just uint64 */
+		uint_val = nm_keyfile_plugin_kf_get_uint64 (info->keyfile, setting_name, key, &err);
+		if (!err) {
+			if (uint_val <= G_MAXUINT)
+				g_object_set (setting, key, (guint) uint_val, NULL);
+			else {
+				nm_log_warn (LOGD_SETTINGS, "Too large FLAGS property (read): '%s/%s' : '%s'",
+				             setting_name, key, G_VALUE_TYPE_NAME (value));
+			}
+		}
+		g_clear_error (&err);
+	} else if (G_VALUE_HOLDS_ENUM (value)) {
+		gint int_val;
+
+		int_val = nm_keyfile_plugin_kf_get_integer (info->keyfile, setting_name, key, &err);
+		if (!err)
+			g_object_set (setting, key, (gint) int_val, NULL);
+		g_clear_error (&err);
 	} else {
 		nm_log_warn (LOGD_SETTINGS, "Unhandled setting property type (read): '%s/%s' : '%s'",
 		             setting_name, key, G_VALUE_TYPE_NAME (value));
@@ -1165,22 +1211,27 @@ read_one_setting_value (NMSetting *setting,
 static NMSetting *
 read_setting (GKeyFile *file, const char *keyfile_path, const char *group)
 {
-	NMSetting *setting;
+	NMSetting *setting = NULL;
 	ReadInfo info = { file, keyfile_path };
 	const char *alias;
+	GType type;
 
 	alias = nm_keyfile_plugin_get_setting_name_for_alias (group);
-	setting = nm_connection_create_setting (alias ? alias : group);
-	if (setting)
+	if (alias)
+		group = alias;
+
+	type = nm_setting_lookup_type (group);
+	if (type) {
+		setting = g_object_new (type, NULL);
 		nm_setting_enumerate_values (setting, read_one_setting_value, &info);
-	else
+	} else
 		nm_log_warn (LOGD_SETTINGS, "Invalid setting name '%s'", group);
 
 	return setting;
 }
 
 static void
-read_vpn_secrets (GKeyFile *file, NMSettingVPN *s_vpn)
+read_vpn_secrets (GKeyFile *file, NMSettingVpn *s_vpn)
 {
 	char **keys, **iter;
 
@@ -1197,30 +1248,6 @@ read_vpn_secrets (GKeyFile *file, NMSettingVPN *s_vpn)
 	g_strfreev (keys);
 }
 
-static void
-ensure_slave_setting (NMConnection *connection)
-{
-	NMSettingConnection *s_con = nm_connection_get_setting_connection (connection);
-	const char *slave_type;
-	GType slave_gtype = G_TYPE_INVALID;
-	NMSetting *setting;
-
-	slave_type = nm_setting_connection_get_slave_type (s_con);
-	if (!slave_type)
-		return;
-
-	if (g_strcmp0 (slave_type, NM_SETTING_BRIDGE_SETTING_NAME) == 0)
-		slave_gtype = NM_TYPE_SETTING_BRIDGE_PORT;
-	else if (g_strcmp0 (slave_type, NM_SETTING_TEAM_SETTING_NAME) == 0)
-		slave_gtype = NM_TYPE_SETTING_TEAM_PORT;
-
-	if (slave_gtype != G_TYPE_INVALID && !nm_connection_get_setting (connection, slave_gtype)) {
-		setting = (NMSetting *) g_object_new (slave_gtype, NULL);
-		g_assert (setting);
-		nm_connection_add_setting (connection, setting);
-	}
-}
-
 NMConnection *
 nm_keyfile_plugin_connection_from_file (const char *filename, GError **error)
 {
@@ -1234,11 +1261,10 @@ nm_keyfile_plugin_connection_from_file (const char *filename, GError **error)
 	gsize length;
 	int i;
 	gboolean vpn_secrets = FALSE;
-	const char *ctype;
 	GError *verify_error = NULL;
 
 	if (stat (filename, &statbuf) != 0 || !S_ISREG (statbuf.st_mode)) {
-		g_set_error_literal (error, KEYFILE_PLUGIN_ERROR, 0,
+		g_set_error_literal (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
 		                     "File did not exist or was not a regular file");
 		return NULL;
 	}
@@ -1246,7 +1272,7 @@ nm_keyfile_plugin_connection_from_file (const char *filename, GError **error)
 	bad_permissions = statbuf.st_mode & 0077;
 
 	if (bad_permissions) {
-		g_set_error (error, KEYFILE_PLUGIN_ERROR, 0,
+		g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
 		             "File permissions (%o) were insecure",
 		             statbuf.st_mode);
 		return NULL;
@@ -1256,7 +1282,7 @@ nm_keyfile_plugin_connection_from_file (const char *filename, GError **error)
 	if (!g_key_file_load_from_file (key_file, filename, G_KEY_FILE_NONE, error))
 		goto out;
 
-	connection = nm_connection_new ();
+	connection = nm_simple_connection_new ();
 
 	groups = g_key_file_get_groups (key_file, &length);
 	for (i = 0; i < length; i++) {
@@ -1271,36 +1297,50 @@ nm_keyfile_plugin_connection_from_file (const char *filename, GError **error)
 			nm_connection_add_setting (connection, setting);
 	}
 
-	/* Make sure that we have the base device type and slave type settings
-	 * even if the keyfile didn't include it, which can happen when the
-	 * setting in question is all default values (like ethernet where
-	 * the MAC address isn't given, or VLAN when the VLAN ID is zero, or
-	 * bridge port with all default settings).
-	 */
 	s_con = nm_connection_get_setting_connection (connection);
-	if (s_con) {
-		ctype = nm_setting_connection_get_connection_type (s_con);
-		if (ctype) {
-			setting = nm_connection_get_setting_by_name (connection, ctype);
-			if (!setting) {
-				NMSetting *base_setting;
-				GType base_setting_type;
-
-				base_setting_type = nm_connection_lookup_setting_type (ctype);
-				if (base_setting_type != G_TYPE_INVALID) {
-					base_setting = (NMSetting *) g_object_new (base_setting_type, NULL);
-					g_assert (base_setting);
-					nm_connection_add_setting (connection, base_setting);
-				}
-			}
-		}
+	if (!s_con) {
+		s_con = NM_SETTING_CONNECTION (nm_setting_connection_new ());
+		nm_connection_add_setting (connection, NM_SETTING (s_con));
+	}
+
+	/* Make sure that we have 'id' even if not explictly specified in the keyfile */
+	if (!nm_setting_connection_get_id (s_con)) {
+		char *base_name;
 
-		ensure_slave_setting (connection);
+		base_name = g_path_get_basename (filename);
+		g_object_set (s_con, NM_SETTING_CONNECTION_ID, base_name, NULL);
+		g_free (base_name);
+	}
+
+	/* Make sure that we have 'uuid' even if not explictly specified in the keyfile */
+	if (!nm_setting_connection_get_uuid (s_con)) {
+		char *hashed_uuid;
+
+		hashed_uuid = nm_utils_uuid_generate_from_strings ("keyfile", filename, NULL);
+		g_object_set (s_con, NM_SETTING_CONNECTION_UUID, hashed_uuid, NULL);
+		g_free (hashed_uuid);
+	}
+
+	/* Make sure that we have 'interface-name' even if it was specified in the
+	 * "wrong" (ie, deprecated) group.
+	 */
+	if (   !nm_setting_connection_get_interface_name (s_con)
+	    && nm_setting_connection_get_connection_type (s_con)) {
+		char *interface_name;
+
+		interface_name = g_key_file_get_string (key_file,
+		                                        nm_setting_connection_get_connection_type (s_con),
+		                                        "interface-name",
+		                                        NULL);
+		if (interface_name) {
+			g_object_set (s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, interface_name, NULL);
+			g_free (interface_name);
+		}
 	}
 
 	/* Handle vpn secrets after the 'vpn' setting was read */
 	if (vpn_secrets) {
-		NMSettingVPN *s_vpn;
+		NMSettingVpn *s_vpn;
 
 		s_vpn = nm_connection_get_setting_vpn (connection);
 		if (s_vpn)
@@ -1309,12 +1349,11 @@ nm_keyfile_plugin_connection_from_file (const char *filename, GError **error)
 
 	g_strfreev (groups);
 
-	/* Verify the connection */
-	if (!nm_connection_verify (connection, &verify_error)) {
-		g_set_error (error, KEYFILE_PLUGIN_ERROR, 0,
-			         "invalid or missing connection property '%s/%s'",
-			         verify_error ? g_type_name (nm_connection_lookup_setting_type_by_quark (verify_error->domain)) : "(unknown)",
-			         (verify_error && verify_error->message) ? verify_error->message : "(unknown)");
+	/* Normalize and verify the connection */
+	if (!nm_connection_normalize (connection, NULL, NULL, &verify_error)) {
+		g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
+			         "invalid connection: %s",
+		             verify_error->message);
 		g_clear_error (&verify_error);
 		g_object_unref (connection);
 		connection = NULL;
diff --git a/src/settings/plugins/keyfile/tests/Makefile.am b/src/settings/plugins/keyfile/tests/Makefile.am
index fae6e4ea..20b9820c 100644
--- a/src/settings/plugins/keyfile/tests/Makefile.am
+++ b/src/settings/plugins/keyfile/tests/Makefile.am
@@ -6,19 +6,16 @@ SUBDIRS=keyfiles
 
 AM_CPPFLAGS = \
 	-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)/libnm-core \
+	-I$(top_builddir)/libnm-core \
 	-I$(top_srcdir)/src \
-	-I$(top_srcdir)/src/logging \
 	-I$(top_srcdir)/src/settings \
 	-I$(srcdir)/../ \
 	$(GLIB_CFLAGS) \
 	$(DBUS_CFLAGS) \
-	$(POLKIT_CFLAGS) \
 	$(CODE_COVERAGE_CFLAGS) \
 	-DG_LOG_DOMAIN=\""NetworkManager-keyfile"\" \
+	-DNETWORKMANAGER_COMPILATION \
 	-DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \
 	-DTEST_KEYFILES_DIR=\"$(abs_srcdir)/keyfiles\" \
 	-DTEST_SCRATCH_DIR=\"$(abs_builddir)/keyfiles\" \
@@ -30,13 +27,10 @@ test_keyfile_SOURCES = \
 	test-keyfile.c \
 	../reader.c \
 	../writer.c \
-	../errors.c \
 	../utils.c
 
 test_keyfile_LDADD = \
 	$(top_builddir)/src/libNetworkManager.la \
-	$(top_builddir)/libnm-glib/libnm-glib.la \
-	$(top_builddir)/libnm-util/libnm-util.la \
 	$(DBUS_LIBS) \
 	$(CODE_COVERAGE_LDFLAGS)
 
diff --git a/src/settings/plugins/keyfile/tests/Makefile.in b/src/settings/plugins/keyfile/tests/Makefile.in
index f7b4b62a..8530bf8c 100644
--- a/src/settings/plugins/keyfile/tests/Makefile.in
+++ b/src/settings/plugins/keyfile/tests/Makefile.in
@@ -105,16 +105,14 @@ CONFIG_CLEAN_FILES =
 CONFIG_CLEAN_VPATH_FILES =
 PROGRAMS = $(noinst_PROGRAMS)
 am__test_keyfile_SOURCES_DIST = test-keyfile.c ../reader.c ../writer.c \
-	../errors.c ../utils.c
+	../utils.c
 @ENABLE_TESTS_TRUE@am_test_keyfile_OBJECTS = test-keyfile.$(OBJEXT) \
 @ENABLE_TESTS_TRUE@	reader.$(OBJEXT) writer.$(OBJEXT) \
-@ENABLE_TESTS_TRUE@	errors.$(OBJEXT) utils.$(OBJEXT)
+@ENABLE_TESTS_TRUE@	utils.$(OBJEXT)
 test_keyfile_OBJECTS = $(am_test_keyfile_OBJECTS)
 am__DEPENDENCIES_1 =
 @ENABLE_TESTS_TRUE@test_keyfile_DEPENDENCIES =  \
 @ENABLE_TESTS_TRUE@	$(top_builddir)/src/libNetworkManager.la \
-@ENABLE_TESTS_TRUE@	$(top_builddir)/libnm-glib/libnm-glib.la \
-@ENABLE_TESTS_TRUE@	$(top_builddir)/libnm-util/libnm-util.la \
 @ENABLE_TESTS_TRUE@	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
 AM_V_lt = $(am__v_lt_@AM_V@)
 am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
@@ -254,6 +252,8 @@ AUTOCONF = @AUTOCONF@
 AUTOHEADER = @AUTOHEADER@
 AUTOMAKE = @AUTOMAKE@
 AWK = @AWK@
+BLUEZ5_CFLAGS = @BLUEZ5_CFLAGS@
+BLUEZ5_LIBS = @BLUEZ5_LIBS@
 CC = @CC@
 CCDEPMODE = @CCDEPMODE@
 CFLAGS = @CFLAGS@
@@ -377,6 +377,7 @@ NEWT_CFLAGS = @NEWT_CFLAGS@
 NEWT_LIBS = @NEWT_LIBS@
 NM = @NM@
 NMEDIT = @NMEDIT@
+NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@
 NM_MAJOR_VERSION = @NM_MAJOR_VERSION@
 NM_MICRO_VERSION = @NM_MICRO_VERSION@
 NM_MINOR_VERSION = @NM_MINOR_VERSION@
@@ -396,6 +397,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
 PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
 PKG_CONFIG = @PKG_CONFIG@
 PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
 PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
@@ -422,7 +424,7 @@ SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@
 SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@
 SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@
 SYSTEM_CA_PATH = @SYSTEM_CA_PATH@
-UDEV_BASE_DIR = @UDEV_BASE_DIR@
+UDEV_DIR = @UDEV_DIR@
 USE_NLS = @USE_NLS@
 UUID_CFLAGS = @UUID_CFLAGS@
 UUID_LIBS = @UUID_LIBS@
@@ -504,19 +506,16 @@ with_valgrind = @with_valgrind@
 @ENABLE_TESTS_TRUE@SUBDIRS = keyfiles
 @ENABLE_TESTS_TRUE@AM_CPPFLAGS = \
 @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)/libnm-core \
+@ENABLE_TESTS_TRUE@	-I$(top_builddir)/libnm-core \
 @ENABLE_TESTS_TRUE@	-I$(top_srcdir)/src \
-@ENABLE_TESTS_TRUE@	-I$(top_srcdir)/src/logging \
 @ENABLE_TESTS_TRUE@	-I$(top_srcdir)/src/settings \
 @ENABLE_TESTS_TRUE@	-I$(srcdir)/../ \
 @ENABLE_TESTS_TRUE@	$(GLIB_CFLAGS) \
 @ENABLE_TESTS_TRUE@	$(DBUS_CFLAGS) \
-@ENABLE_TESTS_TRUE@	$(POLKIT_CFLAGS) \
 @ENABLE_TESTS_TRUE@	$(CODE_COVERAGE_CFLAGS) \
 @ENABLE_TESTS_TRUE@	-DG_LOG_DOMAIN=\""NetworkManager-keyfile"\" \
+@ENABLE_TESTS_TRUE@	-DNETWORKMANAGER_COMPILATION \
 @ENABLE_TESTS_TRUE@	-DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \
 @ENABLE_TESTS_TRUE@	-DTEST_KEYFILES_DIR=\"$(abs_srcdir)/keyfiles\" \
 @ENABLE_TESTS_TRUE@	-DTEST_SCRATCH_DIR=\"$(abs_builddir)/keyfiles\" \
@@ -526,13 +525,10 @@ with_valgrind = @with_valgrind@
 @ENABLE_TESTS_TRUE@	test-keyfile.c \
 @ENABLE_TESTS_TRUE@	../reader.c \
 @ENABLE_TESTS_TRUE@	../writer.c \
-@ENABLE_TESTS_TRUE@	../errors.c \
 @ENABLE_TESTS_TRUE@	../utils.c
 
 @ENABLE_TESTS_TRUE@test_keyfile_LDADD = \
 @ENABLE_TESTS_TRUE@	$(top_builddir)/src/libNetworkManager.la \
-@ENABLE_TESTS_TRUE@	$(top_builddir)/libnm-glib/libnm-glib.la \
-@ENABLE_TESTS_TRUE@	$(top_builddir)/libnm-util/libnm-util.la \
 @ENABLE_TESTS_TRUE@	$(DBUS_LIBS) \
 @ENABLE_TESTS_TRUE@	$(CODE_COVERAGE_LDFLAGS)
 
@@ -590,7 +586,6 @@ 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)/test-keyfile.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils.Po@am__quote@
@@ -645,20 +640,6 @@ writer.obj: ../writer.c
 @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`
 
-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`
-
 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
diff --git a/src/settings/plugins/keyfile/tests/keyfiles/ATT_Data_Connect_BT b/src/settings/plugins/keyfile/tests/keyfiles/ATT_Data_Connect_BT
index cc8a9ee3..162bf72e 100644
--- a/src/settings/plugins/keyfile/tests/keyfiles/ATT_Data_Connect_BT
+++ b/src/settings/plugins/keyfile/tests/keyfiles/ATT_Data_Connect_BT
@@ -16,6 +16,7 @@ apn=ISP.CINGULAR
 
 [serial]
 baud=115200
+parity=o
 
 [bluetooth]
 bdaddr=00:11:22:33:44:55
diff --git a/src/settings/plugins/keyfile/tests/keyfiles/ATT_Data_Connect_Plain b/src/settings/plugins/keyfile/tests/keyfiles/ATT_Data_Connect_Plain
index 236cca0e..902b8427 100644
--- a/src/settings/plugins/keyfile/tests/keyfiles/ATT_Data_Connect_Plain
+++ b/src/settings/plugins/keyfile/tests/keyfiles/ATT_Data_Connect_Plain
@@ -18,3 +18,4 @@ pin=2345
 
 [serial]
 baud=115200
+parity=111
diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Makefile.am b/src/settings/plugins/keyfile/tests/keyfiles/Makefile.am
index 576164d2..4ca4c3fa 100644
--- a/src/settings/plugins/keyfile/tests/keyfiles/Makefile.am
+++ b/src/settings/plugins/keyfile/tests/keyfiles/Makefile.am
@@ -21,7 +21,16 @@ KEYFILES = \
 	Test_Bridge_Component \
 	Test_New_Wired_Group_Name \
 	Test_New_Wireless_Group_Names \
-	Test_Missing_Vlan_Setting
+	Test_minimal_1 \
+	Test_minimal_2 \
+	Test_minimal_slave_1 \
+	Test_minimal_slave_2 \
+	Test_minimal_slave_3 \
+	Test_minimal_slave_4 \
+	Test_Missing_Vlan_Setting \
+	Test_Missing_ID_UUID \
+	Test_Enum_Property \
+	Test_Flags_Property
 
 CERTS = \
 	test-ca-cert.pem \
diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Makefile.in b/src/settings/plugins/keyfile/tests/keyfiles/Makefile.in
index 05660e3e..bc522b1b 100644
--- a/src/settings/plugins/keyfile/tests/keyfiles/Makefile.in
+++ b/src/settings/plugins/keyfile/tests/keyfiles/Makefile.in
@@ -129,6 +129,8 @@ AUTOCONF = @AUTOCONF@
 AUTOHEADER = @AUTOHEADER@
 AUTOMAKE = @AUTOMAKE@
 AWK = @AWK@
+BLUEZ5_CFLAGS = @BLUEZ5_CFLAGS@
+BLUEZ5_LIBS = @BLUEZ5_LIBS@
 CC = @CC@
 CCDEPMODE = @CCDEPMODE@
 CFLAGS = @CFLAGS@
@@ -252,6 +254,7 @@ NEWT_CFLAGS = @NEWT_CFLAGS@
 NEWT_LIBS = @NEWT_LIBS@
 NM = @NM@
 NMEDIT = @NMEDIT@
+NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@
 NM_MAJOR_VERSION = @NM_MAJOR_VERSION@
 NM_MICRO_VERSION = @NM_MICRO_VERSION@
 NM_MINOR_VERSION = @NM_MINOR_VERSION@
@@ -271,6 +274,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
 PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
 PKG_CONFIG = @PKG_CONFIG@
 PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
 PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
@@ -297,7 +301,7 @@ SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@
 SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@
 SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@
 SYSTEM_CA_PATH = @SYSTEM_CA_PATH@
-UDEV_BASE_DIR = @UDEV_BASE_DIR@
+UDEV_DIR = @UDEV_DIR@
 USE_NLS = @USE_NLS@
 UUID_CFLAGS = @UUID_CFLAGS@
 UUID_LIBS = @UUID_LIBS@
@@ -399,7 +403,16 @@ KEYFILES = \
 	Test_Bridge_Component \
 	Test_New_Wired_Group_Name \
 	Test_New_Wireless_Group_Names \
-	Test_Missing_Vlan_Setting
+	Test_minimal_1 \
+	Test_minimal_2 \
+	Test_minimal_slave_1 \
+	Test_minimal_slave_2 \
+	Test_minimal_slave_3 \
+	Test_minimal_slave_4 \
+	Test_Missing_Vlan_Setting \
+	Test_Missing_ID_UUID \
+	Test_Enum_Property \
+	Test_Flags_Property
 
 CERTS = \
 	test-ca-cert.pem \
diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_Enum_Property b/src/settings/plugins/keyfile/tests/keyfiles/Test_Enum_Property
new file mode 100644
index 00000000..52b395b3
--- /dev/null
+++ b/src/settings/plugins/keyfile/tests/keyfiles/Test_Enum_Property
@@ -0,0 +1,8 @@
+[connection]
+id=Test Wired Connection IP6
+uuid=4e80a56d-c99f-4aad-a6dd-b449bc398c57
+type=802-3-ethernet
+
+[ipv6]
+method=auto
+ip6-privacy=2
diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_Flags_Property b/src/settings/plugins/keyfile/tests/keyfiles/Test_Flags_Property
new file mode 100644
index 00000000..3a46611d
--- /dev/null
+++ b/src/settings/plugins/keyfile/tests/keyfiles/Test_Flags_Property
@@ -0,0 +1,11 @@
+[connection]
+id=Test Flags Property
+uuid=05a5ec81-fa72-4b7c-9f85-4a0dfd36c84f
+type=gsm
+
+[gsm]
+number=*99#
+username=username
+password-flags=5
+apn=my.apn
+
diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_Missing_ID_UUID b/src/settings/plugins/keyfile/tests/keyfiles/Test_Missing_ID_UUID
new file mode 100644
index 00000000..138380d0
--- /dev/null
+++ b/src/settings/plugins/keyfile/tests/keyfiles/Test_Missing_ID_UUID
@@ -0,0 +1,9 @@
+# id and uuid keys are missing
+# They will be auto-genetrated by NetworkManager
+
+[connection]
+type=ethernet
+autoconnect=true
+
+[802-3-ethernet]
+mac-address=00:11:22:33:44:55
diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_minimal_1 b/src/settings/plugins/keyfile/tests/keyfiles/Test_minimal_1
new file mode 100644
index 00000000..cac135ad
--- /dev/null
+++ b/src/settings/plugins/keyfile/tests/keyfiles/Test_minimal_1
@@ -0,0 +1,2 @@
+[connection]
+type=802-3-ethernet
diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_minimal_2 b/src/settings/plugins/keyfile/tests/keyfiles/Test_minimal_2
new file mode 100644
index 00000000..bbf2d8d6
--- /dev/null
+++ b/src/settings/plugins/keyfile/tests/keyfiles/Test_minimal_2
@@ -0,0 +1 @@
+[802-3-ethernet]
diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_minimal_slave_1 b/src/settings/plugins/keyfile/tests/keyfiles/Test_minimal_slave_1
new file mode 100644
index 00000000..d3122d53
--- /dev/null
+++ b/src/settings/plugins/keyfile/tests/keyfiles/Test_minimal_slave_1
@@ -0,0 +1,4 @@
+[connection]
+type=802-3-ethernet
+master=br0
+slave-type=bridge
diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_minimal_slave_2 b/src/settings/plugins/keyfile/tests/keyfiles/Test_minimal_slave_2
new file mode 100644
index 00000000..eb1cdace
--- /dev/null
+++ b/src/settings/plugins/keyfile/tests/keyfiles/Test_minimal_slave_2
@@ -0,0 +1,7 @@
+[connection]
+master=br0
+
+[802-3-ethernet]
+
+[bridge-port]
+
diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_minimal_slave_3 b/src/settings/plugins/keyfile/tests/keyfiles/Test_minimal_slave_3
new file mode 100644
index 00000000..7419e97d
--- /dev/null
+++ b/src/settings/plugins/keyfile/tests/keyfiles/Test_minimal_slave_3
@@ -0,0 +1,4 @@
+[connection]
+master=br0
+slave-type=bridge
+[802-3-ethernet]
diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_minimal_slave_4 b/src/settings/plugins/keyfile/tests/keyfiles/Test_minimal_slave_4
new file mode 100644
index 00000000..626b6f68
--- /dev/null
+++ b/src/settings/plugins/keyfile/tests/keyfiles/Test_minimal_slave_4
@@ -0,0 +1,4 @@
+[connection]
+type=802-3-ethernet
+master=br0
+[bridge-port]
diff --git a/src/settings/plugins/keyfile/tests/test-keyfile.c b/src/settings/plugins/keyfile/tests/test-keyfile.c
index cc57c1c3..33e3863c 100644
--- a/src/settings/plugins/keyfile/tests/test-keyfile.c
+++ b/src/settings/plugins/keyfile/tests/test-keyfile.c
@@ -18,29 +18,18 @@
  * Copyright (C) 2008 - 2014 Red Hat, Inc.
  */
 
+#include "config.h"
+
 #include <stdio.h>
 #include <stdarg.h>
 #include <unistd.h>
 #include <string.h>
-#include <netinet/ether.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <sys/socket.h>
-#include <linux/if_infiniband.h>
-
-#include <nm-utils.h>
-#include <nm-setting-connection.h>
-#include <nm-setting-wired.h>
-#include <nm-setting-wireless.h>
-#include <nm-setting-ip4-config.h>
-#include <nm-setting-ip6-config.h>
-#include <nm-setting-bluetooth.h>
-#include <nm-setting-serial.h>
-#include <nm-setting-ppp.h>
-#include <nm-setting-gsm.h>
-#include <nm-setting-8021x.h>
-#include <nm-setting-infiniband.h>
-#include <nm-logging.h>
+
+#include "nm-core-internal.h"
+#include "nm-logging.h"
 
 #include "reader.h"
 #include "writer.h"
@@ -51,69 +40,42 @@
 #define TEST_WIRELESS_FILE TEST_KEYFILES_DIR"/Test_Wireless_Connection"
 
 static void
-check_ip4_address (NMSettingIP4Config *config, int idx, const char *address_str, int plen, const char *gateway_str)
+check_ip_address (NMSettingIPConfig *config, int idx, const char *address, int plen)
 {
-	NMIP4Address *ip4 = nm_setting_ip4_config_get_address (config, idx);
-	guint32 address, gateway;
-
-	g_assert (inet_pton (AF_INET, address_str, &address) == 1);
-	g_assert (inet_pton (AF_INET, gateway_str, &gateway) == 1);
+	NMIPAddress *ip4 = nm_setting_ip_config_get_address (config, idx);
 
 	g_assert (ip4);
-	g_assert (nm_ip4_address_get_address (ip4) == address);
-	g_assert (nm_ip4_address_get_prefix (ip4) == plen);
-	g_assert (nm_ip4_address_get_gateway (ip4) == gateway);
+	g_assert_cmpstr (nm_ip_address_get_address (ip4), ==, address);
+	g_assert_cmpint (nm_ip_address_get_prefix (ip4), ==, plen);
 }
 
 static void
-check_ip6_address (NMSettingIP6Config *config, int idx, const char *address_str, int plen, const char *gateway_str)
+check_ip_route (NMSettingIPConfig *config, int idx, const char *destination, int plen,
+                const char *next_hop, gint64 metric)
 {
-	NMIP6Address *ip6 = nm_setting_ip6_config_get_address (config, idx);
-	struct in6_addr address;
-	struct in6_addr gateway;
+	NMIPRoute *route = nm_setting_ip_config_get_route (config, idx);
 
-	g_assert (inet_pton (AF_INET6, address_str, &address) == 1);
-	g_assert (inet_pton (AF_INET6, gateway_str, &gateway) == 1);
-
-	g_assert (ip6);
-	g_assert (!memcmp (nm_ip6_address_get_address (ip6), &address, sizeof(address)));
-	g_assert (nm_ip6_address_get_prefix (ip6) == plen);
-	g_assert (!memcmp (nm_ip6_address_get_gateway (ip6), &gateway, sizeof(gateway)));
+	g_assert (route);
+	g_assert_cmpstr (nm_ip_route_get_dest (route), ==, destination);
+	g_assert_cmpint (nm_ip_route_get_prefix (route), ==, plen);
+	g_assert_cmpstr (nm_ip_route_get_next_hop (route), ==, next_hop);
+	g_assert_cmpint (nm_ip_route_get_metric (route), ==, metric);
 }
 
-static void
-check_ip4_route (NMSettingIP4Config *config, int idx, const char *destination_str, int plen,
-		const char *nexthop_str, int metric)
+static NMConnection *
+keyfile_read_connection_from_file (const char *filename)
 {
-	NMIP4Route *route = nm_setting_ip4_config_get_route (config, idx);
-	guint32 destination, nexthop;
+	GError *error = NULL;
+	NMConnection *connection;
 
-	g_assert (inet_pton (AF_INET, destination_str, &destination) == 1);
-	g_assert (inet_pton (AF_INET, nexthop_str, &nexthop) == 1);
+	g_assert (filename);
 
-	g_assert (route);
-	g_assert (nm_ip4_route_get_dest (route) == destination);
-	g_assert (nm_ip4_route_get_prefix (route) == plen);
-	g_assert (nm_ip4_route_get_next_hop (route) == nexthop);
-	g_assert (nm_ip4_route_get_metric (route) == metric);
-}
-
-static void
-check_ip6_route (NMSettingIP6Config *config, int idx, const char *destination_str, int plen,
-		const char *next_hop_str, int metric)
-{
-	NMIP6Route *route = nm_setting_ip6_config_get_route (config, idx);
-	struct in6_addr destination;
-	struct in6_addr next_hop;
+	connection = nm_keyfile_plugin_connection_from_file (filename, &error);
+	g_assert_no_error (error);
 
-	g_assert (inet_pton (AF_INET6, destination_str, &destination) == 1);
-	g_assert (inet_pton (AF_INET6, next_hop_str, &next_hop) == 1);
+	nmtst_assert_connection_verifies_without_normalization (connection);
 
-	g_assert (route);
-	g_assert (!memcmp (nm_ip6_route_get_dest (route), &destination, sizeof(destination)));
-	g_assert (nm_ip6_route_get_prefix (route) == plen);
-	g_assert (!memcmp (nm_ip6_route_get_next_hop (route), &next_hop, sizeof(next_hop)));
-	g_assert (nm_ip6_route_get_metric (route) == metric);
+	return connection;
 }
 
 static void
@@ -122,22 +84,16 @@ test_read_valid_wired_connection (void)
 	NMConnection *connection;
 	NMSettingConnection *s_con;
 	NMSettingWired *s_wired;
-	NMSettingIP4Config *s_ip4;
-	NMSettingIP6Config *s_ip6;
+	NMSettingIPConfig *s_ip4;
+	NMSettingIPConfig *s_ip6;
 	GError *error = NULL;
-	const GByteArray *array;
+	const char *mac;
 	char expected_mac_address[ETH_ALEN] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 };
 	const char *tmp;
 	const char *expected_id = "Test Wired Connection";
 	const char *expected_uuid = "4e80a56d-c99f-4aad-a6dd-b449bc398c57";
 	const guint64 expected_timestamp = 6654332;
 	guint64 timestamp;
-	const char *expected_dns1 = "4.2.2.1";
-	const char *expected_dns2 = "4.2.2.2";
-	guint32 addr;
-	struct in6_addr addr6;
-	const char *expected6_dns1 = "1111:dddd::aaaa";
-	const char *expected6_dns2 = "1::cafe";
 	const char *expected6_dnssearch1 = "super-domain.com";
 	const char *expected6_dnssearch2 = "redhat.com";
 	const char *expected6_dnssearch3 = "gnu.org";
@@ -236,18 +192,13 @@ test_read_valid_wired_connection (void)
 	        NM_SETTING_WIRED_SETTING_NAME);
 
 	/* MAC address */
-	array = nm_setting_wired_get_mac_address (s_wired);
-	ASSERT (array != NULL,
+	mac = nm_setting_wired_get_mac_address (s_wired);
+	ASSERT (mac != NULL,
 	        "connection-verify-wired", "failed to verify %s: missing %s / %s key",
 	        TEST_WIRED_FILE,
 	        NM_SETTING_WIRED_SETTING_NAME,
 	        NM_SETTING_WIRED_MAC_ADDRESS);
-	ASSERT (array->len == ETH_ALEN,
-	        "connection-verify-wired", "failed to verify %s: unexpected %s / %s key value length",
-	        TEST_WIRED_FILE,
-	        NM_SETTING_WIRED_SETTING_NAME,
-	        NM_SETTING_WIRED_MAC_ADDRESS);
-	ASSERT (memcmp (array->data, &expected_mac_address[0], sizeof (expected_mac_address)) == 0,
+	ASSERT (nm_utils_hwaddr_matches (mac, -1, expected_mac_address, sizeof (expected_mac_address)),
 	        "connection-verify-wired", "failed to verify %s: unexpected %s / %s key value",
 	        TEST_WIRED_FILE,
 	        NM_SETTING_WIRED_SETTING_NAME,
@@ -268,65 +219,62 @@ test_read_valid_wired_connection (void)
 	        NM_SETTING_IP4_CONFIG_SETTING_NAME);
 
 	/* Method */
-	tmp = nm_setting_ip4_config_get_method (s_ip4);
+	tmp = nm_setting_ip_config_get_method (s_ip4);
 	ASSERT (strcmp (tmp, NM_SETTING_IP4_CONFIG_METHOD_MANUAL) == 0,
 	        "connection-verify-wired", "failed to verify %s: unexpected %s / %s key value",
 	        TEST_WIRED_FILE,
 	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP4_CONFIG_METHOD);
+	        NM_SETTING_IP_CONFIG_METHOD);
 
 	/* DNS Addresses */
-	ASSERT (nm_setting_ip4_config_get_num_dns (s_ip4) == 2,
+	ASSERT (nm_setting_ip_config_get_num_dns (s_ip4) == 2,
 	        "connection-verify-wired", "failed to verify %s: unexpected %s / %s key value",
 	        TEST_WIRED_FILE,
 	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP4_CONFIG_DNS);
+	        NM_SETTING_IP_CONFIG_DNS);
 
-	ASSERT (inet_pton (AF_INET, expected_dns1, &addr) > 0,
-	        "connection-verify-wired", "failed to verify %s: couldn't convert DNS IP address #1",
-	        TEST_WIRED_FILE,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP4_CONFIG_DNS);
-	ASSERT (nm_setting_ip4_config_get_dns (s_ip4, 0) == addr,
+	ASSERT (strcmp (nm_setting_ip_config_get_dns (s_ip4, 0), "4.2.2.1") == 0,
 	        "connection-verify-wired", "failed to verify %s: unexpected %s / %s key value #1",
 	        TEST_WIRED_FILE,
 	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP4_CONFIG_DNS);
+	        NM_SETTING_IP_CONFIG_DNS);
 
-	ASSERT (inet_pton (AF_INET, expected_dns2, &addr) > 0,
-	        "connection-verify-wired", "failed to verify %s: couldn't convert DNS IP address #2",
-	        TEST_WIRED_FILE,
-	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP4_CONFIG_DNS);
-	ASSERT (nm_setting_ip4_config_get_dns (s_ip4, 1) == addr,
+	ASSERT (strcmp (nm_setting_ip_config_get_dns (s_ip4, 1), "4.2.2.2") == 0,
 	        "connection-verify-wired", "failed to verify %s: unexpected %s / %s key value #2",
 	        TEST_WIRED_FILE,
 	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP4_CONFIG_DNS);
+	        NM_SETTING_IP_CONFIG_DNS);
 
 	/* IPv4 addresses */
-	g_assert (nm_setting_ip4_config_get_num_addresses (s_ip4) == 6);
-	check_ip4_address (s_ip4, 0, "2.3.4.5", 24, "2.3.4.6");
-	check_ip4_address (s_ip4, 1, "192.168.0.5", 24, "192.168.0.1");
-	check_ip4_address (s_ip4, 2, "1.2.3.4", 16, "1.2.1.1");
-	check_ip4_address (s_ip4, 3, "3.4.5.6", 16, "0.0.0.0");
-	check_ip4_address (s_ip4, 4, "4.5.6.7", 24, "1.2.3.4");
-	check_ip4_address (s_ip4, 5, "5.6.7.8", 24, "0.0.0.0");
+	g_assert (nm_setting_ip_config_get_num_addresses (s_ip4) == 6);
+	check_ip_address (s_ip4, 0, "2.3.4.5", 24);
+	check_ip_address (s_ip4, 1, "192.168.0.5", 24);
+	check_ip_address (s_ip4, 2, "1.2.3.4", 16);
+	check_ip_address (s_ip4, 3, "3.4.5.6", 16);
+	check_ip_address (s_ip4, 4, "4.5.6.7", 24);
+	check_ip_address (s_ip4, 5, "5.6.7.8", 24);
+
+	/* IPv4 gateway */
+	ASSERT (strcmp (nm_setting_ip_config_get_gateway (s_ip4), "2.3.4.6") == 0,
+	        "connection-verify-wired", "failed to verify %s: unexpected %s / %s key value",
+	        TEST_WIRED_FILE,
+	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
+	        NM_SETTING_IP_CONFIG_GATEWAY);
 
 	/* IPv4 routes */
-	g_assert (nm_setting_ip4_config_get_num_routes (s_ip4) == 12);
-	check_ip4_route (s_ip4, 0, "5.6.7.8", 32, "0.0.0.0", 0);
-	check_ip4_route (s_ip4, 1, "1.2.3.0", 24, "2.3.4.8", 99);
-	check_ip4_route (s_ip4, 2, "1.1.1.2", 12, "0.0.0.0", 0);
-	check_ip4_route (s_ip4, 3, "1.1.1.3", 13, "0.0.0.0", 0);
-	check_ip4_route (s_ip4, 4, "1.1.1.4", 14, "2.2.2.4", 0);
-	check_ip4_route (s_ip4, 5, "1.1.1.5", 15, "2.2.2.5", 0);
-	check_ip4_route (s_ip4, 6, "1.1.1.6", 16, "2.2.2.6", 0);
-	check_ip4_route (s_ip4, 7, "1.1.1.7", 17, "0.0.0.0", 0);
-	check_ip4_route (s_ip4, 8, "1.1.1.8", 18, "0.0.0.0", 0);
-	check_ip4_route (s_ip4, 9, "1.1.1.9", 19, "0.0.0.0", 0);
-	check_ip4_route (s_ip4, 10, "1.1.1.10", 20, "0.0.0.0", 0);
-	check_ip4_route (s_ip4, 11, "1.1.1.11", 21, "0.0.0.0", 21);
+	g_assert (nm_setting_ip_config_get_num_routes (s_ip4) == 12);
+	check_ip_route (s_ip4, 0, "5.6.7.8", 32, NULL, -1);
+	check_ip_route (s_ip4, 1, "1.2.3.0", 24, "2.3.4.8", 99);
+	check_ip_route (s_ip4, 2, "1.1.1.2", 12, NULL, -1);
+	check_ip_route (s_ip4, 3, "1.1.1.3", 13, NULL, -1);
+	check_ip_route (s_ip4, 4, "1.1.1.4", 14, "2.2.2.4", -1);
+	check_ip_route (s_ip4, 5, "1.1.1.5", 15, "2.2.2.5", -1);
+	check_ip_route (s_ip4, 6, "1.1.1.6", 16, "2.2.2.6", -1);
+	check_ip_route (s_ip4, 7, "1.1.1.7", 17, NULL, -1);
+	check_ip_route (s_ip4, 8, "1.1.1.8", 18, NULL, -1);
+	check_ip_route (s_ip4, 9, "1.1.1.9", 19, NULL, -1);
+	check_ip_route (s_ip4, 10, "1.1.1.10", 20, NULL, -1);
+	check_ip_route (s_ip4, 11, "1.1.1.11", 21, NULL, 21);
 
 	/* ===== IPv6 SETTING ===== */
 
@@ -337,182 +285,118 @@ test_read_valid_wired_connection (void)
 	        NM_SETTING_IP6_CONFIG_SETTING_NAME);
 
 	/* Method */
-	tmp = nm_setting_ip6_config_get_method (s_ip6);
+	tmp = nm_setting_ip_config_get_method (s_ip6);
 	ASSERT (strcmp (tmp, NM_SETTING_IP6_CONFIG_METHOD_MANUAL) == 0,
 	        "connection-verify-wired", "failed to verify %s: unexpected %s / %s key value",
 	        TEST_WIRED_FILE,
 	        NM_SETTING_IP6_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP6_CONFIG_METHOD);
+	        NM_SETTING_IP_CONFIG_METHOD);
 
 	/* DNS Addresses */
-	ASSERT (nm_setting_ip6_config_get_num_dns (s_ip6) == 2,
+	ASSERT (nm_setting_ip_config_get_num_dns (s_ip6) == 2,
 	        "connection-verify-wired", "failed to verify %s: unexpected %s / %s key value",
 	        TEST_WIRED_FILE,
 	        NM_SETTING_IP6_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP6_CONFIG_DNS);
+	        NM_SETTING_IP_CONFIG_DNS);
 
-	ASSERT (inet_pton (AF_INET6, expected6_dns1, &addr6) > 0,
-	        "connection-verify-wired", "failed to verify %s: couldn't convert DNS IP6 address #1",
-	        TEST_WIRED_FILE,
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP6_CONFIG_DNS);
-	ASSERT (IN6_ARE_ADDR_EQUAL (nm_setting_ip6_config_get_dns (s_ip6, 0), &addr6),
+	ASSERT (strcmp (nm_setting_ip_config_get_dns (s_ip6, 0), "1111:dddd::aaaa") == 0,
 	        "connection-verify-wired", "failed to verify %s: unexpected %s / %s key value #1",
 	        TEST_WIRED_FILE,
 	        NM_SETTING_IP6_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP6_CONFIG_DNS);
+	        NM_SETTING_IP_CONFIG_DNS);
 
-	ASSERT (inet_pton (AF_INET6, expected6_dns2, &addr6) > 0,
-	        "connection-verify-wired", "failed to verify %s: couldn't convert DNS IP address #2",
-	        TEST_WIRED_FILE,
-	        NM_SETTING_IP6_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP6_CONFIG_DNS);
-	ASSERT (IN6_ARE_ADDR_EQUAL (nm_setting_ip6_config_get_dns (s_ip6, 1), &addr6),
+	ASSERT (strcmp (nm_setting_ip_config_get_dns (s_ip6, 1), "1::cafe") == 0,
 	        "connection-verify-wired", "failed to verify %s: unexpected %s / %s key value #2",
 	        TEST_WIRED_FILE,
 	        NM_SETTING_IP6_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP6_CONFIG_DNS);
+	        NM_SETTING_IP_CONFIG_DNS);
 
 	/* DNS Searches */
-	ASSERT (nm_setting_ip6_config_get_num_dns_searches (s_ip6) == 3,
+	ASSERT (nm_setting_ip_config_get_num_dns_searches (s_ip6) == 3,
 	        "connection-verify-wired", "failed to verify %s: unexpected %s / %s key value",
 	        TEST_WIRED_FILE,
 	        NM_SETTING_IP6_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP6_CONFIG_DNS_SEARCH);
+	        NM_SETTING_IP_CONFIG_DNS_SEARCH);
 
-	ASSERT (!strcmp (nm_setting_ip6_config_get_dns_search (s_ip6, 0), expected6_dnssearch1),
+	ASSERT (!strcmp (nm_setting_ip_config_get_dns_search (s_ip6, 0), expected6_dnssearch1),
 	        "connection-verify-wired", "failed to verify %s: unexpected %s / %s key value #1",
 	        TEST_WIRED_FILE,
 	        NM_SETTING_IP6_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP6_CONFIG_DNS_SEARCH);
-	ASSERT (!strcmp (nm_setting_ip6_config_get_dns_search (s_ip6, 1), expected6_dnssearch2),
+	        NM_SETTING_IP_CONFIG_DNS_SEARCH);
+	ASSERT (!strcmp (nm_setting_ip_config_get_dns_search (s_ip6, 1), expected6_dnssearch2),
 	        "connection-verify-wired", "failed to verify %s: unexpected %s / %s key value #2",
 	        TEST_WIRED_FILE,
 	        NM_SETTING_IP6_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP6_CONFIG_DNS_SEARCH);
-	ASSERT (!strcmp (nm_setting_ip6_config_get_dns_search (s_ip6, 2), expected6_dnssearch3),
+	        NM_SETTING_IP_CONFIG_DNS_SEARCH);
+	ASSERT (!strcmp (nm_setting_ip_config_get_dns_search (s_ip6, 2), expected6_dnssearch3),
 	        "connection-verify-wired", "failed to verify %s: unexpected %s / %s key value #3",
 	        TEST_WIRED_FILE,
 	        NM_SETTING_IP6_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP6_CONFIG_DNS_SEARCH);
+	        NM_SETTING_IP_CONFIG_DNS_SEARCH);
 
 	/* IPv6 addresses */
-	g_assert (nm_setting_ip6_config_get_num_addresses (s_ip6) == 10);
-	check_ip6_address (s_ip6, 0, "2:3:4:5:6:7:8:9", 64, "2:3:4:5:1:2:3:4");
-	check_ip6_address (s_ip6, 1, "abcd:1234:ffff::cdde", 64, "::");
-	check_ip6_address (s_ip6, 2, "1:2:3:4:5:6:7:8", 96, "::");
-	check_ip6_address (s_ip6, 3, "3:4:5:6:7:8:9:0", 128, "::");
-	check_ip6_address (s_ip6, 4, "3:4:5:6:7:8:9:14", 64, "::");
-	check_ip6_address (s_ip6, 5, "3:4:5:6:7:8:9:15", 64, "::");
-	check_ip6_address (s_ip6, 6, "3:4:5:6:7:8:9:16", 66, "::");
-	check_ip6_address (s_ip6, 7, "3:4:5:6:7:8:9:17", 67, "::");
-	check_ip6_address (s_ip6, 8, "3:4:5:6:7:8:9:18", 68, "::");
-	check_ip6_address (s_ip6, 9, "3:4:5:6:7:8:9:19", 69, "1::09");
+	g_assert (nm_setting_ip_config_get_num_addresses (s_ip6) == 10);
+	check_ip_address (s_ip6, 0, "2:3:4:5:6:7:8:9", 64);
+	check_ip_address (s_ip6, 1, "abcd:1234:ffff::cdde", 64);
+	check_ip_address (s_ip6, 2, "1:2:3:4:5:6:7:8", 96);
+	check_ip_address (s_ip6, 3, "3:4:5:6:7:8:9:0", 128);
+	check_ip_address (s_ip6, 4, "3:4:5:6:7:8:9:14", 64);
+	check_ip_address (s_ip6, 5, "3:4:5:6:7:8:9:15", 64);
+	check_ip_address (s_ip6, 6, "3:4:5:6:7:8:9:16", 66);
+	check_ip_address (s_ip6, 7, "3:4:5:6:7:8:9:17", 67);
+	check_ip_address (s_ip6, 8, "3:4:5:6:7:8:9:18", 68);
+	check_ip_address (s_ip6, 9, "3:4:5:6:7:8:9:19", 69);
+
+	/* IPv6 gateway */
+	ASSERT (strcmp (nm_setting_ip_config_get_gateway (s_ip6), "2:3:4:5:1:2:3:4") == 0,
+	        "connection-verify-wired", "failed to verify %s: unexpected %s / %s key value",
+	        TEST_WIRED_FILE,
+	        NM_SETTING_IP6_CONFIG_SETTING_NAME,
+	        NM_SETTING_IP_CONFIG_GATEWAY);
 
 	/* Route #1 */
-	g_assert (nm_setting_ip6_config_get_num_routes (s_ip6) == 7);
-	check_ip6_route (s_ip6, 0, "d:e:f:0:1:2:3:4", 64, "f:e:d:c:1:2:3:4", 0);
-	check_ip6_route (s_ip6, 1, "a:b:c:d::", 64, "f:e:d:c:1:2:3:4", 99);
-	check_ip6_route (s_ip6, 2, "8:7:6:5:4:3:2:1", 128, "::", 0);
-	check_ip6_route (s_ip6, 3, "6:7:8:9:0:1:2:3", 126, "::", 1);
-	check_ip6_route (s_ip6, 4, "7:8:9:0:1:2:3:4", 125, "::", 5);
-	check_ip6_route (s_ip6, 5, "8:9:0:1:2:3:4:5", 124, "::", 6);
-	check_ip6_route (s_ip6, 6, "8:9:0:1:2:3:4:6", 123, "::", 0);
+	g_assert (nm_setting_ip_config_get_num_routes (s_ip6) == 7);
+	check_ip_route (s_ip6, 0, "d:e:f:0:1:2:3:4", 64, "f:e:d:c:1:2:3:4", -1);
+	check_ip_route (s_ip6, 1, "a:b:c:d::", 64, "f:e:d:c:1:2:3:4", 99);
+	check_ip_route (s_ip6, 2, "8:7:6:5:4:3:2:1", 128, NULL, -1);
+	check_ip_route (s_ip6, 3, "6:7:8:9:0:1:2:3", 126, NULL, 1);
+	check_ip_route (s_ip6, 4, "7:8:9:0:1:2:3:4", 125, NULL, 5);
+	check_ip_route (s_ip6, 5, "8:9:0:1:2:3:4:5", 124, NULL, 6);
+	check_ip_route (s_ip6, 6, "8:9:0:1:2:3:4:6", 123, NULL, -1);
 	g_object_unref (connection);
 }
 
 static void
-add_one_ip4_address (NMSettingIP4Config *s_ip4,
-                     const char *addr,
-                     const char *gw,
-                     guint32 prefix)
+add_one_ip_address (NMSettingIPConfig *s_ip,
+                    const char *addr,
+                    guint32 prefix)
 {
-	guint32 tmp;
-	NMIP4Address *ip4_addr;
-
-	ip4_addr = nm_ip4_address_new ();
-	nm_ip4_address_set_prefix (ip4_addr, prefix);
-
-	inet_pton (AF_INET, addr, &tmp);
-	nm_ip4_address_set_address (ip4_addr, tmp);
-
-	inet_pton (AF_INET, gw, &tmp);
-	nm_ip4_address_set_gateway (ip4_addr, tmp);
-
-	nm_setting_ip4_config_add_address (s_ip4, ip4_addr);
-	nm_ip4_address_unref (ip4_addr);
-}
-
-static void
-add_one_ip4_route (NMSettingIP4Config *s_ip4,
-                   const char *dest,
-                   const char *nh,
-                   guint32 prefix,
-                   guint32 metric)
-{
-	guint32 addr;
-	NMIP4Route *route;
-
-	route = nm_ip4_route_new ();
-	nm_ip4_route_set_prefix (route, prefix);
-	nm_ip4_route_set_metric (route, metric);
-
-	inet_pton (AF_INET, dest, &addr);
-	nm_ip4_route_set_dest (route, addr);
-
-	inet_pton (AF_INET, nh, &addr);
-	nm_ip4_route_set_next_hop (route, addr);
-
-	nm_setting_ip4_config_add_route (s_ip4, route);
-	nm_ip4_route_unref (route);
-}
-
-static void
-add_one_ip6_address (NMSettingIP6Config *s_ip6,
-                     const char *addr,
-                     guint32 prefix,
-                     const char *gw)
-{
-	struct in6_addr tmp;
-	NMIP6Address *ip6_addr;
-
-	ip6_addr = nm_ip6_address_new ();
-	nm_ip6_address_set_prefix (ip6_addr, prefix);
-
-	inet_pton (AF_INET6, addr, &tmp);
-	nm_ip6_address_set_address (ip6_addr, &tmp);
-
-	if (gw) {
-		inet_pton (AF_INET6, gw, &tmp);
-		nm_ip6_address_set_gateway (ip6_addr, &tmp);
-	}
+	NMIPAddress *ip_addr;
+	GError *error = NULL;
 
-	nm_setting_ip6_config_add_address (s_ip6, ip6_addr);
-	nm_ip6_address_unref (ip6_addr);
+	ip_addr = nm_ip_address_new (NM_IS_SETTING_IP4_CONFIG (s_ip) ? AF_INET : AF_INET6,
+	                             addr, prefix, &error);
+	g_assert_no_error (error);
+	nm_setting_ip_config_add_address (s_ip, ip_addr);
+	nm_ip_address_unref (ip_addr);
 }
 
 static void
-add_one_ip6_route (NMSettingIP6Config *s_ip6,
-                   const char *dest,
-                   const char *nh,
-                   guint32 prefix,
-                   guint32 metric)
+add_one_ip_route (NMSettingIPConfig *s_ip,
+                  const char *dest,
+                  const char *nh,
+                  guint32 prefix,
+                  gint64 metric)
 {
-	struct in6_addr addr;
-	NMIP6Route *route;
-
-	route = nm_ip6_route_new ();
-	nm_ip6_route_set_prefix (route, prefix);
-	nm_ip6_route_set_metric (route, metric);
-
-	inet_pton (AF_INET6, dest, &addr);
-	nm_ip6_route_set_dest (route, &addr);
-
-	inet_pton (AF_INET6, nh, &addr);
-	nm_ip6_route_set_next_hop (route, &addr);
+	NMIPRoute *route;
+	GError *error = NULL;
 
-	nm_setting_ip6_config_add_route (s_ip6, route);
-	nm_ip6_route_unref (route);
+	g_assert (prefix > 0);
+	route = nm_ip_route_new (NM_IS_SETTING_IP4_CONFIG (s_ip) ? AF_INET : AF_INET6,
+	                         dest, prefix, nh, metric, &error);
+	g_assert_no_error (error);
+	nm_setting_ip_config_add_route (s_ip, route);
+	nm_ip_route_unref (route);
 }
 
 
@@ -522,33 +406,29 @@ test_write_wired_connection (void)
 	NMConnection *connection;
 	NMSettingConnection *s_con;
 	NMSettingWired *s_wired;
-	NMSettingIP4Config *s_ip4;
-	NMSettingIP6Config *s_ip6;
+	NMSettingIPConfig *s_ip4;
+	NMSettingIPConfig *s_ip6;
 	char *uuid;
-	GByteArray *mac;
-	unsigned char tmpmac[] = { 0x99, 0x88, 0x77, 0x66, 0x55, 0x44 };
+	const char *mac = "99:88:77:66:55:44";
 	gboolean success;
 	NMConnection *reread;
 	char *testfile = NULL;
 	GError *error = NULL;
 	pid_t owner_grp;
 	uid_t owner_uid;
-	guint32 addr;
-	struct in6_addr addr6;
 	const char *dns1 = "4.2.2.1";
 	const char *dns2 = "4.2.2.2";
 	const char *address1 = "192.168.0.5";
-	const char *address1_gw = "192.168.0.1";
 	const char *address2 = "1.2.3.4";
-	const char *address2_gw = "1.2.1.1";
+	const char *gw = "192.168.0.1";
 	const char *route1 = "10.10.10.2";
 	const char *route1_nh = "10.10.10.1";
 	const char *route2 = "1.1.1.1";
 	const char *route2_nh = "1.2.1.1";
 	const char *route3 = "2.2.2.2";
-	const char *route3_nh = "0.0.0.0";
+	const char *route3_nh = NULL;
 	const char *route4 = "3.3.3.3";
-	const char *route4_nh = "0.0.0.0";
+	const char *route4_nh = NULL;
 	const char *dns6_1 = "1::cafe";
 	const char *dns6_2 = "2::cafe";
 	const char *address6_1 = "abcd::beef";
@@ -563,7 +443,7 @@ test_write_wired_connection (void)
 	const char *route6_4_nh = "::";
 	guint64 timestamp = 0x12345678L;
 
-	connection = nm_connection_new ();
+	connection = nm_simple_connection_new ();
 
 	/* Connection setting */
 
@@ -585,66 +465,60 @@ test_write_wired_connection (void)
 	s_wired = NM_SETTING_WIRED (nm_setting_wired_new ());
 	nm_connection_add_setting (connection, NM_SETTING (s_wired));
 
-	mac = g_byte_array_sized_new (ETH_ALEN);
-	g_byte_array_append (mac, &tmpmac[0], sizeof (tmpmac));
 	g_object_set (s_wired,
 	              NM_SETTING_WIRED_MAC_ADDRESS, mac,
 	              NM_SETTING_WIRED_MTU, 900,
 	              NULL);
-	g_byte_array_free (mac, TRUE);
 
 	/* IP4 setting */
 
-	s_ip4 = NM_SETTING_IP4_CONFIG (nm_setting_ip4_config_new ());
+	s_ip4 = NM_SETTING_IP_CONFIG (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_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL,
+	              NM_SETTING_IP_CONFIG_GATEWAY, gw,
 	              NULL);
 
 	/* Addresses */
-	add_one_ip4_address (s_ip4, address1, address1_gw, 24);
-	add_one_ip4_address (s_ip4, address2, address2_gw, 8);
+	add_one_ip_address (s_ip4, address1, 24);
+	add_one_ip_address (s_ip4, address2, 8);
 
 	/* Routes */
-	add_one_ip4_route (s_ip4, route1, route1_nh, 24, 3);
-	add_one_ip4_route (s_ip4, route2, route2_nh, 8, 1);
-	add_one_ip4_route (s_ip4, route3, route3_nh, 7, 0);
-	add_one_ip4_route (s_ip4, route4, route4_nh, 6, 4);
+	add_one_ip_route (s_ip4, route1, route1_nh, 24, 3);
+	add_one_ip_route (s_ip4, route2, route2_nh, 8, 1);
+	add_one_ip_route (s_ip4, route3, route3_nh, 7, -1);
+	add_one_ip_route (s_ip4, route4, route4_nh, 6, 4);
 
 	/* DNS servers */
-	inet_pton (AF_INET, dns1, &addr);
-	nm_setting_ip4_config_add_dns (s_ip4, addr);
-	inet_pton (AF_INET, dns2, &addr);
-	nm_setting_ip4_config_add_dns (s_ip4, addr);
+	nm_setting_ip_config_add_dns (s_ip4, dns1);
+	nm_setting_ip_config_add_dns (s_ip4, dns2);
 
 	/* IP6 setting */
 
-	s_ip6 = NM_SETTING_IP6_CONFIG (nm_setting_ip6_config_new ());
+	s_ip6 = NM_SETTING_IP_CONFIG (nm_setting_ip6_config_new ());
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
 
 	g_object_set (s_ip6,
-	              NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_MANUAL,
+	              NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_MANUAL,
 	              NULL);
 
 	/* Addresses */
-	add_one_ip6_address (s_ip6, address6_1, 64, NULL);
-	add_one_ip6_address (s_ip6, address6_2, 56, NULL);
+	add_one_ip_address (s_ip6, address6_1, 64);
+	add_one_ip_address (s_ip6, address6_2, 56);
 
 	/* Routes */
-	add_one_ip6_route (s_ip6, route6_1, route6_1_nh, 64, 3);
-	add_one_ip6_route (s_ip6, route6_2, route6_2_nh, 56, 1);
-	add_one_ip6_route (s_ip6, route6_3, route6_3_nh, 63, 5);
-	add_one_ip6_route (s_ip6, route6_4, route6_4_nh, 62, 0);
+	add_one_ip_route (s_ip6, route6_1, route6_1_nh, 64, 3);
+	add_one_ip_route (s_ip6, route6_2, route6_2_nh, 56, 1);
+	add_one_ip_route (s_ip6, route6_3, route6_3_nh, 63, 5);
+	add_one_ip_route (s_ip6, route6_4, route6_4_nh, 62, -1);
 
 	/* DNS servers */
-	inet_pton (AF_INET6, dns6_1, &addr6);
-	nm_setting_ip6_config_add_dns (s_ip6, &addr6);
-	inet_pton (AF_INET6, dns6_2, &addr6);
-	nm_setting_ip6_config_add_dns (s_ip6, &addr6);
+	nm_setting_ip_config_add_dns (s_ip6, dns6_1);
+	nm_setting_ip_config_add_dns (s_ip6, dns6_2);
 
 	/* DNS searches */
-	nm_setting_ip6_config_add_dns_search (s_ip6, "wallaceandgromit.com");
+	nm_setting_ip_config_add_dns_search (s_ip6, "wallaceandgromit.com");
 
 	/* Write out the connection */
 	owner_uid = geteuid ();
@@ -680,8 +554,8 @@ test_read_ip6_wired_connection (void)
 	NMConnection *connection;
 	NMSettingConnection *s_con;
 	NMSettingWired *s_wired;
-	NMSettingIP4Config *s_ip4;
-	NMSettingIP6Config *s_ip6;
+	NMSettingIPConfig *s_ip4;
+	NMSettingIPConfig *s_ip6;
 	GError *error = NULL;
 	const char *tmp;
 	const char *expected_id = "Test Wired Connection IP6";
@@ -745,18 +619,18 @@ test_read_ip6_wired_connection (void)
 	        NM_SETTING_IP4_CONFIG_SETTING_NAME);
 
 	/* Method */
-	tmp = nm_setting_ip4_config_get_method (s_ip4);
+	tmp = nm_setting_ip_config_get_method (s_ip4);
 	ASSERT (strcmp (tmp, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) == 0,
 	        "connection-verify-wired", "failed to verify %s: unexpected %s / %s key value",
 	        TEST_WIRED_IP6_FILE,
 	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP4_CONFIG_METHOD);
+	        NM_SETTING_IP_CONFIG_METHOD);
 
-	ASSERT (nm_setting_ip4_config_get_num_addresses (s_ip4) == 0,
+	ASSERT (nm_setting_ip_config_get_num_addresses (s_ip4) == 0,
 	        "connection-verify-wired", "failed to verify %s: unexpected %s / %s key value",
 	        TEST_WIRED_IP6_FILE,
 	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP4_CONFIG_DNS);
+	        NM_SETTING_IP_CONFIG_DNS);
 
 	/* ===== IPv6 SETTING ===== */
 
@@ -767,16 +641,23 @@ test_read_ip6_wired_connection (void)
 	        NM_SETTING_IP6_CONFIG_SETTING_NAME);
 
 	/* Method */
-	tmp = nm_setting_ip6_config_get_method (s_ip6);
+	tmp = nm_setting_ip_config_get_method (s_ip6);
 	ASSERT (strcmp (tmp, NM_SETTING_IP6_CONFIG_METHOD_MANUAL) == 0,
 	        "connection-verify-wired", "failed to verify %s: unexpected %s / %s key value",
 	        TEST_WIRED_IP6_FILE,
 	        NM_SETTING_IP6_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP6_CONFIG_METHOD);
+	        NM_SETTING_IP_CONFIG_METHOD);
 
 	/* IPv6 address */
-	g_assert (nm_setting_ip6_config_get_num_addresses (s_ip6) == 1);
-	check_ip6_address (s_ip6, 0, "abcd:1234:ffff::cdde", 64, "abcd:1234:ffff::cdd1");
+	g_assert (nm_setting_ip_config_get_num_addresses (s_ip6) == 1);
+	check_ip_address (s_ip6, 0, "abcd:1234:ffff::cdde", 64);
+
+	/* IPv6 gateway */
+	ASSERT (strcmp (nm_setting_ip_config_get_gateway (s_ip6), "abcd:1234:ffff::cdd1") == 0,
+	        "connection-verify-wired", "failed to verify %s: unexpected %s / %s key value",
+	        TEST_WIRED_IP6_FILE,
+	        NM_SETTING_IP6_CONFIG_SETTING_NAME,
+	        NM_SETTING_IP_CONFIG_GATEWAY);
 
 	g_object_unref (connection);
 }
@@ -787,8 +668,8 @@ test_write_ip6_wired_connection (void)
 	NMConnection *connection;
 	NMSettingConnection *s_con;
 	NMSettingWired *s_wired;
-	NMSettingIP4Config *s_ip4;
-	NMSettingIP6Config *s_ip6;
+	NMSettingIPConfig *s_ip4;
+	NMSettingIPConfig *s_ip6;
 	char *uuid;
 	gboolean success;
 	NMConnection *reread;
@@ -796,12 +677,11 @@ test_write_ip6_wired_connection (void)
 	GError *error = NULL;
 	pid_t owner_grp;
 	uid_t owner_uid;
-	struct in6_addr addr6;
 	const char *dns = "1::cafe";
 	const char *address = "abcd::beef";
 	const char *gw = "dcba::beef";
 
-	connection = nm_connection_new ();
+	connection = nm_simple_connection_new ();
 
 	/* Connection setting */
 
@@ -824,31 +704,31 @@ test_write_ip6_wired_connection (void)
 
 	/* IP4 setting */
 
-	s_ip4 = NM_SETTING_IP4_CONFIG (nm_setting_ip4_config_new ());
+	s_ip4 = NM_SETTING_IP_CONFIG (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_DISABLED,
+	              NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_DISABLED,
 	              NULL);
 
 	/* IP6 setting */
 
-	s_ip6 = NM_SETTING_IP6_CONFIG (nm_setting_ip6_config_new ());
+	s_ip6 = NM_SETTING_IP_CONFIG (nm_setting_ip6_config_new ());
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
 
 	g_object_set (s_ip6,
-	              NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_MANUAL,
+	              NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_MANUAL,
+	              NM_SETTING_IP_CONFIG_GATEWAY, gw,
 	              NULL);
 
 	/* Addresses */
-	add_one_ip6_address (s_ip6, address, 64, gw);
+	add_one_ip_address (s_ip6, address, 64);
 
 	/* DNS servers */
-	inet_pton (AF_INET6, dns, &addr6);
-	nm_setting_ip6_config_add_dns (s_ip6, &addr6);
+	nm_setting_ip_config_add_dns (s_ip6, dns);
 
 	/* DNS searches */
-	nm_setting_ip6_config_add_dns_search (s_ip6, "wallaceandgromit.com");
+	nm_setting_ip_config_add_dns_search (s_ip6, "wallaceandgromit.com");
 
 	/* Write out the connection */
 	owner_uid = geteuid ();
@@ -885,7 +765,7 @@ test_read_wired_mac_case (void)
 	NMSettingConnection *s_con;
 	NMSettingWired *s_wired;
 	GError *error = NULL;
-	const GByteArray *array;
+	const char *mac;
 	char expected_mac_address[ETH_ALEN] = { 0x00, 0x11, 0xaa, 0xbb, 0xcc, 0x55 };
 	const char *tmp;
 	const char *expected_id = "Test Wired Connection MAC Case";
@@ -948,18 +828,13 @@ test_read_wired_mac_case (void)
 	        NM_SETTING_WIRED_SETTING_NAME);
 
 	/* MAC address */
-	array = nm_setting_wired_get_mac_address (s_wired);
-	ASSERT (array != NULL,
+	mac = nm_setting_wired_get_mac_address (s_wired);
+	ASSERT (mac != NULL,
 	        "connection-verify-wired", "failed to verify %s: missing %s / %s key",
 	        TEST_WIRED_MAC_CASE_FILE,
 	        NM_SETTING_WIRED_SETTING_NAME,
 	        NM_SETTING_WIRED_MAC_ADDRESS);
-	ASSERT (array->len == ETH_ALEN,
-	        "connection-verify-wired", "failed to verify %s: unexpected %s / %s key value length",
-	        TEST_WIRED_MAC_CASE_FILE,
-	        NM_SETTING_WIRED_SETTING_NAME,
-	        NM_SETTING_WIRED_MAC_ADDRESS);
-	ASSERT (memcmp (array->data, &expected_mac_address[0], sizeof (expected_mac_address)) == 0,
+	ASSERT (nm_utils_hwaddr_matches (mac, -1, expected_mac_address, sizeof (expected_mac_address)),
 	        "connection-verify-wired", "failed to verify %s: unexpected %s / %s key value",
 	        TEST_WIRED_MAC_CASE_FILE,
 	        NM_SETTING_WIRED_SETTING_NAME,
@@ -977,7 +852,7 @@ test_read_mac_old_format (void)
 	NMSettingWired *s_wired;
 	GError *error = NULL;
 	gboolean success;
-	const GByteArray *array;
+	const char *mac;
 	char expected_mac[ETH_ALEN] = { 0x00, 0x11, 0xaa, 0xbb, 0xcc, 0x55 };
 	char expected_cloned_mac[ETH_ALEN] = { 0x00, 0x16, 0xaa, 0xbb, 0xcc, 0xfe };
 
@@ -993,16 +868,14 @@ test_read_mac_old_format (void)
 	g_assert (s_wired);
 
 	/* MAC address */
-	array = nm_setting_wired_get_mac_address (s_wired);
-	g_assert (array);
-	g_assert_cmpint (array->len, ==, ETH_ALEN);
-	g_assert (memcmp (array->data, expected_mac, ETH_ALEN) == 0);
+	mac = nm_setting_wired_get_mac_address (s_wired);
+	g_assert (mac);
+	g_assert (nm_utils_hwaddr_matches (mac, -1, expected_mac, ETH_ALEN));
 
 	/* Cloned MAC address */
-	array = nm_setting_wired_get_cloned_mac_address (s_wired);
-	g_assert (array);
-	g_assert_cmpint (array->len, ==, ETH_ALEN);
-	g_assert (memcmp (array->data, expected_cloned_mac, ETH_ALEN) == 0);
+	mac = nm_setting_wired_get_cloned_mac_address (s_wired);
+	g_assert (mac);
+	g_assert (nm_utils_hwaddr_matches (mac, -1, expected_cloned_mac, ETH_ALEN));
 
 	g_object_unref (connection);
 }
@@ -1016,7 +889,7 @@ test_read_mac_ib_old_format (void)
 	NMSettingInfiniband *s_ib;
 	GError *error = NULL;
 	gboolean success;
-	const GByteArray *array;
+	const char *mac;
 	guint8 expected_mac[INFINIBAND_ALEN] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
 		0x77, 0x88, 0x99, 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, 0x89,
 		0x90 };
@@ -1033,10 +906,9 @@ test_read_mac_ib_old_format (void)
 	g_assert (s_ib);
 
 	/* MAC address */
-	array = nm_setting_infiniband_get_mac_address (s_ib);
-	g_assert (array);
-	g_assert_cmpint (array->len, ==, INFINIBAND_ALEN);
-	g_assert_cmpint (memcmp (array->data, expected_mac, sizeof (expected_mac)), ==, 0);
+	mac = nm_setting_infiniband_get_mac_address (s_ib);
+	g_assert (mac);
+	g_assert (nm_utils_hwaddr_matches (mac, -1, expected_mac, sizeof (expected_mac)));
 
 	g_object_unref (connection);
 }
@@ -1047,10 +919,10 @@ test_read_valid_wireless_connection (void)
 	NMConnection *connection;
 	NMSettingConnection *s_con;
 	NMSettingWireless *s_wireless;
-	NMSettingIP4Config *s_ip4;
+	NMSettingIPConfig *s_ip4;
 	GError *error = NULL;
-	const GByteArray *array;
-	char expected_bssid[ETH_ALEN] = { 0x00, 0x1a, 0x33, 0x44, 0x99, 0x82 };
+	const char *bssid;
+	const guint8 expected_bssid[ETH_ALEN] = { 0x00, 0x1a, 0x33, 0x44, 0x99, 0x82 };
 	const char *tmp;
 	const char *expected_id = "Test Wireless Connection";
 	const char *expected_uuid = "2f962388-e5f3-45af-a62c-ac220b8f7baa";
@@ -1122,18 +994,13 @@ test_read_valid_wireless_connection (void)
 	        NM_SETTING_WIRED_SETTING_NAME);
 
 	/* BSSID */
-	array = nm_setting_wireless_get_bssid (s_wireless);
-	ASSERT (array != NULL,
+	bssid = nm_setting_wireless_get_bssid (s_wireless);
+	ASSERT (bssid != NULL,
 	        "connection-verify-wireless", "failed to verify %s: missing %s / %s key",
 	        TEST_WIRELESS_FILE,
 	        NM_SETTING_WIRELESS_SETTING_NAME,
 	        NM_SETTING_WIRELESS_BSSID);
-	ASSERT (array->len == ETH_ALEN,
-	        "connection-verify-wireless", "failed to verify %s: unexpected %s / %s key value length",
-	        TEST_WIRELESS_FILE,
-	        NM_SETTING_WIRELESS_SETTING_NAME,
-	        NM_SETTING_WIRELESS_BSSID);
-	ASSERT (memcmp (array->data, &expected_bssid[0], sizeof (expected_bssid)) == 0,
+	ASSERT (nm_utils_hwaddr_matches (bssid, -1, expected_bssid, sizeof (expected_bssid)),
 	        "connection-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
 	        TEST_WIRELESS_FILE,
 	        NM_SETTING_WIRELESS_SETTING_NAME,
@@ -1148,12 +1015,12 @@ test_read_valid_wireless_connection (void)
 	        NM_SETTING_IP4_CONFIG_SETTING_NAME);
 
 	/* Method */
-	tmp = nm_setting_ip4_config_get_method (s_ip4);
+	tmp = nm_setting_ip_config_get_method (s_ip4);
 	ASSERT (strcmp (tmp, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0,
 	        "connection-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
 	        TEST_WIRELESS_FILE,
 	        NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	        NM_SETTING_IP4_CONFIG_METHOD);
+	        NM_SETTING_IP_CONFIG_METHOD);
 
 	g_object_unref (connection);
 }
@@ -1164,12 +1031,11 @@ test_write_wireless_connection (void)
 	NMConnection *connection;
 	NMSettingConnection *s_con;
 	NMSettingWireless *s_wireless;
-	NMSettingIP4Config *s_ip4;
-	NMSettingIP6Config *s_ip6;
+	NMSettingIPConfig *s_ip4;
+	NMSettingIPConfig *s_ip6;
 	char *uuid;
-	GByteArray *bssid;
-	unsigned char tmpbssid[] = { 0xaa, 0xb9, 0xa1, 0x74, 0x55, 0x44 };
-	GByteArray *ssid;
+	const char *bssid = "aa:b9:a1:74:55:44";
+	GBytes *ssid;
 	unsigned char tmpssid[] = { 0x31, 0x33, 0x33, 0x37 };
 	gboolean success;
 	NMConnection *reread;
@@ -1179,7 +1045,7 @@ test_write_wireless_connection (void)
 	uid_t owner_uid;
 	guint64 timestamp = 0x12344433L;
 
-	connection = nm_connection_new ();
+	connection = nm_simple_connection_new ();
 
 	/* Connection setting */
 
@@ -1201,11 +1067,7 @@ test_write_wireless_connection (void)
 	s_wireless = NM_SETTING_WIRELESS (nm_setting_wireless_new ());
 	nm_connection_add_setting (connection, NM_SETTING (s_wireless));
 
-	bssid = g_byte_array_sized_new (ETH_ALEN);
-	g_byte_array_append (bssid, &tmpbssid[0], sizeof (tmpbssid));
-
-	ssid = g_byte_array_sized_new (sizeof (tmpssid));
-	g_byte_array_append (ssid, &tmpssid[0], sizeof (tmpssid));
+	ssid = g_bytes_new (tmpssid, sizeof (tmpssid));
 
 	g_object_set (s_wireless,
 	              NM_SETTING_WIRELESS_BSSID, bssid,
@@ -1213,25 +1075,24 @@ test_write_wireless_connection (void)
 	              NM_SETTING_WIRED_MTU, 1000,
 	              NULL);
 
-	g_byte_array_free (bssid, TRUE);
-	g_byte_array_free (ssid, TRUE);
+	g_bytes_unref (ssid);
 
 	/* IP4 setting */
 
-	s_ip4 = NM_SETTING_IP4_CONFIG (nm_setting_ip4_config_new ());
+	s_ip4 = NM_SETTING_IP_CONFIG (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_AUTO,
+	              NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO,
 	              NULL);
 
 	/* IP6 setting */
 
-	s_ip6 = NM_SETTING_IP6_CONFIG (nm_setting_ip6_config_new ());
+	s_ip6 = NM_SETTING_IP_CONFIG (nm_setting_ip6_config_new ());
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
 
 	g_object_set (s_ip6,
-	              NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO,
+	              NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO,
 	              NULL);
 
 	/* Write out the connection */
@@ -1268,7 +1129,9 @@ test_read_string_ssid (void)
 	NMConnection *connection;
 	NMSettingWireless *s_wireless;
 	GError *error = NULL;
-	const GByteArray *array;
+	GBytes *ssid;
+	const guint8 *ssid_data;
+	gsize ssid_len;
 	const char *expected_ssid = "blah blah ssid 1234";
 
 	connection = nm_keyfile_plugin_connection_from_file (TEST_STRING_SSID_FILE, NULL);
@@ -1287,14 +1150,15 @@ test_read_string_ssid (void)
 	        NM_SETTING_WIRELESS_SETTING_NAME);
 
 	/* SSID */
-	array = nm_setting_wireless_get_ssid (s_wireless);
-	ASSERT (array != NULL,
+	ssid = nm_setting_wireless_get_ssid (s_wireless);
+	ASSERT (ssid != NULL,
 	        "connection-verify-wireless", "failed to verify %s: missing %s / %s key",
 	        TEST_STRING_SSID_FILE,
 	        NM_SETTING_WIRELESS_SETTING_NAME,
 	        NM_SETTING_WIRELESS_SSID);
-	g_assert_cmpint (array->len, ==, strlen (expected_ssid));
-	g_assert (memcmp (array->data, expected_ssid, array->len) == 0);
+	ssid_data = g_bytes_get_data (ssid, &ssid_len);
+	g_assert_cmpint (ssid_len, ==, strlen (expected_ssid));
+	g_assert (memcmp (ssid_data, expected_ssid, ssid_len) == 0);
 
 	g_object_unref (connection);
 }
@@ -1305,9 +1169,9 @@ test_write_string_ssid (void)
 	NMConnection *connection;
 	NMSettingConnection *s_con;
 	NMSettingWireless *s_wireless;
-	NMSettingIP4Config *s_ip4;
+	NMSettingIPConfig *s_ip4;
 	char *uuid, *testfile = NULL, *tmp;
-	GByteArray *ssid;
+	GBytes *ssid;
 	unsigned char tmpssid[] = { 65, 49, 50, 51, 32, 46, 92, 46, 36, 37, 126, 93 };
 	gboolean success;
 	NMConnection *reread;
@@ -1316,7 +1180,7 @@ test_write_string_ssid (void)
 	uid_t owner_uid;
 	GKeyFile *keyfile;
 
-	connection = nm_connection_new ();
+	connection = nm_simple_connection_new ();
 
 	/* Connection setting */
 
@@ -1336,18 +1200,17 @@ test_write_string_ssid (void)
 	s_wireless = NM_SETTING_WIRELESS (nm_setting_wireless_new ());
 	nm_connection_add_setting (connection, NM_SETTING (s_wireless));
 
-	ssid = g_byte_array_sized_new (sizeof (tmpssid));
-	g_byte_array_append (ssid, &tmpssid[0], sizeof (tmpssid));
+	ssid = g_bytes_new (tmpssid, sizeof (tmpssid));
 	g_object_set (s_wireless, NM_SETTING_WIRELESS_SSID, ssid, NULL);
-	g_byte_array_free (ssid, TRUE);
+	g_bytes_unref (ssid);
 
 	/* IP4 setting */
 
-	s_ip4 = NM_SETTING_IP4_CONFIG (nm_setting_ip4_config_new ());
+	s_ip4 = NM_SETTING_IP_CONFIG (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_AUTO,
+	              NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO,
 	              NULL);
 
 	/* Write out the connection */
@@ -1378,8 +1241,7 @@ test_write_string_ssid (void)
 	reread = nm_keyfile_plugin_connection_from_file (testfile, NULL);
 	ASSERT (reread != NULL, "connection-write", "failed to re-read test connection");
 
-	ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE,
-			"connection-write", "written and re-read connection weren't the same");
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_clear_error (&error);
 	unlink (testfile);
@@ -1398,7 +1260,9 @@ test_read_intlist_ssid (void)
 	NMSettingWireless *s_wifi;
 	GError *error = NULL;
 	gboolean success;
-	const GByteArray *array;
+	GBytes *ssid;
+	const guint8 *ssid_data;
+	gsize ssid_len;
 	const char *expected_ssid = "blah1234";
 
 	connection = nm_keyfile_plugin_connection_from_file (TEST_INTLIST_SSID_FILE, &error);
@@ -1413,10 +1277,11 @@ test_read_intlist_ssid (void)
 	s_wifi = nm_connection_get_setting_wireless (connection);
 	g_assert (s_wifi);
 
-	array = nm_setting_wireless_get_ssid (s_wifi);
-	g_assert (array != NULL);
-	g_assert_cmpint (array->len, ==, strlen (expected_ssid));
-	g_assert_cmpint (memcmp (array->data, expected_ssid, strlen (expected_ssid)), ==, 0);
+	ssid = nm_setting_wireless_get_ssid (s_wifi);
+	g_assert (ssid != NULL);
+	ssid_data = g_bytes_get_data (ssid, &ssid_len);
+	g_assert_cmpint (ssid_len, ==, strlen (expected_ssid));
+	g_assert_cmpint (memcmp (ssid_data, expected_ssid, strlen (expected_ssid)), ==, 0);
 
 	g_object_unref (connection);
 }
@@ -1427,9 +1292,9 @@ test_write_intlist_ssid (void)
 	NMConnection *connection;
 	NMSettingConnection *s_con;
 	NMSettingWireless *s_wifi;
-	NMSettingIP4Config *s_ip4;
+	NMSettingIPConfig *s_ip4;
 	char *uuid, *testfile = NULL;
-	GByteArray *ssid;
+	GBytes *ssid;
 	unsigned char tmpssid[] = { 65, 49, 50, 51, 0, 50, 50 };
 	gboolean success;
 	NMConnection *reread;
@@ -1440,7 +1305,7 @@ test_write_intlist_ssid (void)
 	gint *intlist;
 	gsize len = 0, i;
 
-	connection = nm_connection_new ();
+	connection = nm_simple_connection_new ();
 	g_assert (connection);
 
 	/* Connection setting */
@@ -1462,16 +1327,15 @@ test_write_intlist_ssid (void)
 	g_assert (s_wifi);
 	nm_connection_add_setting (connection, NM_SETTING (s_wifi));
 
-	ssid = g_byte_array_sized_new (sizeof (tmpssid));
-	g_byte_array_append (ssid, &tmpssid[0], sizeof (tmpssid));
+	ssid = g_bytes_new (tmpssid, sizeof (tmpssid));
 	g_object_set (s_wifi, NM_SETTING_WIRELESS_SSID, ssid, NULL);
-	g_byte_array_free (ssid, TRUE);
+	g_bytes_unref (ssid);
 
 	/* IP4 setting */
-	s_ip4 = NM_SETTING_IP4_CONFIG (nm_setting_ip4_config_new ());
+	s_ip4 = NM_SETTING_IP_CONFIG (nm_setting_ip4_config_new ());
 	g_assert (s_ip4);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip4));
-	g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL);
+	g_object_set (s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL);
 
 	/* Write out the connection */
 	owner_uid = geteuid ();
@@ -1503,8 +1367,7 @@ test_write_intlist_ssid (void)
 	g_assert_no_error (error);
 	g_assert (reread);
 
-	success = nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT);
-	g_assert (success);
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_clear_error (&error);
 	unlink (testfile);
@@ -1523,7 +1386,9 @@ test_read_intlike_ssid (void)
 	NMSettingWireless *s_wifi;
 	GError *error = NULL;
 	gboolean success;
-	const GByteArray *array;
+	GBytes *ssid;
+	const guint8 *ssid_data;
+	gsize ssid_len;
 	const char *expected_ssid = "101";
 
 	connection = nm_keyfile_plugin_connection_from_file (TEST_INTLIKE_SSID_FILE, &error);
@@ -1538,10 +1403,11 @@ test_read_intlike_ssid (void)
 	s_wifi = nm_connection_get_setting_wireless (connection);
 	g_assert (s_wifi);
 
-	array = nm_setting_wireless_get_ssid (s_wifi);
-	g_assert (array != NULL);
-	g_assert_cmpint (array->len, ==, strlen (expected_ssid));
-	g_assert_cmpint (memcmp (array->data, expected_ssid, strlen (expected_ssid)), ==, 0);
+	ssid = nm_setting_wireless_get_ssid (s_wifi);
+	g_assert (ssid != NULL);
+	ssid_data = g_bytes_get_data (ssid, &ssid_len);
+	g_assert_cmpint (ssid_len, ==, strlen (expected_ssid));
+	g_assert_cmpint (memcmp (ssid_data, expected_ssid, strlen (expected_ssid)), ==, 0);
 
 	g_object_unref (connection);
 }
@@ -1555,7 +1421,9 @@ test_read_intlike_ssid_2 (void)
 	NMSettingWireless *s_wifi;
 	GError *error = NULL;
 	gboolean success;
-	const GByteArray *array;
+	GBytes *ssid;
+	const guint8 *ssid_data;
+	gsize ssid_len;
 	const char *expected_ssid = "11;12;13;";
 
 	connection = nm_keyfile_plugin_connection_from_file (TEST_INTLIKE_SSID_2_FILE, &error);
@@ -1570,10 +1438,11 @@ test_read_intlike_ssid_2 (void)
 	s_wifi = nm_connection_get_setting_wireless (connection);
 	g_assert (s_wifi);
 
-	array = nm_setting_wireless_get_ssid (s_wifi);
-	g_assert (array != NULL);
-	g_assert_cmpint (array->len, ==, strlen (expected_ssid));
-	g_assert_cmpint (memcmp (array->data, expected_ssid, strlen (expected_ssid)), ==, 0);
+	ssid = nm_setting_wireless_get_ssid (s_wifi);
+	g_assert (ssid != NULL);
+	ssid_data = g_bytes_get_data (ssid, &ssid_len);
+	g_assert_cmpint (ssid_len, ==, strlen (expected_ssid));
+	g_assert_cmpint (memcmp (ssid_data, expected_ssid, strlen (expected_ssid)), ==, 0);
 
 	g_object_unref (connection);
 }
@@ -1584,9 +1453,9 @@ test_write_intlike_ssid (void)
 	NMConnection *connection;
 	NMSettingConnection *s_con;
 	NMSettingWireless *s_wifi;
-	NMSettingIP4Config *s_ip4;
+	NMSettingIPConfig *s_ip4;
 	char *uuid, *testfile = NULL;
-	GByteArray *ssid;
+	GBytes *ssid;
 	unsigned char tmpssid[] = { 49, 48, 49 };
 	gboolean success;
 	NMConnection *reread;
@@ -1596,7 +1465,7 @@ test_write_intlike_ssid (void)
 	GKeyFile *keyfile;
 	char *tmp;
 
-	connection = nm_connection_new ();
+	connection = nm_simple_connection_new ();
 	g_assert (connection);
 
 	/* Connection setting */
@@ -1618,16 +1487,15 @@ test_write_intlike_ssid (void)
 	g_assert (s_wifi);
 	nm_connection_add_setting (connection, NM_SETTING (s_wifi));
 
-	ssid = g_byte_array_sized_new (sizeof (tmpssid));
-	g_byte_array_append (ssid, &tmpssid[0], sizeof (tmpssid));
+	ssid = g_bytes_new (tmpssid, sizeof (tmpssid));
 	g_object_set (s_wifi, NM_SETTING_WIRELESS_SSID, ssid, NULL);
-	g_byte_array_free (ssid, TRUE);
+	g_bytes_unref (ssid);
 
 	/* IP4 setting */
-	s_ip4 = NM_SETTING_IP4_CONFIG (nm_setting_ip4_config_new ());
+	s_ip4 = NM_SETTING_IP_CONFIG (nm_setting_ip4_config_new ());
 	g_assert (s_ip4);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip4));
-	g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL);
+	g_object_set (s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL);
 
 	/* Write out the connection */
 	owner_uid = geteuid ();
@@ -1655,8 +1523,7 @@ test_write_intlike_ssid (void)
 	g_assert_no_error (error);
 	g_assert (reread);
 
-	success = nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT);
-	g_assert (success);
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_clear_error (&error);
 	unlink (testfile);
@@ -1672,9 +1539,9 @@ test_write_intlike_ssid_2 (void)
 	NMConnection *connection;
 	NMSettingConnection *s_con;
 	NMSettingWireless *s_wifi;
-	NMSettingIP4Config *s_ip4;
+	NMSettingIPConfig *s_ip4;
 	char *uuid, *testfile = NULL;
-	GByteArray *ssid;
+	GBytes *ssid;
 	unsigned char tmpssid[] = { 49, 49, 59, 49, 50, 59, 49, 51, 59};
 	gboolean success;
 	NMConnection *reread;
@@ -1684,7 +1551,7 @@ test_write_intlike_ssid_2 (void)
 	GKeyFile *keyfile;
 	char *tmp;
 
-	connection = nm_connection_new ();
+	connection = nm_simple_connection_new ();
 	g_assert (connection);
 
 	/* Connection setting */
@@ -1706,16 +1573,15 @@ test_write_intlike_ssid_2 (void)
 	g_assert (s_wifi);
 	nm_connection_add_setting (connection, NM_SETTING (s_wifi));
 
-	ssid = g_byte_array_sized_new (sizeof (tmpssid));
-	g_byte_array_append (ssid, &tmpssid[0], sizeof (tmpssid));
+	ssid = g_bytes_new (tmpssid, sizeof (tmpssid));
 	g_object_set (s_wifi, NM_SETTING_WIRELESS_SSID, ssid, NULL);
-	g_byte_array_free (ssid, TRUE);
+	g_bytes_unref (ssid);
 
 	/* IP4 setting */
-	s_ip4 = NM_SETTING_IP4_CONFIG (nm_setting_ip4_config_new ());
+	s_ip4 = NM_SETTING_IP_CONFIG (nm_setting_ip4_config_new ());
 	g_assert (s_ip4);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip4));
-	g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL);
+	g_object_set (s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL);
 
 	/* Write out the connection */
 	owner_uid = geteuid ();
@@ -1743,8 +1609,7 @@ test_write_intlike_ssid_2 (void)
 	g_assert_no_error (error);
 	g_assert (reread);
 
-	success = nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT);
-	g_assert (success);
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_clear_error (&error);
 	unlink (testfile);
@@ -1765,9 +1630,10 @@ test_read_bt_dun_connection (void)
 	NMSettingSerial *s_serial;
 	NMSettingGsm *s_gsm;
 	GError *error = NULL;
-	const GByteArray *array;
-	char expected_bdaddr[ETH_ALEN] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 };
+	const char *bdaddr;
+	const guint8 expected_bdaddr[ETH_ALEN] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 };
 	const char *tmp;
+	NMSettingSerialParity parity;
 	const char *expected_id = "AT&T Data Connect BT";
 	const char *expected_uuid = "089130ab-ce28-46e4-ad77-d44869b03d19";
 	const char *expected_apn = "ISP.CINGULAR";
@@ -1824,18 +1690,13 @@ test_read_bt_dun_connection (void)
 	        NM_SETTING_WIRED_SETTING_NAME);
 
 	/* BDADDR */
-	array = nm_setting_bluetooth_get_bdaddr (s_bluetooth);
-	ASSERT (array != NULL,
+	bdaddr = nm_setting_bluetooth_get_bdaddr (s_bluetooth);
+	ASSERT (bdaddr != NULL,
 	        "connection-verify-bt", "failed to verify %s: missing %s / %s key",
 	        TEST_BT_DUN_FILE,
 	        NM_SETTING_BLUETOOTH_SETTING_NAME,
 	        NM_SETTING_BLUETOOTH_BDADDR);
-	ASSERT (array->len == ETH_ALEN,
-	        "connection-verify-bt", "failed to verify %s: unexpected %s / %s key value length",
-	        TEST_BT_DUN_FILE,
-	        NM_SETTING_BLUETOOTH_SETTING_NAME,
-	        NM_SETTING_BLUETOOTH_BDADDR);
-	ASSERT (memcmp (array->data, &expected_bdaddr[0], sizeof (expected_bdaddr)) == 0,
+	ASSERT (nm_utils_hwaddr_matches (bdaddr, -1, expected_bdaddr, sizeof (expected_bdaddr)),
 	        "connection-verify-bt", "failed to verify %s: unexpected %s / %s key value",
 	        TEST_BT_DUN_FILE,
 	        NM_SETTING_BLUETOOTH_SETTING_NAME,
@@ -1909,6 +1770,13 @@ test_read_bt_dun_connection (void)
 	        TEST_BT_DUN_FILE,
 	        NM_SETTING_SERIAL_SETTING_NAME);
 
+	parity = nm_setting_serial_get_parity (s_serial);
+	ASSERT (parity == NM_SETTING_SERIAL_PARITY_ODD,
+	        "connection-verify-serial", "failed to verify %s: unexpected %s / %s key value",
+	        TEST_BT_DUN_FILE,
+	        NM_SETTING_SERIAL_SETTING_NAME,
+	        NM_SETTING_SERIAL_PARITY);
+
 	g_object_unref (connection);
 }
 
@@ -1918,11 +1786,10 @@ test_write_bt_dun_connection (void)
 	NMConnection *connection;
 	NMSettingConnection *s_con;
 	NMSettingBluetooth *s_bt;
-	NMSettingIP4Config *s_ip4;
+	NMSettingIPConfig *s_ip4;
 	NMSettingGsm *s_gsm;
 	char *uuid;
-	GByteArray *bdaddr;
-	unsigned char tmpbdaddr[] = { 0xaa, 0xb9, 0xa1, 0x74, 0x55, 0x44 };
+	const char *bdaddr = "aa:b9:a1:74:55:44";
 	gboolean success;
 	NMConnection *reread;
 	char *testfile = NULL;
@@ -1931,7 +1798,7 @@ test_write_bt_dun_connection (void)
 	uid_t owner_uid;
 	guint64 timestamp = 0x12344433L;
 
-	connection = nm_connection_new ();
+	connection = nm_simple_connection_new ();
 
 	/* Connection setting */
 
@@ -1953,23 +1820,18 @@ test_write_bt_dun_connection (void)
 	s_bt = NM_SETTING_BLUETOOTH (nm_setting_bluetooth_new ());
 	nm_connection_add_setting (connection, NM_SETTING (s_bt));
 
-	bdaddr = g_byte_array_sized_new (ETH_ALEN);
-	g_byte_array_append (bdaddr, &tmpbdaddr[0], sizeof (tmpbdaddr));
-
 	g_object_set (s_bt,
 	              NM_SETTING_BLUETOOTH_BDADDR, bdaddr,
 	              NM_SETTING_BLUETOOTH_TYPE, NM_SETTING_BLUETOOTH_TYPE_DUN,
 	              NULL);
 
-	g_byte_array_free (bdaddr, TRUE);
-
 	/* IP4 setting */
 
-	s_ip4 = NM_SETTING_IP4_CONFIG (nm_setting_ip4_config_new ());
+	s_ip4 = NM_SETTING_IP_CONFIG (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_AUTO,
+	              NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO,
 	              NULL);
 
 	/* GSM setting */
@@ -1998,8 +1860,7 @@ test_write_bt_dun_connection (void)
 	reread = nm_keyfile_plugin_connection_from_file (testfile, NULL);
 	ASSERT (reread != NULL, "connection-write", "failed to re-read test connection");
 
-	ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE,
-			"connection-write", "written and re-read connection weren't the same");
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_clear_error (&error);
 	unlink (testfile);
@@ -2021,6 +1882,7 @@ test_read_gsm_connection (void)
 	NMSettingBluetooth *s_bluetooth;
 	GError *error = NULL;
 	const char *tmp;
+	NMSettingSerialParity parity;
 	const char *expected_id = "AT&T Data Connect";
 	const char *expected_apn = "ISP.CINGULAR";
 	const char *expected_username = "ISP@CINGULARGPRS.COM";
@@ -2158,6 +2020,13 @@ test_read_gsm_connection (void)
 	        TEST_GSM_FILE,
 	        NM_SETTING_SERIAL_SETTING_NAME);
 
+	parity = nm_setting_serial_get_parity (s_serial);
+	ASSERT (parity == NM_SETTING_SERIAL_PARITY_ODD,
+	        "connection-verify-serial", "failed to verify %s: unexpected %s / %s key value",
+	        TEST_GSM_FILE,
+	        NM_SETTING_SERIAL_SETTING_NAME,
+	        NM_SETTING_SERIAL_PARITY);
+
 	g_object_unref (connection);
 }
 
@@ -2166,7 +2035,7 @@ test_write_gsm_connection (void)
 {
 	NMConnection *connection;
 	NMSettingConnection *s_con;
-	NMSettingIP4Config *s_ip4;
+	NMSettingIPConfig *s_ip4;
 	NMSettingGsm *s_gsm;
 	char *uuid;
 	gboolean success;
@@ -2177,7 +2046,7 @@ test_write_gsm_connection (void)
 	uid_t owner_uid;
 	guint64 timestamp = 0x12344433L;
 
-	connection = nm_connection_new ();
+	connection = nm_simple_connection_new ();
 
 	/* Connection setting */
 
@@ -2196,11 +2065,11 @@ test_write_gsm_connection (void)
 
 	/* IP4 setting */
 
-	s_ip4 = NM_SETTING_IP4_CONFIG (nm_setting_ip4_config_new ());
+	s_ip4 = NM_SETTING_IP_CONFIG (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_AUTO,
+	              NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO,
 	              NULL);
 
 	/* GSM setting */
@@ -2215,7 +2084,6 @@ test_write_gsm_connection (void)
 	              NM_SETTING_GSM_PIN, "123456",
 	              NM_SETTING_GSM_NETWORK_ID, "254098",
 	              NM_SETTING_GSM_HOME_ONLY, TRUE,
-	              NM_SETTING_GSM_NETWORK_TYPE, NM_SETTING_GSM_NETWORK_TYPE_PREFER_UMTS_HSPA,
 	              NULL);
 
 	/* Write out the connection */
@@ -2233,8 +2101,7 @@ test_write_gsm_connection (void)
 	reread = nm_keyfile_plugin_connection_from_file (testfile, NULL);
 	ASSERT (reread != NULL, "connection-write", "failed to re-read test connection");
 
-	ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE,
-			"connection-write", "written and re-read connection weren't the same");
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	g_clear_error (&error);
 	unlink (testfile);
@@ -2255,7 +2122,7 @@ test_read_wired_8021x_tls_blob_connection (void)
 	GError *error = NULL;
 	const char *tmp;
 	gboolean success;
-	const GByteArray *array;
+	GBytes *blob;
 
 	connection = nm_keyfile_plugin_connection_from_file (TEST_WIRED_TLS_BLOB_FILE, &error);
 	if (connection == NULL) {
@@ -2292,16 +2159,16 @@ test_read_wired_8021x_tls_blob_connection (void)
 	g_assert_cmpint (nm_setting_802_1x_get_ca_cert_scheme (s_8021x), ==, NM_SETTING_802_1X_CK_SCHEME_BLOB);
 
 	/* Make sure it's not a path, since it's a blob */
-	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL,
+	g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL,
 	                       "*assertion*scheme == NM_SETTING_802_1X_CK_SCHEME_PATH*");
 	tmp = nm_setting_802_1x_get_ca_cert_path (s_8021x);
 	g_test_assert_expected_messages ();
 	g_assert (tmp == NULL);
 
 	/* Validate the path */
-	array = nm_setting_802_1x_get_ca_cert_blob (s_8021x);
-	g_assert (array != NULL);
-	g_assert_cmpint (array->len, ==, 568);
+	blob = nm_setting_802_1x_get_ca_cert_blob (s_8021x);
+	g_assert (blob != NULL);
+	g_assert_cmpint (g_bytes_get_size (blob), ==, 568);
 
 	tmp = nm_setting_802_1x_get_client_cert_path (s_8021x);
 	g_assert_cmpstr (tmp, ==, "/home/dcbw/Desktop/certinfra/client.pem");
@@ -2504,14 +2371,14 @@ create_wired_tls_connection (NMSetting8021xCKScheme scheme)
 {
 	NMConnection *connection;
 	NMSettingConnection *s_con;
-	NMSettingIP4Config *s_ip4;
+	NMSettingIPConfig *s_ip4;
 	NMSetting *s_wired;
 	NMSetting8021x *s_8021x;
 	char *uuid;
 	gboolean success;
 	GError *error = NULL;
 
-	connection = nm_connection_new ();
+	connection = nm_simple_connection_new ();
 	g_assert (connection != NULL);
 
 	/* Connection setting */
@@ -2528,9 +2395,9 @@ create_wired_tls_connection (NMSetting8021xCKScheme scheme)
 	g_free (uuid);
 
 	/* IP4 setting */
-	s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
+	s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new ();
 	g_assert (s_ip4);
-	g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL);
+	g_object_set (s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip4));
 
 	/* Wired setting */
@@ -2769,7 +2636,7 @@ test_read_infiniband_connection (void)
 	NMSettingConnection *s_con;
 	NMSettingInfiniband *s_ib;
 	GError *error = NULL;
-	const GByteArray *array;
+	const char *mac;
 	guint8 expected_mac[INFINIBAND_ALEN] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
 		0x77, 0x88, 0x99, 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, 0x89,
 		0x90 };
@@ -2794,10 +2661,9 @@ test_read_infiniband_connection (void)
 	s_ib = nm_connection_get_setting_infiniband (connection);
 	g_assert (s_ib);
 
-	array = nm_setting_infiniband_get_mac_address (s_ib);
-	g_assert (array);
-	g_assert_cmpint (array->len, ==, INFINIBAND_ALEN);
-	g_assert_cmpint (memcmp (array->data, expected_mac, sizeof (expected_mac)), ==, 0);
+	mac = nm_setting_infiniband_get_mac_address (s_ib);
+	g_assert (mac);
+	g_assert (nm_utils_hwaddr_matches (mac, -1, expected_mac, sizeof (expected_mac)));
 
 	g_object_unref (connection);
 }
@@ -2808,13 +2674,10 @@ test_write_infiniband_connection (void)
 	NMConnection *connection;
 	NMSettingConnection *s_con;
 	NMSettingInfiniband *s_ib;
-	NMSettingIP4Config *s_ip4;
-	NMSettingIP6Config *s_ip6;
+	NMSettingIPConfig *s_ip4;
+	NMSettingIPConfig *s_ip6;
 	char *uuid;
-	GByteArray *mac;
-	guint8 tmpmac[] = { 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0xab, 0xbc,
-		0xcd, 0xde, 0xef, 0xf0, 0x0a, 0x1b, 0x2c, 0x3d, 0x4e, 0x5f, 0x6f, 0xba
-	};
+	const char *mac = "99:88:77:66:55:44:ab:bc:cd:de:ef:f0:0a:1b:2c:3d:4e:5f:6f:ba";
 	gboolean success;
 	NMConnection *reread;
 	char *testfile = NULL;
@@ -2822,7 +2685,7 @@ test_write_infiniband_connection (void)
 	pid_t owner_grp;
 	uid_t owner_uid;
 
-	connection = nm_connection_new ();
+	connection = nm_simple_connection_new ();
 	g_assert (connection);
 
 	/* Connection setting */
@@ -2845,26 +2708,23 @@ test_write_infiniband_connection (void)
 	g_assert (s_ib);
 	nm_connection_add_setting (connection, NM_SETTING (s_ib));
 
-	mac = g_byte_array_sized_new (sizeof (tmpmac));
-	g_byte_array_append (mac, &tmpmac[0], sizeof (tmpmac));
 	g_object_set (s_ib,
 	              NM_SETTING_INFINIBAND_MAC_ADDRESS, mac,
 	              NM_SETTING_INFINIBAND_MTU, 900,
 	              NM_SETTING_INFINIBAND_TRANSPORT_MODE, "datagram",
 	              NULL);
-	g_byte_array_free (mac, TRUE);
 
 	/* IP4 setting */
-	s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
+	s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new ();
 	g_assert (s_ip4);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip4));
-	g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL);
+	g_object_set (s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL);
 
 	/* IP6 setting */
-	s_ip6 = (NMSettingIP6Config *) nm_setting_ip6_config_new ();
+	s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new ();
 	g_assert (s_ip6);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
-	g_object_set (s_ip6, NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, NULL);
+	g_object_set (s_ip6, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, NULL);
 
 	/* Write out the connection */
 	owner_uid = geteuid ();
@@ -2895,7 +2755,7 @@ test_read_bridge_main (void)
 {
 	NMConnection *connection;
 	NMSettingConnection *s_con;
-	NMSettingIP4Config *s_ip4;
+	NMSettingIPConfig *s_ip4;
 	NMSettingBridge *s_bridge;
 	GError *error = NULL;
 	const char *expected_id = "Test Bridge Main";
@@ -2914,16 +2774,16 @@ test_read_bridge_main (void)
 	g_assert (s_con);
 	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, expected_id);
 	g_assert_cmpstr (nm_setting_connection_get_uuid (s_con), ==, expected_uuid);
+	g_assert_cmpstr (nm_setting_connection_get_interface_name (s_con), ==, "br0");
 
 	/* 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_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO);
 
 	/* Bridge setting */
 	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_forward_delay (s_bridge), ==, 0);
 	g_assert_cmpuint (nm_setting_bridge_get_stp (s_bridge), ==, TRUE);
 	g_assert_cmpuint (nm_setting_bridge_get_priority (s_bridge), ==, 32744);
@@ -2940,8 +2800,8 @@ test_write_bridge_main (void)
 	NMConnection *connection;
 	NMSettingConnection *s_con;
 	NMSettingBridge *s_bridge;
-	NMSettingIP4Config *s_ip4;
-	NMSettingIP6Config *s_ip6;
+	NMSettingIPConfig *s_ip4;
+	NMSettingIPConfig *s_ip6;
 	char *uuid;
 	gboolean success;
 	NMConnection *reread;
@@ -2950,7 +2810,7 @@ test_write_bridge_main (void)
 	pid_t owner_grp;
 	uid_t owner_uid;
 
-	connection = nm_connection_new ();
+	connection = nm_simple_connection_new ();
 	g_assert (connection);
 
 	/* Connection setting */
@@ -2973,26 +2833,23 @@ test_write_bridge_main (void)
 	g_assert (s_bridge);
 	nm_connection_add_setting (connection, NM_SETTING (s_bridge));
 
-	g_object_set (s_bridge,
-	              NM_SETTING_BRIDGE_INTERFACE_NAME, "br0",
-	              NULL);
-
 	/* IP4 setting */
-	s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
+	s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new ();
 	g_assert (s_ip4);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip4));
 	g_object_set (s_ip4,
-	              NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL,
-	              NM_SETTING_IP4_CONFIG_MAY_FAIL, TRUE,
+	              NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL,
+	              NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE,
+	              NM_SETTING_IP_CONFIG_GATEWAY, "1.1.1.1",
 	              NULL);
 
-	add_one_ip4_address (s_ip4, "1.2.3.4", "1.1.1.1", 24);
+	add_one_ip_address (s_ip4, "1.2.3.4", 24);
 
 	/* IP6 setting */
-	s_ip6 = (NMSettingIP6Config *) nm_setting_ip6_config_new ();
+	s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new ();
 	g_assert (s_ip6);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
-	g_object_set (s_ip6, NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, NULL);
+	g_object_set (s_ip6, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, NULL);
 
 	/* Write out the connection */
 	owner_uid = geteuid ();
@@ -3025,7 +2882,7 @@ test_read_bridge_component (void)
 	NMSettingConnection *s_con;
 	NMSettingBridgePort *s_port;
 	NMSettingWired *s_wired;
-	const GByteArray *array;
+	const char *mac;
 	guint8 expected_mac[ETH_ALEN] = { 0x00, 0x22, 0x15, 0x59, 0x62, 0x97 };
 	GError *error = NULL;
 	const char *expected_id = "Test Bridge Component";
@@ -3050,10 +2907,9 @@ test_read_bridge_component (void)
 	/* Wired setting */
 	s_wired = nm_connection_get_setting_wired (connection);
 	g_assert (s_wired);
-	array = nm_setting_wired_get_mac_address (s_wired);
-	g_assert (array);
-	g_assert_cmpint (array->len, ==, ETH_ALEN);
-	g_assert_cmpint (memcmp (array->data, expected_mac, sizeof (expected_mac)), ==, 0);
+	mac = nm_setting_wired_get_mac_address (s_wired);
+	g_assert (mac);
+	g_assert (nm_utils_hwaddr_matches (mac, -1, expected_mac, sizeof (expected_mac)));
 
 	/* BridgePort setting */
 	s_port = nm_connection_get_setting_bridge_port (connection);
@@ -3073,8 +2929,7 @@ test_write_bridge_component (void)
 	NMSettingBridgePort *s_port;
 	NMSettingWired *s_wired;
 	char *uuid;
-	GByteArray *mac;
-	guint8 tmpmac[] = { 0x99, 0x88, 0x77, 0x66, 0x55, 0x44 };
+	const char *mac = "99:88:77:66:55:44";
 	gboolean success;
 	NMConnection *reread;
 	char *testfile = NULL;
@@ -3082,7 +2937,7 @@ test_write_bridge_component (void)
 	pid_t owner_grp;
 	uid_t owner_uid;
 
-	connection = nm_connection_new ();
+	connection = nm_simple_connection_new ();
 	g_assert (connection);
 
 	/* Connection setting */
@@ -3106,13 +2961,10 @@ test_write_bridge_component (void)
 	g_assert (s_wired);
 	nm_connection_add_setting (connection, NM_SETTING (s_wired));
 
-	mac = g_byte_array_sized_new (ETH_ALEN);
-	g_byte_array_append (mac, &tmpmac[0], sizeof (tmpmac));
 	g_object_set (s_wired,
 	              NM_SETTING_WIRED_MAC_ADDRESS, mac,
 	              NM_SETTING_WIRED_MTU, 1300,
 	              NULL);
-	g_byte_array_free (mac, TRUE);
 
 	/* BridgePort setting */
 	s_port = (NMSettingBridgePort *) nm_setting_bridge_port_new ();
@@ -3151,7 +3003,7 @@ test_read_new_wired_group_name (void)
 {
 	NMConnection *connection;
 	NMSettingWired *s_wired;
-	const GByteArray *array;
+	const char *mac;
 	guint8 expected_mac[ETH_ALEN] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 };
 	GError *error = NULL;
 	gboolean success;
@@ -3168,10 +3020,9 @@ test_read_new_wired_group_name (void)
 	g_assert (s_wired);
 	g_assert_cmpint (nm_setting_wired_get_mtu (s_wired), ==, 1400);
 
-	array = nm_setting_wired_get_mac_address (s_wired);
-	g_assert (array);
-	g_assert_cmpint (array->len, ==, ETH_ALEN);
-	g_assert_cmpint (memcmp (array->data, expected_mac, sizeof (expected_mac)), ==, 0);
+	mac = nm_setting_wired_get_mac_address (s_wired);
+	g_assert (mac);
+	g_assert (nm_utils_hwaddr_matches (mac, -1, expected_mac, sizeof (expected_mac)));
 
 	g_object_unref (connection);
 }
@@ -3193,7 +3044,7 @@ test_write_new_wired_group_name (void)
 	char *s;
 	gint mtu;
 
-	connection = nm_connection_new ();
+	connection = nm_simple_connection_new ();
 	g_assert (connection);
 
 	/* Connection setting */
@@ -3227,7 +3078,7 @@ test_write_new_wired_group_name (void)
 	reread = nm_keyfile_plugin_connection_from_file (testfile, &error);
 	g_assert_no_error (error);
 	g_assert (reread);
-	g_assert (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT));
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	/* Look at the keyfile itself to ensure we wrote out the new group names and type */
 	kf = g_key_file_new ();
@@ -3257,7 +3108,9 @@ test_read_new_wireless_group_names (void)
 	NMConnection *connection;
 	NMSettingWireless *s_wifi;
 	NMSettingWirelessSecurity *s_wsec;
-	const GByteArray *array;
+	GBytes *ssid;
+	const guint8 *ssid_data;
+	gsize ssid_len;
 	const char *expected_ssid = "foobar";
 	GError *error = NULL;
 	gboolean success;
@@ -3273,10 +3126,11 @@ test_read_new_wireless_group_names (void)
 	s_wifi = nm_connection_get_setting_wireless (connection);
 	g_assert (s_wifi);
 
-	array = nm_setting_wireless_get_ssid (s_wifi);
-	g_assert (array);
-	g_assert_cmpint (array->len, ==, strlen (expected_ssid));
-	g_assert_cmpint (memcmp (array->data, expected_ssid, array->len), ==, 0);
+	ssid = nm_setting_wireless_get_ssid (s_wifi);
+	g_assert (ssid);
+	ssid_data = g_bytes_get_data (ssid, &ssid_len);
+	g_assert_cmpint (ssid_len, ==, strlen (expected_ssid));
+	g_assert_cmpint (memcmp (ssid_data, expected_ssid, ssid_len), ==, 0);
 
 	g_assert_cmpstr (nm_setting_wireless_get_mode (s_wifi), ==, NM_SETTING_WIRELESS_MODE_INFRA);
 
@@ -3297,7 +3151,7 @@ test_write_new_wireless_group_names (void)
 	NMSettingWireless *s_wifi;
 	NMSettingWirelessSecurity *s_wsec;
 	char *uuid;
-	GByteArray *ssid;
+	GBytes *ssid;
 	unsigned char tmpssid[] = { 0x31, 0x33, 0x33, 0x37 };
 	const char *expected_psk = "asdfasdfasdfa12315";
 	gboolean success;
@@ -3309,7 +3163,7 @@ test_write_new_wireless_group_names (void)
 	GKeyFile *kf;
 	char *s;
 
-	connection = nm_connection_new ();
+	connection = nm_simple_connection_new ();
 
 	/* Connection setting */
 
@@ -3328,13 +3182,12 @@ test_write_new_wireless_group_names (void)
 	s_wifi = (NMSettingWireless *) nm_setting_wireless_new ();
 	nm_connection_add_setting (connection, NM_SETTING (s_wifi));
 
-	ssid = g_byte_array_sized_new (sizeof (tmpssid));
-	g_byte_array_append (ssid, &tmpssid[0], sizeof (tmpssid));
+	ssid = g_bytes_new (tmpssid, sizeof (tmpssid));
 	g_object_set (s_wifi,
 	              NM_SETTING_WIRELESS_SSID, ssid,
 	              NM_SETTING_WIRELESS_MODE, NM_SETTING_WIRELESS_MODE_INFRA,
 	              NULL);
-	g_byte_array_free (ssid, TRUE);
+	g_bytes_unref (ssid);
 
 	/* WiFi security setting */
 	s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
@@ -3357,7 +3210,7 @@ test_write_new_wireless_group_names (void)
 	reread = nm_keyfile_plugin_connection_from_file (testfile, &error);
 	g_assert_no_error (error);
 	g_assert (reread);
-	g_assert (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT));
+	nmtst_assert_connection_equals (connection, TRUE, reread, FALSE);
 
 	/* Look at the keyfile itself to ensure we wrote out the new group names and type */
 	kf = g_key_file_new ();
@@ -3410,72 +3263,357 @@ test_read_missing_vlan_setting (void)
 	g_object_unref (connection);
 }
 
+static void
+test_read_missing_id_uuid (void)
+{
+	NMConnection *connection;
+	GError *error = NULL;
+	gboolean success;
+
+	connection = nm_keyfile_plugin_connection_from_file (TEST_KEYFILES_DIR"/Test_Missing_ID_UUID", &error);
+	g_assert_no_error (error);
+	g_assert (connection);
+	success = nm_connection_verify (connection, &error);
+	g_assert_no_error (error);
+	g_assert (success);
+
+	/* Ensure the ID and UUID properties are there */
+	g_assert_cmpstr (nm_connection_get_id (connection), ==, "Test_Missing_ID_UUID");
+	g_assert (nm_connection_get_uuid (connection));
+
+	g_object_unref (connection);
+}
+
+static void
+test_read_minimal (void)
+{
+	NMConnection *connection = NULL;
+	gs_unref_object NMConnection *con_archetype = NULL;
+	NMSettingConnection *s_con;
+
+	con_archetype = nmtst_create_minimal_connection ("Test_minimal_x",
+	                                                 "a15bd68f-c32b-40b8-8d27-49e472a85919",
+	                                                 NM_SETTING_WIRED_SETTING_NAME,
+	                                                 &s_con);
+	nmtst_connection_normalize (con_archetype);
+
+
+	connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR"/Test_minimal_1");
+	g_object_set (s_con,
+	              NM_SETTING_CONNECTION_ID, nm_connection_get_id (connection),
+	              NM_SETTING_CONNECTION_UUID, nm_connection_get_uuid (connection),
+	              NULL);
+	nmtst_assert_connection_equals (con_archetype, FALSE, connection, FALSE);
+	g_clear_object (&connection);
+
+
+	connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR"/Test_minimal_2");
+	g_object_set (s_con,
+	              NM_SETTING_CONNECTION_ID, nm_connection_get_id (connection),
+	              NM_SETTING_CONNECTION_UUID, nm_connection_get_uuid (connection),
+	              NULL);
+	nmtst_assert_connection_equals (con_archetype, FALSE, connection, FALSE);
+	g_clear_object (&connection);
+}
+
+static void
+test_read_minimal_slave (void)
+{
+	NMConnection *connection = NULL;
+	gs_unref_object NMConnection *con_archetype = NULL;
+	NMSettingConnection *s_con;
+
+	con_archetype = nmtst_create_minimal_connection ("Test_minimal_slave_x",
+	                                                 "a56b4ca5-7075-43d4-82c7-5d0cb15f7654",
+	                                                 NM_SETTING_WIRED_SETTING_NAME,
+	                                                 &s_con);
+	g_object_set (s_con,
+	              NM_SETTING_CONNECTION_MASTER, "br0",
+	              NM_SETTING_CONNECTION_SLAVE_TYPE, "bridge",
+	              NULL);
+	nmtst_connection_normalize (con_archetype);
+
+
+	connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR"/Test_minimal_slave_1");
+	g_object_set (s_con,
+	              NM_SETTING_CONNECTION_ID, nm_connection_get_id (connection),
+	              NM_SETTING_CONNECTION_UUID, nm_connection_get_uuid (connection),
+	              NULL);
+	nmtst_assert_connection_equals (con_archetype, FALSE, connection, FALSE);
+	g_clear_object (&connection);
+
+
+	connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR"/Test_minimal_slave_2");
+	g_object_set (s_con,
+	              NM_SETTING_CONNECTION_ID, nm_connection_get_id (connection),
+	              NM_SETTING_CONNECTION_UUID, nm_connection_get_uuid (connection),
+	              NULL);
+	nmtst_assert_connection_equals (con_archetype, FALSE, connection, FALSE);
+	g_clear_object (&connection);
+
+	connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR"/Test_minimal_slave_3");
+	g_object_set (s_con,
+	              NM_SETTING_CONNECTION_ID, nm_connection_get_id (connection),
+	              NM_SETTING_CONNECTION_UUID, nm_connection_get_uuid (connection),
+	              NULL);
+	nmtst_assert_connection_equals (con_archetype, FALSE, connection, FALSE);
+	g_clear_object (&connection);
+
+	connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR"/Test_minimal_slave_4");
+	g_object_set (s_con,
+	              NM_SETTING_CONNECTION_ID, nm_connection_get_id (connection),
+	              NM_SETTING_CONNECTION_UUID, nm_connection_get_uuid (connection),
+	              NULL);
+	nmtst_assert_connection_equals (con_archetype, FALSE, connection, FALSE);
+	g_clear_object (&connection);
+}
+
+static void
+test_read_enum_property (void)
+{
+	NMConnection *connection;
+	NMSettingIPConfig *s_ip6;
+	GError *error = NULL;
+	gboolean success;
+
+	connection = nm_keyfile_plugin_connection_from_file (TEST_KEYFILES_DIR"/Test_Enum_Property", &error);
+	g_assert_no_error (error);
+	g_assert (connection);
+	success = nm_connection_verify (connection, &error);
+	g_assert_no_error (error);
+	g_assert (success);
+
+	/* IPv6 setting */
+	s_ip6 = nm_connection_get_setting_ip6_config (connection);
+	g_assert (s_ip6);
+	g_assert_cmpint (nm_setting_ip6_config_get_ip6_privacy (NM_SETTING_IP6_CONFIG (s_ip6)), ==, NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR);
+
+	g_object_unref (connection);
+}
+
+static void
+test_write_enum_property (void)
+{
+	NMConnection *connection;
+	NMSettingConnection *s_con;
+	NMSettingWired *s_wired;
+	NMSettingIPConfig *s_ip6;
+	char *uuid;
+	gboolean success;
+	NMConnection *reread;
+	char *testfile = NULL;
+	GError *error = NULL;
+	pid_t owner_grp;
+	uid_t owner_uid;
+
+	connection = nm_simple_connection_new ();
+
+	/* Connection setting */
+
+	s_con = NM_SETTING_CONNECTION (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 Enum Property",
+	              NM_SETTING_CONNECTION_UUID, uuid,
+	              NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME,
+	              NULL);
+	g_free (uuid);
+
+	/* Wired setting */
+	s_wired = NM_SETTING_WIRED (nm_setting_wired_new ());
+	nm_connection_add_setting (connection, NM_SETTING (s_wired));
+
+	/* IP6 setting */
+	s_ip6 = NM_SETTING_IP_CONFIG (nm_setting_ip6_config_new ());
+	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
+	g_object_set (s_ip6,
+	              NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO,
+	              NM_SETTING_IP6_CONFIG_IP6_PRIVACY, NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR,
+	              NULL);
+
+	nmtst_connection_normalize (connection);
+
+	/* Write out the connection */
+	owner_uid = geteuid ();
+	owner_grp = getegid ();
+	success = nm_keyfile_plugin_write_test_connection (connection, TEST_SCRATCH_DIR, owner_uid, owner_grp, &testfile, &error);
+	g_assert_no_error (error);
+	g_assert (success);
+	g_assert (testfile);
+
+	/* Read the connection back in and compare it to the one we just wrote out */
+	reread = nm_keyfile_plugin_connection_from_file (testfile, &error);
+	g_assert_no_error (error);
+	g_assert (reread);
+
+	nmtst_assert_connection_equals (reread, FALSE, connection, FALSE);
+
+	unlink (testfile);
+	g_free (testfile);
+
+	g_object_unref (reread);
+	g_object_unref (connection);
+}
+
+static void
+test_read_flags_property (void)
+{
+	NMConnection *connection;
+	NMSettingGsm *s_gsm;
+	GError *error = NULL;
+	gboolean success;
+
+	connection = nm_keyfile_plugin_connection_from_file (TEST_KEYFILES_DIR"/Test_Flags_Property", &error);
+	g_assert_no_error (error);
+	g_assert (connection);
+	success = nm_connection_verify (connection, &error);
+	g_assert_no_error (error);
+	g_assert (success);
+
+	/* GSM setting */
+	s_gsm = nm_connection_get_setting_gsm (connection);
+	g_assert (s_gsm);
+	g_assert_cmpint (nm_setting_gsm_get_password_flags (s_gsm), ==,
+	                   NM_SETTING_SECRET_FLAG_AGENT_OWNED | NM_SETTING_SECRET_FLAG_NOT_REQUIRED);
+
+	g_object_unref (connection);
+}
+
+static void
+test_write_flags_property (void)
+{
+	NMConnection *connection;
+	NMSettingConnection *s_con;
+	NMSetting *s_gsm;
+	char *uuid;
+	gboolean success;
+	NMConnection *reread;
+	char *testfile = NULL;
+	GError *error = NULL;
+	pid_t owner_grp;
+	uid_t owner_uid;
+
+	connection = nm_simple_connection_new ();
+
+	/* Connection setting */
+
+	s_con = NM_SETTING_CONNECTION (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 Flags Property",
+	              NM_SETTING_CONNECTION_UUID, uuid,
+	              NM_SETTING_CONNECTION_TYPE, NM_SETTING_GSM_SETTING_NAME,
+	              NULL);
+	g_free (uuid);
+
+	/* GSM setting */
+	s_gsm = nm_setting_gsm_new ();
+	nm_connection_add_setting (connection, s_gsm);
+	g_object_set (s_gsm,
+	              NM_SETTING_GSM_NUMBER, "#99*",
+	              NM_SETTING_GSM_APN, "myapn",
+	              NM_SETTING_GSM_USERNAME, "adfasdfasdf",
+	              NM_SETTING_GSM_PASSWORD_FLAGS, NM_SETTING_SECRET_FLAG_NOT_SAVED | NM_SETTING_SECRET_FLAG_NOT_REQUIRED,
+	              NULL);
+
+	nmtst_connection_normalize (connection);
+
+	/* Write out the connection */
+	owner_uid = geteuid ();
+	owner_grp = getegid ();
+	success = nm_keyfile_plugin_write_test_connection (connection, TEST_SCRATCH_DIR, owner_uid, owner_grp, &testfile, &error);
+	g_assert_no_error (error);
+	g_assert (success);
+	g_assert (testfile);
+
+	/* Read the connection back in and compare it to the one we just wrote out */
+	reread = nm_keyfile_plugin_connection_from_file (testfile, &error);
+	g_assert_no_error (error);
+	g_assert (reread);
+
+	nmtst_assert_connection_equals (reread, FALSE, connection, FALSE);
+
+	unlink (testfile);
+	g_free (testfile);
+
+	g_object_unref (reread);
+	g_object_unref (connection);
+}
+
 NMTST_DEFINE ();
 
 int main (int argc, char **argv)
 {
-	char *base;
-
 	nmtst_init_assert_logging (&argc, &argv);
 
 	/* The tests */
-	test_read_valid_wired_connection ();
-	test_write_wired_connection ();
+	g_test_add_func ("/keyfile/test_read_valid_wired_connection ", test_read_valid_wired_connection);
+	g_test_add_func ("/keyfile/test_write_wired_connection ", test_write_wired_connection);
+
+	g_test_add_func ("/keyfile/test_read_ip6_wired_connection ", test_read_ip6_wired_connection);
+	g_test_add_func ("/keyfile/test_write_ip6_wired_connection ", test_write_ip6_wired_connection);
+
+	g_test_add_func ("/keyfile/test_read_wired_mac_case ", test_read_wired_mac_case);
+	g_test_add_func ("/keyfile/test_read_mac_old_format ", test_read_mac_old_format);
+	g_test_add_func ("/keyfile/test_read_mac_ib_old_format ", test_read_mac_ib_old_format);
 
-	test_read_ip6_wired_connection ();
-	test_write_ip6_wired_connection ();
+	g_test_add_func ("/keyfile/test_read_valid_wireless_connection ", test_read_valid_wireless_connection);
+	g_test_add_func ("/keyfile/test_write_wireless_connection ", test_write_wireless_connection);
 
-	test_read_wired_mac_case ();
-	test_read_mac_old_format ();
-	test_read_mac_ib_old_format ();
+	g_test_add_func ("/keyfile/test_read_string_ssid ", test_read_string_ssid);
+	g_test_add_func ("/keyfile/test_write_string_ssid ", test_write_string_ssid);
 
-	test_read_valid_wireless_connection ();
-	test_write_wireless_connection ();
+	g_test_add_func ("/keyfile/test_read_intlist_ssid ", test_read_intlist_ssid);
+	g_test_add_func ("/keyfile/test_write_intlist_ssid ", test_write_intlist_ssid);
 
-	test_read_string_ssid ();
-	test_write_string_ssid ();
+	g_test_add_func ("/keyfile/test_read_intlike_ssid ", test_read_intlike_ssid);
+	g_test_add_func ("/keyfile/test_write_intlike_ssid ", test_write_intlike_ssid);
 
-	test_read_intlist_ssid ();
-	test_write_intlist_ssid ();
+	g_test_add_func ("/keyfile/test_read_intlike_ssid_2 ", test_read_intlike_ssid_2);
+	g_test_add_func ("/keyfile/test_write_intlike_ssid_2 ", test_write_intlike_ssid_2);
 
-	test_read_intlike_ssid ();
-	test_write_intlike_ssid ();
+	g_test_add_func ("/keyfile/test_read_bt_dun_connection ", test_read_bt_dun_connection);
+	g_test_add_func ("/keyfile/test_write_bt_dun_connection ", test_write_bt_dun_connection);
 
-	test_read_intlike_ssid_2 ();
-	test_write_intlike_ssid_2 ();
+	g_test_add_func ("/keyfile/test_read_gsm_connection ", test_read_gsm_connection);
+	g_test_add_func ("/keyfile/test_write_gsm_connection ", test_write_gsm_connection);
 
-	test_read_bt_dun_connection ();
-	test_write_bt_dun_connection ();
+	g_test_add_func ("/keyfile/test_read_wired_8021x_tls_blob_connection ", test_read_wired_8021x_tls_blob_connection);
+	g_test_add_func ("/keyfile/test_read_wired_8021x_tls_bad_path_connection ", test_read_wired_8021x_tls_bad_path_connection);
 
-	test_read_gsm_connection ();
-	test_write_gsm_connection ();
+	g_test_add_func ("/keyfile/test_read_wired_8021x_tls_old_connection ", test_read_wired_8021x_tls_old_connection);
+	g_test_add_func ("/keyfile/test_read_wired_8021x_tls_new_connection ", test_read_wired_8021x_tls_new_connection);
+	g_test_add_func ("/keyfile/test_write_wired_8021x_tls_connection_path ", test_write_wired_8021x_tls_connection_path);
+	g_test_add_func ("/keyfile/test_write_wired_8021x_tls_connection_blob ", test_write_wired_8021x_tls_connection_blob);
 
-	test_read_wired_8021x_tls_blob_connection ();
-	test_read_wired_8021x_tls_bad_path_connection ();
+	g_test_add_func ("/keyfile/test_read_infiniband_connection ", test_read_infiniband_connection);
+	g_test_add_func ("/keyfile/test_write_infiniband_connection ", test_write_infiniband_connection);
 
-	test_read_wired_8021x_tls_old_connection ();
-	test_read_wired_8021x_tls_new_connection ();
-	test_write_wired_8021x_tls_connection_path ();
-	test_write_wired_8021x_tls_connection_blob ();
+	g_test_add_func ("/keyfile/test_read_bridge_main ", test_read_bridge_main);
+	g_test_add_func ("/keyfile/test_write_bridge_main ", test_write_bridge_main);
+	g_test_add_func ("/keyfile/test_read_bridge_component ", test_read_bridge_component);
+	g_test_add_func ("/keyfile/test_write_bridge_component ", test_write_bridge_component);
 
-	test_read_infiniband_connection ();
-	test_write_infiniband_connection ();
+	g_test_add_func ("/keyfile/test_read_new_wired_group_name ", test_read_new_wired_group_name);
+	g_test_add_func ("/keyfile/test_write_new_wired_group_name ", test_write_new_wired_group_name);
+	g_test_add_func ("/keyfile/test_read_new_wireless_group_names ", test_read_new_wireless_group_names);
+	g_test_add_func ("/keyfile/test_write_new_wireless_group_names ", test_write_new_wireless_group_names);
 
-	test_read_bridge_main ();
-	test_write_bridge_main ();
-	test_read_bridge_component ();
-	test_write_bridge_component ();
+	g_test_add_func ("/keyfile/test_read_missing_vlan_setting ", test_read_missing_vlan_setting);
+	g_test_add_func ("/keyfile/test_read_missing_id_uuid ", test_read_missing_id_uuid);
 
-	test_read_new_wired_group_name ();
-	test_write_new_wired_group_name ();
-	test_read_new_wireless_group_names ();
-	test_write_new_wireless_group_names ();
+	g_test_add_func ("/keyfile/test_read_minimal", test_read_minimal);
+	g_test_add_func ("/keyfile/test_read_minimal_slave", test_read_minimal_slave);
 
-	test_read_missing_vlan_setting ();
+	g_test_add_func ("/keyfile/test_read_enum_property ", test_read_enum_property);
+	g_test_add_func ("/keyfile/test_write_enum_property ", test_write_enum_property);
+	g_test_add_func ("/keyfile/test_read_flags_property ", test_read_flags_property);
+	g_test_add_func ("/keyfile/test_write_flags_property ", test_write_flags_property);
 
-	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/keyfile/utils.c b/src/settings/plugins/keyfile/utils.c
index e2bfc38c..3361d554 100644
--- a/src/settings/plugins/keyfile/utils.c
+++ b/src/settings/plugins/keyfile/utils.c
@@ -18,6 +18,8 @@
  * (C) Copyright 2010 Red Hat, Inc.
  */
 
+#include "config.h"
+
 #include <glib.h>
 #include <stdlib.h>
 #include <string.h>
@@ -229,6 +231,7 @@ nm_keyfile_plugin_kf_set_##stype (GKeyFile *kf, \
 
 DEFINE_KF_WRAPPER(string, gchar*, const gchar*);
 DEFINE_KF_WRAPPER(integer, gint, gint);
+DEFINE_KF_WRAPPER(uint64, guint64, guint64);
 DEFINE_KF_WRAPPER(boolean, gboolean, gboolean);
 DEFINE_KF_WRAPPER(value, gchar*, const gchar*);
 
diff --git a/src/settings/plugins/keyfile/utils.h b/src/settings/plugins/keyfile/utils.h
index 9a2e485b..1a7c2502 100644
--- a/src/settings/plugins/keyfile/utils.h
+++ b/src/settings/plugins/keyfile/utils.h
@@ -61,6 +61,7 @@ void nm_keyfile_plugin_kf_set_##stype (GKeyFile *kf, \
                                        set_ctype value);
 DEFINE_KF_WRAPPER_PROTO(string, gchar*, const gchar*)
 DEFINE_KF_WRAPPER_PROTO(integer, gint, gint)
+DEFINE_KF_WRAPPER_PROTO(uint64, guint64, guint64)
 DEFINE_KF_WRAPPER_PROTO(boolean, gboolean, gboolean)
 DEFINE_KF_WRAPPER_PROTO(value, gchar*, const gchar*)
 
diff --git a/src/settings/plugins/keyfile/writer.c b/src/settings/plugins/keyfile/writer.c
index 5f3ebe25..d342e3f7 100644
--- a/src/settings/plugins/keyfile/writer.c
+++ b/src/settings/plugins/keyfile/writer.c
@@ -19,7 +19,8 @@
  * Copyright (C) 2008 - 2012 Red Hat, Inc.
  */
 
-#include <config.h>
+#include "config.h"
+
 #include <stdlib.h>
 #include <sys/stat.h>
 #include <unistd.h>
@@ -40,7 +41,6 @@
 #include <nm-utils.h>
 #include <string.h>
 #include <arpa/inet.h>
-#include <netinet/ether.h>
 
 #include "nm-dbus-glib-types.h"
 #include "nm-glib-compat.h"
@@ -98,75 +98,77 @@ write_array_of_uint (GKeyFile *file,
 }
 
 static void
-ip4_dns_writer (GKeyFile *file,
-                const char *keyfile_dir,
-                const char *uuid,
-                NMSetting *setting,
-                const char *key,
-                const GValue *value)
+dns_writer (GKeyFile *file,
+            const char *keyfile_dir,
+            const char *uuid,
+            NMSetting *setting,
+            const char *key,
+            const GValue *value)
 {
-	GArray *array;
 	char **list;
-	int i, num = 0;
 
-	g_return_if_fail (G_VALUE_HOLDS (value, DBUS_TYPE_G_UINT_ARRAY));
-
-	array = (GArray *) g_value_get_boxed (value);
-	if (!array || !array->len)
-		return;
-
-	list = g_new0 (char *, array->len + 1);
-
-	for (i = 0; i < array->len; i++) {
-		char *buf = g_new (char, INET_ADDRSTRLEN);
-		guint32 addr;
-
-		addr = g_array_index (array, guint32, i);
-		nm_utils_inet4_ntop (addr, buf);
-		list[num++] = buf;
+	list = g_value_get_boxed (value);
+	if (list && list[0]) {
+		nm_keyfile_plugin_kf_set_string_list (file, nm_setting_get_name (setting), key,
+		                                      (const char **) list, g_strv_length (list));
 	}
-
-	nm_keyfile_plugin_kf_set_string_list (file, nm_setting_get_name (setting), key, (const char **) list, num);
-	g_strfreev (list);
 }
 
 static void
-write_ip4_values (GKeyFile *file,
-                  const char *setting_name,
-                  GPtrArray *array,
-                  gboolean is_route)
+write_ip_values (GKeyFile *file,
+                 const char *setting_name,
+                 GPtrArray *array,
+                 const char *gateway,
+                 gboolean is_route)
 {
 	GString *output;
-	int i;
-	guint32 addr, gw, plen, metric;
+	int family, i;
+	const char *addr, *gw;
+	guint32 plen, metric;
 	char key_name[30], *key_name_idx;
 
 	if (!array->len)
 		return;
 
+	family = !strcmp (setting_name, NM_SETTING_IP4_CONFIG_SETTING_NAME) ? AF_INET : AF_INET6;
+
 	strcpy (key_name, is_route ? "route" : "address");
 	key_name_idx = key_name + strlen (key_name);
 
 	output = g_string_sized_new (2*INET_ADDRSTRLEN + 10);
 	for (i = 0; i < array->len; i++) {
-		GArray *tuple = g_ptr_array_index (array, i);
+		if (is_route) {
+			NMIPRoute *route = array->pdata[i];
+
+			addr = nm_ip_route_get_dest (route);
+			plen = nm_ip_route_get_prefix (route);
+			gw = nm_ip_route_get_next_hop (route);
+			metric = MAX (0, nm_ip_route_get_metric (route));
+		} else {
+			NMIPAddress *address = array->pdata[i];
 
-		addr = g_array_index (tuple, guint32, 0);
-		plen = g_array_index (tuple, guint32, 1);
-		gw = g_array_index (tuple, guint32, 2);
-		metric = is_route ? g_array_index (tuple, guint32, 3) : 0;
+			addr = nm_ip_address_get_address (address);
+			plen = nm_ip_address_get_prefix (address);
+			gw = i == 0 ? gateway : NULL;
+			metric = 0;
+		}
 
 		g_string_set_size (output, 0);
-		g_string_append_printf (output, "%s/%u",
-		                        nm_utils_inet4_ntop (addr, NULL),
-		                        (unsigned) plen);
+		g_string_append_printf (output, "%s/%u", addr, plen);
 		if (metric || gw) {
 			/* Older versions of the plugin do not support the form
 			 * "a.b.c.d/plen,,metric", so, we always have to write the
-			 * gateway, even if it's 0.0.0.0.
-			 * The current version support reading of the above form. */
-			g_string_append_c (output, ',');
-			g_string_append (output, nm_utils_inet4_ntop (gw, NULL));
+			 * gateway, even if there isn't one.
+			 * The current version supports reading of the above form.
+			 */
+			if (!gw) {
+				if (family == AF_INET)
+					gw = "0.0.0.0";
+				else
+					gw = "::";
+			}
+
+			g_string_append_printf (output, ",%s", gw);
 			if (metric)
 				g_string_append_printf (output, ",%lu", (unsigned long) metric);
 		}
@@ -178,21 +180,20 @@ write_ip4_values (GKeyFile *file,
 }
 
 static void
-ip4_addr_writer (GKeyFile *file,
-                 const char *keyfile_dir,
-                 const char *uuid,
-                 NMSetting *setting,
-                 const char *key,
-                 const GValue *value)
+addr_writer (GKeyFile *file,
+             const char *keyfile_dir,
+             const char *uuid,
+             NMSetting *setting,
+             const char *key,
+             const GValue *value)
 {
 	GPtrArray *array;
 	const char *setting_name = nm_setting_get_name (setting);
-
-	g_return_if_fail (G_VALUE_HOLDS (value, DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT));
+	const char *gateway = nm_setting_ip_config_get_gateway (NM_SETTING_IP_CONFIG (setting));
 
 	array = (GPtrArray *) g_value_get_boxed (value);
 	if (array && array->len)
-		write_ip4_values (file, setting_name, array, FALSE);
+		write_ip_values (file, setting_name, array, gateway, FALSE);
 }
 
 static void
@@ -207,223 +208,30 @@ ip4_addr_label_writer (GKeyFile *file,
 }
 
 static void
-ip4_route_writer (GKeyFile *file,
-                  const char *keyfile_dir,
-                  const char *uuid,
-                  NMSetting *setting,
-                  const char *key,
-                  const GValue *value)
-{
-	GPtrArray *array;
-	const char *setting_name = nm_setting_get_name (setting);
-
-	g_return_if_fail (G_VALUE_HOLDS (value, DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT));
-
-	array = (GPtrArray *) g_value_get_boxed (value);
-	if (array && array->len)
-		write_ip4_values (file, setting_name, array, TRUE);
-}
-
-static void
-ip6_dns_writer (GKeyFile *file,
+gateway_writer (GKeyFile *file,
                 const char *keyfile_dir,
                 const char *uuid,
                 NMSetting *setting,
                 const char *key,
                 const GValue *value)
 {
-	GPtrArray *array;
-	GByteArray *byte_array;
-	char **list;
-	int i, num = 0;
-
-	g_return_if_fail (G_VALUE_HOLDS (value, DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UCHAR));
-
-	array = (GPtrArray *) g_value_get_boxed (value);
-	if (!array || !array->len)
-		return;
-
-	list = g_new0 (char *, array->len + 1);
-
-	for (i = 0; i < array->len; i++) {
-		char *buf = g_new (char, INET6_ADDRSTRLEN);
-
-		byte_array = g_ptr_array_index (array, i);
-		nm_utils_inet6_ntop ((const struct in6_addr *) byte_array->data, buf);
-		list[num++] = buf;
-	}
-
-	nm_keyfile_plugin_kf_set_string_list (file, nm_setting_get_name (setting), key, (const char **) list, num);
-	g_strfreev (list);
-}
-
-static void
-ip6_array_to_addr (GValueArray *values,
-                   guint32 idx,
-                   char *buf,
-                   struct in6_addr *out_addr)
-{
-	GByteArray *byte_array;
-	GValue *addr_val;
-	const struct in6_addr *addr;
-
-	addr_val = g_value_array_get_nth (values, idx);
-	byte_array = g_value_get_boxed (addr_val);
-	addr = (const struct in6_addr *) byte_array->data;
-
-	nm_utils_inet6_ntop (addr, buf);
-
-	if (out_addr)
-		*out_addr = *addr;
-}
-
-static char *
-ip6_array_to_addr_prefix (GValueArray *values, gboolean force_write_gateway)
-{
-	GValue *prefix_val;
-	char *ret = NULL;
-	GString *ip6_str;
-	char buf[INET6_ADDRSTRLEN];
-	struct in6_addr addr;
-
-	/* address */
-	ip6_array_to_addr (values, 0, buf, NULL);
-
-	/* Enough space for the address, '/', and the prefix */
-	ip6_str = g_string_sized_new ((INET6_ADDRSTRLEN * 2) + 5);
-
-	/* prefix */
-	g_string_append (ip6_str, buf);
-	prefix_val = g_value_array_get_nth (values, 1);
-	g_string_append_printf (ip6_str, "/%u", g_value_get_uint (prefix_val));
-
-	ip6_array_to_addr (values, 2, buf, &addr);
-	if (force_write_gateway || !IN6_IS_ADDR_UNSPECIFIED (&addr))
-		g_string_append_printf (ip6_str, ",%s", buf);
-
-	ret = ip6_str->str;
-	g_string_free (ip6_str, FALSE);
-
-	return ret;
-}
-
-static void
-ip6_addr_writer (GKeyFile *file,
-                 const char *keyfile_dir,
-                 const char *uuid,
-                 NMSetting *setting,
-                 const char *key,
-                 const GValue *value)
-{
-	GPtrArray *array;
-	const char *setting_name = nm_setting_get_name (setting);
-	int i, j;
-
-	g_return_if_fail (G_VALUE_HOLDS (value, DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS));
-
-	array = (GPtrArray *) g_value_get_boxed (value);
-	if (!array || !array->len)
-		return;
-
-	for (i = 0, j = 1; i < array->len; i++) {
-		GValueArray *values = g_ptr_array_index (array, i);
-		char *key_name, *ip6_addr;
-
-		if (values->n_values != 3) {
-			nm_log_warn (LOGD_SETTINGS, "%s: error writing IP6 address %d (address array "
-			             "length %d is not 3)", __func__, i, values->n_values);
-			continue;
-		}
-
-		/* we allow omitting the gateway if it's :: */
-		ip6_addr = ip6_array_to_addr_prefix (values, FALSE);
-		/* Write it out */
-		key_name = g_strdup_printf ("address%d", j++);
-		nm_keyfile_plugin_kf_set_string (file, setting_name, key_name, ip6_addr);
-		g_free (key_name);
-		g_free (ip6_addr);
-	}
+	/* skip */
 }
 
 static void
-ip6_route_writer (GKeyFile *file,
-                  const char *keyfile_dir,
-                  const char *uuid,
-                  NMSetting *setting,
-                  const char *key,
-                  const GValue *value)
+route_writer (GKeyFile *file,
+              const char *keyfile_dir,
+              const char *uuid,
+              NMSetting *setting,
+              const char *key,
+              const GValue *value)
 {
 	GPtrArray *array;
 	const char *setting_name = nm_setting_get_name (setting);
-	GString *output;
-	int i, j;
-
-	g_return_if_fail (G_VALUE_HOLDS (value, DBUS_TYPE_G_ARRAY_OF_IP6_ROUTE));
 
 	array = (GPtrArray *) g_value_get_boxed (value);
-	if (!array || !array->len)
-		return;
-
-	for (i = 0, j = 1; i < array->len; i++) {
-		GValueArray *values = g_ptr_array_index (array, i);
-		char *key_name;
-		char *addr_str;
-		guint metric;
-
-		output = g_string_new ("");
-
-		/* Metric */
-		value = g_value_array_get_nth (values, 3);
-		metric = g_value_get_uint (value);
-
-		/* Address, prefix and next hop
-		 * We allow omitting the gateway ::, if we also omit the metric
-		 * and force writing of the gateway, if we add a non zero metric.
-		 * The current version of the reader also supports the syntax
-		 * "a:b:c::/plen,,metric" for a gateway ::.
-		 * As older versions of the plugin, cannot read this form,
-		 * we always write the gateway, whenever we also write the metric.
-		 * But if possible, we omit them both (",::,0") or only the metric
-		 * (",0").
-		 **/
-		addr_str = ip6_array_to_addr_prefix (values, metric != 0);
-		g_string_append (output, addr_str);
-		g_free (addr_str);
-
-		if (metric != 0)
-			g_string_append_printf (output, ",%u", metric);
-
-		/* Write it out */
-		key_name = g_strdup_printf ("route%d", j++);
-		nm_keyfile_plugin_kf_set_string (file, setting_name, key_name, output->str);
-		g_free (key_name);
-
-		g_string_free (output, TRUE);
-	}
-}
-
-
-static void
-mac_address_writer (GKeyFile *file,
-                    const char *keyfile_dir,
-                    const char *uuid,
-                    NMSetting *setting,
-                    const char *key,
-                    const GValue *value)
-{
-	GByteArray *array;
-	const char *setting_name = nm_setting_get_name (setting);
-	char *mac;
-
-	g_return_if_fail (G_VALUE_HOLDS (value, DBUS_TYPE_G_UCHAR_ARRAY));
-
-	array = (GByteArray *) g_value_get_boxed (value);
-	if (!array || !array->len)
-		return;
-
-	mac = nm_utils_hwaddr_ntoa_len (array->data, array->len);
-	nm_keyfile_plugin_kf_set_string (file, setting_name, key, mac);
-	g_free (mac);
+	if (array && array->len)
+		write_ip_values (file, setting_name, array, NULL, TRUE);
 }
 
 static void
@@ -472,24 +280,29 @@ ssid_writer (GKeyFile *file,
              const char *key,
              const GValue *value)
 {
-	GByteArray *array;
+	GBytes *bytes;
+	const guint8 *ssid_data;
+	gsize ssid_len;
 	const char *setting_name = nm_setting_get_name (setting);
 	gboolean new_format = TRUE;
 	unsigned int semicolons = 0;
 	int i, *tmp_array;
 	char *ssid;
 
-	g_return_if_fail (G_VALUE_HOLDS (value, DBUS_TYPE_G_UCHAR_ARRAY));
+	g_return_if_fail (G_VALUE_HOLDS (value, G_TYPE_BYTES));
 
-	array = (GByteArray *) g_value_get_boxed (value);
-	if (!array || !array->len)
+	bytes = g_value_get_boxed (value);
+	if (!bytes)
+		return;
+	ssid_data = g_bytes_get_data (bytes, &ssid_len);
+	if (ssid_len == 0)
 		return;
 
 	/* Check whether each byte is printable.  If not, we have to use an
 	 * integer list, otherwise we can just use a string.
 	 */
-	for (i = 0; i < array->len; i++) {
-		char c = array->data[i] & 0xFF;
+	for (i = 0; i < ssid_len; i++) {
+		char c = ssid_data[i] & 0xFF;
 		if (!g_ascii_isprint (c)) {
 			new_format = FALSE;
 			break;
@@ -499,26 +312,26 @@ ssid_writer (GKeyFile *file,
 	}
 
 	if (new_format) {
-		ssid = g_malloc0 (array->len + semicolons + 1);
+		ssid = g_malloc0 (ssid_len + semicolons + 1);
 		if (semicolons == 0)
-			memcpy (ssid, array->data, array->len);
+			memcpy (ssid, ssid_data, ssid_len);
 		else {
 			/* Escape semicolons with backslashes to make strings
 			 * containing ';', such as '16;17;' unambiguous */
 			int j = 0;
-			for (i = 0; i < array->len; i++) {
-				if (array->data[i] == ';')
+			for (i = 0; i < ssid_len; i++) {
+				if (ssid_data[i] == ';')
 					ssid[j++] = '\\';
-				ssid[j++] = array->data[i];
+				ssid[j++] = ssid_data[i];
 			}
 		}
 		nm_keyfile_plugin_kf_set_string (file, setting_name, key, ssid);
 		g_free (ssid);
 	} else {
-		tmp_array = g_new (gint, array->len);
-		for (i = 0; i < array->len; i++)
-			tmp_array[i] = (int) array->data[i];
-		nm_keyfile_plugin_kf_set_integer_list (file, setting_name, key, tmp_array, array->len);
+		tmp_array = g_new (gint, ssid_len);
+		for (i = 0; i < ssid_len; i++)
+			tmp_array[i] = (int) ssid_data[i];
+		nm_keyfile_plugin_kf_set_integer_list (file, setting_name, key, tmp_array, ssid_len);
 		g_free (tmp_array);
 	}
 }
@@ -555,7 +368,7 @@ typedef struct ObjectType {
 	NMSetting8021xCKScheme (*scheme_func) (NMSetting8021x *setting);
 	NMSetting8021xCKFormat (*format_func) (NMSetting8021x *setting);
 	const char *           (*path_func)   (NMSetting8021x *setting);
-	const GByteArray *     (*blob_func)   (NMSetting8021x *setting);
+	GBytes *               (*blob_func)   (NMSetting8021x *setting);
 } ObjectType;
 
 static const ObjectType objtypes[10] = {
@@ -612,7 +425,8 @@ static const ObjectType objtypes[10] = {
 
 static gboolean
 write_cert_key_file (const char *path,
-                     const GByteArray *data,
+                     const guint8 *data,
+                     gsize data_len,
                      GError **error)
 {
 	char *tmppath;
@@ -627,7 +441,7 @@ write_cert_key_file (const char *path,
 	errno = 0;
 	fd = mkstemp (tmppath);
 	if (fd < 0) {
-		g_set_error (error, KEYFILE_PLUGIN_ERROR, 0,
+		g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
 		             "Could not create temporary file for '%s': %d",
 		             path, errno);
 		goto out;
@@ -638,18 +452,18 @@ write_cert_key_file (const char *path,
 	if (fchmod (fd, S_IRUSR | S_IWUSR) != 0) {
 		close (fd);
 		unlink (tmppath);
-		g_set_error (error, KEYFILE_PLUGIN_ERROR, 0,
+		g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
 		             "Could not set permissions for temporary file '%s': %d",
 		             path, errno);
 		goto out;
 	}
 
 	errno = 0;
-	written = write (fd, data->data, data->len);
-	if (written != data->len) {
+	written = write (fd, data, data_len);
+	if (written != data_len) {
 		close (fd);
 		unlink (tmppath);
-		g_set_error (error, KEYFILE_PLUGIN_ERROR, 0,
+		g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
 		             "Could not write temporary file for '%s': %d",
 		             path, errno);
 		goto out;
@@ -662,7 +476,7 @@ write_cert_key_file (const char *path,
 		success = TRUE;
 	else {
 		unlink (tmppath);
-		g_set_error (error, KEYFILE_PLUGIN_ERROR, 0,
+		g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
 		             "Could not rename temporary file to '%s': %d",
 		             path, errno);
 	}
@@ -714,13 +528,16 @@ cert_writer (GKeyFile *file,
 
 		nm_keyfile_plugin_kf_set_string (file, setting_name, key, path);
 	} else if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) {
-		const GByteArray *blob;
+		GBytes *blob;
+		const guint8 *blob_data;
+		gsize blob_len;
 		gboolean success;
 		GError *error = NULL;
 		char *new_path;
 
 		blob = objtype->blob_func (NM_SETTING_802_1X (setting));
 		g_assert (blob);
+		blob_data = g_bytes_get_data (blob, &blob_len);
 
 		if (objtype->format_func) {
 			/* Get the extension for a private key */
@@ -729,7 +546,7 @@ cert_writer (GKeyFile *file,
 				ext = "p12";
 		} else {
 			/* DER or PEM format certificate? */
-			if (blob->len > 2 && blob->data[0] == 0x30 && blob->data[1] == 0x82)
+			if (blob_len > 2 && blob_data[0] == 0x30 && blob_data[1] == 0x82)
 				ext = "der";
 		}
 
@@ -739,7 +556,7 @@ cert_writer (GKeyFile *file,
 		new_path = g_strdup_printf ("%s/%s-%s.%s", keyfile_dir, uuid, objtype->suffix, ext);
 		g_assert (new_path);
 
-		success = write_cert_key_file (new_path, blob, &error);
+		success = write_cert_key_file (new_path, blob_data, blob_len, &error);
 		if (success) {
 			/* Write the path value to the keyfile */
 			nm_keyfile_plugin_kf_set_string (file, setting_name, key, new_path);
@@ -774,54 +591,33 @@ static KeyWriter key_writers[] = {
 	{ NM_SETTING_CONNECTION_SETTING_NAME,
 	  NM_SETTING_CONNECTION_TYPE,
 	  setting_alias_writer },
-	{ NM_SETTING_BRIDGE_SETTING_NAME,
-	  NM_SETTING_BRIDGE_MAC_ADDRESS,
-	  mac_address_writer },
 	{ NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	  NM_SETTING_IP4_CONFIG_ADDRESSES,
-	  ip4_addr_writer },
+	  NM_SETTING_IP_CONFIG_ADDRESSES,
+	  addr_writer },
 	{ NM_SETTING_IP4_CONFIG_SETTING_NAME,
 	  "address-labels",
 	  ip4_addr_label_writer },
 	{ NM_SETTING_IP6_CONFIG_SETTING_NAME,
-	  NM_SETTING_IP6_CONFIG_ADDRESSES,
-	  ip6_addr_writer },
+	  NM_SETTING_IP_CONFIG_ADDRESSES,
+	  addr_writer },
 	{ NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	  NM_SETTING_IP4_CONFIG_ROUTES,
-	  ip4_route_writer },
+	  NM_SETTING_IP_CONFIG_GATEWAY,
+	  gateway_writer },
 	{ NM_SETTING_IP6_CONFIG_SETTING_NAME,
-	  NM_SETTING_IP6_CONFIG_ROUTES,
-	  ip6_route_writer },
+	  NM_SETTING_IP_CONFIG_GATEWAY,
+	  gateway_writer },
 	{ NM_SETTING_IP4_CONFIG_SETTING_NAME,
-	  NM_SETTING_IP4_CONFIG_DNS,
-	  ip4_dns_writer },
+	  NM_SETTING_IP_CONFIG_ROUTES,
+	  route_writer },
 	{ NM_SETTING_IP6_CONFIG_SETTING_NAME,
-	  NM_SETTING_IP6_CONFIG_DNS,
-	  ip6_dns_writer },
-	{ NM_SETTING_WIRED_SETTING_NAME,
-	  NM_SETTING_WIRED_MAC_ADDRESS,
-	  mac_address_writer },
-	{ NM_SETTING_WIRED_SETTING_NAME,
-	  NM_SETTING_WIRED_CLONED_MAC_ADDRESS,
-	  mac_address_writer },
-	{ NM_SETTING_WIRELESS_SETTING_NAME,
-	  NM_SETTING_WIRELESS_MAC_ADDRESS,
-	  mac_address_writer },
-	{ NM_SETTING_WIRELESS_SETTING_NAME,
-	  NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS,
-	  mac_address_writer },
-	{ NM_SETTING_WIRELESS_SETTING_NAME,
-	  NM_SETTING_WIRELESS_BSSID,
-	  mac_address_writer },
-	{ NM_SETTING_BLUETOOTH_SETTING_NAME,
-	  NM_SETTING_BLUETOOTH_BDADDR,
-	  mac_address_writer },
-	{ NM_SETTING_INFINIBAND_SETTING_NAME,
-	  NM_SETTING_INFINIBAND_MAC_ADDRESS,
-	  mac_address_writer },
-	{ NM_SETTING_WIMAX_SETTING_NAME,
-	  NM_SETTING_WIMAX_MAC_ADDRESS,
-	  mac_address_writer },
+	  NM_SETTING_IP_CONFIG_ROUTES,
+	  route_writer },
+	{ NM_SETTING_IP4_CONFIG_SETTING_NAME,
+	  NM_SETTING_IP_CONFIG_DNS,
+	  dns_writer },
+	{ NM_SETTING_IP6_CONFIG_SETTING_NAME,
+	  NM_SETTING_IP_CONFIG_DNS,
+	  dns_writer },
 	{ NM_SETTING_WIRELESS_SETTING_NAME,
 	  NM_SETTING_WIRELESS_SSID,
 	  ssid_writer },
@@ -896,7 +692,8 @@ write_setting_value (NMSetting *setting,
 	if (pspec && (pspec->flags & NM_SETTING_PARAM_SECRET) && !NM_IS_SETTING_VPN (setting)) {
 		NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE;
 
-		nm_setting_get_secret_flags (setting, key, &secret_flags, NULL);
+		if (!nm_setting_get_secret_flags (setting, key, &secret_flags, NULL))
+			g_assert_not_reached ();
 		if (secret_flags != NM_SETTING_SECRET_FLAG_NONE)
 			return;
 	}
@@ -926,49 +723,53 @@ write_setting_value (NMSetting *setting,
 		numstr = g_strdup_printf ("%" G_GUINT64_FORMAT, g_value_get_uint64 (value));
 		nm_keyfile_plugin_kf_set_value (info->keyfile, setting_name, key, numstr);
 		g_free (numstr);
+	} else if (type == G_TYPE_INT64) {
+		char *numstr;
+
+		numstr = g_strdup_printf ("%" G_GINT64_FORMAT, g_value_get_int64 (value));
+		nm_keyfile_plugin_kf_set_value (info->keyfile, setting_name, key, numstr);
+		g_free (numstr);
 	} else if (type == G_TYPE_BOOLEAN) {
 		nm_keyfile_plugin_kf_set_boolean (info->keyfile, setting_name, key, g_value_get_boolean (value));
 	} else if (type == G_TYPE_CHAR) {
 		nm_keyfile_plugin_kf_set_integer (info->keyfile, setting_name, key, (int) g_value_get_schar (value));
-	} else if (type == DBUS_TYPE_G_UCHAR_ARRAY) {
-		GByteArray *array;
+	} else if (type == G_TYPE_BYTES) {
+		GBytes *bytes;
+		const guint8 *data;
+		gsize len = 0;
 
-		array = (GByteArray *) g_value_get_boxed (value);
-		if (array && array->len > 0) {
+		bytes = g_value_get_boxed (value);
+		data = bytes ? g_bytes_get_data (bytes, &len) : NULL;
+
+		if (data != NULL && len > 0) {
 			int *tmp_array;
 			int i;
 
-			tmp_array = g_new (gint, array->len);
-			for (i = 0; i < array->len; i++)
-				tmp_array[i] = (int) array->data[i];
+			tmp_array = g_new (gint, len);
+			for (i = 0; i < len; i++)
+				tmp_array[i] = (int) data[i];
 
-			nm_keyfile_plugin_kf_set_integer_list (info->keyfile, setting_name, key, tmp_array, array->len);
+			nm_keyfile_plugin_kf_set_integer_list (info->keyfile, setting_name, key, tmp_array, len);
 			g_free (tmp_array);
 		}
-	} else if (type == DBUS_TYPE_G_LIST_OF_STRING) {
-		GSList *list;
-		GSList *iter;
-
-		list = (GSList *) g_value_get_boxed (value);
-		if (list) {
-			char **array;
-			int i = 0;
+	} else if (type == G_TYPE_STRV) {
+		char **array;
 
-			array = g_new (char *, g_slist_length (list));
-			for (iter = list; iter; iter = iter->next)
-				array[i++] = iter->data;
-
-			nm_keyfile_plugin_kf_set_string_list (info->keyfile, setting_name, key, (const gchar **const) array, i);
-			g_free (array);
-		}
-	} else if (type == DBUS_TYPE_G_MAP_OF_STRING) {
+		array = (char **) g_value_get_boxed (value);
+		nm_keyfile_plugin_kf_set_string_list (info->keyfile, setting_name, key, (const gchar **const) array, g_strv_length (array));
+	} else if (type == G_TYPE_HASH_TABLE) {
 		write_hash_of_string (info->keyfile, setting, key, value);
-	} else if (type == DBUS_TYPE_G_UINT_ARRAY) {
+	} else if (type == G_TYPE_ARRAY) {
 		if (!write_array_of_uint (info->keyfile, setting, key, value)) {
 			nm_log_warn (LOGD_SETTINGS, "Unhandled setting property type (write) '%s/%s' : '%s'", 
 			             setting_name, key, g_type_name (type));
 		}
-	} else {
+	} else if (G_VALUE_HOLDS_FLAGS (value)) {
+		/* Flags are guint but GKeyFile has no uint reader, just uint64 */
+		nm_keyfile_plugin_kf_set_uint64 (info->keyfile, setting_name, key, (guint64) g_value_get_flags (value));
+	} else if (G_VALUE_HOLDS_ENUM (value))
+		nm_keyfile_plugin_kf_set_integer (info->keyfile, setting_name, key, (gint) g_value_get_enum (value));
+	else {
 		nm_log_warn (LOGD_SETTINGS, "Unhandled setting property type (write) '%s/%s' : '%s'", 
 		             setting_name, key, g_type_name (type));
 	}
@@ -1021,11 +822,7 @@ _internal_write_connection (NMConnection *connection,
 	}
 
 	id = nm_connection_get_id (connection);
-	if (!id) {
-		g_set_error (error, KEYFILE_PLUGIN_ERROR, 0,
-		             "%s.%d: connection had no ID", __FILE__, __LINE__);
-		return FALSE;
-	}
+	g_assert (id && *id);
 
 	info.keyfile = key_file = g_key_file_new ();
 	info.keyfile_dir = keyfile_dir;
@@ -1065,7 +862,7 @@ _internal_write_connection (NMConnection *connection,
 				 * is edited to contain the same ID as the other one.
 				 * Give up.
 				 */
-				g_set_error (error, KEYFILE_PLUGIN_ERROR, 0,
+				g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
 				                    "%s.%d: could not find suitable keyfile file name (%s already used)",
 				                    __FILE__, __LINE__, path);
 				g_free (path);
@@ -1082,7 +879,7 @@ _internal_write_connection (NMConnection *connection,
 
 	g_file_set_contents (path, data, len, &local_err);
 	if (local_err) {
-		g_set_error (error, KEYFILE_PLUGIN_ERROR, 0,
+		g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
 		             "%s.%d: error writing to file '%s': %s", __FILE__, __LINE__,
 		             path, local_err->message);
 		g_error_free (local_err);
@@ -1091,13 +888,13 @@ _internal_write_connection (NMConnection *connection,
 	}
 
 	if (chown (path, owner_uid, owner_grp) < 0) {
-		g_set_error (error, KEYFILE_PLUGIN_ERROR, 0,
+		g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
 		             "%s.%d: error chowning '%s': %d", __FILE__, __LINE__,
 		             path, errno);
 		unlink (path);
 	} else {
 		if (chmod (path, S_IRUSR | S_IWUSR) < 0) {
-			g_set_error (error, KEYFILE_PLUGIN_ERROR, 0,
+			g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
 			             "%s.%d: error setting permissions on '%s': %d", __FILE__,
 			             __LINE__, path, errno);
 			unlink (path);