summary refs log tree commit diff
path: root/libnm-core
diff options
context:
space:
mode:
Diffstat (limited to 'libnm-core')
-rw-r--r--libnm-core/crypto.c826
-rw-r--r--libnm-core/crypto.h137
-rw-r--r--libnm-core/crypto_gnutls.c (renamed from libnm-core/nm-crypto-gnutls.c)317
-rw-r--r--libnm-core/crypto_nss.c (renamed from libnm-core/nm-crypto-nss.c)368
-rw-r--r--libnm-core/meson.build52
-rw-r--r--libnm-core/nm-connection.c257
-rw-r--r--libnm-core/nm-connection.h3
-rw-r--r--libnm-core/nm-core-enum-types.c.template1
-rw-r--r--libnm-core/nm-core-internal.h212
-rw-r--r--libnm-core/nm-core-types.h7
-rw-r--r--libnm-core/nm-crypto-impl.h74
-rw-r--r--libnm-core/nm-crypto.c1035
-rw-r--r--libnm-core/nm-crypto.h125
-rw-r--r--libnm-core/nm-dbus-interface.h77
-rw-r--r--libnm-core/nm-dbus-types.xml105
-rw-r--r--libnm-core/nm-dbus-utils.c6
-rw-r--r--libnm-core/nm-keyfile-utils.c14
-rw-r--r--libnm-core/nm-keyfile-utils.h12
-rw-r--r--libnm-core/nm-keyfile.c453
-rw-r--r--libnm-core/nm-property-compare.c8
-rw-r--r--libnm-core/nm-setting-6lowpan.c230
-rw-r--r--libnm-core/nm-setting-6lowpan.h54
-rw-r--r--libnm-core/nm-setting-8021x.c2767
-rw-r--r--libnm-core/nm-setting-8021x.h2
-rw-r--r--libnm-core/nm-setting-adsl.c22
-rw-r--r--libnm-core/nm-setting-bluetooth.c31
-rw-r--r--libnm-core/nm-setting-bond.c52
-rw-r--r--libnm-core/nm-setting-bridge-port.c19
-rw-r--r--libnm-core/nm-setting-bridge.c41
-rw-r--r--libnm-core/nm-setting-cdma.c21
-rw-r--r--libnm-core/nm-setting-connection.c192
-rw-r--r--libnm-core/nm-setting-connection.h31
-rw-r--r--libnm-core/nm-setting-dcb.c101
-rw-r--r--libnm-core/nm-setting-dcb.h6
-rw-r--r--libnm-core/nm-setting-dummy.c12
-rw-r--r--libnm-core/nm-setting-ethtool.c342
-rw-r--r--libnm-core/nm-setting-ethtool.h125
-rw-r--r--libnm-core/nm-setting-generic.c12
-rw-r--r--libnm-core/nm-setting-gsm.c41
-rw-r--r--libnm-core/nm-setting-infiniband.c30
-rw-r--r--libnm-core/nm-setting-ip-config.c91
-rw-r--r--libnm-core/nm-setting-ip-config.h8
-rw-r--r--libnm-core/nm-setting-ip-tunnel.c45
-rw-r--r--libnm-core/nm-setting-ip4-config.c90
-rw-r--r--libnm-core/nm-setting-ip6-config.c81
-rw-r--r--libnm-core/nm-setting-macsec.c19
-rw-r--r--libnm-core/nm-setting-macvlan.c18
-rw-r--r--libnm-core/nm-setting-match.c295
-rw-r--r--libnm-core/nm-setting-match.h63
-rw-r--r--libnm-core/nm-setting-olpc-mesh.c32
-rw-r--r--libnm-core/nm-setting-ovs-bridge.c17
-rw-r--r--libnm-core/nm-setting-ovs-interface.c17
-rw-r--r--libnm-core/nm-setting-ovs-patch.c17
-rw-r--r--libnm-core/nm-setting-ovs-port.c17
-rw-r--r--libnm-core/nm-setting-ppp.c19
-rw-r--r--libnm-core/nm-setting-pppoe.c21
-rw-r--r--libnm-core/nm-setting-private.h130
-rw-r--r--libnm-core/nm-setting-proxy.c20
-rw-r--r--libnm-core/nm-setting-serial.c40
-rw-r--r--libnm-core/nm-setting-sriov.c1357
-rw-r--r--libnm-core/nm-setting-sriov.h123
-rw-r--r--libnm-core/nm-setting-tc-config.c77
-rw-r--r--libnm-core/nm-setting-team-port.c55
-rw-r--r--libnm-core/nm-setting-team-port.h8
-rw-r--r--libnm-core/nm-setting-team.c101
-rw-r--r--libnm-core/nm-setting-team.h30
-rw-r--r--libnm-core/nm-setting-tun.c19
-rw-r--r--libnm-core/nm-setting-user.c48
-rw-r--r--libnm-core/nm-setting-vlan.c46
-rw-r--r--libnm-core/nm-setting-vpn.c67
-rw-r--r--libnm-core/nm-setting-vxlan.c18
-rw-r--r--libnm-core/nm-setting-wimax.c32
-rw-r--r--libnm-core/nm-setting-wired.c83
-rw-r--r--libnm-core/nm-setting-wireless-security.c40
-rw-r--r--libnm-core/nm-setting-wireless.c81
-rw-r--r--libnm-core/nm-setting-wpan.c274
-rw-r--r--libnm-core/nm-setting-wpan.h59
-rw-r--r--libnm-core/nm-setting.c1303
-rw-r--r--libnm-core/nm-setting.h17
-rw-r--r--libnm-core/nm-utils-private.h8
-rw-r--r--libnm-core/nm-utils.c757
-rw-r--r--libnm-core/nm-utils.h13
-rw-r--r--libnm-core/nm-version.h14
-rw-r--r--libnm-core/tests/meson.build3
-rw-r--r--libnm-core/tests/test-crypto.c109
-rw-r--r--libnm-core/tests/test-general.c383
-rw-r--r--libnm-core/tests/test-keyfile.c14
-rw-r--r--libnm-core/tests/test-setting.c325
88 files changed, 4989 insertions, 9735 deletions
diff --git a/libnm-core/crypto.c b/libnm-core/crypto.c
new file mode 100644
index 00000000..319f8055
--- /dev/null
+++ b/libnm-core/crypto.c
@@ -0,0 +1,826 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+
+/*
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2007 - 2011 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
+
+#include <string.h>
+#include <strings.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "crypto.h"
+#include "nm-errors.h"
+
+#define PEM_RSA_KEY_BEGIN "-----BEGIN RSA PRIVATE KEY-----"
+#define PEM_RSA_KEY_END   "-----END RSA PRIVATE KEY-----"
+
+#define PEM_DSA_KEY_BEGIN "-----BEGIN DSA PRIVATE KEY-----"
+#define PEM_DSA_KEY_END   "-----END DSA PRIVATE KEY-----"
+
+#define PEM_CERT_BEGIN    "-----BEGIN CERTIFICATE-----"
+#define PEM_CERT_END      "-----END CERTIFICATE-----"
+
+#define PEM_PKCS8_ENC_KEY_BEGIN "-----BEGIN ENCRYPTED PRIVATE KEY-----"
+#define PEM_PKCS8_ENC_KEY_END   "-----END ENCRYPTED PRIVATE KEY-----"
+
+#define PEM_PKCS8_DEC_KEY_BEGIN "-----BEGIN PRIVATE KEY-----"
+#define PEM_PKCS8_DEC_KEY_END   "-----END PRIVATE KEY-----"
+
+static gboolean
+find_tag (const char *tag,
+          const guint8 *data,
+          gsize data_len,
+          gsize start_at,
+          gsize *out_pos)
+{
+	gsize i, taglen;
+	gsize len = data_len - start_at;
+
+	g_return_val_if_fail (out_pos != NULL, FALSE);
+
+	taglen = strlen (tag);
+	if (len >= taglen) {
+		for (i = 0; i < len - taglen + 1; i++) {
+			if (memcmp (data + start_at + i, tag, taglen) == 0) {
+				*out_pos = start_at + i;
+				return TRUE;
+			}
+		}
+	}
+	return FALSE;
+}
+
+#define DEK_INFO_TAG "DEK-Info: "
+#define PROC_TYPE_TAG "Proc-Type: "
+
+static GByteArray *
+parse_old_openssl_key_file (const guint8 *data,
+                            gsize data_len,
+                            NMCryptoKeyType *out_key_type,
+                            char **out_cipher,
+                            char **out_iv,
+                            GError **error)
+{
+	GByteArray *bindata = NULL;
+	char **lines = NULL;
+	char **ln = NULL;
+	gsize start = 0, end = 0;
+	GString *str = NULL;
+	int enc_tags = 0;
+	NMCryptoKeyType key_type;
+	char *iv = NULL;
+	char *cipher = NULL;
+	unsigned char *tmp = NULL;
+	gsize tmp_len = 0;
+	const char *start_tag;
+	const char *end_tag;
+	guint8 save_end = 0;
+
+	*out_key_type = NM_CRYPTO_KEY_TYPE_UNKNOWN;
+	*out_iv = NULL;
+	*out_cipher = NULL;
+
+	if (find_tag (PEM_RSA_KEY_BEGIN, data, data_len, 0, &start)) {
+		key_type = NM_CRYPTO_KEY_TYPE_RSA;
+		start_tag = PEM_RSA_KEY_BEGIN;
+		end_tag = PEM_RSA_KEY_END;
+	} else if (find_tag (PEM_DSA_KEY_BEGIN, data, data_len, 0, &start)) {
+		key_type = NM_CRYPTO_KEY_TYPE_DSA;
+		start_tag = PEM_DSA_KEY_BEGIN;
+		end_tag = PEM_DSA_KEY_END;
+	} else
+		goto parse_error;
+
+	start += strlen (start_tag);
+	if (!find_tag (end_tag, data, data_len, start, &end)) {
+		g_set_error (error, NM_CRYPTO_ERROR,
+		             NM_CRYPTO_ERROR_INVALID_DATA,
+		             _("PEM key file had no end tag '%s'."),
+		             end_tag);
+		goto parse_error;
+	}
+
+	save_end = data[end];
+	((guint8 *)data)[end] = '\0';
+	lines = g_strsplit ((const char *) (data + start), "\n", 0);
+	((guint8 *)data)[end] = save_end;
+
+	if (!lines || g_strv_length (lines) <= 1) {
+		g_set_error (error, NM_CRYPTO_ERROR,
+		             NM_CRYPTO_ERROR_INVALID_DATA,
+		             _("Doesn't look like a PEM private key file."));
+		goto parse_error;
+	}
+
+	str = g_string_new_len (NULL, end - start);
+	for (ln = lines; *ln; ln++) {
+		char *p = *ln;
+
+		/* Chug leading spaces */
+		p = g_strstrip (p);
+		if (!*p)
+			continue;
+
+		if (!strncmp (p, PROC_TYPE_TAG, strlen (PROC_TYPE_TAG))) {
+			if (enc_tags++ != 0 || str->len != 0) {
+				g_set_error (error, NM_CRYPTO_ERROR,
+				             NM_CRYPTO_ERROR_INVALID_DATA,
+				             _("Malformed PEM file: Proc-Type was not first tag."));
+				goto parse_error;
+			}
+
+			p += strlen (PROC_TYPE_TAG);
+			if (strcmp (p, "4,ENCRYPTED")) {
+				g_set_error (error, NM_CRYPTO_ERROR,
+				             NM_CRYPTO_ERROR_INVALID_DATA,
+				             _("Malformed PEM file: unknown Proc-Type tag '%s'."),
+				             p);
+				goto parse_error;
+			}
+		} else if (!strncmp (p, DEK_INFO_TAG, strlen (DEK_INFO_TAG))) {
+			static const char *const known_ciphers[] = { CIPHER_DES_EDE3_CBC,
+			                                             CIPHER_DES_CBC,
+			                                             CIPHER_AES_128_CBC,
+			                                             CIPHER_AES_192_CBC,
+			                                             CIPHER_AES_256_CBC };
+			char *comma;
+			guint i;
+
+			if (enc_tags++ != 1 || str->len != 0) {
+				g_set_error (error, NM_CRYPTO_ERROR,
+				             NM_CRYPTO_ERROR_INVALID_DATA,
+				             _("Malformed PEM file: DEK-Info was not the second tag."));
+				goto parse_error;
+			}
+
+			p += strlen (DEK_INFO_TAG);
+
+			/* Grab the IV first */
+			comma = strchr (p, ',');
+			if (!comma || (*(comma + 1) == '\0')) {
+				g_set_error (error, NM_CRYPTO_ERROR,
+				             NM_CRYPTO_ERROR_INVALID_DATA,
+				             _("Malformed PEM file: no IV found in DEK-Info tag."));
+				goto parse_error;
+			}
+			*comma++ = '\0';
+			if (!g_ascii_isxdigit (*comma)) {
+				g_set_error (error, NM_CRYPTO_ERROR,
+				             NM_CRYPTO_ERROR_INVALID_DATA,
+				             _("Malformed PEM file: invalid format of IV in DEK-Info tag."));
+				goto parse_error;
+			}
+			iv = g_strdup (comma);
+
+			/* Get the private key cipher */
+			for (i = 0; i < G_N_ELEMENTS (known_ciphers); i++) {
+				if (!g_ascii_strcasecmp (p, known_ciphers[i])) {
+					cipher = g_strdup (known_ciphers[i]);
+					break;
+				}
+			}
+			if (i == G_N_ELEMENTS (known_ciphers)) {
+				g_set_error (error, NM_CRYPTO_ERROR,
+				             NM_CRYPTO_ERROR_INVALID_DATA,
+				             _("Malformed PEM file: unknown private key cipher '%s'."),
+				             p);
+				goto parse_error;
+			}
+		} else {
+			if (enc_tags == 1) {
+				g_set_error (error, NM_CRYPTO_ERROR,
+				             NM_CRYPTO_ERROR_INVALID_DATA,
+				             "Malformed PEM file: both Proc-Type and DEK-Info tags are required.");
+				goto parse_error;
+			}
+			g_string_append (str, p);
+		}
+	}
+
+	tmp = g_base64_decode (str->str, &tmp_len);
+	if (tmp == NULL || !tmp_len) {
+		g_set_error (error, NM_CRYPTO_ERROR,
+		             NM_CRYPTO_ERROR_INVALID_DATA,
+		             _("Could not decode private key."));
+		goto parse_error;
+	}
+	g_string_free (str, TRUE);
+
+	if (lines)
+		g_strfreev (lines);
+
+	bindata = g_byte_array_sized_new (tmp_len);
+	g_byte_array_append (bindata, tmp, tmp_len);
+	g_free (tmp);
+
+	*out_key_type = key_type;
+	*out_iv = iv;
+	*out_cipher = cipher;
+	return bindata;
+
+parse_error:
+	g_free (tmp);
+	g_free (cipher);
+	g_free (iv);
+	if (str)
+		g_string_free (str, TRUE);
+	if (lines)
+		g_strfreev (lines);
+	return NULL;
+}
+
+static GByteArray *
+parse_pkcs8_key_file (const guint8 *data,
+                      gsize data_len,
+                      gboolean *out_encrypted,
+                      GError **error)
+{
+	GByteArray *key = NULL;
+	gsize start = 0, end = 0;
+	unsigned char *der = NULL;
+	guint8 save_end;
+	gsize length = 0;
+	const char *start_tag = NULL, *end_tag = NULL;
+	gboolean encrypted = FALSE;
+
+	/* Try encrypted first, decrypted next */
+	if (find_tag (PEM_PKCS8_ENC_KEY_BEGIN, data, data_len, 0, &start)) {
+		start_tag = PEM_PKCS8_ENC_KEY_BEGIN;
+		end_tag = PEM_PKCS8_ENC_KEY_END;
+		encrypted = TRUE;
+	} else if (find_tag (PEM_PKCS8_DEC_KEY_BEGIN, data, data_len, 0, &start)) {
+		start_tag = PEM_PKCS8_DEC_KEY_BEGIN;
+		end_tag = PEM_PKCS8_DEC_KEY_END;
+		encrypted = FALSE;
+	} else {
+		g_set_error_literal (error, NM_CRYPTO_ERROR,
+		                     NM_CRYPTO_ERROR_INVALID_DATA,
+		                     _("Failed to find expected PKCS#8 start tag."));
+		return NULL;
+	}
+
+	start += strlen (start_tag);
+	if (!find_tag (end_tag, data, data_len, start, &end)) {
+		g_set_error (error, NM_CRYPTO_ERROR,
+		             NM_CRYPTO_ERROR_INVALID_DATA,
+		             _("Failed to find expected PKCS#8 end tag '%s'."),
+		             end_tag);
+		return NULL;
+	}
+
+	/* g_base64_decode() wants a NULL-terminated string */
+	save_end = data[end];
+	((guint8 *)data)[end] = '\0';
+	der = g_base64_decode ((const char *) (data + start), &length);
+	((guint8 *)data)[end] = save_end;
+
+	if (der && length) {
+		key = g_byte_array_sized_new (length);
+		g_byte_array_append (key, der, length);
+		g_assert (key->len == length);
+		*out_encrypted = encrypted;
+	} else {
+		g_set_error_literal (error, NM_CRYPTO_ERROR,
+		                     NM_CRYPTO_ERROR_INVALID_DATA,
+		                     _("Failed to decode PKCS#8 private key."));
+	}
+
+	g_free (der);
+	return key;
+}
+
+static GByteArray *
+file_to_g_byte_array (const char *filename, GError **error)
+{
+	char *contents;
+	GByteArray *array = NULL;
+	gsize length = 0;
+
+	if (g_file_get_contents (filename, &contents, &length, error)) {
+		array = g_byte_array_sized_new (length);
+		g_byte_array_append (array, (guint8 *) contents, length);
+		g_assert (array->len == length);
+		g_free (contents);
+	}
+	return array;
+}
+
+/*
+ * Convert a hex string into bytes.
+ */
+static char *
+convert_iv (const char *src,
+            gsize *out_len,
+            GError **error)
+{
+	int num;
+	int i;
+	char conv[3];
+	char *c;
+
+	g_return_val_if_fail (src != NULL, NULL);
+
+	num = strlen (src);
+	if (num % 2) {
+		g_set_error (error, NM_CRYPTO_ERROR,
+		             NM_CRYPTO_ERROR_INVALID_DATA,
+		             _("IV must be an even number of bytes in length."));
+		return NULL;
+	}
+
+	num /= 2;
+	c = g_malloc0 (num + 1);
+
+	conv[2] = '\0';
+	for (i = 0; i < num; i++) {
+		conv[0] = src[(i * 2)];
+		conv[1] = src[(i * 2) + 1];
+		if (!g_ascii_isxdigit (conv[0]) || !g_ascii_isxdigit (conv[1])) {
+			g_set_error (error, NM_CRYPTO_ERROR,
+			             NM_CRYPTO_ERROR_INVALID_DATA,
+			             _("IV contains non-hexadecimal digits."));
+			goto error;
+		}
+
+		c[i] = strtol(conv, NULL, 16);
+	}
+	*out_len = num;
+	return c;
+
+error:
+	g_free (c);
+	return NULL;
+}
+
+char *
+crypto_make_des_aes_key (const char *cipher,
+                         const char *salt,
+                         const gsize salt_len,
+                         const char *password,
+                         gsize *out_len,
+                         GError **error)
+{
+	char *key;
+	guint32 digest_len;
+
+	g_return_val_if_fail (cipher != NULL, NULL);
+	g_return_val_if_fail (salt != NULL, NULL);
+	g_return_val_if_fail (salt_len >= 8, NULL);
+	g_return_val_if_fail (password != NULL, NULL);
+	g_return_val_if_fail (out_len != NULL, NULL);
+
+	if (!strcmp (cipher, CIPHER_DES_EDE3_CBC))
+		digest_len = 24;
+	else if (!strcmp (cipher, CIPHER_DES_CBC))
+		digest_len = 8;
+	else if (!strcmp (cipher, CIPHER_AES_128_CBC))
+		digest_len = 16;
+	else if (!strcmp (cipher, CIPHER_AES_192_CBC))
+		digest_len = 24;
+	else if (!strcmp (cipher, CIPHER_AES_256_CBC))
+		digest_len = 32;
+	else {
+		g_set_error (error, NM_CRYPTO_ERROR,
+		             NM_CRYPTO_ERROR_UNKNOWN_CIPHER,
+		             _("Private key cipher '%s' was unknown."),
+		             cipher);
+		return NULL;
+	}
+
+	if (password[0] == '\0')
+		return NULL;
+
+	key = g_malloc0 (digest_len + 1);
+
+	crypto_md5_hash (salt,
+	                 8,
+	                 password,
+	                 strlen (password),
+	                 key,
+	                 digest_len);
+
+	*out_len = digest_len;
+	return key;
+}
+
+static GByteArray *
+decrypt_key (const char *cipher,
+             int key_type,
+             const guint8 *data,
+             gsize data_len,
+             const char *iv,
+             const char *password,
+             GError **error)
+{
+	char *bin_iv = NULL;
+	gsize bin_iv_len = 0;
+	char *key = NULL;
+	gsize key_len = 0;
+	char *output = NULL;
+	gsize decrypted_len = 0;
+	GByteArray *decrypted = NULL;
+
+	g_return_val_if_fail (password != NULL, NULL);
+
+	bin_iv = convert_iv (iv, &bin_iv_len, error);
+	if (!bin_iv)
+		return NULL;
+
+	/* Convert the password and IV into a DES or AES key */
+	key = crypto_make_des_aes_key (cipher, bin_iv, bin_iv_len, password, &key_len, error);
+	if (!key || !key_len)
+		goto out;
+
+	output = crypto_decrypt (cipher, key_type,
+	                         data, data_len,
+	                         bin_iv, bin_iv_len,
+	                         key, key_len,
+	                         &decrypted_len,
+	                         error);
+	if (output && decrypted_len) {
+		decrypted = g_byte_array_sized_new (decrypted_len);
+		g_byte_array_append (decrypted, (guint8 *) output, decrypted_len);
+	}
+
+out:
+	/* Don't leak stale key material */
+	if (key)
+		memset (key, 0, key_len);
+	g_free (output);
+	g_free (key);
+	g_free (bin_iv);
+
+	return decrypted;
+}
+
+GByteArray *
+crypto_decrypt_openssl_private_key_data (const guint8 *data,
+                                         gsize data_len,
+                                         const char *password,
+                                         NMCryptoKeyType *out_key_type,
+                                         GError **error)
+{
+	GByteArray *decrypted = NULL;
+	NMCryptoKeyType key_type = NM_CRYPTO_KEY_TYPE_UNKNOWN;
+	GByteArray *parsed;
+	char *iv = NULL;
+	char *cipher = NULL;
+
+	g_return_val_if_fail (data != NULL, NULL);
+	if (out_key_type)
+		g_return_val_if_fail (*out_key_type == NM_CRYPTO_KEY_TYPE_UNKNOWN, NULL);
+
+	if (!crypto_init (error))
+		return NULL;
+
+	parsed = parse_old_openssl_key_file (data, data_len, &key_type, &cipher, &iv, NULL);
+	/* return the key type even if decryption failed */
+	if (out_key_type)
+		*out_key_type = key_type;
+
+	if (!parsed) {
+		g_set_error (error, NM_CRYPTO_ERROR,
+		             NM_CRYPTO_ERROR_INVALID_DATA,
+		             _("Unable to determine private key type."));
+		return NULL;
+	}
+
+	if (password) {
+		if (!cipher || !iv) {
+			g_set_error (error, NM_CRYPTO_ERROR,
+			             NM_CRYPTO_ERROR_INVALID_PASSWORD,
+			             _("Password provided, but key was not encrypted."));
+		} else {
+			decrypted = decrypt_key (cipher,
+			                         key_type,
+			                         parsed->data,
+			                         parsed->len,
+			                         iv,
+			                         password,
+			                         error);
+		}
+	} else if (!cipher && !iv)
+		decrypted = g_byte_array_ref (parsed);
+
+	g_byte_array_unref (parsed);
+	g_free (cipher);
+	g_free (iv);
+
+	return decrypted;
+}
+
+GByteArray *
+crypto_decrypt_openssl_private_key (const char *file,
+                                    const char *password,
+                                    NMCryptoKeyType *out_key_type,
+                                    GError **error)
+{
+	GByteArray *contents;
+	GByteArray *key = NULL;
+
+	if (!crypto_init (error))
+		return NULL;
+
+	contents = file_to_g_byte_array (file, error);
+	if (contents) {
+		key = crypto_decrypt_openssl_private_key_data (contents->data, contents->len,
+		                                               password, out_key_type, error);
+		g_byte_array_free (contents, TRUE);
+	}
+	return key;
+}
+
+static GByteArray *
+extract_pem_cert_data (GByteArray *contents, GError **error)
+{
+	GByteArray *cert = NULL;
+	gsize start = 0, end = 0;
+	unsigned char *der = NULL;
+	guint8 save_end;
+	gsize length = 0;
+
+	if (!find_tag (PEM_CERT_BEGIN, contents->data, contents->len, 0, &start)) {
+		g_set_error (error, NM_CRYPTO_ERROR,
+		             NM_CRYPTO_ERROR_INVALID_DATA,
+		             _("PEM certificate had no start tag '%s'."),
+		             PEM_CERT_BEGIN);
+		goto done;
+	}
+
+	start += strlen (PEM_CERT_BEGIN);
+	if (!find_tag (PEM_CERT_END, contents->data, contents->len, start, &end)) {
+		g_set_error (error, NM_CRYPTO_ERROR,
+		             NM_CRYPTO_ERROR_INVALID_DATA,
+		             _("PEM certificate had no end tag '%s'."),
+		             PEM_CERT_END);
+		goto done;
+	}
+
+	/* g_base64_decode() wants a NULL-terminated string */
+	save_end = contents->data[end];
+	contents->data[end] = '\0';
+	der = g_base64_decode ((const char *) (contents->data + start), &length);
+	contents->data[end] = save_end;
+
+	if (der && length) {
+		cert = g_byte_array_sized_new (length);
+		g_byte_array_append (cert, der, length);
+		g_assert (cert->len == length);
+	} else {
+		g_set_error (error, NM_CRYPTO_ERROR,
+		             NM_CRYPTO_ERROR_INVALID_DATA,
+		             _("Failed to decode certificate."));
+	}
+
+done:
+	g_free (der);
+	return cert;
+}
+
+GByteArray *
+crypto_load_and_verify_certificate (const char *file,
+                                    NMCryptoFileFormat *out_file_format,
+                                    GError **error)
+{
+	GByteArray *array, *contents;
+
+	g_return_val_if_fail (file != NULL, NULL);
+	g_return_val_if_fail (out_file_format != NULL, NULL);
+	g_return_val_if_fail (*out_file_format == NM_CRYPTO_FILE_FORMAT_UNKNOWN, NULL);
+
+	if (!crypto_init (error))
+		return NULL;
+
+	contents = file_to_g_byte_array (file, error);
+	if (!contents)
+		return NULL;
+
+	/* Check for PKCS#12 */
+	if (crypto_is_pkcs12_data (contents->data, contents->len, NULL)) {
+		*out_file_format = NM_CRYPTO_FILE_FORMAT_PKCS12;
+		return contents;
+	}
+
+	/* Check for plain DER format */
+	if (contents->len > 2 && contents->data[0] == 0x30 && contents->data[1] == 0x82) {
+		*out_file_format = crypto_verify_cert (contents->data, contents->len, error);
+	} else {
+		array = extract_pem_cert_data (contents, error);
+		if (!array) {
+			g_byte_array_free (contents, TRUE);
+			return NULL;
+		}
+
+		*out_file_format = crypto_verify_cert (array->data, array->len, error);
+		g_byte_array_free (array, TRUE);
+	}
+
+	if (*out_file_format != NM_CRYPTO_FILE_FORMAT_X509) {
+		g_byte_array_free (contents, TRUE);
+		contents = NULL;
+	}
+
+	return contents;
+}
+
+gboolean
+crypto_is_pkcs12_data (const guint8 *data,
+                       gsize data_len,
+                       GError **error)
+{
+	GError *local = NULL;
+	gboolean success;
+
+	if (!data_len)
+		return FALSE;
+
+	g_return_val_if_fail (data != NULL, FALSE);
+
+	if (!crypto_init (error))
+		return FALSE;
+
+	success = crypto_verify_pkcs12 (data, data_len, NULL, &local);
+	if (success == FALSE) {
+		/* If the error was just a decryption error, then it's pkcs#12 */
+		if (local) {
+			if (g_error_matches (local, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_DECRYPTION_FAILED)) {
+				success = TRUE;
+				g_error_free (local);
+			} else
+				g_propagate_error (error, local);
+		}
+	}
+	return success;
+}
+
+gboolean
+crypto_is_pkcs12_file (const char *file, GError **error)
+{
+	GByteArray *contents;
+	gboolean success = FALSE;
+
+	g_return_val_if_fail (file != NULL, FALSE);
+
+	if (!crypto_init (error))
+		return FALSE;
+
+	contents = file_to_g_byte_array (file, error);
+	if (contents) {
+		success = crypto_is_pkcs12_data (contents->data, contents->len, error);
+		g_byte_array_free (contents, TRUE);
+	}
+	return success;
+}
+
+/* Verifies that a private key can be read, and if a password is given, that
+ * the private key can be decrypted with that password.
+ */
+NMCryptoFileFormat
+crypto_verify_private_key_data (const guint8 *data,
+                                gsize data_len,
+                                const char *password,
+                                gboolean *out_is_encrypted,
+                                GError **error)
+{
+	GByteArray *tmp;
+	NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
+	NMCryptoKeyType ktype = NM_CRYPTO_KEY_TYPE_UNKNOWN;
+	gboolean is_encrypted = FALSE;
+
+	g_return_val_if_fail (data != NULL, NM_CRYPTO_FILE_FORMAT_UNKNOWN);
+	g_return_val_if_fail (out_is_encrypted == NULL || *out_is_encrypted == FALSE, NM_CRYPTO_FILE_FORMAT_UNKNOWN);
+
+	if (!crypto_init (error))
+		return NM_CRYPTO_FILE_FORMAT_UNKNOWN;
+
+	/* Check for PKCS#12 first */
+	if (crypto_is_pkcs12_data (data, data_len, NULL)) {
+		is_encrypted = TRUE;
+		if (!password || crypto_verify_pkcs12 (data, data_len, password, error))
+			format = NM_CRYPTO_FILE_FORMAT_PKCS12;
+	} else {
+		/* Maybe it's PKCS#8 */
+		tmp = parse_pkcs8_key_file (data, data_len, &is_encrypted, NULL);
+		if (tmp) {
+			if (!password || crypto_verify_pkcs8 (tmp->data, tmp->len, is_encrypted, password, error))
+				format = NM_CRYPTO_FILE_FORMAT_RAW_KEY;
+		} else {
+			char *cipher, *iv;
+
+			/* Or it's old-style OpenSSL */
+			tmp = parse_old_openssl_key_file (data, data_len, &ktype,
+			                                  &cipher, &iv, NULL);
+			if (tmp) {
+				format = NM_CRYPTO_FILE_FORMAT_RAW_KEY;
+				is_encrypted = (cipher && iv);
+				g_free (cipher);
+				g_free (iv);
+			}
+		}
+
+		if (tmp) {
+			/* Don't leave key data around */
+			memset (tmp->data, 0, tmp->len);
+			g_byte_array_free (tmp, TRUE);
+		}
+	}
+
+	if (out_is_encrypted)
+		*out_is_encrypted = is_encrypted;
+	return format;
+}
+
+NMCryptoFileFormat
+crypto_verify_private_key (const char *filename,
+                           const char *password,
+                           gboolean *out_is_encrypted,
+                           GError **error)
+{
+	GByteArray *contents;
+	NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
+
+	g_return_val_if_fail (filename != NULL, NM_CRYPTO_FILE_FORMAT_UNKNOWN);
+
+	if (!crypto_init (error))
+		return NM_CRYPTO_FILE_FORMAT_UNKNOWN;
+
+	contents = file_to_g_byte_array (filename, error);
+	if (contents) {
+		format = crypto_verify_private_key_data (contents->data, contents->len, password, out_is_encrypted, error);
+		g_byte_array_free (contents, TRUE);
+	}
+	return format;
+}
+
+void
+crypto_md5_hash (const char *salt,
+                 gssize salt_len,
+                 const char *password,
+                 gssize password_len,
+                 char *buffer,
+                 gsize buflen)
+{
+	GChecksum *ctx;
+	gsize digest_len;
+	char digest[16];
+	gsize bufidx = 0;
+	int i;
+
+	nm_assert (g_checksum_type_get_length (G_CHECKSUM_MD5) == sizeof (digest));
+
+	g_return_if_fail (password_len == 0 || password);
+	g_return_if_fail (buffer != NULL);
+	g_return_if_fail (buflen > 0);
+	g_return_if_fail (salt_len == 0 || salt);
+
+	ctx = g_checksum_new (G_CHECKSUM_MD5);
+
+	if (salt_len < 0)
+		salt_len = strlen (salt);
+	if (password_len < 0)
+		password_len = strlen (password);
+
+	for (;;) {
+		if (password_len > 0)
+			g_checksum_update (ctx, (const guchar *) password, password_len);
+		if (salt_len > 0)
+			g_checksum_update (ctx, (const guchar *) salt, salt_len);
+
+		digest_len = sizeof (digest);
+		g_checksum_get_digest (ctx, (guchar *) digest, &digest_len);
+		nm_assert (digest_len == sizeof (digest));
+
+		for (i = 0; i < sizeof (digest); i++) {
+			if (bufidx >= buflen)
+				goto done;
+			buffer[bufidx++] = digest[i];
+		}
+
+		g_checksum_reset (ctx);
+		g_checksum_update (ctx, (const guchar *) digest, sizeof (digest));
+	}
+
+done:
+	memset (digest, 0, sizeof (digest));
+	g_checksum_free (ctx);
+}
diff --git a/libnm-core/crypto.h b/libnm-core/crypto.h
new file mode 100644
index 00000000..d20d6f31
--- /dev/null
+++ b/libnm-core/crypto.h
@@ -0,0 +1,137 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+
+/*
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2007 - 2014 Red Hat, Inc.
+ */
+
+#ifndef __CRYPTO_H__
+#define __CRYPTO_H__
+
+#if !((NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_PRIVATE)
+#error Cannot use this header.
+#endif
+
+#define MD5_HASH_LEN 20
+#define CIPHER_DES_EDE3_CBC "DES-EDE3-CBC"
+#define CIPHER_DES_CBC      "DES-CBC"
+#define CIPHER_AES_128_CBC  "AES-128-CBC"
+#define CIPHER_AES_192_CBC  "AES-192-CBC"
+#define CIPHER_AES_256_CBC  "AES-256-CBC"
+
+typedef enum {
+	NM_CRYPTO_KEY_TYPE_UNKNOWN = 0,
+	NM_CRYPTO_KEY_TYPE_RSA,
+	NM_CRYPTO_KEY_TYPE_DSA
+} NMCryptoKeyType;
+
+typedef enum {
+	NM_CRYPTO_FILE_FORMAT_UNKNOWN = 0,
+	NM_CRYPTO_FILE_FORMAT_X509,
+	NM_CRYPTO_FILE_FORMAT_RAW_KEY,
+	NM_CRYPTO_FILE_FORMAT_PKCS12
+} NMCryptoFileFormat;
+
+gboolean crypto_init (GError **error);
+
+GByteArray *crypto_decrypt_openssl_private_key_data (const guint8 *data,
+                                                     gsize data_len,
+                                                     const char *password,
+                                                     NMCryptoKeyType *out_key_type,
+                                                     GError **error);
+
+GByteArray *crypto_decrypt_openssl_private_key (const char *file,
+                                                const char *password,
+                                                NMCryptoKeyType *out_key_type,
+                                                GError **error);
+
+GByteArray *crypto_load_and_verify_certificate (const char *file,
+                                                NMCryptoFileFormat *out_file_format,
+                                                GError **error);
+
+gboolean crypto_is_pkcs12_file (const char *file, GError **error);
+
+gboolean crypto_is_pkcs12_data (const guint8 *data, gsize len, GError **error);
+
+NMCryptoFileFormat crypto_verify_private_key_data (const guint8 *data,
+                                                   gsize data_len,
+                                                   const char *password,
+                                                   gboolean *out_is_encrypted,
+                                                   GError **error);
+
+NMCryptoFileFormat crypto_verify_private_key (const char *file,
+                                              const char *password,
+                                              gboolean *out_is_encrypted,
+                                              GError **error);
+
+/* Internal utils API bits for crypto providers */
+
+void crypto_md5_hash (const char *salt,
+                      gssize salt_len,
+                      const char *password,
+                      gssize password_len,
+                      char *buffer,
+                      gsize buflen);
+
+char *crypto_make_des_aes_key (const char *cipher,
+                               const char *salt,
+                               const gsize salt_len,
+                               const char *password,
+                               gsize *out_len,
+                               GError **error);
+
+char * crypto_decrypt (const char *cipher,
+                       int key_type,
+                       const guint8 *data,
+                       gsize data_len,
+                       const char *iv,
+                       const gsize iv_len,
+                       const char *key,
+                       const gsize key_len,
+                       gsize *out_len,
+                       GError **error);
+
+char * crypto_encrypt (const char *cipher,
+                       const guint8 *data,
+                       gsize data_len,
+                       const char *iv,
+                       gsize iv_len,
+                       const char *key,
+                       gsize key_len,
+                       gsize *out_len,
+                       GError **error);
+
+gboolean crypto_randomize (void *buffer, gsize buffer_len, GError **error);
+
+NMCryptoFileFormat crypto_verify_cert (const guint8 *data,
+                                       gsize len,
+                                       GError **error);
+
+gboolean crypto_verify_pkcs12 (const guint8 *data,
+                               gsize data_len,
+                               const char *password,
+                               GError **error);
+
+gboolean crypto_verify_pkcs8 (const guint8 *data,
+                              gsize data_len,
+                              gboolean is_encrypted,
+                              const char *password,
+                              GError **error);
+
+#endif  /* __CRYPTO_H__ */
diff --git a/libnm-core/nm-crypto-gnutls.c b/libnm-core/crypto_gnutls.c
index 6c897e6d..49181ee7 100644
--- a/libnm-core/nm-crypto-gnutls.c
+++ b/libnm-core/crypto_gnutls.c
@@ -23,53 +23,26 @@
 
 #include "nm-default.h"
 
-#include "nm-crypto-impl.h"
-
 #include <gnutls/gnutls.h>
 #include <gnutls/crypto.h>
 #include <gnutls/x509.h>
 #include <gnutls/pkcs12.h>
 
-#include "nm-utils/nm-secret-utils.h"
+#include "crypto.h"
 #include "nm-errors.h"
 
-/*****************************************************************************/
-
-static gboolean
-_get_cipher_info (NMCryptoCipherType cipher,
-                  int *out_cipher_mech,
-                  guint8 *out_real_iv_len)
-{
-	static const int cipher_mechs[] = {
-		[NM_CRYPTO_CIPHER_DES_EDE3_CBC] = GNUTLS_CIPHER_3DES_CBC,
-		[NM_CRYPTO_CIPHER_DES_CBC]      = GNUTLS_CIPHER_DES_CBC,
-		[NM_CRYPTO_CIPHER_AES_128_CBC]  = GNUTLS_CIPHER_AES_128_CBC,
-		[NM_CRYPTO_CIPHER_AES_192_CBC]  = GNUTLS_CIPHER_AES_192_CBC,
-		[NM_CRYPTO_CIPHER_AES_256_CBC]  = GNUTLS_CIPHER_AES_256_CBC,
-	};
-
-	g_return_val_if_fail (_NM_INT_NOT_NEGATIVE (cipher) && (gsize) cipher < G_N_ELEMENTS (cipher_mechs), FALSE);
-
-	if (cipher_mechs[cipher] == 0)
-		return FALSE;
+#define SALT_LEN 8
 
-	NM_SET_OUT (out_cipher_mech, cipher_mechs[cipher]);
-	NM_SET_OUT (out_real_iv_len, nm_crypto_cipher_get_info (cipher)->real_iv_len);
-	return TRUE;
-}
-
-/*****************************************************************************/
+static gboolean initialized = FALSE;
 
 gboolean
-_nm_crypto_init (GError **error)
+crypto_init (GError **error)
 {
-	static gboolean initialized = FALSE;
-
 	if (initialized)
 		return TRUE;
 
-	if (gnutls_global_init () != 0) {
-		gnutls_global_deinit ();
+	if (gnutls_global_init() != 0) {
+		gnutls_global_deinit();
 		g_set_error_literal (error, NM_CRYPTO_ERROR,
 		                     NM_CRYPTO_ERROR_FAILED,
 		                     _("Failed to initialize the crypto engine."));
@@ -80,47 +53,61 @@ _nm_crypto_init (GError **error)
 	return TRUE;
 }
 
-/*****************************************************************************/
-
-guint8 *
-_nmtst_crypto_decrypt (NMCryptoCipherType cipher,
-                       const guint8 *data,
-                       gsize data_len,
-                       const guint8 *iv,
-                       gsize iv_len,
-                       const guint8 *key,
-                       gsize key_len,
-                       gsize *out_len,
-                       GError **error)
+char *
+crypto_decrypt (const char *cipher,
+                int key_type,
+                const guint8 *data,
+                gsize data_len,
+                const char *iv,
+                const gsize iv_len,
+                const char *key,
+                const gsize key_len,
+                gsize *out_len,
+                GError **error)
 {
 	gnutls_cipher_hd_t ctx;
 	gnutls_datum_t key_dt, iv_dt;
 	int err;
-	int cipher_mech;
-	nm_auto_clear_secret_ptr NMSecretPtr output = { 0 };
-	guint8 pad_i, pad_len;
-	guint8 real_iv_len;
+	int cipher_mech, i;
+	char *output = NULL;
+	gboolean success = FALSE;
+	gsize pad_len, real_iv_len;
+
+	if (!crypto_init (error))
+		return NULL;
 
-	if (!_get_cipher_info (cipher, &cipher_mech, &real_iv_len)) {
+	if (!strcmp (cipher, CIPHER_DES_EDE3_CBC)) {
+		cipher_mech = GNUTLS_CIPHER_3DES_CBC;
+		real_iv_len = SALT_LEN;
+	} else if (!strcmp (cipher, CIPHER_DES_CBC)) {
+		cipher_mech = GNUTLS_CIPHER_DES_CBC;
+		real_iv_len = SALT_LEN;
+	} else if (!strcmp (cipher, CIPHER_AES_128_CBC)) {
+		cipher_mech = GNUTLS_CIPHER_AES_128_CBC;
+		real_iv_len = 16;
+	} else if (!strcmp (cipher, CIPHER_AES_192_CBC)) {
+		cipher_mech = GNUTLS_CIPHER_AES_192_CBC;
+		real_iv_len = 16;
+	} else if (!strcmp (cipher, CIPHER_AES_256_CBC)) {
+		cipher_mech = GNUTLS_CIPHER_AES_256_CBC;
+		real_iv_len = 16;
+	} else {
 		g_set_error (error, NM_CRYPTO_ERROR,
 		             NM_CRYPTO_ERROR_UNKNOWN_CIPHER,
-		             _("Unsupported key cipher for decryption"));
+		             _("Private key cipher '%s' was unknown."),
+		             cipher);
 		return NULL;
 	}
 
-	if (!_nm_crypto_init (error))
-		return NULL;
-
 	if (iv_len < real_iv_len) {
 		g_set_error (error, NM_CRYPTO_ERROR,
 		             NM_CRYPTO_ERROR_INVALID_DATA,
-		             _("Invalid IV length (must be at least %u)."),
-		             (guint) real_iv_len);
+		             _("Invalid IV length (must be at least %zd)."),
+		             real_iv_len);
 		return NULL;
 	}
 
-	output.len = data_len;
-	output.bin = g_malloc (data_len);
+	output = g_malloc0 (data_len);
 
 	key_dt.data = (unsigned char *) key;
 	key_dt.size = key_len;
@@ -133,81 +120,107 @@ _nmtst_crypto_decrypt (NMCryptoCipherType cipher,
 		             NM_CRYPTO_ERROR_DECRYPTION_FAILED,
 		             _("Failed to initialize the decryption cipher context: %s (%s)"),
 		             gnutls_strerror_name (err), gnutls_strerror (err));
-		return NULL;
+		goto out;
 	}
 
-	err = gnutls_cipher_decrypt2 (ctx, data, data_len, output.bin, output.len);
-
-	gnutls_cipher_deinit (ctx);
-
+	err = gnutls_cipher_decrypt2 (ctx, data, data_len, output, data_len);
 	if (err < 0) {
 		g_set_error (error, NM_CRYPTO_ERROR,
 		             NM_CRYPTO_ERROR_DECRYPTION_FAILED,
 		             _("Failed to decrypt the private key: %s (%s)"),
 		             gnutls_strerror_name (err), gnutls_strerror (err));
-		return NULL;
+		goto out;
 	}
-
-	pad_len = output.len > 0
-	          ? output.bin[output.len - 1]
-	          : 0;
+	pad_len = output[data_len - 1];
 
 	/* Check if the padding at the end of the decrypted data is valid */
-	if (   pad_len == 0
-	    || pad_len > real_iv_len) {
+	if (pad_len == 0 || pad_len > real_iv_len) {
 		g_set_error (error, NM_CRYPTO_ERROR,
 		             NM_CRYPTO_ERROR_DECRYPTION_FAILED,
 		             _("Failed to decrypt the private key: unexpected padding length."));
-		return NULL;
+		goto out;
 	}
 
 	/* Validate tail padding; last byte is the padding size, and all pad bytes
 	 * should contain the padding size.
 	 */
-	for (pad_i = 1; pad_i <= pad_len; ++pad_i) {
-		if (output.bin[data_len - pad_i] != pad_len) {
+	for (i = 1; i <= pad_len; ++i) {
+		if (output[data_len - i] != pad_len) {
 			g_set_error (error, NM_CRYPTO_ERROR,
 			             NM_CRYPTO_ERROR_DECRYPTION_FAILED,
 			             _("Failed to decrypt the private key."));
-			return NULL;
+			goto out;
 		}
 	}
 
-	*out_len = output.len - pad_len;
-	return g_steal_pointer (&output.bin);
+	*out_len = data_len - pad_len;
+	success = TRUE;
+
+out:
+	if (!success) {
+		if (output) {
+			/* Don't expose key material */
+			memset (output, 0, data_len);
+			g_free (output);
+			output = NULL;
+		}
+	}
+	gnutls_cipher_deinit (ctx);
+	return output;
 }
 
-guint8 *
-_nmtst_crypto_encrypt (NMCryptoCipherType cipher,
-                       const guint8 *data,
-                       gsize data_len,
-                       const guint8 *iv,
-                       gsize iv_len,
-                       const guint8 *key,
-                       gsize key_len,
-                       gsize *out_len,
-                       GError **error)
+char *
+crypto_encrypt (const char *cipher,
+                const guint8 *data,
+                gsize data_len,
+                const char *iv,
+                const gsize iv_len,
+                const char *key,
+                gsize key_len,
+                gsize *out_len,
+                GError **error)
 {
 	gnutls_cipher_hd_t ctx;
 	gnutls_datum_t key_dt, iv_dt;
 	int err;
 	int cipher_mech;
-	nm_auto_clear_secret_ptr NMSecretPtr output = { 0 };
-	nm_auto_clear_secret_ptr NMSecretPtr padded_buf = { 0 };
-	gsize i, pad_len;
+	char *output = NULL;
+	gboolean success = FALSE;
+	gsize padded_buf_len, pad_len, output_len;
+	char *padded_buf = NULL;
+	guint32 i;
 
-	nm_assert (iv_len);
+	if (!crypto_init (error))
+		return NULL;
 
-	if (   cipher == NM_CRYPTO_CIPHER_DES_CBC
-	    || !_get_cipher_info (cipher, &cipher_mech, NULL)) {
+	if (!strcmp (cipher, CIPHER_DES_EDE3_CBC))
+		cipher_mech = GNUTLS_CIPHER_3DES_CBC;
+	else if (!strcmp (cipher, CIPHER_AES_128_CBC))
+		cipher_mech = GNUTLS_CIPHER_AES_128_CBC;
+	else if (!strcmp (cipher, CIPHER_AES_192_CBC))
+		cipher_mech = GNUTLS_CIPHER_AES_192_CBC;
+	else if (!strcmp (cipher, CIPHER_AES_256_CBC))
+		cipher_mech = GNUTLS_CIPHER_AES_256_CBC;
+	else {
 		g_set_error (error, NM_CRYPTO_ERROR,
 		             NM_CRYPTO_ERROR_UNKNOWN_CIPHER,
-		             _("Unsupported key cipher for encryption"));
+		             _("Private key cipher '%s' was unknown."),
+		             cipher);
 		return NULL;
 	}
 
-	if (!_nm_crypto_init (error))
-		return NULL;
+	/* If data_len % ivlen == 0, then we add another complete block
+	 * onto the end so that the decrypter knows there's padding.
+	 */
+	pad_len = iv_len - (data_len % iv_len);
+	output_len = padded_buf_len = data_len + pad_len;
+	padded_buf = g_malloc0 (padded_buf_len);
+
+	memcpy (padded_buf, data, data_len);
+	for (i = 0; i < pad_len; i++)
+		padded_buf[data_len + i] = (guint8) (pad_len & 0xFF);
+
+	output = g_malloc0 (output_len);
 
 	key_dt.data = (unsigned char *) key;
 	key_dt.size = key_len;
@@ -220,50 +233,51 @@ _nmtst_crypto_encrypt (NMCryptoCipherType cipher,
 		             NM_CRYPTO_ERROR_ENCRYPTION_FAILED,
 		             _("Failed to initialize the encryption cipher context: %s (%s)"),
 		             gnutls_strerror_name (err), gnutls_strerror (err));
-		return NULL;
+		goto out;
 	}
 
-	/* If data_len % ivlen == 0, then we add another complete block
-	 * onto the end so that the decrypter knows there's padding.
-	 */
-	pad_len = iv_len - (data_len % iv_len);
-
-	padded_buf.len = data_len + pad_len;
-	padded_buf.bin = g_malloc (padded_buf.len);
-	memcpy (padded_buf.bin, data, data_len);
-	for (i = 0; i < pad_len; i++)
-		padded_buf.bin[data_len + i] = (guint8) (pad_len & 0xFF);
-
-	output.len = padded_buf.len;
-	output.bin = g_malloc (output.len);
-
-	err = gnutls_cipher_encrypt2 (ctx, padded_buf.bin, padded_buf.len, output.bin, output.len);
-
-	gnutls_cipher_deinit (ctx);
-
+	err = gnutls_cipher_encrypt2 (ctx, padded_buf, padded_buf_len, output, output_len);
 	if (err < 0) {
 		g_set_error (error, NM_CRYPTO_ERROR,
 		             NM_CRYPTO_ERROR_ENCRYPTION_FAILED,
 		             _("Failed to encrypt the data: %s (%s)"),
 		             gnutls_strerror_name (err), gnutls_strerror (err));
-		return NULL;
+		goto out;
 	}
 
-	*out_len = output.len;
-	return g_steal_pointer (&output.bin);
+	*out_len = output_len;
+	success = TRUE;
+
+out:
+	if (padded_buf) {
+		memset (padded_buf, 0, padded_buf_len);
+		g_free (padded_buf);
+		padded_buf = NULL;
+	}
+
+	if (!success) {
+		if (output) {
+			/* Don't expose key material */
+			memset (output, 0, output_len);
+			g_free (output);
+			output = NULL;
+		}
+	}
+	gnutls_cipher_deinit (ctx);
+	return output;
 }
 
-gboolean
-_nm_crypto_verify_x509 (const guint8 *data,
-                        gsize len,
-                        GError **error)
+NMCryptoFileFormat
+crypto_verify_cert (const unsigned char *data,
+                    gsize len,
+                    GError **error)
 {
 	gnutls_x509_crt_t der;
 	gnutls_datum_t dt;
 	int err;
 
-	if (!_nm_crypto_init (error))
-		return FALSE;
+	if (!crypto_init (error))
+		return NM_CRYPTO_FILE_FORMAT_UNKNOWN;
 
 	err = gnutls_x509_crt_init (&der);
 	if (err < 0) {
@@ -271,7 +285,7 @@ _nm_crypto_verify_x509 (const guint8 *data,
 		             NM_CRYPTO_ERROR_INVALID_DATA,
 		             _("Error initializing certificate data: %s"),
 		             gnutls_strerror (err));
-		return FALSE;
+		return NM_CRYPTO_FILE_FORMAT_UNKNOWN;
 	}
 
 	/* Try DER first */
@@ -280,35 +294,36 @@ _nm_crypto_verify_x509 (const guint8 *data,
 	err = gnutls_x509_crt_import (der, &dt, GNUTLS_X509_FMT_DER);
 	if (err == GNUTLS_E_SUCCESS) {
 		gnutls_x509_crt_deinit (der);
-		return TRUE;
+		return NM_CRYPTO_FILE_FORMAT_X509;
 	}
 
 	/* And PEM next */
 	err = gnutls_x509_crt_import (der, &dt, GNUTLS_X509_FMT_PEM);
 	gnutls_x509_crt_deinit (der);
 	if (err == GNUTLS_E_SUCCESS)
-		return TRUE;
+		return NM_CRYPTO_FILE_FORMAT_X509;
 
 	g_set_error (error, NM_CRYPTO_ERROR,
 	             NM_CRYPTO_ERROR_INVALID_DATA,
 	             _("Couldn't decode certificate: %s"),
 	             gnutls_strerror (err));
-	return FALSE;
+	return NM_CRYPTO_FILE_FORMAT_UNKNOWN;
 }
 
 gboolean
-_nm_crypto_verify_pkcs12 (const guint8 *data,
-                          gsize data_len,
-                          const char *password,
-                          GError **error)
+crypto_verify_pkcs12 (const guint8 *data,
+                      gsize data_len,
+                      const char *password,
+                      GError **error)
 {
 	gnutls_pkcs12_t p12;
 	gnutls_datum_t dt;
+	gboolean success = FALSE;
 	int err;
 
 	g_return_val_if_fail (data != NULL, FALSE);
 
-	if (!_nm_crypto_init (error))
+	if (!crypto_init (error))
 		return FALSE;
 
 	dt.data = (unsigned char *) data;
@@ -333,32 +348,31 @@ _nm_crypto_verify_pkcs12 (const guint8 *data,
 			             NM_CRYPTO_ERROR_INVALID_DATA,
 			             _("Couldn't decode PKCS#12 file: %s"),
 			             gnutls_strerror (err));
-			gnutls_pkcs12_deinit (p12);
-			return FALSE;
+			goto out;
 		}
 	}
 
 	err = gnutls_pkcs12_verify_mac (p12, password);
-
-	gnutls_pkcs12_deinit (p12);
-
-	if (err != GNUTLS_E_SUCCESS) {
+	if (err == GNUTLS_E_SUCCESS)
+		success = TRUE;
+	else {
 		g_set_error (error, NM_CRYPTO_ERROR,
 		             NM_CRYPTO_ERROR_DECRYPTION_FAILED,
 		             _("Couldn't verify PKCS#12 file: %s"),
 		             gnutls_strerror (err));
-		return FALSE;
 	}
 
-	return TRUE;
+out:
+	gnutls_pkcs12_deinit (p12);
+	return success;
 }
 
 gboolean
-_nm_crypto_verify_pkcs8 (const guint8 *data,
-                         gsize data_len,
-                         gboolean is_encrypted,
-                         const char *password,
-                         GError **error)
+crypto_verify_pkcs8 (const guint8 *data,
+                     gsize data_len,
+                     gboolean is_encrypted,
+                     const char *password,
+                     GError **error)
 {
 	gnutls_x509_privkey_t p8;
 	gnutls_datum_t dt;
@@ -366,9 +380,12 @@ _nm_crypto_verify_pkcs8 (const guint8 *data,
 
 	g_return_val_if_fail (data != NULL, FALSE);
 
-	if (!_nm_crypto_init (error))
+	if (!crypto_init (error))
 		return FALSE;
 
+	dt.data = (unsigned char *) data;
+	dt.size = data_len;
+
 	err = gnutls_x509_privkey_init (&p8);
 	if (err < 0) {
 		g_set_error (error, NM_CRYPTO_ERROR,
@@ -378,15 +395,11 @@ _nm_crypto_verify_pkcs8 (const guint8 *data,
 		return FALSE;
 	}
 
-	dt.data = (unsigned char *) data;
-	dt.size = data_len;
-
 	err = gnutls_x509_privkey_import_pkcs8 (p8,
 	                                        &dt,
 	                                        GNUTLS_X509_FMT_DER,
 	                                        is_encrypted ? password : NULL,
 	                                        is_encrypted ? 0 : GNUTLS_PKCS_PLAIN);
-
 	gnutls_x509_privkey_deinit (p8);
 
 	if (err < 0) {
@@ -410,9 +423,9 @@ _nm_crypto_verify_pkcs8 (const guint8 *data,
 }
 
 gboolean
-_nm_crypto_randomize (void *buffer, gsize buffer_len, GError **error)
+crypto_randomize (void *buffer, gsize buffer_len, GError **error)
 {
-	if (!_nm_crypto_init (error))
+	if (!crypto_init (error))
 		return FALSE;
 
 	gnutls_rnd (GNUTLS_RND_RANDOM, buffer, buffer_len);
diff --git a/libnm-core/nm-crypto-nss.c b/libnm-core/crypto_nss.c
index 711dde4b..9a0c4334 100644
--- a/libnm-core/nm-crypto-nss.c
+++ b/libnm-core/crypto_nss.c
@@ -23,8 +23,6 @@
 
 #include "nm-default.h"
 
-#include "nm-crypto-impl.h"
-
 #include <prinit.h>
 #include <nss.h>
 #include <pk11pub.h>
@@ -35,46 +33,20 @@
 #include <ciferfam.h>
 #include <p12plcy.h>
 
-#include "nm-utils/nm-secret-utils.h"
+#include "crypto.h"
 #include "nm-errors.h"
 
-/*****************************************************************************/
-
-static gboolean
-_get_cipher_info (NMCryptoCipherType cipher,
-                  CK_MECHANISM_TYPE *out_cipher_mech,
-                  guint8 *out_real_iv_len)
-{
-	static const CK_MECHANISM_TYPE cipher_mechs[] = {
-		[NM_CRYPTO_CIPHER_DES_EDE3_CBC] = CKM_DES3_CBC_PAD,
-		[NM_CRYPTO_CIPHER_DES_CBC]      = CKM_DES_CBC_PAD,
-		[NM_CRYPTO_CIPHER_AES_128_CBC]  = CKM_AES_CBC_PAD,
-		[NM_CRYPTO_CIPHER_AES_192_CBC]  = CKM_AES_CBC_PAD,
-		[NM_CRYPTO_CIPHER_AES_256_CBC]  = CKM_AES_CBC_PAD,
-	};
-
-	g_return_val_if_fail (_NM_INT_NOT_NEGATIVE (cipher) && (gsize) cipher < G_N_ELEMENTS (cipher_mechs), FALSE);
-
-	if (!cipher_mechs[cipher])
-		return FALSE;
-
-	NM_SET_OUT (out_cipher_mech, cipher_mechs[cipher]);
-	NM_SET_OUT (out_real_iv_len, nm_crypto_cipher_get_info (cipher)->real_iv_len);
-	return TRUE;
-}
-
-/*****************************************************************************/
+static gboolean initialized = FALSE;
 
 gboolean
-_nm_crypto_init (GError **error)
+crypto_init (GError **error)
 {
-	static gboolean initialized = FALSE;
 	SECStatus ret;
 
 	if (initialized)
 		return TRUE;
 
-	PR_Init (PR_USER_THREAD, PR_PRIORITY_NORMAL, 1);
+	PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 1);
 	ret = NSS_NoDB_Init (NULL);
 	if (ret != SECSuccess) {
 		g_set_error (error, NM_CRYPTO_ERROR,
@@ -85,61 +57,74 @@ _nm_crypto_init (GError **error)
 		return FALSE;
 	}
 
-	SEC_PKCS12EnableCipher (PKCS12_RC4_40, 1);
-	SEC_PKCS12EnableCipher (PKCS12_RC4_128, 1);
-	SEC_PKCS12EnableCipher (PKCS12_RC2_CBC_40, 1);
-	SEC_PKCS12EnableCipher (PKCS12_RC2_CBC_128, 1);
-	SEC_PKCS12EnableCipher (PKCS12_DES_56, 1);
-	SEC_PKCS12EnableCipher (PKCS12_DES_EDE3_168, 1);
-	SEC_PKCS12SetPreferredCipher (PKCS12_DES_EDE3_168, 1);
+	SEC_PKCS12EnableCipher(PKCS12_RC4_40, 1);
+	SEC_PKCS12EnableCipher(PKCS12_RC4_128, 1);
+	SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_40, 1);
+	SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_128, 1);
+	SEC_PKCS12EnableCipher(PKCS12_DES_56, 1);
+	SEC_PKCS12EnableCipher(PKCS12_DES_EDE3_168, 1);
+	SEC_PKCS12SetPreferredCipher(PKCS12_DES_EDE3_168, 1);
 
 	initialized = TRUE;
 	return TRUE;
 }
 
-guint8 *
-_nmtst_crypto_decrypt (NMCryptoCipherType cipher,
-                       const guint8 *data,
-                       gsize data_len,
-                       const guint8 *iv,
-                       gsize iv_len,
-                       const guint8 *key,
-                       gsize key_len,
-                       gsize *out_len,
-                       GError **error)
+char *
+crypto_decrypt (const char *cipher,
+                int key_type,
+                const guint8 *data,
+                gsize data_len,
+                const char *iv,
+                const gsize iv_len,
+                const char *key,
+                const gsize key_len,
+                gsize *out_len,
+                GError **error)
 {
+	char *output = NULL;
+	int decrypted_len = 0;
 	CK_MECHANISM_TYPE cipher_mech;
 	PK11SlotInfo *slot = NULL;
 	SECItem key_item;
 	PK11SymKey *sym_key = NULL;
 	SECItem *sec_param = NULL;
 	PK11Context *ctx = NULL;
-	nm_auto_clear_secret_ptr NMSecretPtr output = { 0 };
 	SECStatus s;
 	gboolean success = FALSE;
-	int decrypted_len = 0;
-	unsigned extra = 0;
-	unsigned pad_len = 0;
-	guint32 i;
-	guint8 real_iv_len;
+	unsigned pad_len = 0, extra = 0;
+	guint32 i, real_iv_len = 0;
+
+	if (!crypto_init (error))
+		return NULL;
 
-	if (!_get_cipher_info (cipher, &cipher_mech, &real_iv_len)) {
+	if (!strcmp (cipher, CIPHER_DES_EDE3_CBC)) {
+		cipher_mech = CKM_DES3_CBC_PAD;
+		real_iv_len = 8;
+	} else if (!strcmp (cipher, CIPHER_DES_CBC)) {
+		cipher_mech = CKM_DES_CBC_PAD;
+		real_iv_len = 8;
+	} else if (NM_IN_STRSET (cipher, CIPHER_AES_128_CBC,
+	                                 CIPHER_AES_192_CBC,
+	                                 CIPHER_AES_256_CBC)) {
+		cipher_mech = CKM_AES_CBC_PAD;
+		real_iv_len = 16;
+	} else {
 		g_set_error (error, NM_CRYPTO_ERROR,
 		             NM_CRYPTO_ERROR_UNKNOWN_CIPHER,
-		             _("Unsupported key cipher for decryption"));
+		             _("Private key cipher '%s' was unknown."),
+		             cipher);
 		return NULL;
 	}
 
 	if (iv_len < real_iv_len) {
 		g_set_error (error, NM_CRYPTO_ERROR,
 		             NM_CRYPTO_ERROR_INVALID_DATA,
-		             _("Invalid IV length (must be at least %u)."),
-		             (guint) real_iv_len);
+		             _("Invalid IV length (must be at least %d)."),
+		             real_iv_len);
 		return NULL;
 	}
 
-	if (!_nm_crypto_init (error))
-		return NULL;
+	output = g_malloc0 (data_len);
 
 	slot = PK11_GetBestSlot (cipher_mech, NULL);
 	if (!slot) {
@@ -177,13 +162,10 @@ _nmtst_crypto_decrypt (NMCryptoCipherType cipher,
 		goto out;
 	}
 
-	output.len = data_len;
-	output.bin = g_malloc (data_len);
-
 	s = PK11_CipherOp (ctx,
-	                   (unsigned char *) output.bin,
+	                   (unsigned char *) output,
 	                   &decrypted_len,
-	                   output.len,
+	                   data_len,
 	                   data,
 	                   data_len);
 	if (s != SECSuccess) {
@@ -202,7 +184,7 @@ _nmtst_crypto_decrypt (NMCryptoCipherType cipher,
 	}
 
 	s = PK11_DigestFinal (ctx,
-	                      (unsigned char *) &output.bin[decrypted_len],
+	                      (unsigned char *) (output + decrypted_len),
 	                      &extra,
 	                      data_len - decrypted_len);
 	if (s != SECSuccess) {
@@ -212,7 +194,6 @@ _nmtst_crypto_decrypt (NMCryptoCipherType cipher,
 		             PORT_GetError ());
 		goto out;
 	}
-
 	decrypted_len += extra;
 	pad_len = data_len - decrypted_len;
 
@@ -228,7 +209,7 @@ _nmtst_crypto_decrypt (NMCryptoCipherType cipher,
 	 * should contain the padding size.
 	 */
 	for (i = pad_len; i > 0; i--) {
-		if (output.bin[data_len - i] != pad_len) {
+		if (output[data_len - i] != pad_len) {
 			g_set_error (error, NM_CRYPTO_ERROR,
 			             NM_CRYPTO_ERROR_DECRYPTION_FAILED,
 			             _("Failed to decrypt the private key."));
@@ -236,6 +217,7 @@ _nmtst_crypto_decrypt (NMCryptoCipherType cipher,
 		}
 	}
 
+	*out_len = decrypted_len;
 	success = TRUE;
 
 out:
@@ -248,25 +230,27 @@ out:
 	if (slot)
 		PK11_FreeSlot (slot);
 
-	if (!success)
-		return NULL;
-
-	if (decrypted_len < output.len)
-		nm_explicit_bzero (&output.bin[decrypted_len], output.len - decrypted_len);
-	*out_len = decrypted_len;
-	return g_steal_pointer (&output.bin);
+	if (!success) {
+		if (output) {
+			/* Don't expose key material */
+			memset (output, 0, data_len);
+			g_free (output);
+			output = NULL;
+		}
+	}
+	return output;
 }
 
-guint8 *
-_nmtst_crypto_encrypt (NMCryptoCipherType cipher,
-                       const guint8 *data,
-                       gsize data_len,
-                       const guint8 *iv,
-                       gsize iv_len,
-                       const guint8 *key,
-                       gsize key_len,
-                       gsize *out_len,
-                       GError **error)
+char *
+crypto_encrypt (const char *cipher,
+                const guint8 *data,
+                gsize data_len,
+                const char *iv,
+                gsize iv_len,
+                const char *key,
+                gsize key_len,
+                gsize *out_len,
+                GError **error)
 {
 	SECStatus ret;
 	CK_MECHANISM_TYPE cipher_mech = CKM_DES3_CBC_PAD;
@@ -276,29 +260,49 @@ _nmtst_crypto_encrypt (NMCryptoCipherType cipher,
 	PK11SymKey *sym_key = NULL;
 	SECItem *sec_param = NULL;
 	PK11Context *ctx = NULL;
-	nm_auto_clear_secret_ptr NMSecretPtr padded_buf = { 0 };
-	nm_auto_clear_secret_ptr NMSecretPtr output = { 0 };
+	unsigned char *output, *padded_buf;
+	gsize output_len;
 	int encrypted_len = 0, i;
 	gboolean success = FALSE;
-	gsize pad_len;
+	gsize padded_buf_len, pad_len;
+
+	if (!crypto_init (error))
+		return NULL;
 
-	if (   cipher == NM_CRYPTO_CIPHER_DES_CBC
-	    || !_get_cipher_info (cipher, &cipher_mech, NULL)) {
+	if (!strcmp (cipher, CIPHER_DES_EDE3_CBC))
+		cipher_mech = CKM_DES3_CBC_PAD;
+	else if (NM_IN_STRSET (cipher,
+	                       CIPHER_AES_128_CBC,
+	                       CIPHER_AES_192_CBC,
+	                       CIPHER_AES_256_CBC))
+		cipher_mech = CKM_AES_CBC_PAD;
+	else {
 		g_set_error (error, NM_CRYPTO_ERROR,
 		             NM_CRYPTO_ERROR_UNKNOWN_CIPHER,
-		             _("Unsupported key cipher for encryption"));
+		             _("Private key cipher '%s' was unknown."),
+		             cipher);
 		return NULL;
 	}
 
-	if (!_nm_crypto_init (error))
-		return NULL;
+	/* If data->len % ivlen == 0, then we add another complete block
+	 * onto the end so that the decrypter knows there's padding.
+	 */
+	pad_len = iv_len - (data_len % iv_len);
+	output_len = padded_buf_len = data_len + pad_len;
+	padded_buf = g_malloc0 (padded_buf_len);
+
+	memcpy (padded_buf, data, data_len);
+	for (i = 0; i < pad_len; i++)
+		padded_buf[data_len + i] = (guint8) (pad_len & 0xFF);
+
+	output = g_malloc0 (output_len);
 
 	slot = PK11_GetBestSlot (cipher_mech, NULL);
 	if (!slot) {
 		g_set_error (error, NM_CRYPTO_ERROR,
 		             NM_CRYPTO_ERROR_FAILED,
 		             _("Failed to initialize the encryption cipher slot."));
-		return NULL;
+		goto out;
 	}
 
 	sym_key = PK11_ImportSymKey (slot, cipher_mech, PK11_OriginUnwrap, CKA_ENCRYPT, &key_item, NULL);
@@ -325,22 +329,7 @@ _nmtst_crypto_encrypt (NMCryptoCipherType cipher,
 		goto out;
 	}
 
-	/* If data->len % ivlen == 0, then we add another complete block
-	 * onto the end so that the decrypter knows there's padding.
-	 */
-	pad_len = iv_len - (data_len % iv_len);
-
-	padded_buf.len = data_len + pad_len;
-	padded_buf.bin = g_malloc (padded_buf.len);
-
-	memcpy (padded_buf.bin, data, data_len);
-	for (i = 0; i < pad_len; i++)
-		padded_buf.bin[data_len + i] = (guint8) (pad_len & 0xFF);
-
-	output.len = padded_buf.len;
-	output.bin = g_malloc (output.len);
-
-	ret = PK11_CipherOp (ctx, output.bin, &encrypted_len, output.len, padded_buf.bin, padded_buf.len);
+	ret = PK11_CipherOp (ctx, output, &encrypted_len, output_len, padded_buf, padded_buf_len);
 	if (ret != SECSuccess) {
 		g_set_error (error, NM_CRYPTO_ERROR,
 		             NM_CRYPTO_ERROR_ENCRYPTION_FAILED,
@@ -349,41 +338,46 @@ _nmtst_crypto_encrypt (NMCryptoCipherType cipher,
 		goto out;
 	}
 
-	if (encrypted_len != output.len) {
+	if (encrypted_len != output_len) {
 		g_set_error (error, NM_CRYPTO_ERROR,
 		             NM_CRYPTO_ERROR_ENCRYPTION_FAILED,
 		             _("Unexpected amount of data after encrypting."));
 		goto out;
 	}
 
+	*out_len = encrypted_len;
 	success = TRUE;
 
 out:
 	if (ctx)
 		PK11_DestroyContext (ctx, PR_TRUE);
-	if (sec_param)
-		SECITEM_FreeItem (sec_param, PR_TRUE);
 	if (sym_key)
 		PK11_FreeSymKey (sym_key);
+	if (sec_param)
+		SECITEM_FreeItem (sec_param, PR_TRUE);
 	if (slot)
 		PK11_FreeSlot (slot);
 
-	if (!success)
-		return NULL;
+	memset (padded_buf, 0, padded_buf_len);
+	g_free (padded_buf);
 
-	*out_len = output.len;
-	return g_steal_pointer (&output.bin);
+	if (!success) {
+		memset (output, 0, output_len);
+		g_free (output);
+		output = NULL;
+	}
+	return (char *) output;
 }
 
-gboolean
-_nm_crypto_verify_x509 (const guint8 *data,
-                        gsize len,
-                        GError **error)
+NMCryptoFileFormat
+crypto_verify_cert (const unsigned char *data,
+                    gsize len,
+                    GError **error)
 {
 	CERTCertificate *cert;
 
-	if (!_nm_crypto_init (error))
-		return FALSE;
+	if (!crypto_init (error))
+		return NM_CRYPTO_FILE_FORMAT_UNKNOWN;
 
 	/* Try DER/PEM first */
 	cert = CERT_DecodeCertFromPackage ((char *) data, len);
@@ -391,85 +385,76 @@ _nm_crypto_verify_x509 (const guint8 *data,
 		g_set_error (error, NM_CRYPTO_ERROR,
 		             NM_CRYPTO_ERROR_INVALID_DATA,
 		             _("Couldn't decode certificate: %d"),
-		             PORT_GetError ());
-		return FALSE;
+		             PORT_GetError());
+		return NM_CRYPTO_FILE_FORMAT_UNKNOWN;
 	}
 
 	CERT_DestroyCertificate (cert);
-	return TRUE;
+	return NM_CRYPTO_FILE_FORMAT_X509;
 }
 
 gboolean
-_nm_crypto_verify_pkcs12 (const guint8 *data,
-                          gsize data_len,
-                          const char *password,
-                          GError **error)
+crypto_verify_pkcs12 (const guint8 *data,
+                      gsize data_len,
+                      const char *password,
+                      GError **error)
 {
 	SEC_PKCS12DecoderContext *p12ctx = NULL;
 	SECItem pw = { 0 };
 	PK11SlotInfo *slot = NULL;
 	SECStatus s;
-	gboolean success = FALSE;
+	gunichar2 *ucs2_password;
+	glong ucs2_chars = 0;
+#ifndef WORDS_BIGENDIAN
+	guint16 *p;
+#endif /* WORDS_BIGENDIAN */
 
-	g_return_val_if_fail (!error || !*error, FALSE);
+	if (error)
+		g_return_val_if_fail (*error == NULL, FALSE);
 
-	if (!_nm_crypto_init (error))
+	if (!crypto_init (error))
 		return FALSE;
 
 	/* PKCS#12 passwords are apparently UCS2 BIG ENDIAN, and NSS doesn't do
 	 * any conversions for us.
 	 */
 	if (password && *password) {
-		nm_auto_clear_secret_ptr NMSecretPtr ucs2_password = { 0 };
-
-		if (g_utf8_validate (password, -1, NULL)) {
-			long ucs2_chars;
-
-			ucs2_password.bin = (guint8 *) g_utf8_to_utf16 (password, strlen (password), NULL, &ucs2_chars, NULL);
-
-			/* cannot fail, because password is valid UTF-8*/
-			nm_assert (ucs2_password.bin && ucs2_chars > 0);
-
-			ucs2_password.len = ucs2_chars * 2;
-		}
-
-		if (!ucs2_password.bin || ucs2_password.len == 0) {
+		if (!g_utf8_validate (password, -1, NULL)) {
 			g_set_error (error, NM_CRYPTO_ERROR,
 			             NM_CRYPTO_ERROR_INVALID_PASSWORD,
 			             _("Password must be UTF-8"));
 			return FALSE;
 		}
-
-		pw.data = PORT_ZAlloc (ucs2_password.len + 2);
-		memcpy (pw.data, ucs2_password.bin, ucs2_password.len);
-		pw.len = ucs2_password.len + 2;
-
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-		{
-			guint16 *p, *p_end;
-
-			p_end = (guint16 *) &(((guint8 *) pw.data)[ucs2_password.len]);
-			for (p = (guint16 *) pw.data; p < p_end; p++)
-				*p = GUINT16_SWAP_LE_BE (*p);
-		}
-#endif
-	}
-
-	slot = PK11_GetInternalKeySlot ();
-	if (!slot) {
-		g_set_error (error, NM_CRYPTO_ERROR,
-		             NM_CRYPTO_ERROR_FAILED,
-		             _("Couldn't initialize slot"));
-		goto out;
+		ucs2_password = g_utf8_to_utf16 (password, strlen (password), NULL, &ucs2_chars, NULL);
+		/* Can't fail if g_utf8_validate() succeeded */
+		g_return_val_if_fail (ucs2_password != NULL && ucs2_chars != 0, FALSE);
+
+		ucs2_chars *= 2;  /* convert # UCS2 characters -> bytes */
+		pw.data = PORT_ZAlloc(ucs2_chars + 2);
+		memcpy (pw.data, ucs2_password, ucs2_chars);
+		pw.len = ucs2_chars + 2;  /* include terminating NULL */
+
+		memset (ucs2_password, 0, ucs2_chars);
+		g_free (ucs2_password);
+
+#ifndef WORDS_BIGENDIAN
+		for (p = (guint16 *) pw.data; p < (guint16 *) (pw.data + pw.len); p++)
+			*p = GUINT16_SWAP_LE_BE (*p);
+#endif /* WORDS_BIGENDIAN */
+	} else {
+		/* NULL password */
+		pw.data = NULL;
+		pw.len = 0;
 	}
 
+	slot = PK11_GetInternalKeySlot();
 	p12ctx = SEC_PKCS12DecoderStart (&pw, slot, NULL, NULL, NULL, NULL, NULL, NULL);
 	if (!p12ctx) {
 		g_set_error (error, NM_CRYPTO_ERROR,
 		             NM_CRYPTO_ERROR_FAILED,
 		             _("Couldn't initialize PKCS#12 decoder: %d"),
-		             PORT_GetError ());
-		goto out;
+		             PORT_GetError());
+		goto error;
 	}
 
 	s = SEC_PKCS12DecoderUpdate (p12ctx, (guint8 *)data, data_len);
@@ -477,8 +462,8 @@ _nm_crypto_verify_pkcs12 (const guint8 *data,
 		g_set_error (error, NM_CRYPTO_ERROR,
 		             NM_CRYPTO_ERROR_INVALID_DATA,
 		             _("Couldn't decode PKCS#12 file: %d"),
-		             PORT_GetError ());
-		goto out;
+		             PORT_GetError());
+		goto error;
 	}
 
 	s = SEC_PKCS12DecoderVerify (p12ctx);
@@ -486,34 +471,35 @@ _nm_crypto_verify_pkcs12 (const guint8 *data,
 		g_set_error (error, NM_CRYPTO_ERROR,
 		             NM_CRYPTO_ERROR_DECRYPTION_FAILED,
 		             _("Couldn't verify PKCS#12 file: %d"),
-		             PORT_GetError ());
-		goto out;
+		             PORT_GetError());
+		goto error;
 	}
 
-	success = TRUE;
+	SEC_PKCS12DecoderFinish (p12ctx);
+	SECITEM_ZfreeItem (&pw, PR_FALSE);
+	return TRUE;
 
-out:
+error:
 	if (p12ctx)
 		SEC_PKCS12DecoderFinish (p12ctx);
-	if (slot)
-		PK11_FreeSlot (slot);
 
-	if (pw.data)
-		SECITEM_ZfreeItem (&pw, PR_FALSE);
+	if (slot)
+		PK11_FreeSlot(slot);
 
-	return success;
+	SECITEM_ZfreeItem (&pw, PR_FALSE);
+	return FALSE;
 }
 
 gboolean
-_nm_crypto_verify_pkcs8 (const guint8 *data,
-                         gsize data_len,
-                         gboolean is_encrypted,
-                         const char *password,
-                         GError **error)
+crypto_verify_pkcs8 (const guint8 *data,
+                     gsize data_len,
+                     gboolean is_encrypted,
+                     const char *password,
+                     GError **error)
 {
 	g_return_val_if_fail (data != NULL, FALSE);
 
-	if (!_nm_crypto_init (error))
+	if (!crypto_init (error))
 		return FALSE;
 
 	/* NSS apparently doesn't do PKCS#8 natively, but you have to put the
@@ -524,11 +510,11 @@ _nm_crypto_verify_pkcs8 (const guint8 *data,
 }
 
 gboolean
-_nm_crypto_randomize (void *buffer, gsize buffer_len, GError **error)
+crypto_randomize (void *buffer, gsize buffer_len, GError **error)
 {
 	SECStatus s;
 
-	if (!_nm_crypto_init (error))
+	if (!crypto_init (error))
 		return FALSE;
 
 	s = PK11_GenerateRandom (buffer, buffer_len);
diff --git a/libnm-core/meson.build b/libnm-core/meson.build
index ac13a1be..7b143706 100644
--- a/libnm-core/meson.build
+++ b/libnm-core/meson.build
@@ -5,7 +5,6 @@ libnm_core_headers = files(
   'nm-core-types.h',
   'nm-dbus-interface.h',
   'nm-errors.h',
-  'nm-setting-6lowpan.h',
   'nm-setting-8021x.h',
   'nm-setting-adsl.h',
   'nm-setting-bluetooth.h',
@@ -16,7 +15,6 @@ libnm_core_headers = files(
   'nm-setting-connection.h',
   'nm-setting-dcb.h',
   'nm-setting-dummy.h',
-  'nm-setting-ethtool.h',
   'nm-setting-generic.h',
   'nm-setting-gsm.h',
   'nm-setting-infiniband.h',
@@ -26,7 +24,6 @@ libnm_core_headers = files(
   'nm-setting-ip6-config.h',
   'nm-setting-macsec.h',
   'nm-setting-macvlan.h',
-  'nm-setting-match.h',
   'nm-setting-olpc-mesh.h',
   'nm-setting-ovs-bridge.h',
   'nm-setting-ovs-interface.h',
@@ -36,7 +33,6 @@ libnm_core_headers = files(
   'nm-setting-pppoe.h',
   'nm-setting-proxy.h',
   'nm-setting-serial.h',
-  'nm-setting-sriov.h',
   'nm-setting-tc-config.h',
   'nm-setting-team-port.h',
   'nm-setting-team.h',
@@ -49,7 +45,6 @@ libnm_core_headers = files(
   'nm-setting-wired.h',
   'nm-setting-wireless-security.h',
   'nm-setting-wireless.h',
-  'nm-setting-wpan.h',
   'nm-setting.h',
   'nm-simple-connection.h',
   'nm-utils.h',
@@ -60,7 +55,6 @@ libnm_core_headers = files(
 )
 
 libnm_core_settings_sources = files(
-  'nm-setting-6lowpan.c',
   'nm-setting-8021x.c',
   'nm-setting-adsl.c',
   'nm-setting-bluetooth.c',
@@ -71,7 +65,6 @@ libnm_core_settings_sources = files(
   'nm-setting-connection.c',
   'nm-setting-dcb.c',
   'nm-setting-dummy.c',
-  'nm-setting-ethtool.c',
   'nm-setting-generic.c',
   'nm-setting-gsm.c',
   'nm-setting-infiniband.c',
@@ -81,7 +74,6 @@ libnm_core_settings_sources = files(
   'nm-setting-ip6-config.c',
   'nm-setting-macsec.c',
   'nm-setting-macvlan.c',
-  'nm-setting-match.c',
   'nm-setting-olpc-mesh.c',
   'nm-setting-ovs-bridge.c',
   'nm-setting-ovs-interface.c',
@@ -91,7 +83,6 @@ libnm_core_settings_sources = files(
   'nm-setting-pppoe.c',
   'nm-setting-proxy.c',
   'nm-setting-serial.c',
-  'nm-setting-sriov.c',
   'nm-setting-tc-config.c',
   'nm-setting-team-port.c',
   'nm-setting-team.c',
@@ -103,12 +94,12 @@ libnm_core_settings_sources = files(
   'nm-setting-wimax.c',
   'nm-setting-wired.c',
   'nm-setting-wireless-security.c',
-  'nm-setting-wireless.c',
-  'nm-setting-wpan.c'
+  'nm-setting-wireless.c'
 )
 
 libnm_core_sources = libnm_core_settings_sources + files(
-  'nm-crypto.c',
+  'crypto.c',
+  'crypto_' + crypto + '.c',
   'nm-connection.c',
   'nm-dbus-utils.c',
   'nm-errors.c',
@@ -136,6 +127,7 @@ libnm_core_enum = gnome.mkenums(
 )
 
 deps = [
+  crypto_dep,
   dl_dep,
   libudev_dep,
   shared_dep,
@@ -146,6 +138,12 @@ deps = [
 cflags = [
   '-DG_LOG_DOMAIN="@0@"'.format(libnm_name),
   '-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_LIBNM_CORE',
+  '-DLIBEXECDIR="@0@"'.format(nm_libexecdir),
+  '-DNMLOCALEDIR="@0@"'.format(nm_localedir),
+  '-DNMCONFDIR="@0@"'.format(nm_pkgconfdir),
+  '-DNMLIBDIR="@0@"'.format(nm_pkglibdir),
+  '-DNMPLUGINDIR="@0@"'.format(nm_plugindir),
+  '-DNMVPNDIR="@0@"'.format(nm_vpndir)
 ]
 
 if enable_json_validation
@@ -153,36 +151,9 @@ if enable_json_validation
   deps += jansson_dep
 endif
 
-if (crypto_gnutls_dep.found())
-  libnm_crypto_gnutls = static_library(
-    'nm-crypto-gnutls',
-    sources: [ 'nm-crypto-gnutls.c' ],
-    dependencies: deps + [ crypto_gnutls_dep ],
-    c_args: cflags
-  )
-endif
-
-if (crypto_nss_dep.found())
-  libnm_crypto_nss = static_library(
-    'nm-crypto-nss',
-    sources: [ 'nm-crypto-nss.c' ],
-    dependencies: deps + [ crypto_nss_dep ],
-    c_args: cflags
-  )
-endif
-
-if crypto == 'gnutls'
-  libnm_crypto = libnm_crypto_gnutls
-elif crypto == 'nss'
-  libnm_crypto = libnm_crypto_nss
-else
-  error('bug')
-endif
-
 libnm_core_sources_all =  libnm_core_sources
 libnm_core_sources_all += libnm_core_enum
-libnm_core_sources_all += shared_nm_meta_setting_c
-libnm_core_sources_all += shared_nm_ethtool_utils_c
+libnm_core_sources_all += shared_nm_utils_nm_meta_setting_c
 libnm_core_sources_all += shared_files_libnm_core
 libnm_core_sources_all += [version_header]
 
@@ -190,7 +161,6 @@ libnm_core = static_library(
   'nm-core',
   sources: libnm_core_sources_all,
   dependencies: deps,
-  link_with: libnm_crypto,
   c_args: cflags
 )
 
diff --git a/libnm-core/nm-connection.c b/libnm-core/nm-connection.c
index 172f9c99..0c4d7ce1 100644
--- a/libnm-core/nm-connection.c
+++ b/libnm-core/nm-connection.c
@@ -16,7 +16,7 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * Copyright 2007 - 2018 Red Hat, Inc.
+ * Copyright 2007 - 2017 Red Hat, Inc.
  * Copyright 2007 - 2008 Novell, Inc.
  */
 
@@ -225,40 +225,6 @@ nm_connection_get_setting_by_name (NMConnection *connection, const char *name)
 	return type ? _connection_get_setting (connection, type) : NULL;
 }
 
-/*****************************************************************************/
-
-gpointer /* (NMSetting *) */
-_nm_connection_check_main_setting (NMConnection *connection,
-                                   const char *setting_name,
-                                   GError **error)
-{
-	NMSetting *setting;
-
-	nm_assert (NM_IS_CONNECTION (connection));
-	nm_assert (setting_name);
-
-	if (!nm_connection_is_type (connection, setting_name)) {
-		nm_utils_error_set (error,
-		                    NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE,
-		                    "connection type is not \"%s\"",
-		                    setting_name);
-		return NULL;
-	}
-
-	setting = nm_connection_get_setting_by_name (connection, setting_name);
-	if (!setting) {
-		nm_utils_error_set (error,
-		                    NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE,
-		                    "connection misses \"%s\" settings",
-		                    setting_name);
-		return NULL;
-	}
-
-	return setting;
-}
-
-/*****************************************************************************/
-
 static gboolean
 validate_permissions_type (GVariant *variant, GError **error)
 {
@@ -843,34 +809,16 @@ _normalize_ethernet_link_neg (NMConnection *self)
 	return FALSE;
 }
 
-/**
- * _supports_addr_family:
- * @self: a #NMConnection
- * @family: AF_*
- *
- * Check whether the connection supports certain L3 address family,
- * in order to be able to tell whether is should have the corresponding
- * setting ("ipv4" for AF_INET and "ipv6" for AF_INET6).
- *
- * If AF_UNSPEC is given, then the function checks whether the connection
- * supports any L3 configuration at all.
- *
- * Returns: %TRUE if the AF is supported, %FALSE otherwise
- **/
 static gboolean
-_supports_addr_family (NMConnection *self, int family)
+_without_ip_config (NMConnection *self)
 {
 	const char *connection_type = nm_connection_get_connection_type (self);
 
-	g_return_val_if_fail (connection_type, TRUE);
+	g_return_val_if_fail (connection_type, FALSE);
 	if (strcmp (connection_type, NM_SETTING_OVS_INTERFACE_SETTING_NAME) == 0)
-		return TRUE;
-	if (strcmp (connection_type, NM_SETTING_WPAN_SETTING_NAME) == 0)
 		return FALSE;
-	if (strcmp (connection_type, NM_SETTING_6LOWPAN_SETTING_NAME) == 0)
-		return family == AF_INET6 || family == AF_UNSPEC;
 
-	return !nm_setting_connection_get_master (nm_connection_get_setting_connection (self));
+	return !!nm_setting_connection_get_master (nm_connection_get_setting_connection (self));
 }
 
 static gboolean
@@ -893,18 +841,32 @@ _normalize_ip_config (NMConnection *self, GHashTable *parameters)
 	s_ip6 = nm_connection_get_setting_ip6_config (self);
 	s_proxy = nm_connection_get_setting_proxy (self);
 
-	if (_supports_addr_family (self, AF_INET)) {
+	if (_without_ip_config (self)) {
+		/* Slave connections don't have IP configuration. */
+
+		if (s_ip4)
+			nm_connection_remove_setting (self, NM_TYPE_SETTING_IP4_CONFIG);
+
+		if (s_ip6)
+			nm_connection_remove_setting (self, NM_TYPE_SETTING_IP6_CONFIG);
+
+		if (s_proxy)
+			nm_connection_remove_setting (self, NM_TYPE_SETTING_PROXY);
+
+		return s_ip4 || s_ip6 || s_proxy;
+	} else {
+		/* Ensure all non-slave connections have IP4 and IP6 settings objects. If no
+		 * IP6 setting was specified, then assume that means IP6 config is allowed
+		 * to fail. But if no IP4 setting was specified, assume the caller was just
+		 * being lazy.
+		 */
 		if (!s_ip4) {
-			 /* But if no IP4 setting was specified, assume the caller was just
-			  * being lazy and use the default method.
-			  */
 			setting = nm_setting_ip4_config_new ();
 
 			g_object_set (setting,
 			              NM_SETTING_IP_CONFIG_METHOD, default_ip4_method,
 			              NULL);
 			nm_connection_add_setting (self, setting);
-			changed = TRUE;
 		} else {
 			if (   nm_setting_ip_config_get_gateway (s_ip4)
 			    && nm_setting_ip_config_get_never_default (s_ip4)) {
@@ -928,18 +890,7 @@ _normalize_ip_config (NMConnection *self, GHashTable *parameters)
 				changed = TRUE;
 			}
 		}
-	} else {
-		if (s_ip4) {
-			nm_connection_remove_setting (self, NM_TYPE_SETTING_IP4_CONFIG);
-			changed = TRUE;
-		}
-	}
-
-	if (_supports_addr_family (self, AF_INET6)) {
 		if (!s_ip6) {
-			/* If no IP6 setting was specified, then assume that means IP6 config is
-			 * allowed to fail.
-			 */
 			setting = nm_setting_ip6_config_new ();
 
 			g_object_set (setting,
@@ -947,7 +898,6 @@ _normalize_ip_config (NMConnection *self, GHashTable *parameters)
 			              NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE,
 			              NULL);
 			nm_connection_add_setting (self, setting);
-			changed = TRUE;
 		} else {
 			const char *token;
 
@@ -980,27 +930,14 @@ _normalize_ip_config (NMConnection *self, GHashTable *parameters)
 				changed = TRUE;
 			}
 		}
-	} else {
-		if (s_ip6) {
-			nm_connection_remove_setting (self, NM_TYPE_SETTING_IP6_CONFIG);
-			changed = TRUE;
-		}
-	}
 
-	if (_supports_addr_family (self, AF_UNSPEC)) {
 		if (!s_proxy) {
 			setting = nm_setting_proxy_new ();
 			nm_connection_add_setting (self, setting);
-			changed = TRUE;
 		}
-	} else {
-		if (s_proxy) {
-			nm_connection_remove_setting (self, NM_TYPE_SETTING_PROXY);
-			changed = TRUE;
-		}
-	}
 
-	return changed;
+		return !s_ip4 || !s_ip6 || !s_proxy || changed;
+	}
 }
 
 static gboolean
@@ -1192,38 +1129,6 @@ _normalize_ovs_interface_type (NMConnection *self, GHashTable *parameters)
 }
 
 static gboolean
-_normalize_ip_tunnel_wired_setting (NMConnection *self, GHashTable *parameters)
-{
-	NMSettingIPTunnel *s_ip_tunnel;
-
-	s_ip_tunnel = nm_connection_get_setting_ip_tunnel (self);
-	if (!s_ip_tunnel)
-		return FALSE;
-
-	if (   nm_connection_get_setting_wired (self)
-	    && !NM_IN_SET (nm_setting_ip_tunnel_get_mode (s_ip_tunnel),
-	                   NM_IP_TUNNEL_MODE_GRETAP,
-	                   NM_IP_TUNNEL_MODE_IP6GRETAP)) {
-		nm_connection_remove_setting (self, NM_TYPE_SETTING_WIRED);
-		return TRUE;
-	}
-
-	return FALSE;
-}
-
-static gboolean
-_normalize_sriov_vf_order (NMConnection *self, GHashTable *parameters)
-{
-	NMSettingSriov *s_sriov;
-
-	s_sriov = NM_SETTING_SRIOV (nm_connection_get_setting (self, NM_TYPE_SETTING_SRIOV));
-	if (!s_sriov)
-		return FALSE;
-
-	return _nm_setting_sriov_sort_vfs (s_sriov);
-}
-
-static gboolean
 _normalize_required_settings (NMConnection *self, GHashTable *parameters)
 {
 	NMSettingBluetooth *s_bt = nm_connection_get_setting_bluetooth (self);
@@ -1383,79 +1288,39 @@ _nm_connection_verify (NMConnection *connection, GError **error)
 	nm_assert (normalizable_error_type != NM_SETTING_VERIFY_ERROR);
 	if (NM_IN_SET (normalizable_error_type, NM_SETTING_VERIFY_SUCCESS,
 	                                        NM_SETTING_VERIFY_NORMALIZABLE)) {
-		if (_supports_addr_family (connection, AF_INET)) {
-			if (!s_ip4 && normalizable_error_type == NM_SETTING_VERIFY_SUCCESS) {
-				g_set_error_literal (&normalizable_error,
-				                     NM_CONNECTION_ERROR,
-				                     NM_CONNECTION_ERROR_MISSING_SETTING,
-				                     _("setting is required for non-slave connections"));
-				g_prefix_error (&normalizable_error, "%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME);
-
-				/* having a master without IP config was not a verify() error, accept
-				 * it for backward compatibility. */
-				normalizable_error_type = NM_SETTING_VERIFY_NORMALIZABLE;
-			}
-		} else {
-			if (s_ip4) {
+		if (_without_ip_config (connection)) {
+			if (s_ip4 || s_ip6 || s_proxy) {
 				g_clear_error (&normalizable_error);
 				g_set_error_literal (&normalizable_error,
 				                     NM_CONNECTION_ERROR,
 				                     NM_CONNECTION_ERROR_INVALID_SETTING,
 				                     _("setting not allowed in slave connection"));
-				g_prefix_error (&normalizable_error, "%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME);
+				g_prefix_error (&normalizable_error, "%s: ",
+				                s_ip4
+				                ? NM_SETTING_IP4_CONFIG_SETTING_NAME
+				                : (s_ip6
+				                   ? NM_SETTING_IP6_CONFIG_SETTING_NAME
+				                   : NM_SETTING_PROXY_SETTING_NAME));
 				/* having a slave with IP config *was* and is a verify() error. */
 				normalizable_error_type = NM_SETTING_VERIFY_NORMALIZABLE_ERROR;
 			}
-		}
-
-		if (_supports_addr_family (connection, AF_INET6)) {
-			if (!s_ip6 && normalizable_error_type == NM_SETTING_VERIFY_SUCCESS) {
-				g_set_error_literal (&normalizable_error,
-				                     NM_CONNECTION_ERROR,
-				                     NM_CONNECTION_ERROR_MISSING_SETTING,
-				                     _("setting is required for non-slave connections"));
-				g_prefix_error (&normalizable_error, "%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME);
-
-				/* having a master without IP config was not a verify() error, accept
-				 * it for backward compatibility. */
-				normalizable_error_type = NM_SETTING_VERIFY_NORMALIZABLE;
-			}
 		} else {
-			if (s_ip6) {
-				g_clear_error (&normalizable_error);
-				g_set_error_literal (&normalizable_error,
-				                     NM_CONNECTION_ERROR,
-				                     NM_CONNECTION_ERROR_INVALID_SETTING,
-				                     _("setting not allowed in slave connection"));
-				g_prefix_error (&normalizable_error, "%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME);
-				/* having a slave with IP config *was* and is a verify() error. */
-				normalizable_error_type = NM_SETTING_VERIFY_NORMALIZABLE_ERROR;
-			}
-		}
-
-		if (_supports_addr_family (connection, AF_UNSPEC)) {
-			if (!s_proxy && normalizable_error_type == NM_SETTING_VERIFY_SUCCESS) {
+			if (   normalizable_error_type == NM_SETTING_VERIFY_SUCCESS
+			    && (!s_ip4 || !s_ip6 || !s_proxy)) {
 				g_set_error_literal (&normalizable_error,
 				                     NM_CONNECTION_ERROR,
 				                     NM_CONNECTION_ERROR_MISSING_SETTING,
 				                     _("setting is required for non-slave connections"));
-				g_prefix_error (&normalizable_error, "%s: ", NM_SETTING_PROXY_SETTING_NAME);
-
-				/* having a master without proxy config was not a verify() error, accept
+				g_prefix_error (&normalizable_error, "%s: ",
+				                !s_ip4
+				                ? NM_SETTING_IP4_CONFIG_SETTING_NAME
+				                : (!s_ip6
+				                   ? NM_SETTING_IP6_CONFIG_SETTING_NAME
+				                   : NM_SETTING_PROXY_SETTING_NAME));
+				/* having a master without IP config was not a verify() error, accept
 				 * it for backward compatibility. */
 				normalizable_error_type = NM_SETTING_VERIFY_NORMALIZABLE;
 			}
-		} else {
-			if (s_proxy) {
-				g_clear_error (&normalizable_error);
-				g_set_error_literal (&normalizable_error,
-				                     NM_CONNECTION_ERROR,
-				                     NM_CONNECTION_ERROR_INVALID_SETTING,
-				                     _("setting not allowed in slave connection"));
-				g_prefix_error (&normalizable_error, "%s: ", NM_SETTING_PROXY_SETTING_NAME);
-				/* having a slave with proxy config *was* and is a verify() error. */
-				normalizable_error_type = NM_SETTING_VERIFY_NORMALIZABLE_ERROR;
-			}
 		}
 	}
 
@@ -1568,8 +1433,6 @@ nm_connection_normalize (NMConnection *connection,
 	was_modified |= _normalize_team_port_config (connection, parameters);
 	was_modified |= _normalize_bluetooth_type (connection, parameters);
 	was_modified |= _normalize_ovs_interface_type (connection, parameters);
-	was_modified |= _normalize_ip_tunnel_wired_setting (connection, parameters);
-	was_modified |= _normalize_sriov_vf_order (connection, parameters);
 
 	/* Verify anew. */
 	success = _nm_connection_verify (connection, error);
@@ -1995,10 +1858,9 @@ nm_connection_for_each_setting_value (NMConnection *connection,
  * nm_connection_dump:
  * @connection: the #NMConnection
  *
- * Print the connection (including secrets!) to stdout. For debugging
- * purposes ONLY, should NOT be used for serialization of the setting,
- * or machine-parsed in any way. The output format is not guaranteed to
- * be stable and may change at any time.
+ * Print the connection to stdout.  For debugging purposes ONLY, should NOT
+ * be used for serialization of the connection or machine-parsed in any way. The
+ * output format is not guaranteed to be stable and may change at any time.
  **/
 void
 nm_connection_dump (NMConnection *connection)
@@ -2081,32 +1943,6 @@ nm_connection_get_interface_name (NMConnection *connection)
 	return s_con ? nm_setting_connection_get_interface_name (s_con) : NULL;
 }
 
-NMConnectionMultiConnect
-_nm_connection_get_multi_connect (NMConnection *connection)
-{
-	NMSettingConnection *s_con;
-	NMConnectionMultiConnect multi_connect;
-	const NMConnectionMultiConnect DEFAULT = NM_CONNECTION_MULTI_CONNECT_SINGLE;
-
-	/* connection.multi_connect property cannot be specified via regular
-	 * connection defaults in NetworkManager.conf, because those are per-device,
-	 * and we need to determine the multi_connect independent of a particular
-	 * device.
-	 *
-	 * There is however still a default-value, so theoretically, the default
-	 * value could be specified in NetworkManager.conf. Just not as [connection*]
-	 * and indepdented of a device. */
-
-	s_con = nm_connection_get_setting_connection (connection);
-	if (!s_con)
-		return DEFAULT;
-
-	multi_connect = nm_setting_connection_get_multi_connect (s_con);
-	return multi_connect == NM_CONNECTION_MULTI_CONNECT_DEFAULT
-	       ? DEFAULT
-	       : multi_connect;
-}
-
 gboolean
 _nm_connection_verify_required_interface_name (NMConnection *connection,
                                                GError **error)
@@ -2197,8 +2033,7 @@ nm_connection_is_virtual (NMConnection *connection)
 	if (!type)
 		return FALSE;
 
-	if (   !strcmp (type, NM_SETTING_6LOWPAN_SETTING_NAME)
-	    || !strcmp (type, NM_SETTING_BOND_SETTING_NAME)
+	if (   !strcmp (type, NM_SETTING_BOND_SETTING_NAME)
 	    || !strcmp (type, NM_SETTING_DUMMY_SETTING_NAME)
 	    || !strcmp (type, NM_SETTING_TEAM_SETTING_NAME)
 	    || !strcmp (type, NM_SETTING_BRIDGE_SETTING_NAME)
diff --git a/libnm-core/nm-connection.h b/libnm-core/nm-connection.h
index 802f68ba..6d23cfdb 100644
--- a/libnm-core/nm-connection.h
+++ b/libnm-core/nm-connection.h
@@ -16,7 +16,7 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * Copyright 2007 - 2018 Red Hat, Inc.
+ * Copyright 2007 - 2017 Red Hat, Inc.
  * Copyright 2007 - 2008 Novell, Inc.
  */
 
@@ -231,7 +231,6 @@ NMSettingProxy *           nm_connection_get_setting_proxy             (NMConnec
 NMSettingSerial *          nm_connection_get_setting_serial            (NMConnection *connection);
 NM_AVAILABLE_IN_1_12
 NMSettingTCConfig *        nm_connection_get_setting_tc_config         (NMConnection *connection);
-NM_AVAILABLE_IN_1_2
 NMSettingTun *             nm_connection_get_setting_tun               (NMConnection *connection);
 NMSettingVpn *             nm_connection_get_setting_vpn               (NMConnection *connection);
 NMSettingWimax *           nm_connection_get_setting_wimax             (NMConnection *connection);
diff --git a/libnm-core/nm-core-enum-types.c.template b/libnm-core/nm-core-enum-types.c.template
index 605fa34a..9c08f526 100644
--- a/libnm-core/nm-core-enum-types.c.template
+++ b/libnm-core/nm-core-enum-types.c.template
@@ -48,7 +48,6 @@
 #include "nm-setting-wired.h"
 #include "nm-setting-wireless-security.h"
 #include "nm-setting-wireless.h"
-#include "nm-setting-wpan.h"
 #include "nm-setting.h"
 #include "nm-simple-connection.h"
 #include "nm-utils.h"
diff --git a/libnm-core/nm-core-internal.h b/libnm-core/nm-core-internal.h
index f0d4e40f..2a2045e6 100644
--- a/libnm-core/nm-core-internal.h
+++ b/libnm-core/nm-core-internal.h
@@ -15,7 +15,7 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2014 - 2018 Red Hat, Inc.
+ * (C) Copyright 2014 - 2017 Red Hat, Inc.
  */
 
 #ifndef NM_CORE_NM_INTERNAL_H
@@ -37,7 +37,6 @@
 
 #include "nm-connection.h"
 #include "nm-core-enum-types.h"
-#include "nm-setting-6lowpan.h"
 #include "nm-setting-8021x.h"
 #include "nm-setting-adsl.h"
 #include "nm-setting-bluetooth.h"
@@ -57,7 +56,6 @@
 #include "nm-setting-ip6-config.h"
 #include "nm-setting-macsec.h"
 #include "nm-setting-macvlan.h"
-#include "nm-setting-match.h"
 #include "nm-setting-olpc-mesh.h"
 #include "nm-setting-ovs-bridge.h"
 #include "nm-setting-ovs-interface.h"
@@ -66,7 +64,6 @@
 #include "nm-setting-ppp.h"
 #include "nm-setting-pppoe.h"
 #include "nm-setting-serial.h"
-#include "nm-setting-sriov.h"
 #include "nm-setting-tc-config.h"
 #include "nm-setting-team-port.h"
 #include "nm-setting-team.h"
@@ -78,14 +75,12 @@
 #include "nm-setting-wired.h"
 #include "nm-setting-wireless-security.h"
 #include "nm-setting-wireless.h"
-#include "nm-setting-wpan.h"
 #include "nm-setting.h"
 #include "nm-simple-connection.h"
 #include "nm-utils.h"
 #include "nm-vpn-dbus-interface.h"
 #include "nm-core-types-internal.h"
 #include "nm-vpn-editor-plugin.h"
-#include "nm-meta-setting.h"
 
 /* IEEE 802.1D-1998 timer values */
 #define NM_BR_MIN_HELLO_TIME    1
@@ -142,10 +137,6 @@ gboolean _nm_connection_replace_settings (NMConnection *connection,
                                           NMSettingParseFlags parse_flags,
                                           GError **error);
 
-gpointer _nm_connection_check_main_setting (NMConnection *connection,
-                                            const char *setting_name,
-                                            GError **error);
-
 /**
  * NMSettingVerifyResult:
  * @NM_SETTING_VERIFY_SUCCESS: the setting verifies successfully
@@ -170,43 +161,49 @@ NMConnection *_nm_simple_connection_new_from_dbus (GVariant      *dict,
                                                    NMSettingParseFlags parse_flags,
                                                    GError       **error);
 
+/*
+ * A setting's priority should roughly follow the OSI layer model, but it also
+ * controls which settings get asked for secrets first.  Thus settings which
+ * relate to things that must be working first, like hardware, should get a
+ * higher priority than things which layer on top of the hardware.  For example,
+ * the GSM/CDMA settings should provide secrets before the PPP setting does,
+ * because a PIN is required to unlock the device before PPP can even start.
+ * Even settings without secrets should be assigned the right priority.
+ *
+ * 0: reserved for invalid
+ *
+ * 1: reserved for the Connection setting
+ *
+ * 2,3: hardware-related settings like Ethernet, Wi-Fi, InfiniBand, Bridge, etc.
+ * These priority 1 settings are also "base types", which means that at least
+ * one of them is required for the connection to be valid, and their name is
+ * valid in the 'type' property of the Connection setting.
+ *
+ * 4: hardware-related auxiliary settings that require a base setting to be
+ * successful first, like Wi-Fi security, 802.1x, etc.
+ *
+ * 5: hardware-independent settings that are required before IP connectivity
+ * can be established, like PPP, PPPoE, etc.
+ *
+ * 6: IP-level stuff
+ *
+ * 10: NMSettingUser
+ */
+typedef enum { /*< skip >*/
+	NM_SETTING_PRIORITY_INVALID     = 0,
+	NM_SETTING_PRIORITY_CONNECTION  = 1,
+	NM_SETTING_PRIORITY_HW_BASE     = 2,
+	NM_SETTING_PRIORITY_HW_NON_BASE = 3,
+	NM_SETTING_PRIORITY_HW_AUX      = 4,
+	NM_SETTING_PRIORITY_AUX         = 5,
+	NM_SETTING_PRIORITY_IP          = 6,
+	NM_SETTING_PRIORITY_USER        = 10,
+} NMSettingPriority;
+
 NMSettingPriority _nm_setting_get_setting_priority (NMSetting *setting);
 
 gboolean _nm_setting_get_property (NMSetting *setting, const char *name, GValue *value);
 
-/*****************************************************************************/
-
-GHashTable *_nm_setting_gendata_hash (NMSetting *setting,
-                                      gboolean create_if_necessary);
-
-void _nm_setting_gendata_notify (NMSetting *setting,
-                                 gboolean keys_changed);
-
-guint _nm_setting_gendata_get_all (NMSetting *setting,
-                                   const char *const**out_names,
-                                   GVariant *const**out_values);
-
-gboolean _nm_setting_gendata_reset_from_hash (NMSetting *setting,
-                                              GHashTable *new);
-
-void _nm_setting_gendata_to_gvalue (NMSetting *setting,
-                                    GValue *value);
-
-GVariant *nm_setting_gendata_get (NMSetting *setting,
-                                  const char *name);
-
-const char *const*nm_setting_gendata_get_all_names (NMSetting *setting,
-                                                    guint *out_len);
-
-GVariant *const*nm_setting_gendata_get_all_values (NMSetting *setting);
-
-/*****************************************************************************/
-
-guint nm_setting_ethtool_init_features (NMSettingEthtool *setting,
-                                        NMTernary *requested /* indexed by NMEthtoolID - _NM_ETHTOOL_ID_FEATURE_FIRST */);
-
-/*****************************************************************************/
-
 #define NM_UTILS_HWADDR_LEN_MAX_STR (NM_UTILS_HWADDR_LEN_MAX * 3)
 
 guint8 *_nm_utils_hwaddr_aton (const char *asc, gpointer buffer, gsize buffer_length, gsize *out_length);
@@ -215,13 +212,6 @@ const char *nm_utils_hwaddr_ntoa_buf (gconstpointer addr, gsize addr_len, gboole
 char *_nm_utils_bin2str (gconstpointer addr, gsize length, gboolean upper_case);
 void _nm_utils_bin2str_full (gconstpointer addr, gsize length, const char delimiter, gboolean upper_case, char *out);
 
-guint8 *_nm_utils_str2bin_full (const char *asc,
-                                gboolean delimiter_required,
-                                const char *delimiter_candidates,
-                                guint8 *buffer,
-                                gsize buffer_length,
-                                gsize *out_len);
-
 GSList *    _nm_utils_hash_values_to_slist (GHashTable *hash);
 
 GHashTable *_nm_utils_copy_strdict (GHashTable *strdict);
@@ -234,9 +224,6 @@ gboolean _nm_ip_route_attribute_validate_all (const NMIPRoute *route);
 const char **_nm_ip_route_get_attribute_names (const NMIPRoute *route, gboolean sorted, guint *out_length);
 GHashTable *_nm_ip_route_get_attributes_direct (NMIPRoute *route);
 
-NMSriovVF *_nm_utils_sriov_vf_from_strparts (const char *index, const char *detail, GError **error);
-gboolean _nm_sriov_vf_attribute_validate_all (const NMSriovVF *vf, GError **error);
-
 static inline void
 _nm_auto_ip_route_unref (NMIPRoute **v)
 {
@@ -245,6 +232,12 @@ _nm_auto_ip_route_unref (NMIPRoute **v)
 }
 #define nm_auto_ip_route_unref nm_auto (_nm_auto_ip_route_unref)
 
+GPtrArray *_nm_utils_copy_slist_to_array (const GSList *list,
+                                          NMUtilsCopyFunc copy_func,
+                                          GDestroyNotify unref_func);
+GSList    *_nm_utils_copy_array_to_slist (const GPtrArray *array,
+                                          NMUtilsCopyFunc copy_func);
+
 GPtrArray *_nm_utils_copy_array (const GPtrArray *array,
                                  NMUtilsCopyFunc copy_func,
                                  GDestroyNotify free_func);
@@ -252,6 +245,15 @@ GPtrArray *_nm_utils_copy_object_array (const GPtrArray *array);
 
 gssize _nm_utils_ptrarray_find_first (gconstpointer *list, gssize len, gconstpointer needle);
 
+gssize _nm_utils_ptrarray_find_binary_search (gconstpointer *list,
+                                              gsize len,
+                                              gconstpointer needle,
+                                              GCompareDataFunc cmpfcn,
+                                              gpointer user_data,
+                                              gssize *out_idx_first,
+                                              gssize *out_idx_last);
+gssize _nm_utils_array_find_binary_search (gconstpointer list, gsize elem_size, gsize len, gconstpointer needle, GCompareDataFunc cmpfcn, gpointer user_data);
+
 GSList *    _nm_utils_strv_to_slist (char **strv, gboolean deep_copy);
 char **     _nm_utils_slist_to_strv (GSList *slist, gboolean deep_copy);
 
@@ -294,6 +296,12 @@ void _nm_dbus_errors_init (void);
 
 extern gboolean _nm_utils_is_manager_process;
 
+GByteArray *nm_utils_rsa_key_encrypt (const guint8 *data,
+                                      gsize len,
+                                      const char *in_password,
+                                      char **out_password,
+                                      GError **error);
+
 gulong _nm_dbus_signal_connect_data (GDBusProxy *proxy,
                                      const char *signal_name,
                                      const GVariantType *signature,
@@ -310,11 +318,11 @@ GVariant *_nm_dbus_proxy_call_finish (GDBusProxy           *proxy,
                                       GError              **error);
 
 GVariant *_nm_dbus_proxy_call_sync   (GDBusProxy           *proxy,
-                                      const char           *method_name,
+                                      const gchar          *method_name,
                                       GVariant             *parameters,
                                       const GVariantType   *reply_type,
                                       GDBusCallFlags        flags,
-                                      int                   timeout_msec,
+                                      gint                  timeout_msec,
                                       GCancellable         *cancellable,
                                       GError              **error);
 
@@ -323,13 +331,6 @@ gboolean _nm_dbus_error_has_name (GError     *error,
 
 /*****************************************************************************/
 
-char *_nm_utils_ssid_to_string_arr (const guint8 *ssid, gsize len);
-char *_nm_utils_ssid_to_string (GBytes *ssid);
-char *_nm_utils_ssid_to_utf8 (GBytes *ssid);
-gboolean _nm_utils_is_empty_ssid (GBytes *ssid);
-
-/*****************************************************************************/
-
 gboolean _nm_vpn_plugin_info_check_file (const char *filename,
                                          gboolean check_absolute,
                                          gboolean do_validate_filename,
@@ -426,8 +427,6 @@ _nm_connection_get_uuid (NMConnection *connection)
 	return connection ? nm_connection_get_uuid (connection) : NULL;
 }
 
-NMConnectionMultiConnect _nm_connection_get_multi_connect (NMConnection *connection);
-
 /*****************************************************************************/
 
 typedef enum {
@@ -512,89 +511,4 @@ _nm_connection_type_is_master (const char *type)
 gboolean _nm_utils_dhcp_duid_valid (const char *duid, GBytes **out_duid_bin);
 
 /*****************************************************************************/
-
-gboolean _nm_setting_sriov_sort_vfs (NMSettingSriov *setting);
-
-/*****************************************************************************/
-
-typedef struct _NMSettInfoSetting NMSettInfoSetting;
-
-typedef GVariant *(*NMSettingPropertyGetFunc)           (NMSetting     *setting,
-                                                         const char    *property);
-typedef GVariant *(*NMSettingPropertySynthFunc)         (NMSetting     *setting,
-                                                         NMConnection  *connection,
-                                                         const char    *property);
-typedef gboolean  (*NMSettingPropertySetFunc)           (NMSetting     *setting,
-                                                         GVariant      *connection_dict,
-                                                         const char    *property,
-                                                         GVariant      *value,
-                                                         NMSettingParseFlags parse_flags,
-                                                         GError       **error);
-typedef gboolean  (*NMSettingPropertyNotSetFunc)        (NMSetting     *setting,
-                                                         GVariant      *connection_dict,
-                                                         const char    *property,
-                                                         NMSettingParseFlags parse_flags,
-                                                         GError       **error);
-typedef GVariant *(*NMSettingPropertyTransformToFunc)   (const GValue *from);
-typedef void      (*NMSettingPropertyTransformFromFunc) (GVariant *from,
-                                                          GValue *to);
-
-typedef struct {
-	const char *name;
-	GParamSpec *param_spec;
-	const GVariantType *dbus_type;
-
-	NMSettingPropertyGetFunc           get_func;
-	NMSettingPropertySynthFunc         synth_func;
-	NMSettingPropertySetFunc           set_func;
-	NMSettingPropertyNotSetFunc        not_set_func;
-
-	NMSettingPropertyTransformToFunc   to_dbus;
-	NMSettingPropertyTransformFromFunc from_dbus;
-} NMSettInfoProperty;
-
-typedef struct {
-	const GVariantType *(*get_variant_type) (const struct _NMSettInfoSetting *sett_info,
-	                                         const char *name,
-	                                         GError **error);
-} NMSettInfoSettGendata;
-
-typedef struct {
-	/* if set, then this setting class has no own fields. Instead, its
-	 * data is entirely based on gendata. Meaning: it tracks all data
-	 * as native GVariants.
-	 * It might have some GObject properties, but these are merely accessors
-	 * to the underlying gendata.
-	 *
-	 * Note, that at the moment there are few hooks, to customize the behavior
-	 * of the setting further. They are currently unneeded. This is desired,
-	 * but could be added when there is a good reason.
-	 *
-	 * However, a few hooks there are... see NMSettInfoSettGendata. */
-	const NMSettInfoSettGendata *gendata_info;
-} NMSettInfoSettDetail;
-
-struct _NMSettInfoSetting {
-	NMSettingClass *setting_class;
-	const NMSettInfoProperty *property_infos;
-	guint property_infos_len;
-	NMSettInfoSettDetail detail;
-};
-
-const NMSettInfoSetting *_nm_sett_info_setting_get (NMSettingClass *setting_class);
-
-const NMSettInfoProperty *_nm_sett_info_property_get (NMSettingClass *setting_class,
-                                                      const char *property_name);
-
-/*****************************************************************************/
-
-NMSetting8021xCKScheme _nm_setting_802_1x_cert_get_scheme (GBytes *bytes, GError **error);
-
-GBytes *_nm_setting_802_1x_cert_value_to_bytes (NMSetting8021xCKScheme scheme,
-                                                const guint8 *val_bin,
-                                                gssize val_len,
-                                                GError **error);
-
-/*****************************************************************************/
-
 #endif
diff --git a/libnm-core/nm-core-types.h b/libnm-core/nm-core-types.h
index 89d99579..6a274333 100644
--- a/libnm-core/nm-core-types.h
+++ b/libnm-core/nm-core-types.h
@@ -15,7 +15,7 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
- * Copyright 2014 - 2018 Red Hat, Inc.
+ * Copyright 2014 - 2017 Red Hat, Inc.
  */
 
 #ifndef __NM_CORE_TYPES_H__
@@ -29,7 +29,6 @@
 
 typedef struct _NMConnection              NMConnection;
 typedef struct _NMSetting                 NMSetting;
-typedef struct _NMSetting6Lowpan          NMSetting6Lowpan;
 typedef struct _NMSetting8021x            NMSetting8021x;
 typedef struct _NMSettingAdsl             NMSettingAdsl;
 typedef struct _NMSettingBluetooth        NMSettingBluetooth;
@@ -40,7 +39,6 @@ typedef struct _NMSettingCdma             NMSettingCdma;
 typedef struct _NMSettingConnection       NMSettingConnection;
 typedef struct _NMSettingDcb              NMSettingDcb;
 typedef struct _NMSettingDummy            NMSettingDummy;
-typedef struct _NMSettingEthtool          NMSettingEthtool;
 typedef struct _NMSettingGeneric          NMSettingGeneric;
 typedef struct _NMSettingGsm              NMSettingGsm;
 typedef struct _NMSettingInfiniband       NMSettingInfiniband;
@@ -51,7 +49,6 @@ typedef struct _NMSettingIP4Config        NMSettingIP4Config;
 typedef struct _NMSettingIP6Config        NMSettingIP6Config;
 typedef struct _NMSettingMacsec           NMSettingMacsec;
 typedef struct _NMSettingMacvlan          NMSettingMacvlan;
-typedef struct _NMSettingMatch            NMSettingMatch;
 typedef struct _NMSettingOlpcMesh         NMSettingOlpcMesh;
 typedef struct _NMSettingOvsBridge        NMSettingOvsBridge;
 typedef struct _NMSettingOvsInterface     NMSettingOvsInterface;
@@ -60,7 +57,6 @@ typedef struct _NMSettingOvsPort          NMSettingOvsPort;
 typedef struct _NMSettingPpp              NMSettingPpp;
 typedef struct _NMSettingPppoe            NMSettingPppoe;
 typedef struct _NMSettingSerial           NMSettingSerial;
-typedef struct _NMSettingSriov            NMSettingSriov;
 typedef struct _NMSettingTCConfig         NMSettingTCConfig;
 typedef struct _NMSettingTeam             NMSettingTeam;
 typedef struct _NMSettingTeamPort         NMSettingTeamPort;
@@ -73,7 +69,6 @@ typedef struct _NMSettingWimax            NMSettingWimax;
 typedef struct _NMSettingWired            NMSettingWired;
 typedef struct _NMSettingWireless         NMSettingWireless;
 typedef struct _NMSettingWirelessSecurity NMSettingWirelessSecurity;
-typedef struct _NMSettingWpan             NMSettingWpan;
 typedef struct _NMSimpleConnection        NMSimpleConnection;
 
 #endif  /* __NM_CORE_TYPES_H__ */
diff --git a/libnm-core/nm-crypto-impl.h b/libnm-core/nm-crypto-impl.h
deleted file mode 100644
index 91865152..00000000
--- a/libnm-core/nm-crypto-impl.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-
-/*
- * Dan Williams <dcbw@redhat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA.
- *
- * Copyright 2007 - 2018 Red Hat, Inc.
- */
-
-#ifndef __NM_CRYPTO_IMPL_H__
-#define __NM_CRYPTO_IMPL_H__
-
-#if !((NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_PRIVATE)
-#error Cannot use this header.
-#endif
-
-#include "nm-crypto.h"
-
-gboolean _nm_crypto_init (GError **error);
-
-gboolean _nm_crypto_randomize (void *buffer, gsize buffer_len, GError **error);
-
-gboolean _nm_crypto_verify_x509 (const guint8 *data,
-                                 gsize len,
-                                 GError **error);
-
-gboolean _nm_crypto_verify_pkcs12 (const guint8 *data,
-                                   gsize data_len,
-                                   const char *password,
-                                   GError **error);
-
-gboolean _nm_crypto_verify_pkcs8 (const guint8 *data,
-                                  gsize data_len,
-                                  gboolean is_encrypted,
-                                  const char *password,
-                                  GError **error);
-
-/*****************************************************************************/
-
-guint8 *_nmtst_crypto_encrypt (NMCryptoCipherType cipher,
-                               const guint8 *data,
-                               gsize data_len,
-                               const guint8 *iv,
-                               gsize iv_len,
-                               const guint8 *key,
-                               gsize key_len,
-                               gsize *out_len,
-                               GError **error);
-
-guint8 *_nmtst_crypto_decrypt (NMCryptoCipherType cipher,
-                               const guint8 *data,
-                               gsize data_len,
-                               const guint8 *iv,
-                               gsize iv_len,
-                               const guint8 *key,
-                               gsize key_len,
-                               gsize *out_len,
-                               GError **error);
-
-#endif  /* __NM_CRYPTO_IMPL_H__ */
diff --git a/libnm-core/nm-crypto.c b/libnm-core/nm-crypto.c
deleted file mode 100644
index 7a6e8d18..00000000
--- a/libnm-core/nm-crypto.c
+++ /dev/null
@@ -1,1035 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-
-/*
- * Dan Williams <dcbw@redhat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA.
- *
- * Copyright 2007 - 2018 Red Hat, Inc.
- */
-
-#include "nm-default.h"
-
-#include "nm-crypto.h"
-
-#include <string.h>
-#include <strings.h>
-#include <unistd.h>
-#include <stdlib.h>
-
-#include "nm-utils/nm-secret-utils.h"
-#include "nm-utils/nm-io-utils.h"
-
-#include "nm-crypto-impl.h"
-#include "nm-utils.h"
-#include "nm-errors.h"
-
-#define PEM_RSA_KEY_BEGIN "-----BEGIN RSA PRIVATE KEY-----"
-#define PEM_RSA_KEY_END   "-----END RSA PRIVATE KEY-----"
-
-#define PEM_DSA_KEY_BEGIN "-----BEGIN DSA PRIVATE KEY-----"
-#define PEM_DSA_KEY_END   "-----END DSA PRIVATE KEY-----"
-
-#define PEM_CERT_BEGIN    "-----BEGIN CERTIFICATE-----"
-#define PEM_CERT_END      "-----END CERTIFICATE-----"
-
-#define PEM_PKCS8_ENC_KEY_BEGIN "-----BEGIN ENCRYPTED PRIVATE KEY-----"
-#define PEM_PKCS8_ENC_KEY_END   "-----END ENCRYPTED PRIVATE KEY-----"
-
-#define PEM_PKCS8_DEC_KEY_BEGIN "-----BEGIN PRIVATE KEY-----"
-#define PEM_PKCS8_DEC_KEY_END   "-----END PRIVATE KEY-----"
-
-/*****************************************************************************/
-
-static const NMCryptoCipherInfo cipher_infos[] = {
-#define _CI(_cipher, _name, _digest_len, _real_iv_len) \
-	[(_cipher) - 1] = { .cipher = _cipher, .name = ""_name"", .digest_len = _digest_len, .real_iv_len = _real_iv_len }
-	_CI (NM_CRYPTO_CIPHER_DES_EDE3_CBC, "DES-EDE3-CBC", 24,  8),
-	_CI (NM_CRYPTO_CIPHER_DES_CBC,      "DES-CBC",       8,  8),
-	_CI (NM_CRYPTO_CIPHER_AES_128_CBC,  "AES-128-CBC",  16, 16),
-	_CI (NM_CRYPTO_CIPHER_AES_192_CBC,  "AES-192-CBC",  24, 16),
-	_CI (NM_CRYPTO_CIPHER_AES_256_CBC,  "AES-256-CBC",  32, 16),
-};
-
-const NMCryptoCipherInfo *
-nm_crypto_cipher_get_info (NMCryptoCipherType cipher)
-{
-	g_return_val_if_fail (cipher > NM_CRYPTO_CIPHER_UNKNOWN && (gsize) cipher < G_N_ELEMENTS (cipher_infos) + 1, NULL);
-
-#if NM_MORE_ASSERTS > 10
-	{
-		int i, j;
-
-		for (i = 0; i < (int) G_N_ELEMENTS (cipher_infos); i++) {
-			const NMCryptoCipherInfo *info = &cipher_infos[i];
-
-			nm_assert (info->cipher == (NMCryptoCipherType) (i + 1));
-			nm_assert (info->name && info->name[0]);
-			for (j = 0; j < i; j++)
-				nm_assert (g_ascii_strcasecmp (info->name, cipher_infos[j].name) != 0);
-		}
-	}
-#endif
-
-	return &cipher_infos[cipher - 1];
-}
-
-const NMCryptoCipherInfo *
-nm_crypto_cipher_get_info_by_name (const char *cipher_name, gssize p_len)
-{
-	int i;
-
-	nm_assert (nm_crypto_cipher_get_info (NM_CRYPTO_CIPHER_DES_CBC)->cipher == NM_CRYPTO_CIPHER_DES_CBC);
-
-	if (p_len < 0) {
-		if (!cipher_name)
-			return FALSE;
-		p_len = strlen (cipher_name);
-	}
-
-	for (i = 0; i < (int) G_N_ELEMENTS (cipher_infos); i++) {
-		const NMCryptoCipherInfo *info = &cipher_infos[i];
-
-		if (   (gsize) p_len == strlen (info->name)
-		    && g_ascii_strncasecmp (info->name, cipher_name, p_len) == 0)
-			return info;
-	}
-	return NULL;
-}
-
-/*****************************************************************************/
-
-static gboolean
-find_tag (const char *tag,
-          const guint8 *data,
-          gsize data_len,
-          gsize start_at,
-          gsize *out_pos)
-{
-	gsize i, taglen;
-	gsize len = data_len - start_at;
-
-	g_return_val_if_fail (out_pos != NULL, FALSE);
-
-	taglen = strlen (tag);
-	if (len >= taglen) {
-		for (i = 0; i < len - taglen + 1; i++) {
-			if (memcmp (data + start_at + i, tag, taglen) == 0) {
-				*out_pos = start_at + i;
-				return TRUE;
-			}
-		}
-	}
-	return FALSE;
-}
-
-#define DEK_INFO_TAG "DEK-Info: "
-#define PROC_TYPE_TAG "Proc-Type: "
-
-static char *
-_extract_line (const guint8 **p, const guint8 *p_end)
-{
-	const guint8 *x, *x0;
-
-	nm_assert (p);
-	nm_assert (p_end);
-	nm_assert (*p);
-	nm_assert (*p < p_end);
-
-	x = x0 = *p;
-	while (TRUE) {
-		if (x == p_end) {
-			*p = p_end;
-			break;
-		}
-		if (*x == '\0') {
-			/* the data contains embedded NUL. This is the end. */
-			*p = p_end;
-			break;
-		}
-		if (*x == '\n') {
-			*p = x + 1;
-			break;
-		}
-		x++;
-	}
-
-	if (x == x0)
-		return NULL;
-	return g_strndup ((char *) x0, x - x0);
-}
-
-static gboolean
-parse_old_openssl_key_file (const guint8 *data,
-                            gsize data_len,
-                            NMSecretPtr *out_parsed,
-                            NMCryptoKeyType *out_key_type,
-                            NMCryptoCipherType *out_cipher,
-                            char **out_iv,
-                            GError **error)
-{
-	gsize start = 0, end = 0;
-	nm_auto_free_secret char *str = NULL;
-	char *str_p;
-	gsize str_len;
-	int enc_tags = 0;
-	NMCryptoKeyType key_type;
-	nm_auto_clear_secret_ptr NMSecretPtr parsed = { 0 };
-	nm_auto_clear_secret_ptr NMSecretPtr data_content = { 0 };
-	nm_auto_free_secret char *iv = NULL;
-	NMCryptoCipherType cipher = NM_CRYPTO_CIPHER_UNKNOWN;
-	const char *start_tag;
-	const char *end_tag;
-	const guint8 *data_start, *data_end;
-
-	nm_assert (!out_parsed || (out_parsed->len == 0 && !out_parsed->bin));
-	nm_assert (!out_iv || !*out_iv);
-
-	NM_SET_OUT (out_key_type, NM_CRYPTO_KEY_TYPE_UNKNOWN);
-	NM_SET_OUT (out_cipher, NM_CRYPTO_CIPHER_UNKNOWN);
-
-	if (find_tag (PEM_RSA_KEY_BEGIN, data, data_len, 0, &start)) {
-		key_type = NM_CRYPTO_KEY_TYPE_RSA;
-		start_tag = PEM_RSA_KEY_BEGIN;
-		end_tag = PEM_RSA_KEY_END;
-	} else if (find_tag (PEM_DSA_KEY_BEGIN, data, data_len, 0, &start)) {
-		key_type = NM_CRYPTO_KEY_TYPE_DSA;
-		start_tag = PEM_DSA_KEY_BEGIN;
-		end_tag = PEM_DSA_KEY_END;
-	} else {
-		g_set_error (error, NM_CRYPTO_ERROR,
-		             NM_CRYPTO_ERROR_INVALID_DATA,
-		             _("PEM key file had no start tag"));
-		return FALSE;
-	}
-
-	start += strlen (start_tag);
-	if (!find_tag (end_tag, data, data_len, start, &end)) {
-		g_set_error (error, NM_CRYPTO_ERROR,
-		             NM_CRYPTO_ERROR_INVALID_DATA,
-		             _("PEM key file had no end tag '%s'."),
-		             end_tag);
-		return FALSE;
-	}
-
-	str_len = end - start + 1;
-	str = g_new (char, str_len);
-	str[0] = '\0';
-	str_p = str;
-
-	data_start = &data[start];
-	data_end = &data[end];
-
-	while (data_start < data_end) {
-		nm_auto_free_secret char *line = NULL;
-		char *p;
-
-		line = _extract_line (&data_start, data_end);
-		if (!line)
-			continue;
-
-		p = nm_secret_strchomp (nm_str_skip_leading_spaces (line));
-
-		if (!strncmp (p, PROC_TYPE_TAG, strlen (PROC_TYPE_TAG))) {
-			if (enc_tags++ != 0 || str_p != str) {
-				g_set_error (error, NM_CRYPTO_ERROR,
-				             NM_CRYPTO_ERROR_INVALID_DATA,
-				             _("Malformed PEM file: Proc-Type was not first tag."));
-				return FALSE;
-			}
-
-			p += strlen (PROC_TYPE_TAG);
-			if (strcmp (p, "4,ENCRYPTED")) {
-				g_set_error (error, NM_CRYPTO_ERROR,
-				             NM_CRYPTO_ERROR_INVALID_DATA,
-				             _("Malformed PEM file: unknown Proc-Type tag '%s'."),
-				             p);
-				return FALSE;
-			}
-		} else if (!strncmp (p, DEK_INFO_TAG, strlen (DEK_INFO_TAG))) {
-			const NMCryptoCipherInfo *cipher_info;
-			char *comma;
-			gsize p_len;
-
-			if (enc_tags++ != 1 || str_p != str) {
-				g_set_error (error, NM_CRYPTO_ERROR,
-				             NM_CRYPTO_ERROR_INVALID_DATA,
-				             _("Malformed PEM file: DEK-Info was not the second tag."));
-				return FALSE;
-			}
-
-			p += strlen (DEK_INFO_TAG);
-
-			/* Grab the IV first */
-			comma = strchr (p, ',');
-			if (!comma || (*(comma + 1) == '\0')) {
-				g_set_error (error, NM_CRYPTO_ERROR,
-				             NM_CRYPTO_ERROR_INVALID_DATA,
-				             _("Malformed PEM file: no IV found in DEK-Info tag."));
-				return FALSE;
-			}
-			p_len = comma - p;
-			comma++;
-			if (!g_ascii_isxdigit (*comma)) {
-				g_set_error (error, NM_CRYPTO_ERROR,
-				             NM_CRYPTO_ERROR_INVALID_DATA,
-				             _("Malformed PEM file: invalid format of IV in DEK-Info tag."));
-				return FALSE;
-			}
-			nm_free_secret (iv);
-			iv = g_strdup (comma);
-
-			/* Get the private key cipher */
-			cipher_info = nm_crypto_cipher_get_info_by_name (p, p_len);
-			if (!cipher_info) {
-				g_set_error (error, NM_CRYPTO_ERROR,
-				             NM_CRYPTO_ERROR_INVALID_DATA,
-				             _("Malformed PEM file: unknown private key cipher '%s'."),
-				             p);
-				return FALSE;
-			}
-			cipher = cipher_info->cipher;
-		} else {
-			if (enc_tags == 1) {
-				g_set_error (error, NM_CRYPTO_ERROR,
-				             NM_CRYPTO_ERROR_INVALID_DATA,
-				             "Malformed PEM file: both Proc-Type and DEK-Info tags are required.");
-				return FALSE;
-			}
-			nm_utils_strbuf_append_str (&str_p, &str_len, p);
-			nm_assert (str_len > 0);
-		}
-	}
-
-	parsed.bin = (guint8 *) g_base64_decode (str, &parsed.len);
-	if (!parsed.bin || parsed.len == 0) {
-		g_set_error (error, NM_CRYPTO_ERROR,
-		             NM_CRYPTO_ERROR_INVALID_DATA,
-		             _("Could not decode private key."));
-		nm_secret_ptr_clear (&parsed);
-		return FALSE;
-	}
-
-	NM_SET_OUT (out_key_type, key_type);
-	NM_SET_OUT (out_iv, g_steal_pointer (&iv));
-	NM_SET_OUT (out_cipher, cipher);
-	nm_secret_ptr_move (out_parsed, &parsed);
-	return TRUE;
-}
-
-static gboolean
-parse_pkcs8_key_file (const guint8 *data,
-                      gsize data_len,
-                      NMSecretPtr *parsed,
-                      gboolean *out_encrypted,
-                      GError **error)
-{
-	gsize start = 0, end = 0;
-	gs_free guchar *der = NULL;
-	const char *start_tag = NULL, *end_tag = NULL;
-	gboolean encrypted = FALSE;
-	nm_auto_free_secret char *der_base64 = NULL;
-
-	nm_assert (parsed);
-	nm_assert (!parsed->bin);
-	nm_assert (parsed->len == 0);
-	nm_assert (out_encrypted);
-
-	/* Try encrypted first, decrypted next */
-	if (find_tag (PEM_PKCS8_ENC_KEY_BEGIN, data, data_len, 0, &start)) {
-		start_tag = PEM_PKCS8_ENC_KEY_BEGIN;
-		end_tag = PEM_PKCS8_ENC_KEY_END;
-		encrypted = TRUE;
-	} else if (find_tag (PEM_PKCS8_DEC_KEY_BEGIN, data, data_len, 0, &start)) {
-		start_tag = PEM_PKCS8_DEC_KEY_BEGIN;
-		end_tag = PEM_PKCS8_DEC_KEY_END;
-		encrypted = FALSE;
-	} else {
-		g_set_error_literal (error, NM_CRYPTO_ERROR,
-		                     NM_CRYPTO_ERROR_INVALID_DATA,
-		                     _("Failed to find expected PKCS#8 start tag."));
-		return FALSE;
-	}
-
-	start += strlen (start_tag);
-	if (!find_tag (end_tag, data, data_len, start, &end)) {
-		g_set_error (error, NM_CRYPTO_ERROR,
-		             NM_CRYPTO_ERROR_INVALID_DATA,
-		             _("Failed to find expected PKCS#8 end tag '%s'."),
-		             end_tag);
-		return FALSE;
-	}
-
-	/* g_base64_decode() wants a NULL-terminated string */
-	der_base64 = g_strndup ((char *) &data[start], end - start);
-
-	parsed->bin = (guint8 *) g_base64_decode (der_base64, &parsed->len);
-	if (!parsed->bin || parsed->len == 0) {
-		g_set_error_literal (error, NM_CRYPTO_ERROR,
-		                     NM_CRYPTO_ERROR_INVALID_DATA,
-		                     _("Failed to decode PKCS#8 private key."));
-		nm_secret_ptr_clear (parsed);
-		return FALSE;
-	}
-
-	*out_encrypted = encrypted;
-	return TRUE;
-}
-
-static gboolean
-file_read_contents (const char *filename,
-                    NMSecretPtr *out_contents,
-                    GError **error)
-{
-	nm_assert (out_contents);
-	nm_assert (out_contents->len == 0);
-	nm_assert (!out_contents->str);
-
-	return nm_utils_file_get_contents (-1,
-	                                   filename,
-	                                   100*1024*1024,
-	                                   NM_UTILS_FILE_GET_CONTENTS_FLAG_SECRET,
-	                                   &out_contents->str,
-	                                   &out_contents->len,
-	                                   error) >= 0;
-}
-
-GBytes *
-nm_crypto_read_file (const char *filename,
-                     GError **error)
-{
-	nm_auto_clear_secret_ptr NMSecretPtr contents = { 0 };
-
-	g_return_val_if_fail (filename, NULL);
-
-	if (!file_read_contents (filename, &contents, error))
-		return NULL;
-	return nm_secret_copy_to_gbytes (contents.bin, contents.len);
-}
-
-/*
- * Convert a hex string into bytes.
- */
-static guint8 *
-_nmtst_convert_iv (const char *src,
-                   gsize *out_len,
-                   GError **error)
-{
-	gsize i, num;
-	gs_free guint8 *c = NULL;
-	int c0, c1;
-
-	nm_assert (src);
-
-	num = strlen (src);
-	if (   num == 0
-	    || (num % 2) != 0) {
-		g_set_error (error, NM_CRYPTO_ERROR,
-		             NM_CRYPTO_ERROR_INVALID_DATA,
-		             _("IV must be an even number of bytes in length."));
-		return NULL;
-	}
-
-	num /= 2;
-	c = g_malloc (num + 1);
-
-	/* defensively add trailing NUL. This function returns binary data,
-	 * do not assume it's NUL terminated. */
-	c[num] = '\0';
-
-	for (i = 0; i < num; i++) {
-		if (   ((c0 = nm_utils_hexchar_to_int (*(src++))) < 0)
-		    || ((c1 = nm_utils_hexchar_to_int (*(src++))) < 0)) {
-			g_set_error (error, NM_CRYPTO_ERROR,
-			             NM_CRYPTO_ERROR_INVALID_DATA,
-			             _("IV contains non-hexadecimal digits."));
-			nm_explicit_bzero (c, i);
-			return FALSE;
-		}
-
-		c[i] = (c0 << 4) + c1;
-	}
-	*out_len = num;
-	return g_steal_pointer (&c);
-}
-
-guint8 *
-nmtst_crypto_make_des_aes_key (NMCryptoCipherType cipher,
-                               const guint8 *salt,
-                               gsize salt_len,
-                               const char *password,
-                               gsize *out_len,
-                               GError **error)
-{
-	guint8 *key;
-	const NMCryptoCipherInfo *cipher_info;
-
-	g_return_val_if_fail (salt != NULL, NULL);
-	g_return_val_if_fail (salt_len >= 8, NULL);
-	g_return_val_if_fail (password != NULL, NULL);
-	g_return_val_if_fail (out_len != NULL, NULL);
-
-	*out_len = 0;
-
-	cipher_info = nm_crypto_cipher_get_info (cipher);
-
-	g_return_val_if_fail (cipher_info, NULL);
-
-	if (password[0] == '\0')
-		return NULL;
-
-	key = g_malloc (cipher_info->digest_len);
-
-	nm_crypto_md5_hash (salt,
-	                    8,
-	                    (guint8 *) password,
-	                    strlen (password),
-	                    key,
-	                    cipher_info->digest_len);
-
-	*out_len = cipher_info->digest_len;
-	return key;
-}
-
-static gboolean
-_nmtst_decrypt_key (NMCryptoCipherType cipher,
-                    const guint8 *data,
-                    gsize data_len,
-                    const char *iv,
-                    const char *password,
-                    NMSecretPtr *parsed,
-                    GError **error)
-{
-	nm_auto_clear_secret_ptr NMSecretPtr bin_iv = { 0 };
-	nm_auto_clear_secret_ptr NMSecretPtr key = { 0 };
-	gs_free char *output = NULL;
-
-	nm_assert (password);
-	nm_assert (cipher != NM_CRYPTO_CIPHER_UNKNOWN);
-	nm_assert (iv);
-	nm_assert (parsed);
-	nm_assert (!parsed->bin);
-	nm_assert (parsed->len == 0);
-
-	bin_iv.bin = _nmtst_convert_iv (iv, &bin_iv.len, error);
-	if (!bin_iv.bin)
-		return FALSE;
-
-	if (bin_iv.len < 8) {
-		g_set_error (error,
-		             NM_CRYPTO_ERROR,
-		             NM_CRYPTO_ERROR_INVALID_DATA,
-		             _("IV must contain at least 8 characters"));
-		return FALSE;
-	}
-
-	/* Convert the password and IV into a DES or AES key */
-	key.bin = nmtst_crypto_make_des_aes_key (cipher, bin_iv.bin, bin_iv.len, password, &key.len, error);
-	if (!key.bin || !key.len)
-		return FALSE;
-
-	parsed->bin = _nmtst_crypto_decrypt (cipher,
-	                                     data,
-	                                     data_len,
-	                                     bin_iv.bin,
-	                                     bin_iv.len,
-	                                     key.bin,
-	                                     key.len,
-	                                     &parsed->len,
-	                                     error);
-	if (!parsed->bin || parsed->len == 0) {
-		nm_secret_ptr_clear (parsed);
-		return FALSE;
-	}
-
-	return TRUE;
-}
-
-GBytes *
-nmtst_crypto_decrypt_openssl_private_key_data (const guint8 *data,
-                                               gsize data_len,
-                                               const char *password,
-                                               NMCryptoKeyType *out_key_type,
-                                               GError **error)
-{
-	NMCryptoKeyType key_type = NM_CRYPTO_KEY_TYPE_UNKNOWN;
-	nm_auto_clear_secret_ptr NMSecretPtr parsed = { 0 };
-	nm_auto_free_secret char *iv = NULL;
-	NMCryptoCipherType cipher = NM_CRYPTO_CIPHER_UNKNOWN;
-
-	g_return_val_if_fail (data != NULL, NULL);
-
-	NM_SET_OUT (out_key_type, NM_CRYPTO_KEY_TYPE_UNKNOWN);
-
-	if (!_nm_crypto_init (error))
-		return NULL;
-
-	if (!parse_old_openssl_key_file (data, data_len, &parsed, &key_type, &cipher, &iv, NULL)) {
-		g_set_error (error, NM_CRYPTO_ERROR,
-		             NM_CRYPTO_ERROR_INVALID_DATA,
-		             _("Unable to determine private key type."));
-		return NULL;
-	}
-
-	NM_SET_OUT (out_key_type, key_type);
-
-	if (password) {
-		nm_auto_clear_secret_ptr NMSecretPtr parsed2 = { 0 };
-
-		if (cipher == NM_CRYPTO_CIPHER_UNKNOWN || !iv) {
-			g_set_error (error, NM_CRYPTO_ERROR,
-			             NM_CRYPTO_ERROR_INVALID_PASSWORD,
-			             _("Password provided, but key was not encrypted."));
-			return NULL;
-		}
-
-		if (!_nmtst_decrypt_key (cipher,
-		                         parsed.bin,
-		                         parsed.len,
-		                         iv,
-		                         password,
-		                         &parsed2,
-		                         error))
-			return NULL;
-
-		return nm_secret_copy_to_gbytes (parsed2.bin, parsed2.len);
-	}
-
-	if (cipher != NM_CRYPTO_CIPHER_UNKNOWN || iv)
-		return NULL;
-
-	return nm_secret_copy_to_gbytes (parsed.bin, parsed.len);
-}
-
-GBytes *
-nmtst_crypto_decrypt_openssl_private_key (const char *file,
-                                          const char *password,
-                                          NMCryptoKeyType *out_key_type,
-                                          GError **error)
-{
-	nm_auto_clear_secret_ptr NMSecretPtr contents = { 0 };
-
-	if (!_nm_crypto_init (error))
-		return NULL;
-
-	if (!file_read_contents (file, &contents, error))
-		return NULL;
-
-	return nmtst_crypto_decrypt_openssl_private_key_data (contents.bin,
-	                                                      contents.len,
-	                                                      password,
-	                                                      out_key_type,
-	                                                      error);
-}
-
-static gboolean
-extract_pem_cert_data (const guint8 *contents,
-                       gsize contents_len,
-                       NMSecretPtr *out_cert,
-                       GError **error)
-{
-	gsize start = 0;
-	gsize end = 0;
-	nm_auto_free_secret char *der_base64 = NULL;
-
-	nm_assert (contents);
-	nm_assert (out_cert);
-	nm_assert (out_cert->len == 0);
-	nm_assert (!out_cert->ptr);
-
-	if (!find_tag (PEM_CERT_BEGIN, contents, contents_len, 0, &start)) {
-		g_set_error (error, NM_CRYPTO_ERROR,
-		             NM_CRYPTO_ERROR_INVALID_DATA,
-		             _("PEM certificate had no start tag '%s'."),
-		             PEM_CERT_BEGIN);
-		return FALSE;
-	}
-
-	start += strlen (PEM_CERT_BEGIN);
-	if (!find_tag (PEM_CERT_END, contents, contents_len, start, &end)) {
-		g_set_error (error, NM_CRYPTO_ERROR,
-		             NM_CRYPTO_ERROR_INVALID_DATA,
-		             _("PEM certificate had no end tag '%s'."),
-		             PEM_CERT_END);
-		return FALSE;
-	}
-
-	/* g_base64_decode() wants a NULL-terminated string */
-	der_base64 = g_strndup ((const char *) &contents[start], end - start);
-
-	out_cert->bin = (guint8 *) g_base64_decode (der_base64, &out_cert->len);
-	if (!out_cert->bin || !out_cert->len) {
-		g_set_error (error, NM_CRYPTO_ERROR,
-		             NM_CRYPTO_ERROR_INVALID_DATA,
-		             _("Failed to decode certificate."));
-		nm_secret_ptr_clear (out_cert);
-		return FALSE;
-	}
-
-	return TRUE;
-}
-
-gboolean
-nm_crypto_load_and_verify_certificate (const char *file,
-                                       NMCryptoFileFormat *out_file_format,
-                                       GBytes **out_certificate,
-                                       GError **error)
-{
-	nm_auto_clear_secret_ptr NMSecretPtr contents = { 0 };
-
-	g_return_val_if_fail (file, FALSE);
-	nm_assert (!error || !*error);
-
-	if (!_nm_crypto_init (error))
-		goto out;
-
-	if (!file_read_contents (file, &contents, error))
-		goto out;
-
-	if (contents.len == 0) {
-		g_set_error (error,
-		             NM_CRYPTO_ERROR,
-		             NM_CRYPTO_ERROR_INVALID_DATA,
-		             _("Certificate file is empty"));
-		goto out;
-	}
-
-	/* Check for PKCS#12 */
-	if (nm_crypto_is_pkcs12_data (contents.bin, contents.len, NULL)) {
-		NM_SET_OUT (out_file_format, NM_CRYPTO_FILE_FORMAT_PKCS12);
-		NM_SET_OUT (out_certificate, nm_secret_copy_to_gbytes (contents.bin, contents.len));
-		return TRUE;
-	}
-
-	/* Check for plain DER format */
-	if (contents.len > 2 && contents.bin[0] == 0x30 && contents.bin[1] == 0x82) {
-		if (_nm_crypto_verify_x509 (contents.bin, contents.len, NULL)) {
-			NM_SET_OUT (out_file_format, NM_CRYPTO_FILE_FORMAT_X509);
-			NM_SET_OUT (out_certificate, nm_secret_copy_to_gbytes (contents.bin, contents.len));
-			return TRUE;
-		}
-	} else {
-		nm_auto_clear_secret_ptr NMSecretPtr pem_cert = { 0 };
-
-		if (extract_pem_cert_data (contents.bin, contents.len, &pem_cert, NULL)) {
-			if (_nm_crypto_verify_x509 (pem_cert.bin, pem_cert.len, NULL)) {
-				NM_SET_OUT (out_file_format, NM_CRYPTO_FILE_FORMAT_X509);
-				NM_SET_OUT (out_certificate, nm_secret_copy_to_gbytes (contents.bin, contents.len));
-				return TRUE;
-			}
-		}
-	}
-
-	g_set_error (error,
-	             NM_CRYPTO_ERROR,
-	             NM_CRYPTO_ERROR_INVALID_DATA,
-	             _("Failed to recognize certificate"));
-
-out:
-	NM_SET_OUT (out_file_format, NM_CRYPTO_FILE_FORMAT_UNKNOWN);
-	NM_SET_OUT (out_certificate, NULL);
-	return FALSE;
-}
-
-gboolean
-nm_crypto_is_pkcs12_data (const guint8 *data,
-                          gsize data_len,
-                          GError **error)
-{
-	GError *local = NULL;
-	gboolean success;
-
-	if (!data_len) {
-		g_set_error (error,
-		             NM_CRYPTO_ERROR,
-		             NM_CRYPTO_ERROR_INVALID_DATA,
-		             _("Certificate file is empty"));
-		return FALSE;
-	}
-
-	g_return_val_if_fail (data != NULL, FALSE);
-
-	if (!_nm_crypto_init (error))
-		return FALSE;
-
-	success = _nm_crypto_verify_pkcs12 (data, data_len, NULL, &local);
-	if (success == FALSE) {
-		/* If the error was just a decryption error, then it's pkcs#12 */
-		if (local) {
-			if (g_error_matches (local, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_DECRYPTION_FAILED)) {
-				success = TRUE;
-				g_error_free (local);
-			} else
-				g_propagate_error (error, local);
-		}
-	}
-	return success;
-}
-
-gboolean
-nm_crypto_is_pkcs12_file (const char *file, GError **error)
-{
-	nm_auto_clear_secret_ptr NMSecretPtr contents = { 0 };
-
-	g_return_val_if_fail (file != NULL, FALSE);
-
-	if (!_nm_crypto_init (error))
-		return FALSE;
-
-	if (!file_read_contents (file, &contents, error))
-		return FALSE;
-
-	return nm_crypto_is_pkcs12_data (contents.bin, contents.len, error);
-}
-
-/* Verifies that a private key can be read, and if a password is given, that
- * the private key can be decrypted with that password.
- */
-NMCryptoFileFormat
-nm_crypto_verify_private_key_data (const guint8 *data,
-                                   gsize data_len,
-                                   const char *password,
-                                   gboolean *out_is_encrypted,
-                                   GError **error)
-{
-	NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
-	gboolean is_encrypted = FALSE;
-
-	g_return_val_if_fail (data != NULL, NM_CRYPTO_FILE_FORMAT_UNKNOWN);
-	g_return_val_if_fail (out_is_encrypted == NULL || *out_is_encrypted == FALSE, NM_CRYPTO_FILE_FORMAT_UNKNOWN);
-
-	if (!_nm_crypto_init (error))
-		return NM_CRYPTO_FILE_FORMAT_UNKNOWN;
-
-	/* Check for PKCS#12 first */
-	if (nm_crypto_is_pkcs12_data (data, data_len, NULL)) {
-		is_encrypted = TRUE;
-		if (   !password
-		    || _nm_crypto_verify_pkcs12 (data, data_len, password, error))
-			format = NM_CRYPTO_FILE_FORMAT_PKCS12;
-	} else {
-		nm_auto_clear_secret_ptr NMSecretPtr parsed = { 0 };
-
-		/* Maybe it's PKCS#8 */
-		if (parse_pkcs8_key_file (data, data_len, &parsed, &is_encrypted, NULL)) {
-			if (   !password
-			    || _nm_crypto_verify_pkcs8 (parsed.bin, parsed.len, is_encrypted, password, error))
-				format = NM_CRYPTO_FILE_FORMAT_RAW_KEY;
-		} else {
-			NMCryptoCipherType cipher;
-			nm_auto_free_secret char *iv = NULL;
-
-			/* Or it's old-style OpenSSL */
-			if (parse_old_openssl_key_file (data, data_len, NULL, NULL, &cipher, &iv, NULL)) {
-				format = NM_CRYPTO_FILE_FORMAT_RAW_KEY;
-				is_encrypted = (cipher != NM_CRYPTO_CIPHER_UNKNOWN && iv);
-			}
-		}
-	}
-
-	if (   format == NM_CRYPTO_FILE_FORMAT_UNKNOWN
-	    && error
-	    && !*error) {
-		g_set_error (error,
-		             NM_CRYPTO_ERROR,
-		             NM_CRYPTO_ERROR_INVALID_DATA,
-		             _("not a valid private key"));
-	}
-
-	if (out_is_encrypted)
-		*out_is_encrypted = is_encrypted;
-	return format;
-}
-
-NMCryptoFileFormat
-nm_crypto_verify_private_key (const char *filename,
-                              const char *password,
-                              gboolean *out_is_encrypted,
-                              GError **error)
-{
-	nm_auto_clear_secret_ptr NMSecretPtr contents = { 0 };
-
-	g_return_val_if_fail (filename != NULL, NM_CRYPTO_FILE_FORMAT_UNKNOWN);
-
-	if (!_nm_crypto_init (error))
-		return NM_CRYPTO_FILE_FORMAT_UNKNOWN;
-
-	if (!file_read_contents (filename, &contents, error))
-		return NM_CRYPTO_FILE_FORMAT_UNKNOWN;
-
-	return nm_crypto_verify_private_key_data (contents.bin, contents.len, password, out_is_encrypted, error);
-}
-
-void
-nm_crypto_md5_hash (const guint8 *salt,
-                    gsize salt_len,
-                    const guint8 *password,
-                    gsize password_len,
-                    guint8 *buffer,
-                    gsize buflen)
-{
-	nm_auto_free_checksum GChecksum *ctx = NULL;
-#define MD5_DIGEST_LEN 16
-	nm_auto_clear_static_secret_ptr const NMSecretPtr digest = NM_SECRET_PTR_STATIC (MD5_DIGEST_LEN);
-	gsize bufidx = 0;
-	int i;
-
-	nm_assert (g_checksum_type_get_length (G_CHECKSUM_MD5) == MD5_DIGEST_LEN);
-
-	g_return_if_fail (password_len == 0 || password);
-	g_return_if_fail (buffer);
-	g_return_if_fail (buflen > 0);
-	g_return_if_fail (salt_len == 0 || salt);
-
-	ctx = g_checksum_new (G_CHECKSUM_MD5);
-
-	for (;;) {
-		gsize digest_len;
-
-		if (password_len > 0)
-			g_checksum_update (ctx, (const guchar *) password, password_len);
-		if (salt_len > 0)
-			g_checksum_update (ctx, (const guchar *) salt, salt_len);
-
-		digest_len = MD5_DIGEST_LEN;
-		g_checksum_get_digest (ctx, digest.bin, &digest_len);
-		nm_assert (digest_len == MD5_DIGEST_LEN);
-
-		for (i = 0; i < MD5_DIGEST_LEN; i++) {
-			if (bufidx >= buflen)
-				return;
-			buffer[bufidx++] = digest.bin[i];
-		}
-
-		g_checksum_reset (ctx);
-		g_checksum_update (ctx, digest.ptr, MD5_DIGEST_LEN);
-	}
-}
-
-gboolean
-nm_crypto_randomize (void *buffer, gsize buffer_len, GError **error)
-{
-	return _nm_crypto_randomize (buffer, buffer_len, error);
-}
-
-
-/**
- * nmtst_crypto_rsa_key_encrypt:
- * @data: (array length=len): RSA private key data to be encrypted
- * @len: length of @data
- * @in_password: (allow-none): existing password to use, if any
- * @out_password: (out) (allow-none): if @in_password was %NULL, a random
- *  password will be generated and returned in this argument
- * @error: detailed error information on return, if an error occurred
- *
- * Encrypts the given RSA private key data with the given password (or generates
- * a password if no password was given) and converts the data to PEM format
- * suitable for writing to a file. It uses Triple DES cipher for the encryption.
- *
- * Returns: (transfer full): on success, PEM-formatted data suitable for writing
- * to a PEM-formatted certificate/private key file.
- **/
-GBytes *
-nmtst_crypto_rsa_key_encrypt (const guint8 *data,
-                              gsize len,
-                              const char *in_password,
-                              char **out_password,
-                              GError **error)
-{
-	guint8 salt[8];
-	nm_auto_clear_secret_ptr NMSecretPtr key = { 0 };
-	nm_auto_clear_secret_ptr NMSecretPtr enc = { 0 };
-	gs_unref_ptrarray GPtrArray *pem = NULL;
-	nm_auto_free_secret char *tmp_password = NULL;
-	nm_auto_free_secret char *enc_base64 = NULL;
-	gsize enc_base64_len;
-	const char *p;
-	gsize ret_len, ret_idx;
-	guint i;
-	NMSecretBuf *ret;
-
-	g_return_val_if_fail (data, NULL);
-	g_return_val_if_fail (len > 0, NULL);
-	g_return_val_if_fail (!out_password || !*out_password, NULL);
-
-	/* Make the password if needed */
-	if (!in_password) {
-		nm_auto_clear_static_secret_ptr NMSecretPtr pw_buf = NM_SECRET_PTR_STATIC (32);
-
-		if (!nm_crypto_randomize (pw_buf.bin, pw_buf.len, error))
-			return NULL;
-		tmp_password = nm_utils_bin2hexstr (pw_buf.bin, pw_buf.len, -1);
-		in_password = tmp_password;
-	}
-
-	if (!nm_crypto_randomize (salt, sizeof (salt), error))
-		return NULL;
-
-	key.bin = nmtst_crypto_make_des_aes_key (NM_CRYPTO_CIPHER_DES_EDE3_CBC, salt, sizeof (salt), in_password, &key.len, NULL);
-	if (!key.bin)
-		g_return_val_if_reached (NULL);
-
-	enc.bin = _nmtst_crypto_encrypt (NM_CRYPTO_CIPHER_DES_EDE3_CBC, data, len, salt, sizeof (salt), key.bin, key.len, &enc.len, error);
-	if (!enc.bin)
-		return NULL;
-
-	/* What follows is not the most efficient way to construct the pem
-	 * file line-by-line. At least, it makes sure, that the data will be cleared
-	 * again and not left around in memory.
-	 *
-	 * If this would not be test code, we should improve the implementation
-	 * to avoid some of the copying. */
-	pem = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_free_secret);
-
-	g_ptr_array_add (pem, g_strdup ("-----BEGIN RSA PRIVATE KEY-----\n"));
-	g_ptr_array_add (pem, g_strdup ("Proc-Type: 4,ENCRYPTED\n"));
-
-	/* Convert the salt to a hex string */
-	g_ptr_array_add (pem, g_strdup_printf ("DEK-Info: %s,",
-	                                       nm_crypto_cipher_get_info (NM_CRYPTO_CIPHER_DES_EDE3_CBC)->name));
-	g_ptr_array_add (pem, nm_utils_bin2hexstr (salt, sizeof (salt), sizeof (salt) * 2));
-	g_ptr_array_add (pem, g_strdup ("\n\n"));
-
-	/* Convert the encrypted key to a base64 string */
-	enc_base64 = g_base64_encode ((const guchar *) enc.bin, enc.len);
-	enc_base64_len = strlen (enc_base64);
-	for (p = enc_base64; (p - enc_base64) < (ptrdiff_t) enc_base64_len; p += 64) {
-		g_ptr_array_add (pem, g_strndup (p, 64));
-		g_ptr_array_add (pem, g_strdup ("\n"));
-	}
-
-	g_ptr_array_add (pem, g_strdup ("-----END RSA PRIVATE KEY-----\n"));
-
-	ret_len = 0;
-	for (i = 0; i < pem->len; i++)
-		ret_len += strlen (pem->pdata[i]);
-
-	ret = nm_secret_buf_new (ret_len + 1);
-	ret_idx = 0;
-	for (i = 0; i < pem->len; i++) {
-		const char *line = pem->pdata[i];
-		gsize line_l = strlen (line);
-
-		memcpy (&ret->bin[ret_idx], line, line_l);
-		ret_idx += line_l;
-		nm_assert (ret_idx <= ret_len);
-	}
-	nm_assert (ret_idx == ret_len);
-	ret->bin[ret_len] = '\0';
-
-	NM_SET_OUT (out_password, g_strdup (tmp_password));
-	return nm_secret_buf_to_gbytes_take (ret, ret_len);
-}
diff --git a/libnm-core/nm-crypto.h b/libnm-core/nm-crypto.h
deleted file mode 100644
index 54fbbc5f..00000000
--- a/libnm-core/nm-crypto.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-
-/*
- * Dan Williams <dcbw@redhat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA.
- *
- * Copyright 2007 - 2014 Red Hat, Inc.
- */
-
-#ifndef __NM_CRYPTO_H__
-#define __NM_CRYPTO_H__
-
-#if !((NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_CORE_PRIVATE)
-#error Cannot use this header.
-#endif
-
-typedef enum {
-	NM_CRYPTO_CIPHER_UNKNOWN,
-	NM_CRYPTO_CIPHER_DES_EDE3_CBC,
-	NM_CRYPTO_CIPHER_DES_CBC,
-	NM_CRYPTO_CIPHER_AES_128_CBC,
-	NM_CRYPTO_CIPHER_AES_192_CBC,
-	NM_CRYPTO_CIPHER_AES_256_CBC,
-} NMCryptoCipherType;
-
-typedef struct {
-	const char *name;
-	NMCryptoCipherType cipher;
-	guint8 digest_len;
-	guint8 real_iv_len;
-} NMCryptoCipherInfo;
-
-const NMCryptoCipherInfo *nm_crypto_cipher_get_info (NMCryptoCipherType cipher);
-const NMCryptoCipherInfo *nm_crypto_cipher_get_info_by_name (const char *cipher_name, gssize p_len);
-
-typedef enum {
-	NM_CRYPTO_KEY_TYPE_UNKNOWN = 0,
-	NM_CRYPTO_KEY_TYPE_RSA,
-	NM_CRYPTO_KEY_TYPE_DSA
-} NMCryptoKeyType;
-
-typedef enum {
-	NM_CRYPTO_FILE_FORMAT_UNKNOWN = 0,
-	NM_CRYPTO_FILE_FORMAT_X509,
-	NM_CRYPTO_FILE_FORMAT_RAW_KEY,
-	NM_CRYPTO_FILE_FORMAT_PKCS12
-} NMCryptoFileFormat;
-
-/*****************************************************************************/
-
-GBytes *nm_crypto_read_file (const char *filename,
-                             GError **error);
-
-gboolean nm_crypto_load_and_verify_certificate (const char *file,
-                                                NMCryptoFileFormat *out_file_format,
-                                                GBytes **out_certificat,
-                                                GError **error);
-
-gboolean nm_crypto_is_pkcs12_file (const char *file, GError **error);
-
-gboolean nm_crypto_is_pkcs12_data (const guint8 *data, gsize len, GError **error);
-
-NMCryptoFileFormat nm_crypto_verify_private_key_data (const guint8 *data,
-                                                      gsize data_len,
-                                                      const char *password,
-                                                      gboolean *out_is_encrypted,
-                                                      GError **error);
-
-NMCryptoFileFormat nm_crypto_verify_private_key (const char *file,
-                                                 const char *password,
-                                                 gboolean *out_is_encrypted,
-                                                 GError **error);
-
-void nm_crypto_md5_hash (const guint8 *salt,
-                         gsize salt_len,
-                         const guint8 *password,
-                         gsize password_len,
-                         guint8 *buffer,
-                         gsize buflen);
-
-gboolean nm_crypto_randomize (void *buffer, gsize buffer_len, GError **error);
-
-/*****************************************************************************/
-
-GBytes *nmtst_crypto_decrypt_openssl_private_key_data (const guint8 *data,
-                                                       gsize data_len,
-                                                       const char *password,
-                                                       NMCryptoKeyType *out_key_type,
-                                                       GError **error);
-
-GBytes *nmtst_crypto_decrypt_openssl_private_key (const char *file,
-                                                  const char *password,
-                                                  NMCryptoKeyType *out_key_type,
-                                                  GError **error);
-
-GBytes *nmtst_crypto_rsa_key_encrypt (const guint8 *data,
-                                      gsize len,
-                                      const char *in_password,
-                                      char **out_password,
-                                      GError **error);
-
-guint8 *nmtst_crypto_make_des_aes_key (NMCryptoCipherType cipher,
-                                       const guint8 *salt,
-                                       gsize salt_len,
-                                       const char *password,
-                                       gsize *out_len,
-                                       GError **error);
-
-/*****************************************************************************/
-
-#endif  /* __NM_CRYPTO_H__ */
diff --git a/libnm-core/nm-dbus-interface.h b/libnm-core/nm-dbus-interface.h
index 4e12dc63..e7c0bc2c 100644
--- a/libnm-core/nm-dbus-interface.h
+++ b/libnm-core/nm-dbus-interface.h
@@ -14,7 +14,7 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
- * Copyright 2004 - 2018 Red Hat, Inc.
+ * Copyright 2004 - 2017 Red Hat, Inc.
  */
 
 /* Definitions related to NetworkManager's D-Bus interfaces.
@@ -73,11 +73,8 @@
 #define NM_DBUS_INTERFACE_DEVICE_MACVLAN       NM_DBUS_INTERFACE_DEVICE ".Macvlan"
 #define NM_DBUS_INTERFACE_DEVICE_PPP           NM_DBUS_INTERFACE_DEVICE ".Ppp"
 #define NM_DBUS_INTERFACE_DEVICE_VXLAN         NM_DBUS_INTERFACE_DEVICE ".Vxlan"
-#define NM_DBUS_INTERFACE_DEVICE_WIREGUARD     NM_DBUS_INTERFACE_DEVICE ".WireGuard"
 #define NM_DBUS_INTERFACE_DEVICE_GRE           NM_DBUS_INTERFACE_DEVICE ".Gre"
 #define NM_DBUS_INTERFACE_DEVICE_IP_TUNNEL     NM_DBUS_INTERFACE_DEVICE ".IPTunnel"
-#define NM_DBUS_INTERFACE_DEVICE_WPAN          NM_DBUS_INTERFACE_DEVICE ".Wpan"
-#define NM_DBUS_INTERFACE_DEVICE_6LOWPAN       NM_DBUS_INTERFACE_DEVICE ".Lowpan"
 #define NM_DBUS_INTERFACE_DEVICE_STATISTICS    NM_DBUS_INTERFACE_DEVICE ".Statistics"
 #define NM_DBUS_INTERFACE_CHECKPOINT           NM_DBUS_INTERFACE ".Checkpoint"
 
@@ -215,9 +212,6 @@ typedef enum {
  * @NM_DEVICE_TYPE_OVS_INTERFACE: a Open vSwitch interface
  * @NM_DEVICE_TYPE_OVS_PORT: a Open vSwitch port
  * @NM_DEVICE_TYPE_OVS_BRIDGE: a Open vSwitch bridge
- * @NM_DEVICE_TYPE_WPAN: a IEEE 802.15.4 (WPAN) MAC Layer Device
- * @NM_DEVICE_TYPE_6LOWPAN: 6LoWPAN interface
- * @NM_DEVICE_TYPE_WIREGUARD: a WireGuard interface
  *
  * #NMDeviceType values indicate the type of hardware represented by a
  * device object.
@@ -250,9 +244,6 @@ typedef enum {
 	NM_DEVICE_TYPE_OVS_INTERFACE = 24,
 	NM_DEVICE_TYPE_OVS_PORT      = 25,
 	NM_DEVICE_TYPE_OVS_BRIDGE    = 26,
-	NM_DEVICE_TYPE_WPAN          = 27,
-	NM_DEVICE_TYPE_6LOWPAN       = 28,
-	NM_DEVICE_TYPE_WIREGUARD     = 29,
 } NMDeviceType;
 
 /**
@@ -562,7 +553,6 @@ typedef enum {
  * @NM_DEVICE_STATE_REASON_OVSDB_FAILED: problem communicating with Open vSwitch database
  * @NM_DEVICE_STATE_REASON_IP_ADDRESS_DUPLICATE: a duplicate IP address was detected
  * @NM_DEVICE_STATE_REASON_IP_METHOD_UNSUPPORTED: The selected IP method is not supported
- * @NM_DEVICE_STATE_REASON_SRIOV_CONFIGURATION_FAILED: configuration of SR-IOV parameters failed
  *
  * Device state change reason codes
  */
@@ -633,7 +623,6 @@ typedef enum {
 	NM_DEVICE_STATE_REASON_OVSDB_FAILED                   = 63,
 	NM_DEVICE_STATE_REASON_IP_ADDRESS_DUPLICATE           = 64,
 	NM_DEVICE_STATE_REASON_IP_METHOD_UNSUPPORTED          = 65,
-	NM_DEVICE_STATE_REASON_SRIOV_CONFIGURATION_FAILED     = 66,
 } NMDeviceStateReason;
 
 /**
@@ -656,30 +645,6 @@ typedef enum {
 } NMMetered;
 
 /**
- * NMConnectionMultiConnect:
- * @NM_CONNECTION_MULTI_CONNECT_DEFAULT: indicates that the per-connection
- *   setting is unspecified. In this case, it will fallback to the default
- *   value, which is @NM_CONNECTION_MULTI_CONNECT_SINGLE.
- * @NM_CONNECTION_MULTI_CONNECT_SINGLE: the connection profile can only
- *   be active once at each moment. Activating a profile that is already active,
- *   will first deactivate it.
- * @NM_CONNECTION_MULTI_CONNECT_MANUAL_MULTIPLE: the profile can
- *   be manually activated multiple times on different devices. However,
- *   regarding autoconnect, the profile will autoconnect only if it is
- *   currently not connected otherwise.
- * @NM_CONNECTION_MULTI_CONNECT_MULTIPLE: the profile can autoactivate
- *   and be manually activated multiple times together.
- *
- * Since: 1.14
- */
-typedef enum {
-	NM_CONNECTION_MULTI_CONNECT_DEFAULT           = 0,
-	NM_CONNECTION_MULTI_CONNECT_SINGLE            = 1,
-	NM_CONNECTION_MULTI_CONNECT_MANUAL_MULTIPLE   = 2,
-	NM_CONNECTION_MULTI_CONNECT_MULTIPLE          = 3,
-} NMConnectionMultiConnect;
-
-/**
  * NMActiveConnectionState:
  * @NM_ACTIVE_CONNECTION_STATE_UNKNOWN: the state of the connection is unknown
  * @NM_ACTIVE_CONNECTION_STATE_ACTIVATING: a network connection is being prepared
@@ -838,18 +803,16 @@ typedef enum /*< flags >*/ {
 
 /**
  * NMIPTunnelMode:
- * @NM_IP_TUNNEL_MODE_UNKNOWN:   Unknown/unset tunnel mode
- * @NM_IP_TUNNEL_MODE_IPIP:      IP in IP tunnel
- * @NM_IP_TUNNEL_MODE_GRE:       GRE tunnel
- * @NM_IP_TUNNEL_MODE_SIT:       SIT tunnel
- * @NM_IP_TUNNEL_MODE_ISATAP:    ISATAP tunnel
- * @NM_IP_TUNNEL_MODE_VTI:       VTI tunnel
- * @NM_IP_TUNNEL_MODE_IP6IP6:    IPv6 in IPv6 tunnel
- * @NM_IP_TUNNEL_MODE_IPIP6:     IPv4 in IPv6 tunnel
- * @NM_IP_TUNNEL_MODE_IP6GRE:    IPv6 GRE tunnel
- * @NM_IP_TUNNEL_MODE_VTI6:      IPv6 VTI tunnel
- * @NM_IP_TUNNEL_MODE_GRETAP:    GRETAP tunnel
- * @NM_IP_TUNNEL_MODE_IP6GRETAP: IPv6 GRETAP tunnel
+ * @NM_IP_TUNNEL_MODE_UNKNOWN: Unknown/unset tunnel mode
+ * @NM_IP_TUNNEL_MODE_IPIP:    IP in IP tunnel
+ * @NM_IP_TUNNEL_MODE_GRE:     GRE tunnel
+ * @NM_IP_TUNNEL_MODE_SIT:     SIT tunnel
+ * @NM_IP_TUNNEL_MODE_ISATAP:  ISATAP tunnel
+ * @NM_IP_TUNNEL_MODE_VTI:     VTI tunnel
+ * @NM_IP_TUNNEL_MODE_IP6IP6:  IPv6 in IPv6 tunnel
+ * @NM_IP_TUNNEL_MODE_IPIP6:   IPv4 in IPv6 tunnel
+ * @NM_IP_TUNNEL_MODE_IP6GRE:  IPv6 GRE tunnel
+ * @NM_IP_TUNNEL_MODE_VTI6:    IPv6 VTI tunnel
  *
  * The tunneling mode.
  *
@@ -866,8 +829,6 @@ typedef enum {
 	NM_IP_TUNNEL_MODE_IPIP6       = 7,
 	NM_IP_TUNNEL_MODE_IP6GRE      = 8,
 	NM_IP_TUNNEL_MODE_VTI6        = 9,
-	NM_IP_TUNNEL_MODE_GRETAP      = 10,
-	NM_IP_TUNNEL_MODE_IP6GRETAP   = 11,
 } NMIPTunnelMode;
 
 /**
@@ -1020,20 +981,4 @@ typedef enum { /*< flags >*/
 	NM_SETTINGS_UPDATE2_FLAG_BLOCK_AUTOCONNECT          = (1LL <<  5),
 } NMSettingsUpdate2Flags;
 
-/**
- * NMTernary:
- * @NM_TERNARY_DEFAULT: use the globally-configured default value.
- * @NM_TERNARY_FALSE: the option is disabled.
- * @NM_TERNARY_TRUE: the option is enabled.
- *
- * An boolean value that can be overridden by a default.
- *
- * Since: 1.14
- **/
-typedef enum {
-	NM_TERNARY_DEFAULT = -1,
-	NM_TERNARY_FALSE = 0,
-	NM_TERNARY_TRUE = 1,
-} NMTernary;
-
 #endif /* __NM_DBUS_INTERFACE_H__ */
diff --git a/libnm-core/nm-dbus-types.xml b/libnm-core/nm-dbus-types.xml
index e3e9fca9..117e4243 100644
--- a/libnm-core/nm-dbus-types.xml
+++ b/libnm-core/nm-dbus-types.xml
@@ -292,21 +292,6 @@
               <entry role="enum_member_value"><para>= <literal>26</literal></para><para></para></entry>
               <entry role="enum_member_description"><para>a Open vSwitch bridge</para><para></para></entry>
             </row>
-            <row role="constant">
-              <entry role="enum_member_name"><para>NM_DEVICE_TYPE_WPAN</para><para></para></entry>
-              <entry role="enum_member_value"><para>= <literal>27</literal></para><para></para></entry>
-              <entry role="enum_member_description"><para>a IEEE 802.15.4 (WPAN) MAC Layer Device</para><para></para></entry>
-            </row>
-            <row role="constant">
-              <entry role="enum_member_name"><para>NM_DEVICE_TYPE_6LOWPAN</para><para></para></entry>
-              <entry role="enum_member_value"><para>= <literal>28</literal></para><para></para></entry>
-              <entry role="enum_member_description"><para>6LoWPAN interface</para><para></para></entry>
-            </row>
-            <row role="constant">
-              <entry role="enum_member_name"><para>NM_DEVICE_TYPE_WIREGUARD</para><para></para></entry>
-              <entry role="enum_member_value"><para>= <literal>29</literal></para><para></para></entry>
-              <entry role="enum_member_description"><para>a WireGuard interface</para><para></para></entry>
-            </row>
           </tbody>
         </tgroup>
       </informaltable>
@@ -1147,11 +1132,6 @@
               <entry role="enum_member_value"><para>= <literal>65</literal></para><para></para></entry>
               <entry role="enum_member_description"><para>The selected IP method is not supported</para><para></para></entry>
             </row>
-            <row role="constant">
-              <entry role="enum_member_name"><para>NM_DEVICE_STATE_REASON_SRIOV_CONFIGURATION_FAILED</para><para></para></entry>
-              <entry role="enum_member_value"><para>= <literal>66</literal></para><para></para></entry>
-              <entry role="enum_member_description"><para>configuration of SR-IOV parameters failed</para><para></para></entry>
-            </row>
           </tbody>
         </tgroup>
       </informaltable>
@@ -1203,46 +1183,6 @@
     </refsect3>
   </refsect2>
 
-  <refsect2 id="NMConnectionMultiConnect" role="enum">
-    <title>enum NMConnectionMultiConnect</title>
-    <indexterm zone="NMConnectionMultiConnect">
-      <primary>NMConnectionMultiConnect</primary>
-    </indexterm>
-    <para><para>Since: 1.14</para><para></para></para>
-    <refsect3 role="enum_members">
-      <title>Values</title>
-      <informaltable role="enum_members_table" pgwide="1" frame="none">
-        <tgroup cols="4">
-          <colspec colname="enum_members_name" colwidth="300px" />
-          <colspec colname="enum_members_value" colwidth="100px"/>
-          <colspec colname="enum_members_description" />
-          <tbody>
-            <row role="constant">
-              <entry role="enum_member_name"><para>NM_CONNECTION_MULTI_CONNECT_DEFAULT</para><para></para></entry>
-              <entry role="enum_member_value"><para>= <literal>0</literal></para><para></para></entry>
-              <entry role="enum_member_description"><para>indicates that the per-connection setting is unspecified. In this case, it will fallback to the default value, which is @NM_CONNECTION_MULTI_CONNECT_SINGLE.</para><para></para></entry>
-            </row>
-            <row role="constant">
-              <entry role="enum_member_name"><para>NM_CONNECTION_MULTI_CONNECT_SINGLE</para><para></para></entry>
-              <entry role="enum_member_value"><para>= <literal>1</literal></para><para></para></entry>
-              <entry role="enum_member_description"><para>the connection profile can only be active once at each moment. Activating a profile that is already active, will first deactivate it.</para><para></para></entry>
-            </row>
-            <row role="constant">
-              <entry role="enum_member_name"><para>NM_CONNECTION_MULTI_CONNECT_MANUAL_MULTIPLE</para><para></para></entry>
-              <entry role="enum_member_value"><para>= <literal>2</literal></para><para></para></entry>
-              <entry role="enum_member_description"><para>the profile can be manually activated multiple times on different devices. However, regarding autoconnect, the profile will autoconnect only if it is currently not connected otherwise.</para><para></para></entry>
-            </row>
-            <row role="constant">
-              <entry role="enum_member_name"><para>NM_CONNECTION_MULTI_CONNECT_MULTIPLE</para><para></para></entry>
-              <entry role="enum_member_value"><para>= <literal>3</literal></para><para></para></entry>
-              <entry role="enum_member_description"><para>the profile can autoactivate and be manually activated multiple times together.</para><para></para></entry>
-            </row>
-          </tbody>
-        </tgroup>
-      </informaltable>
-    </refsect3>
-  </refsect2>
-
   <refsect2 id="NMActiveConnectionState" role="enum">
     <title>enum NMActiveConnectionState</title>
     <indexterm zone="NMActiveConnectionState">
@@ -1532,16 +1472,6 @@
               <entry role="enum_member_value"><para>= <literal>9</literal></para><para></para></entry>
               <entry role="enum_member_description"><para>IPv6 VTI tunnel</para><para></para></entry>
             </row>
-            <row role="constant">
-              <entry role="enum_member_name"><para>NM_IP_TUNNEL_MODE_GRETAP</para><para></para></entry>
-              <entry role="enum_member_value"><para>= <literal>10</literal></para><para></para></entry>
-              <entry role="enum_member_description"><para>GRETAP tunnel</para><para></para></entry>
-            </row>
-            <row role="constant">
-              <entry role="enum_member_name"><para>NM_IP_TUNNEL_MODE_IP6GRETAP</para><para></para></entry>
-              <entry role="enum_member_value"><para>= <literal>11</literal></para><para></para></entry>
-              <entry role="enum_member_description"><para>IPv6 GRETAP tunnel</para><para></para></entry>
-            </row>
           </tbody>
         </tgroup>
       </informaltable>
@@ -1783,39 +1713,4 @@
     </refsect3>
   </refsect2>
 
-  <refsect2 id="NMTernary" role="enum">
-    <title>enum NMTernary</title>
-    <indexterm zone="NMTernary">
-      <primary>NMTernary</primary>
-    </indexterm>
-    <para><para>An boolean value that can be overridden by a default.</para><para>Since: 1.14</para><para></para></para>
-    <refsect3 role="enum_members">
-      <title>Values</title>
-      <informaltable role="enum_members_table" pgwide="1" frame="none">
-        <tgroup cols="4">
-          <colspec colname="enum_members_name" colwidth="300px" />
-          <colspec colname="enum_members_value" colwidth="100px"/>
-          <colspec colname="enum_members_description" />
-          <tbody>
-            <row role="constant">
-              <entry role="enum_member_name"><para>NM_TERNARY_DEFAULT</para><para></para></entry>
-              <entry role="enum_member_value"><para>= <literal>-1</literal></para><para></para></entry>
-              <entry role="enum_member_description"><para>use the globally-configured default value.</para><para></para></entry>
-            </row>
-            <row role="constant">
-              <entry role="enum_member_name"><para>NM_TERNARY_FALSE</para><para></para></entry>
-              <entry role="enum_member_value"><para>= <literal>0</literal></para><para></para></entry>
-              <entry role="enum_member_description"><para>the option is disabled.</para><para></para></entry>
-            </row>
-            <row role="constant">
-              <entry role="enum_member_name"><para>NM_TERNARY_TRUE</para><para></para></entry>
-              <entry role="enum_member_value"><para>= <literal>1</literal></para><para></para></entry>
-              <entry role="enum_member_description"><para>the option is enabled.</para><para></para></entry>
-            </row>
-          </tbody>
-        </tgroup>
-      </informaltable>
-    </refsect3>
-  </refsect2>
-
 </refentry>
diff --git a/libnm-core/nm-dbus-utils.c b/libnm-core/nm-dbus-utils.c
index 25af7c99..8389bf36 100644
--- a/libnm-core/nm-dbus-utils.c
+++ b/libnm-core/nm-dbus-utils.c
@@ -117,7 +117,7 @@ dbus_signal_meta_marshal (GClosure     *closure,
  *
  * The argument types in @c_handler correspond to the types output by
  * g_dbus_gvariant_to_gvalue(), except for 'ay' and 'aay'. In particular:
- * - both 16-bit and 32-bit integers are passed as #int/#guint
+ * - both 16-bit and 32-bit integers are passed as #gint/#guint
  * - 'as' values are passed as #GStrv (char **)
  * - all other array, tuple, and dict types are passed as #GVariant
  *
@@ -245,11 +245,11 @@ _nm_dbus_proxy_call_finish (GDBusProxy          *proxy,
  */
 GVariant *
 _nm_dbus_proxy_call_sync (GDBusProxy          *proxy,
-                          const char          *method_name,
+                          const gchar         *method_name,
                           GVariant            *parameters,
                           const GVariantType  *reply_type,
                           GDBusCallFlags       flags,
-                          int                  timeout_msec,
+                          gint                 timeout_msec,
                           GCancellable        *cancellable,
                           GError             **error)
 {
diff --git a/libnm-core/nm-keyfile-utils.c b/libnm-core/nm-keyfile-utils.c
index 21f8b07d..5000b583 100644
--- a/libnm-core/nm-keyfile-utils.c
+++ b/libnm-core/nm-keyfile-utils.c
@@ -109,8 +109,8 @@ nm_keyfile_plugin_kf_set_##stype##_list (GKeyFile *kf, \
 	g_key_file_set_##stype##_list (kf, alias ?: group, key, list, length); \
 }
 
-DEFINE_KF_LIST_WRAPPER(integer, int*, int);
-DEFINE_KF_LIST_WRAPPER(string, char **, const char* const);
+DEFINE_KF_LIST_WRAPPER(integer, gint*, gint);
+DEFINE_KF_LIST_WRAPPER(string, gchar **, const gchar* const);
 
 void
 nm_keyfile_plugin_kf_set_integer_list_uint8 (GKeyFile *kf,
@@ -173,19 +173,19 @@ nm_keyfile_plugin_kf_set_##stype (GKeyFile *kf, \
 	g_key_file_set_##stype (kf, alias ?: group, key, value); \
 }
 
-DEFINE_KF_WRAPPER(string, char*, const char*);
-DEFINE_KF_WRAPPER(integer, int, int);
+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, char*, const char*);
+DEFINE_KF_WRAPPER(value, gchar*, const gchar*);
 
-char **
+gchar **
 nm_keyfile_plugin_kf_get_keys (GKeyFile *kf,
                                const char *group,
                                gsize *out_length,
                                GError **error)
 {
-	char **keys;
+	gchar **keys;
 	const char *alias;
 	GError *local = NULL;
 
diff --git a/libnm-core/nm-keyfile-utils.h b/libnm-core/nm-keyfile-utils.h
index 46a6d564..832ad0b4 100644
--- a/libnm-core/nm-keyfile-utils.h
+++ b/libnm-core/nm-keyfile-utils.h
@@ -46,8 +46,8 @@ void nm_keyfile_plugin_kf_set_##stype##_list  (GKeyFile *kf, \
                                                const char *key, \
                                                set_ctype list[], \
                                                gsize length);
-DEFINE_KF_LIST_WRAPPER_PROTO(integer, int*, int)
-DEFINE_KF_LIST_WRAPPER_PROTO(string, char**, const char* const)
+DEFINE_KF_LIST_WRAPPER_PROTO(integer, gint*, gint)
+DEFINE_KF_LIST_WRAPPER_PROTO(string, gchar**, const gchar* const)
 
 void nm_keyfile_plugin_kf_set_integer_list_uint8 (GKeyFile *kf,
                                                   const char *group,
@@ -66,14 +66,14 @@ void nm_keyfile_plugin_kf_set_##stype (GKeyFile *kf, \
                                        const char *group, \
                                        const char *key, \
                                        set_ctype value);
-DEFINE_KF_WRAPPER_PROTO(string, char*, const char*)
-DEFINE_KF_WRAPPER_PROTO(integer, int, int)
+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, char*, const char*)
+DEFINE_KF_WRAPPER_PROTO(value, gchar*, const gchar*)
 
 /* Misc */
-char ** nm_keyfile_plugin_kf_get_keys    (GKeyFile *kf,
+gchar ** nm_keyfile_plugin_kf_get_keys    (GKeyFile *kf,
                                            const char *group,
                                            gsize *out_length,
                                            GError **error);
diff --git a/libnm-core/nm-keyfile.c b/libnm-core/nm-keyfile.c
index c7d87869..c894e250 100644
--- a/libnm-core/nm-keyfile.c
+++ b/libnm-core/nm-keyfile.c
@@ -33,7 +33,6 @@
 #include <string.h>
 #include <linux/pkt_sched.h>
 
-#include "nm-utils/nm-secret-utils.h"
 #include "nm-common-macros.h"
 #include "nm-core-internal.h"
 #include "nm-keyfile-utils.h"
@@ -120,49 +119,6 @@ setting_alias_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *k
 }
 
 static void
-sriov_vfs_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key)
-{
-	const char *setting_name = nm_setting_get_name (setting);
-	gs_unref_ptrarray GPtrArray *vfs = NULL;
-	gs_strfreev char **keys = NULL;
-	gsize n_keys = 0;
-	int i;
-
-	keys = nm_keyfile_plugin_kf_get_keys (info->keyfile, setting_name, &n_keys, NULL);
-	if (!keys || n_keys == 0)
-		return;
-
-	vfs = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_sriov_vf_unref);
-
-	for (i = 0; i < n_keys; i++) {
-		gs_free char *value = NULL;
-		NMSriovVF *vf;
-		const char *rest;
-
-		if (!g_str_has_prefix (keys[i], "vf."))
-			continue;
-
-		rest = &keys[i][3];
-
-		if (!NM_STRCHAR_ALL (rest, ch, g_ascii_isdigit (ch)))
-			continue;
-
-		value = nm_keyfile_plugin_kf_get_string (info->keyfile,
-		                                         setting_name,
-		                                         keys[i],
-		                                         NULL);
-
-		vf = _nm_utils_sriov_vf_from_strparts (rest, value, NULL);
-		if (vf)
-			g_ptr_array_add (vfs, vf);
-	}
-
-	g_object_set (G_OBJECT (setting),
-	              key, vfs,
-	              NULL);
-}
-
-static void
 read_array_of_uint (GKeyFile *file,
                     NMSetting *setting,
                     const char *key)
@@ -775,7 +731,7 @@ ip6_addr_gen_mode_parser (KeyfileReaderInfo *info, NMSetting *setting, const cha
 	} else
 		addr_gen_mode = NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64;
 
-	g_object_set (G_OBJECT (setting), key, (int) addr_gen_mode, NULL);
+	g_object_set (G_OBJECT (setting), key, (gint) addr_gen_mode, NULL);
 }
 
 static void
@@ -940,7 +896,7 @@ unescape_semicolons (char *str)
 			i++;
 		str[j++] = str[i++];;
 	}
-	nm_explicit_bzero (&str[j], i - j);
+	str[j] = '\0';
 	return j;
 }
 
@@ -951,10 +907,9 @@ get_bytes (KeyfileReaderInfo *info,
            gboolean zero_terminate,
            gboolean unescape_semicolon)
 {
-	nm_auto_free_secret char *tmp_string = NULL;
+	gs_free char *tmp_string = NULL;
 	gboolean may_be_int_list = TRUE;
 	gsize length;
-	GBytes *result;
 
 	/* New format: just a string
 	 * Old format: integer list; e.g. 11;25;38;
@@ -988,11 +943,12 @@ get_bytes (KeyfileReaderInfo *info,
 
 	/* Try to parse the string as a integer list. */
 	if (may_be_int_list && length > 0) {
-		nm_auto_free_secret_buf NMSecretBuf *bin = NULL;
+		gs_free guint8 *bin_data = NULL;
 		const char *const s = tmp_string;
 		gsize i, d;
+		const gsize BIN_DATA_LEN = (length / 2 + 3);
 
-		bin = nm_secret_buf_new (length / 2 + 3);
+		bin_data = g_malloc (BIN_DATA_LEN);
 
 #define DIGIT(c) ((c) - '0')
 		i = 0;
@@ -1025,8 +981,8 @@ get_bytes (KeyfileReaderInfo *info,
 				break;
 			}
 
-			nm_assert (d < bin->len);
-			bin->bin[d++] = n;
+			bin_data[d++] = n;
+			nm_assert (d < BIN_DATA_LEN);
 
 			/* allow whitespace after the digit. */
 			while (g_ascii_isspace (s[i]))
@@ -1044,23 +1000,16 @@ get_bytes (KeyfileReaderInfo *info,
 		 * string format before. We expect that this conversion cannot fail. */
 		if (d > 0) {
 			/* note that @zero_terminate does not add a terminating '\0' to
-			 * binary data as an integer list. If the bytes are expressed as
-			 * an integer list, all potential NUL characters are supposed to
-			 * be included there explicitly.
+			 * binary data as an integer list.
 			 *
-			 * However, in the spirit of defensive programming, we do append a
-			 * NUL character to the buffer, although this character is hidden
-			 * and only a mitigation for bugs. */
-
-			if (d + 10 < bin->len) {
-				/* hm, too much unused memory. Copy the memory to a suitable
-				 * sized buffer. */
-				return nm_secret_copy_to_gbytes (bin->bin, d);
-			}
-
-			nm_assert (d < bin->len);
-			bin->bin[d] = '\0';
-			return nm_secret_buf_to_gbytes_take (g_steal_pointer (&bin), d);
+			 * But we add a '\0' to the bin_data pointer, just to avoid somebody
+			 * (erronously!) reading the binary data as C-string.
+			 *
+			 * @d itself does not entail the '\0'. */
+			nm_assert (d + 1 <= BIN_DATA_LEN);
+			bin_data = g_realloc (bin_data, d + 1);
+			bin_data[d] = '\0';
+			return g_bytes_new_take (g_steal_pointer (&bin_data), d);
 		}
 	}
 
@@ -1071,13 +1020,8 @@ get_bytes (KeyfileReaderInfo *info,
 		length++;
 	if (length == 0)
 		return NULL;
-
-	result = g_bytes_new_with_free_func (tmp_string,
-	                                     length,
-	                                     (GDestroyNotify) nm_free_secret,
-	                                     tmp_string);
-	tmp_string = NULL;
-	return result;
+	tmp_string = g_realloc (tmp_string, length + (zero_terminate ? 0 : 1));
+	return g_bytes_new_take (g_steal_pointer (&tmp_string), length);
 }
 
 static void
@@ -1121,12 +1065,12 @@ get_cert_path (const char *base_dir, const guint8 *cert_path, gsize cert_path_le
 	g_return_val_if_fail (base_dir != NULL, NULL);
 	g_return_val_if_fail (cert_path != NULL, NULL);
 
-	path = g_strndup ((char *) cert_path, cert_path_len);
+	base = path = g_malloc0 (cert_path_len + 1);
+	memcpy (path, cert_path, cert_path_len);
 
 	if (path[0] == '/')
 		return path;
 
-	base = path;
 	p = strrchr (path, '/');
 	if (p)
 		base = p + 1;
@@ -1160,9 +1104,8 @@ nm_keyfile_detect_unqualified_path_scheme (const char *base_dir,
 	const char *data = pdata;
 	gboolean exists = FALSE;
 	gsize validate_len;
-	gsize path_len, pathuri_len;
 	gs_free char *path = NULL;
-	gs_free char *pathuri = NULL;
+	GByteArray *tmp;
 
 	g_return_val_if_fail (base_dir && base_dir[0] == '/', NULL);
 
@@ -1205,16 +1148,18 @@ nm_keyfile_detect_unqualified_path_scheme (const char *base_dir,
 	 * When returning TRUE, we must also be sure that @data_len does not look like
 	 * the deprecated format of list of integers. With this implementation that is the
 	 * case, as long as @consider_exists is FALSE. */
-	path_len = strlen (path);
-	pathuri_len = (NM_STRLEN (NM_KEYFILE_CERT_SCHEME_PREFIX_PATH) + 1) + path_len;
-	pathuri = g_new (char, pathuri_len);
-	memcpy (pathuri, NM_KEYFILE_CERT_SCHEME_PREFIX_PATH, NM_STRLEN (NM_KEYFILE_CERT_SCHEME_PREFIX_PATH));
-	memcpy (&pathuri[NM_STRLEN (NM_KEYFILE_CERT_SCHEME_PREFIX_PATH)], path, path_len + 1);
-	if (nm_setting_802_1x_check_cert_scheme (pathuri, pathuri_len, NULL) != NM_SETTING_802_1X_CK_SCHEME_PATH)
+	tmp = g_byte_array_sized_new (strlen (NM_KEYFILE_CERT_SCHEME_PREFIX_PATH) + strlen (path) + 1);
+	g_byte_array_append (tmp, (const guint8 *) NM_KEYFILE_CERT_SCHEME_PREFIX_PATH, strlen (NM_KEYFILE_CERT_SCHEME_PREFIX_PATH));
+	g_byte_array_append (tmp, (const guint8 *) path, strlen (path) + 1);
+	if (nm_setting_802_1x_check_cert_scheme (tmp->data, tmp->len, NULL) != NM_SETTING_802_1X_CK_SCHEME_PATH) {
+		g_byte_array_unref (tmp);
 		return NULL;
+	}
+	g_free (path);
+	path = (char *) g_byte_array_free (tmp, FALSE);
 
 	NM_SET_OUT (out_exists, exists);
-	return g_steal_pointer (&pathuri);
+	return g_steal_pointer (&path);
 }
 
 #define HAS_SCHEME_PREFIX(bin, bin_len, scheme) \
@@ -1448,7 +1393,7 @@ qdisc_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key)
 {
 	const char *setting_name = nm_setting_get_name (setting);
 	GPtrArray *qdiscs;
-	gs_strfreev char **keys = NULL;
+	gs_strfreev gchar **keys = NULL;
 	gsize n_keys = 0;
 	int i;
 
@@ -1496,7 +1441,7 @@ tfilter_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key)
 {
 	const char *setting_name = nm_setting_get_name (setting);
 	GPtrArray *tfilters;
-	gs_strfreev char **keys = NULL;
+	gs_strfreev gchar **keys = NULL;
 	gsize n_keys = 0;
 	int i;
 
@@ -1565,37 +1510,6 @@ setting_alias_writer (KeyfileWriterInfo *info,
 }
 
 static void
-sriov_vfs_writer (KeyfileWriterInfo *info,
-                  NMSetting *setting,
-                  const char *key,
-                  const GValue *value)
-{
-	GPtrArray *vfs;
-	guint i;
-
-	vfs = g_value_get_boxed (value);
-	if (!vfs)
-		return;
-
-	for (i = 0; i < vfs->len; i++) {
-		const NMSriovVF *vf = vfs->pdata[i];
-		gs_free char *kf_value = NULL;
-		char kf_key[32];
-
-		kf_value = nm_utils_sriov_vf_to_str (vf, TRUE, NULL);
-		if (!kf_value)
-			continue;
-
-		nm_sprintf_buf (kf_key, "vf.%u", nm_sriov_vf_get_index (vf));
-
-		nm_keyfile_plugin_kf_set_string (info->keyfile,
-		                                 nm_setting_get_name (setting),
-		                                 kf_key,
-		                                 kf_value);
-	}
-}
-
-static void
 write_array_of_uint (GKeyFile *file,
                      NMSetting *setting,
                      const char *key,
@@ -1611,7 +1525,7 @@ write_array_of_uint (GKeyFile *file,
 
 	g_return_if_fail (g_array_get_element_size (array) == sizeof (guint));
 
-	tmp_array = g_new (int, array->len);
+	tmp_array = g_new (gint, array->len);
 	for (i = 0; i < array->len; i++) {
 		guint v = g_array_index (array, guint, i);
 
@@ -2108,16 +2022,18 @@ typedef struct {
 	})
 
 typedef struct {
+	const char *setting_name;
 	const ParseInfoProperty*const*properties;
 } ParseInfoSetting;
 
-#define PARSE_INFO_SETTING(setting_type, ...) \
-	[setting_type] = (&((const ParseInfoSetting) { \
+#define PARSE_INFO_SETTING(_setting_name, ...) \
+	{ \
+		.setting_name = _setting_name, \
 		__VA_ARGS__ \
-	}))
+	}
 
-static const ParseInfoSetting *const parse_infos[_NM_META_SETTING_TYPE_NUM] = {
-	PARSE_INFO_SETTING (NM_META_SETTING_TYPE_WIRELESS,
+static const ParseInfoSetting parse_infos[] = {
+	PARSE_INFO_SETTING (NM_SETTING_WIRELESS_SETTING_NAME,
 		PARSE_INFO_PROPERTIES (
 			PARSE_INFO_PROPERTY (NM_SETTING_WIRELESS_BSSID,
 				.parser        = mac_address_parser_ETHER,
@@ -2134,7 +2050,7 @@ static const ParseInfoSetting *const parse_infos[_NM_META_SETTING_TYPE_NUM] = {
 			),
 		),
 	),
-	PARSE_INFO_SETTING (NM_META_SETTING_TYPE_802_1X,
+	PARSE_INFO_SETTING (NM_SETTING_802_1X_SETTING_NAME,
 		PARSE_INFO_PROPERTIES (
 			PARSE_INFO_PROPERTY (NM_SETTING_802_1X_CA_CERT,
 				.parser        = cert_parser,
@@ -2166,7 +2082,7 @@ static const ParseInfoSetting *const parse_infos[_NM_META_SETTING_TYPE_NUM] = {
 			),
 		),
 	),
-	PARSE_INFO_SETTING (NM_META_SETTING_TYPE_WIRED,
+	PARSE_INFO_SETTING (NM_SETTING_WIRED_SETTING_NAME,
 		PARSE_INFO_PROPERTIES (
 			PARSE_INFO_PROPERTY (NM_SETTING_WIRED_CLONED_MAC_ADDRESS,
 				.parser        = mac_address_parser_ETHER_cloned,
@@ -2176,28 +2092,28 @@ static const ParseInfoSetting *const parse_infos[_NM_META_SETTING_TYPE_NUM] = {
 			),
 		),
 	),
-	PARSE_INFO_SETTING (NM_META_SETTING_TYPE_BLUETOOTH,
+	PARSE_INFO_SETTING (NM_SETTING_BLUETOOTH_SETTING_NAME,
 		PARSE_INFO_PROPERTIES (
 			PARSE_INFO_PROPERTY (NM_SETTING_BLUETOOTH_BDADDR,
 				.parser        = mac_address_parser_ETHER,
 			),
 		),
 	),
-	PARSE_INFO_SETTING (NM_META_SETTING_TYPE_BOND,
+	PARSE_INFO_SETTING (NM_SETTING_BOND_SETTING_NAME,
 		PARSE_INFO_PROPERTIES (
 			PARSE_INFO_PROPERTY (NM_SETTING_BOND_OPTIONS,
 				.parser_no_check_key = TRUE,
 			),
 		),
 	),
-	PARSE_INFO_SETTING (NM_META_SETTING_TYPE_BRIDGE,
+	PARSE_INFO_SETTING (NM_SETTING_BRIDGE_SETTING_NAME,
 		PARSE_INFO_PROPERTIES (
 			PARSE_INFO_PROPERTY (NM_SETTING_BRIDGE_MAC_ADDRESS,
 				.parser        = mac_address_parser_ETHER,
 			),
 		),
 	),
-	PARSE_INFO_SETTING (NM_META_SETTING_TYPE_CONNECTION,
+	PARSE_INFO_SETTING (NM_SETTING_CONNECTION_SETTING_NAME,
 		PARSE_INFO_PROPERTIES (
 			PARSE_INFO_PROPERTY (NM_SETTING_CONNECTION_READ_ONLY,
 				.parser_skip   = TRUE,
@@ -2209,14 +2125,14 @@ static const ParseInfoSetting *const parse_infos[_NM_META_SETTING_TYPE_NUM] = {
 			),
 		),
 	),
-	PARSE_INFO_SETTING (NM_META_SETTING_TYPE_INFINIBAND,
+	PARSE_INFO_SETTING (NM_SETTING_INFINIBAND_SETTING_NAME,
 		PARSE_INFO_PROPERTIES (
 			PARSE_INFO_PROPERTY (NM_SETTING_INFINIBAND_MAC_ADDRESS,
 				.parser        = mac_address_parser_INFINIBAND,
 			),
 		),
 	),
-	PARSE_INFO_SETTING (NM_META_SETTING_TYPE_IP4_CONFIG,
+	PARSE_INFO_SETTING (NM_SETTING_IP4_CONFIG_SETTING_NAME,
 		PARSE_INFO_PROPERTIES (
 			PARSE_INFO_PROPERTY (NM_SETTING_IP_CONFIG_ADDRESSES,
 				.parser_no_check_key = TRUE,
@@ -2238,7 +2154,7 @@ static const ParseInfoSetting *const parse_infos[_NM_META_SETTING_TYPE_NUM] = {
 			),
 		),
 	),
-	PARSE_INFO_SETTING (NM_META_SETTING_TYPE_IP6_CONFIG,
+	PARSE_INFO_SETTING (NM_SETTING_IP6_CONFIG_SETTING_NAME,
 		PARSE_INFO_PROPERTIES (
 			PARSE_INFO_PROPERTY (NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE,
 				.parser_no_check_key = TRUE,
@@ -2266,23 +2182,14 @@ static const ParseInfoSetting *const parse_infos[_NM_META_SETTING_TYPE_NUM] = {
 			),
 		),
 	),
-	PARSE_INFO_SETTING (NM_META_SETTING_TYPE_SERIAL,
+	PARSE_INFO_SETTING (NM_SETTING_SERIAL_SETTING_NAME,
 		PARSE_INFO_PROPERTIES (
 			PARSE_INFO_PROPERTY (NM_SETTING_SERIAL_PARITY,
 				.parser        = parity_parser,
 			),
 		),
 	),
-	PARSE_INFO_SETTING (NM_META_SETTING_TYPE_SRIOV,
-		PARSE_INFO_PROPERTIES (
-			PARSE_INFO_PROPERTY (NM_SETTING_SRIOV_VFS,
-				.parser_no_check_key = TRUE,
-				.parser        = sriov_vfs_parser,
-				.writer        = sriov_vfs_writer,
-			),
-		),
-	),
-	PARSE_INFO_SETTING (NM_META_SETTING_TYPE_TC_CONFIG,
+	PARSE_INFO_SETTING (NM_SETTING_TC_CONFIG_SETTING_NAME,
 		PARSE_INFO_PROPERTIES (
 			PARSE_INFO_PROPERTY (NM_SETTING_TC_CONFIG_QDISCS,
 				.parser_no_check_key = TRUE,
@@ -2296,7 +2203,7 @@ static const ParseInfoSetting *const parse_infos[_NM_META_SETTING_TYPE_NUM] = {
 			),
 		),
 	),
-	PARSE_INFO_SETTING (NM_META_SETTING_TYPE_TEAM,
+	PARSE_INFO_SETTING (NM_SETTING_TEAM_SETTING_NAME,
 		PARSE_INFO_PROPERTIES (
 			PARSE_INFO_PROPERTY (NM_SETTING_TEAM_CONFIG,
 				.parser        = team_config_parser,
@@ -2363,7 +2270,7 @@ static const ParseInfoSetting *const parse_infos[_NM_META_SETTING_TYPE_NUM] = {
 			),
 		),
 	),
-	PARSE_INFO_SETTING (NM_META_SETTING_TYPE_TEAM_PORT,
+	PARSE_INFO_SETTING (NM_SETTING_TEAM_PORT_SETTING_NAME,
 		PARSE_INFO_PROPERTIES (
 			PARSE_INFO_PROPERTY (NM_SETTING_TEAM_CONFIG,
 				.parser        = team_config_parser,
@@ -2394,21 +2301,21 @@ static const ParseInfoSetting *const parse_infos[_NM_META_SETTING_TYPE_NUM] = {
 			),
 		),
 	),
-	PARSE_INFO_SETTING (NM_META_SETTING_TYPE_USER,
+	PARSE_INFO_SETTING (NM_SETTING_USER_SETTING_NAME,
 		PARSE_INFO_PROPERTIES (
 			PARSE_INFO_PROPERTY (NM_SETTING_USER_DATA,
 				.parser_no_check_key = TRUE,
 			),
 		),
 	),
-	PARSE_INFO_SETTING (NM_META_SETTING_TYPE_VLAN,
+	PARSE_INFO_SETTING (NM_SETTING_VLAN_SETTING_NAME,
 		PARSE_INFO_PROPERTIES (
 			PARSE_INFO_PROPERTY (NM_SETTING_VLAN_FLAGS,
 				.writer_persist_default = TRUE,
 			),
 		),
 	),
-	PARSE_INFO_SETTING (NM_META_SETTING_TYPE_VPN,
+	PARSE_INFO_SETTING (NM_SETTING_VPN_SETTING_NAME,
 		PARSE_INFO_PROPERTIES (
 			PARSE_INFO_PROPERTY (NM_SETTING_VPN_DATA,
 				.parser_no_check_key = TRUE,
@@ -2430,7 +2337,7 @@ static const ParseInfoSetting *const parse_infos[_NM_META_SETTING_TYPE_NUM] = {
 			),
 		),
 	),
-	PARSE_INFO_SETTING (NM_META_SETTING_TYPE_WIMAX,
+	PARSE_INFO_SETTING (NM_SETTING_WIMAX_SETTING_NAME,
 		PARSE_INFO_PROPERTIES (
 			PARSE_INFO_PROPERTY (NM_SETTING_WIMAX_MAC_ADDRESS,
 				.parser        = mac_address_parser_ETHER,
@@ -2440,24 +2347,21 @@ static const ParseInfoSetting *const parse_infos[_NM_META_SETTING_TYPE_NUM] = {
 };
 
 static const ParseInfoProperty *
-_parse_info_find (NMSetting *setting,
-                  const char *property_name,
-                  const char **out_setting_name)
+_parse_info_find (const char *setting_name, const char *property_name)
 {
-	const NMMetaSettingInfo *setting_info;
-	const ParseInfoSetting *pis;
 	gssize idx;
 
-#if NM_MORE_ASSERTS > 10
+#if NM_MORE_ASSERTS > 5
 	{
 		guint i, j;
 
 		for (i = 0; i < G_N_ELEMENTS (parse_infos); i++) {
-			pis = parse_infos[i];
-
-			if (!pis)
-				continue;
+			const ParseInfoSetting *pis = &parse_infos[i];
 
+			g_assert (pis->setting_name);
+			if (   i > 0
+				&& strcmp (pis[-1].setting_name, pis->setting_name) >= 0)
+				g_error ("Wrong order at index #%d: \"%s\" before \"%s\"", i - 1, pis[-1].setting_name, pis->setting_name);
 			g_assert (pis->properties);
 			g_assert (pis->properties[0]);
 			for (j = 0; pis->properties[j]; j++) {
@@ -2467,35 +2371,31 @@ _parse_info_find (NMSetting *setting,
 				g_assert (pip->property_name);
 				if (   j > 0
 				    && (pip0 = pis->properties[j - 1])
-				    && strcmp (pip0->property_name, pip->property_name) >= 0) {
-					g_error ("Wrong order at index #%d.%d: \"%s.%s\" before \"%s.%s\"",
-					         i, j - 1,
-					         nm_meta_setting_infos[i].setting_name, pip0->property_name,
-					         nm_meta_setting_infos[i].setting_name, pip->property_name);
-				}
+				    && strcmp (pip0->property_name, pip->property_name) >= 0)
+					g_error ("Wrong order at index #%d.%d: \"%s.%s\" before \"%s.%s\"", i, j - 1, pis->setting_name, pip0->property_name, pis->setting_name, pip->property_name);
 			}
 		}
 	}
 #endif
 
-	if (   !NM_IS_SETTING (setting)
-	    || !(setting_info = NM_SETTING_GET_CLASS (setting)->setting_info)) {
-		/* handle invalid setting objects gracefully. */
-		*out_setting_name = NULL;
-		return NULL;
-	}
-
-	*out_setting_name = setting_info->setting_name;
-
-	if ((pis = parse_infos[setting_info->meta_type])) {
-		G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (ParseInfoProperty, property_name) == 0);
-		idx = nm_utils_ptrarray_find_binary_search ((gconstpointer *) pis->properties,
-		                                            NM_PTRARRAY_LEN (pis->properties),
-		                                            &property_name,
-		                                            nm_strcmp_p_with_data,
-		                                            NULL,
-		                                            NULL,
-		                                            NULL);
+	G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (ParseInfoSetting, setting_name) == 0);
+	idx = _nm_utils_array_find_binary_search (parse_infos,
+	                                          sizeof (ParseInfoSetting),
+	                                          G_N_ELEMENTS (parse_infos),
+	                                          &setting_name,
+	                                          nm_strcmp_p_with_data,
+	                                          NULL);
+	if (idx >= 0) {
+		const ParseInfoSetting *pis = &parse_infos[idx];
+
+		nm_assert (nm_streq (pis->setting_name, setting_name));
+		idx = _nm_utils_ptrarray_find_binary_search ((gconstpointer *) pis->properties,
+		                                             NM_PTRARRAY_LEN (pis->properties),
+		                                             &property_name,
+		                                             nm_strcmp_p_with_data,
+		                                             NULL,
+		                                             NULL,
+		                                             NULL);
 		if (idx >= 0)
 			return pis->properties[idx];
 	}
@@ -2526,9 +2426,9 @@ read_one_setting_value (NMSetting *setting,
 	if (!(flags & G_PARAM_WRITABLE))
 		return;
 
-	pip = _parse_info_find (setting, key, &setting_name);
+	setting_name = nm_setting_get_name (setting);
 
-	nm_assert (setting_name);
+	pip = _parse_info_find (setting_name, key);
 
 	if (   !pip
 	    && nm_streq (key, NM_SETTING_NAME))
@@ -2621,7 +2521,7 @@ read_one_setting_value (NMSetting *setting,
 		} else
 			g_object_set (setting, key, int_val, NULL);
 	} else if (type == G_TYPE_BYTES) {
-		int *tmp;
+		gint *tmp;
 		GByteArray *array;
 		GBytes *bytes;
 		gsize length;
@@ -2654,7 +2554,7 @@ read_one_setting_value (NMSetting *setting,
 		g_bytes_unref (bytes);
 		g_free (tmp);
 	} else if (type == G_TYPE_STRV) {
-		char **sa;
+		gchar **sa;
 		gsize length;
 
 		sa = nm_keyfile_plugin_kf_get_string_list (keyfile, setting_name, key, &length, NULL);
@@ -2680,11 +2580,11 @@ read_one_setting_value (NMSetting *setting,
 			}
 		}
 	} else if (G_VALUE_HOLDS_ENUM (value)) {
-		int int_val;
+		gint int_val;
 
 		int_val = nm_keyfile_plugin_kf_get_integer (keyfile, setting_name, key, &err);
 		if (!err)
-			g_object_set (setting, key, (int) int_val, NULL);
+			g_object_set (setting, key, (gint) int_val, NULL);
 	} else {
 		if (!handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN,
 		                 _("unhandled setting property type '%s'"),
@@ -2696,8 +2596,6 @@ read_one_setting_value (NMSetting *setting,
 static NMSetting *
 read_setting (KeyfileReaderInfo *info)
 {
-	const NMSettInfoSetting *sett_info;
-	gs_unref_object NMSetting *setting = NULL;
 	const char *alias;
 	GType type;
 
@@ -2706,92 +2604,22 @@ read_setting (KeyfileReaderInfo *info)
 		alias = info->group;
 
 	type = nm_setting_lookup_type (alias);
-	if (!type) {
-		handle_warn (info, NULL, NM_KEYFILE_WARN_SEVERITY_WARN,
-		             _("invalid setting name '%s'"), info->group);
-		return NULL;
-	}
+	if (type) {
+		NMSetting *setting = g_object_new (type, NULL);
 
-	setting = g_object_new (type, NULL);
-
-	info->setting = setting;
-
-	sett_info = _nm_sett_info_setting_get (NM_SETTING_GET_CLASS (setting));
-
-	if (sett_info->detail.gendata_info) {
-		gs_free char **keys = NULL;
-		gsize i, n_keys;
-
-		keys = g_key_file_get_keys (info->keyfile, info->group, &n_keys, NULL);
-		if (n_keys > 0) {
-			GHashTable *h = _nm_setting_gendata_hash (setting, TRUE);
-
-			nm_utils_strv_sort (keys, n_keys);
-			for (i = 0; i < n_keys; i++) {
-				gs_free char *key = keys[i];
-				gs_free_error GError *local = NULL;
-				const GVariantType *variant_type;
-				GVariant *variant;
-
-				/* a GKeyfile can return duplicate keys, there is just no API to make sense
-				 * of them. Skip them. */
-				if (   i + 1 < n_keys
-				    && nm_streq (key, keys[i + 1]))
-					continue;
-
-				/* currently, the API is very simple. The setting class just returns
-				 * the desired variant type, and keyfile reader will try to parse
-				 * it accordingly. Note, that this does currently not allow, that
-				 * a particular key can contain different variant types, nor is it
-				 * very flexible in general.
-				 *
-				 * We add flexibility when we need it. Keep it simple for now. */
-				variant_type = sett_info->detail.gendata_info->get_variant_type (sett_info,
-				                                                                 key,
-				                                                                 &local);
-				if (!variant_type) {
-					if (!handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN,
-					                  _("invalid key '%s.%s'"),
-					                  info->group, key))
-						break;
-					continue;
-				}
-
-				if (g_variant_type_equal (variant_type, G_VARIANT_TYPE_BOOLEAN)) {
-					gboolean v;
-
-					v = g_key_file_get_boolean (info->keyfile,
-					                            info->group,
-					                            key,
-					                            &local);
-					if (local) {
-						if (!handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN,
-						                  _("key '%s.%s' is not boolean"),
-						                  info->group, key))
-							break;
-						continue;
-					}
-					variant = g_variant_new_boolean (v);
-				} else {
-					nm_assert_not_reached ();
-					continue;
-				}
-
-				g_hash_table_insert (h,
-				                     g_steal_pointer (&key),
-				                     g_variant_take_ref (variant));
-			}
-			for (; i < n_keys; i++)
-				g_free (keys[i]);
-		}
-	} else
+		info->setting = setting;
 		nm_setting_enumerate_values (setting, read_one_setting_value, info);
+		info->setting = NULL;
+		if (!info->error)
+			return setting;
 
-	info->setting = NULL;
+		g_object_unref (setting);
+	} else {
+		handle_warn (info, NULL, NM_KEYFILE_WARN_SEVERITY_WARN,
+		             _("invalid setting name '%s'"), info->group);
+	}
 
-	if (info->error)
-		return NULL;
-	return g_steal_pointer (&setting);
+	return NULL;
 }
 
 static void
@@ -2846,7 +2674,7 @@ nm_keyfile_read (GKeyFile *keyfile,
 	gs_unref_object NMConnection *connection = NULL;
 	NMSettingConnection *s_con;
 	NMSetting *setting;
-	char **groups;
+	gchar **groups;
 	gsize length;
 	int i;
 	gboolean vpn_secrets = FALSE;
@@ -2866,7 +2694,7 @@ nm_keyfile_read (GKeyFile *keyfile,
 			base_dir = base_dir_free = g_get_current_dir ();
 		}
 	} else
-		g_return_val_if_fail (base_dir[0] == '/', NULL);
+		g_return_val_if_fail ("/", NULL);
 
 	connection = nm_simple_connection_new ();
 
@@ -2972,22 +2800,12 @@ write_setting_value (NMSetting *setting,
 	if (info->error)
 		return;
 
+	setting_name = nm_setting_get_name (setting);
+
 	pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (setting), key);
 	nm_assert (pspec);
 
-	pip = _parse_info_find (setting, key, &setting_name);
-
-	if (!setting_name) {
-		/* the setting type is unknown. That is highly unexpected
-		 * (and as this is currently only called from NetworkManager
-		 * daemon, not possible).
-		 *
-		 * Still, handle it gracefully, because later keyfile writer will become
-		 * public API of libnm, where @setting is (untrusted) user input.
-		 *
-		 * Gracefully here just means: ignore the setting. */
-		return;
-	}
+	pip = _parse_info_find (setting_name, key);
 
 	if (   !pip
 	    && nm_streq (key, NM_SETTING_NAME))
@@ -3061,7 +2879,7 @@ write_setting_value (NMSetting *setting,
 		char **array;
 
 		array = (char **) g_value_get_boxed (value);
-		nm_keyfile_plugin_kf_set_string_list (info->keyfile, setting_name, key, (const char **const) array, g_strv_length (array));
+		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 == G_TYPE_ARRAY) {
@@ -3070,7 +2888,7 @@ write_setting_value (NMSetting *setting,
 		/* 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, (int) g_value_get_enum (value));
+		nm_keyfile_plugin_kf_set_integer (info->keyfile, setting_name, key, (gint) g_value_get_enum (value));
 	else
 		g_warn_if_reached ();
 }
@@ -3082,8 +2900,6 @@ nm_keyfile_write (NMConnection *connection,
                   GError **error)
 {
 	KeyfileWriterInfo info = { 0 };
-	gs_free NMSetting **settings = NULL;
-	guint i, length = 0;
 
 	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
 	g_return_val_if_fail (!error || !*error, NULL);
@@ -3096,59 +2912,12 @@ nm_keyfile_write (NMConnection *connection,
 	info.error = NULL;
 	info.handler = handler;
 	info.user_data = user_data;
-
-	settings = nm_connection_get_settings (connection, &length);
-	for (i = 0; i < length; i++) {
-		const NMSettInfoSetting *sett_info;
-		NMSetting *setting = settings[i];
-
-		sett_info = _nm_sett_info_setting_get (NM_SETTING_GET_CLASS (setting));
-
-		if (sett_info->detail.gendata_info) {
-			guint k, n_keys;
-			const char *const*keys;
-
-			nm_assert (!nm_keyfile_plugin_get_alias_for_setting_name (sett_info->setting_class->setting_info->setting_name));
-
-			n_keys = _nm_setting_gendata_get_all (setting, &keys, NULL);
-
-			if (n_keys > 0) {
-				const char *setting_name = sett_info->setting_class->setting_info->setting_name;
-				GHashTable *h = _nm_setting_gendata_hash (setting, FALSE);
-
-				for (k = 0; k < n_keys; k++) {
-					const char *key = keys[k];
-					GVariant *v;
-
-					v = g_hash_table_lookup (h, key);
-
-					if (g_variant_is_of_type (v, G_VARIANT_TYPE_BOOLEAN)) {
-						g_key_file_set_boolean (info.keyfile,
-						                        setting_name,
-						                        key,
-						                        g_variant_get_boolean (v));
-					} else {
-						/* BUG: The variant type is not implemented. Since the connection
-						 * verifies, this can only mean we either wrongly didn't reject
-						 * the connection as invalid, or we didn't properly implement the
-						 * variant type. */
-						nm_assert_not_reached ();
-						continue;
-					}
-				}
-			}
-		} else
-			nm_setting_enumerate_values (setting, write_setting_value, &info);
-
-		if (info.error)
-			break;
-	}
+	nm_connection_for_each_setting_value (connection, write_setting_value, &info);
 
 	if (info.error) {
 		g_propagate_error (error, info.error);
 		g_key_file_unref (info.keyfile);
 		return NULL;
 	}
-
 	return info.keyfile;
 }
diff --git a/libnm-core/nm-property-compare.c b/libnm-core/nm-property-compare.c
index 2a3ee397..64ed663c 100644
--- a/libnm-core/nm-property-compare.c
+++ b/libnm-core/nm-property-compare.c
@@ -27,7 +27,7 @@
 
 #include "nm-property-compare.h"
 
-static int
+static gint
 _nm_property_compare_collection (GVariant *value1, GVariant *value2)
 {
 	GVariant *child1, *child2;
@@ -55,7 +55,7 @@ _nm_property_compare_collection (GVariant *value1, GVariant *value2)
 	return 0;
 }
 
-static int
+static gint
 _nm_property_compare_vardict (GVariant *value1, GVariant *value2)
 {
 	GVariantIter iter;
@@ -87,7 +87,7 @@ _nm_property_compare_vardict (GVariant *value1, GVariant *value2)
 	return 0;
 }
 
-static int
+static gint
 _nm_property_compare_strdict (GVariant *value1, GVariant *value2)
 {
 	GVariantIter iter;
@@ -119,7 +119,7 @@ nm_property_compare (GVariant *value1, GVariant *value2)
 {
 	const GVariantType *type1;
 	const GVariantType *type2;
-	int ret;
+	gint ret;
 
 	if (value1 == value2)
 		return 0;
diff --git a/libnm-core/nm-setting-6lowpan.c b/libnm-core/nm-setting-6lowpan.c
deleted file mode 100644
index c0ce232d..00000000
--- a/libnm-core/nm-setting-6lowpan.c
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA.
- *
- * Copyright 2018 Red Hat, Inc.
- */
-
-#include "nm-default.h"
-
-#include "nm-setting-private.h"
-#include "nm-setting-6lowpan.h"
-
-NM_GOBJECT_PROPERTIES_DEFINE_BASE (
-	PROP_PARENT,
-);
-
-typedef struct {
-	char *parent;
-} NMSetting6LowpanPrivate;
-
-/**
- * NMSetting6Lowpan:
- *
- * 6LoWPAN Settings
- */
-struct _NMSetting6Lowpan {
-	NMSetting parent;
-};
-
-struct _NMSetting6LowpanClass {
-	NMSettingClass parent;
-};
-
-/**
- * SECTION:nm-setting-6lowpan
- * @short_description: Describes connection properties for 6LoWPAN interfaces
- *
- * The #NMSetting6Lowpan object is a #NMSetting subclass that describes properties
- * necessary for connection to 6LoWPAN interfaces.
- **/
-
-G_DEFINE_TYPE (NMSetting6Lowpan, nm_setting_6lowpan, NM_TYPE_SETTING)
-
-#define NM_SETTING_6LOWPAN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_6LOWPAN, NMSetting6LowpanPrivate))
-
-
-/**
- * nm_setting_6lowpan_new:
- *
- * Creates a new #NMSetting6Lowpan object with default values.
- *
- * Returns: (transfer full): the new empty #NMSetting6Lowpan object
- *
- * Since: 1.14
- **/
-NMSetting *
-nm_setting_6lowpan_new (void)
-{
-	return (NMSetting *) g_object_new (NM_TYPE_SETTING_6LOWPAN, NULL);
-}
-
-/**
- * nm_setting_6lowpan_get_parent:
- * @setting: the #NMSetting6Lowpan
- *
- * Returns: the #NMSetting6Lowpan:parent property of the setting
- *
- * Since: 1.14
- **/
-const char *
-nm_setting_6lowpan_get_parent (NMSetting6Lowpan *setting)
-{
-	g_return_val_if_fail (NM_IS_SETTING_6LOWPAN (setting), NULL);
-	return NM_SETTING_6LOWPAN_GET_PRIVATE (setting)->parent;
-}
-
-/*********************************************************************/
-
-static gboolean
-verify (NMSetting *setting, NMConnection *connection, GError **error)
-{
-	NMSetting6LowpanPrivate *priv = NM_SETTING_6LOWPAN_GET_PRIVATE (setting);
-	NMSettingConnection *s_con = NULL;
-
-	if (connection)
-		s_con = nm_connection_get_setting_connection (connection);
-
-	if (!priv->parent) {
-		g_set_error (error,
-		             NM_CONNECTION_ERROR,
-		             NM_CONNECTION_ERROR_MISSING_PROPERTY,
-		             _("property is not specified"));
-		g_prefix_error (error, "%s.%s: ", NM_SETTING_6LOWPAN_SETTING_NAME, NM_SETTING_6LOWPAN_PARENT);
-		return FALSE;
-	}
-
-
-
-	if (nm_utils_is_uuid (priv->parent)) {
-		/* If we have an NMSettingConnection:master with slave-type="6lowpan",
-		 * then it must be the same UUID.
-		 */
-		if (s_con) {
-			const char *master = NULL, *slave_type = NULL;
-
-			slave_type = nm_setting_connection_get_slave_type (s_con);
-			if (!g_strcmp0 (slave_type, NM_SETTING_6LOWPAN_SETTING_NAME))
-				master = nm_setting_connection_get_master (s_con);
-
-			if (master && g_strcmp0 (priv->parent, master) != 0) {
-				g_set_error (error,
-				             NM_CONNECTION_ERROR,
-				             NM_CONNECTION_ERROR_INVALID_PROPERTY,
-				             _("'%s' value doesn't match '%s=%s'"),
-				             priv->parent, NM_SETTING_CONNECTION_MASTER, master);
-				g_prefix_error (error, "%s.%s: ", NM_SETTING_6LOWPAN_SETTING_NAME, NM_SETTING_6LOWPAN_PARENT);
-				return FALSE;
-			}
-		}
-	} else if (!nm_utils_iface_valid_name (priv->parent)) {
-		/* parent must be either a UUID or an interface name */
-		g_set_error (error,
-		             NM_CONNECTION_ERROR,
-		             NM_CONNECTION_ERROR_INVALID_PROPERTY,
-		             _("'%s' is neither an UUID nor an interface name"),
-		             priv->parent);
-		g_prefix_error (error, "%s.%s: ", NM_SETTING_6LOWPAN_SETTING_NAME, NM_SETTING_6LOWPAN_PARENT);
-		return FALSE;
-	}
-
-	return TRUE;
-}
-
-static void
-nm_setting_6lowpan_init (NMSetting6Lowpan *setting)
-{
-}
-
-static void
-set_property (GObject *object, guint prop_id,
-              const GValue *value, GParamSpec *pspec)
-{
-	NMSetting6Lowpan *setting = NM_SETTING_6LOWPAN (object);
-	NMSetting6LowpanPrivate *priv = NM_SETTING_6LOWPAN_GET_PRIVATE (setting);
-
-	switch (prop_id) {
-	case PROP_PARENT:
-		g_free (priv->parent);
-		priv->parent = g_value_dup_string (value);
-		break;
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-		break;
-	}
-}
-
-static void
-get_property (GObject *object, guint prop_id,
-              GValue *value, GParamSpec *pspec)
-{
-	NMSetting6Lowpan *setting = NM_SETTING_6LOWPAN (object);
-	NMSetting6LowpanPrivate *priv = NM_SETTING_6LOWPAN_GET_PRIVATE (setting);
-
-	switch (prop_id) {
-	case PROP_PARENT:
-		g_value_set_string (value, priv->parent);
-		break;
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-		break;
-	}
-}
-
-static void
-finalize (GObject *object)
-{
-	NMSetting6Lowpan *setting = NM_SETTING_6LOWPAN (object);
-	NMSetting6LowpanPrivate *priv = NM_SETTING_6LOWPAN_GET_PRIVATE (setting);
-
-	g_free (priv->parent);
-
-	G_OBJECT_CLASS (nm_setting_6lowpan_parent_class)->finalize (object);
-}
-
-static void
-nm_setting_6lowpan_class_init (NMSetting6LowpanClass *klass)
-{
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	NMSettingClass *setting_class = NM_SETTING_CLASS (klass);
-
-	g_type_class_add_private (klass, sizeof (NMSetting6LowpanPrivate));
-
-	object_class->set_property = set_property;
-	object_class->get_property = get_property;
-	object_class->finalize     = finalize;
-
-	setting_class->verify = verify;
-
-	/**
-	 * NMSetting6Lowpan:parent:
-	 *
-	 * If given, specifies the parent interface name or parent connection UUID
-	 * from which this 6LowPAN interface should be created.
-	 *
-	 * Since: 1.14
-	 **/
-	obj_properties[PROP_PARENT] =
-	    g_param_spec_string (NM_SETTING_6LOWPAN_PARENT, "", "",
-	                         NULL,
-	                         G_PARAM_READWRITE |
-	                         G_PARAM_CONSTRUCT |
-	                         NM_SETTING_PARAM_INFERRABLE |
-	                         G_PARAM_STATIC_STRINGS);
-
-	g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
-
-	_nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_6LOWPAN);
-}
diff --git a/libnm-core/nm-setting-6lowpan.h b/libnm-core/nm-setting-6lowpan.h
deleted file mode 100644
index 73f57b7c..00000000
--- a/libnm-core/nm-setting-6lowpan.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA.
- *
- * Copyright 2018 Red Hat, Inc.
- */
-
-#ifndef __NM_SETTING_6LOWPAN_H__
-#define __NM_SETTING_6LOWPAN_H__
-
-#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION)
-#error "Only <NetworkManager.h> can be included directly."
-#endif
-
-#include "nm-setting.h"
-
-G_BEGIN_DECLS
-
-#define NM_TYPE_SETTING_6LOWPAN            (nm_setting_6lowpan_get_type ())
-#define NM_SETTING_6LOWPAN(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_6LOWPAN, NMSetting6Lowpan))
-#define NM_SETTING_6LOWPAN_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_6LOWPANCONFIG, NMSetting6LowpanClass))
-#define NM_IS_SETTING_6LOWPAN(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_6LOWPAN))
-#define NM_IS_SETTING_6LOWPAN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_6LOWPAN))
-#define NM_SETTING_6LOWPAN_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_6LOWPAN, NMSetting6LowpanClass))
-
-#define NM_SETTING_6LOWPAN_SETTING_NAME         "6lowpan"
-
-#define NM_SETTING_6LOWPAN_PARENT               "parent"
-
-typedef struct _NMSetting6LowpanClass NMSetting6LowpanClass;
-
-NM_AVAILABLE_IN_1_14
-GType nm_setting_6lowpan_get_type (void);
-NM_AVAILABLE_IN_1_14
-NMSetting *nm_setting_6lowpan_new (void);
-
-NM_AVAILABLE_IN_1_14
-const char *nm_setting_6lowpan_get_parent (NMSetting6Lowpan *setting);
-
-G_END_DECLS
-
-#endif /* __NM_SETTING_6LOWPAN_H__ */
diff --git a/libnm-core/nm-setting-8021x.c b/libnm-core/nm-setting-8021x.c
index 7e004c90..482cbbe2 100644
--- a/libnm-core/nm-setting-8021x.c
+++ b/libnm-core/nm-setting-8021x.c
@@ -26,9 +26,8 @@
 
 #include <string.h>
 
-#include "nm-utils/nm-secret-utils.h"
 #include "nm-utils.h"
-#include "nm-crypto.h"
+#include "crypto.h"
 #include "nm-utils-private.h"
 #include "nm-setting-private.h"
 #include "nm-core-enum-types.h"
@@ -61,89 +60,16 @@
  *       ISBN: 978-1587051548
  **/
 
-/*****************************************************************************/
+G_DEFINE_TYPE_WITH_CODE (NMSetting8021x, nm_setting_802_1x, NM_TYPE_SETTING,
+                         _nm_register_setting (802_1X, NM_SETTING_PRIORITY_HW_AUX))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_802_1X)
 
-static NMSetting8021xCKFormat
-_crypto_format_to_ck (NMCryptoFileFormat format)
-{
-	G_STATIC_ASSERT ( (NM_SETTING_802_1X_CK_FORMAT_UNKNOWN == (NMSetting8021xCKFormat) NM_CRYPTO_FILE_FORMAT_UNKNOWN) );
-	G_STATIC_ASSERT ( (NM_SETTING_802_1X_CK_FORMAT_X509    == (NMSetting8021xCKFormat) NM_CRYPTO_FILE_FORMAT_X509) );
-	G_STATIC_ASSERT ( (NM_SETTING_802_1X_CK_FORMAT_RAW_KEY == (NMSetting8021xCKFormat) NM_CRYPTO_FILE_FORMAT_RAW_KEY) );
-	G_STATIC_ASSERT ( (NM_SETTING_802_1X_CK_FORMAT_PKCS12  == (NMSetting8021xCKFormat) NM_CRYPTO_FILE_FORMAT_PKCS12) );
-
-	nm_assert (NM_IN_SET (format, NM_CRYPTO_FILE_FORMAT_UNKNOWN,
-	                              NM_CRYPTO_FILE_FORMAT_X509,
-	                              NM_CRYPTO_FILE_FORMAT_RAW_KEY,
-	                              NM_CRYPTO_FILE_FORMAT_PKCS12));
-	return (NMSetting8021xCKFormat) format;
-}
+#define NM_SETTING_802_1X_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_802_1X, NMSetting8021xPrivate))
 
-/*****************************************************************************/
-
-typedef void (*EAPMethodNeedSecretsFunc) (NMSetting8021x *self,
-                                          GPtrArray *secrets,
-                                          gboolean phase2);
-
-typedef gboolean (*EAPMethodValidateFunc)(NMSetting8021x *self,
-                                          gboolean phase2,
-                                          GError **error);
-
-typedef struct {
-	const char *method;
-	EAPMethodNeedSecretsFunc ns_func;
-	EAPMethodValidateFunc v_func;
-} EAPMethodsTable;
-
-static EAPMethodsTable eap_methods_table[];
-
-/*****************************************************************************/
-
-NM_GOBJECT_PROPERTIES_DEFINE (NMSetting8021x,
-	PROP_EAP,
-	PROP_IDENTITY,
-	PROP_ANONYMOUS_IDENTITY,
-	PROP_PAC_FILE,
-	PROP_CA_CERT,
-	PROP_CA_CERT_PASSWORD,
-	PROP_CA_CERT_PASSWORD_FLAGS,
-	PROP_CA_PATH,
-	PROP_SUBJECT_MATCH,
-	PROP_ALTSUBJECT_MATCHES,
-	PROP_DOMAIN_SUFFIX_MATCH,
-	PROP_CLIENT_CERT,
-	PROP_CLIENT_CERT_PASSWORD,
-	PROP_CLIENT_CERT_PASSWORD_FLAGS,
-	PROP_PHASE1_PEAPVER,
-	PROP_PHASE1_PEAPLABEL,
-	PROP_PHASE1_FAST_PROVISIONING,
-	PROP_PHASE1_AUTH_FLAGS,
-	PROP_PHASE2_AUTH,
-	PROP_PHASE2_AUTHEAP,
-	PROP_PHASE2_CA_CERT,
-	PROP_PHASE2_CA_CERT_PASSWORD,
-	PROP_PHASE2_CA_CERT_PASSWORD_FLAGS,
-	PROP_PHASE2_CA_PATH,
-	PROP_PHASE2_SUBJECT_MATCH,
-	PROP_PHASE2_ALTSUBJECT_MATCHES,
-	PROP_PHASE2_DOMAIN_SUFFIX_MATCH,
-	PROP_PHASE2_CLIENT_CERT,
-	PROP_PHASE2_CLIENT_CERT_PASSWORD,
-	PROP_PHASE2_CLIENT_CERT_PASSWORD_FLAGS,
-	PROP_PASSWORD,
-	PROP_PASSWORD_FLAGS,
-	PROP_PASSWORD_RAW,
-	PROP_PASSWORD_RAW_FLAGS,
-	PROP_PRIVATE_KEY,
-	PROP_PRIVATE_KEY_PASSWORD,
-	PROP_PRIVATE_KEY_PASSWORD_FLAGS,
-	PROP_PHASE2_PRIVATE_KEY,
-	PROP_PHASE2_PRIVATE_KEY_PASSWORD,
-	PROP_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS,
-	PROP_PIN,
-	PROP_PIN_FLAGS,
-	PROP_SYSTEM_CA_CERTS,
-	PROP_AUTH_TIMEOUT,
-);
+G_STATIC_ASSERT ( (NM_SETTING_802_1X_CK_FORMAT_UNKNOWN == (NMSetting8021xCKFormat) NM_CRYPTO_FILE_FORMAT_UNKNOWN) );
+G_STATIC_ASSERT ( (NM_SETTING_802_1X_CK_FORMAT_X509    == (NMSetting8021xCKFormat) NM_CRYPTO_FILE_FORMAT_X509) );
+G_STATIC_ASSERT ( (NM_SETTING_802_1X_CK_FORMAT_RAW_KEY == (NMSetting8021xCKFormat) NM_CRYPTO_FILE_FORMAT_RAW_KEY) );
+G_STATIC_ASSERT ( (NM_SETTING_802_1X_CK_FORMAT_PKCS12  == (NMSetting8021xCKFormat) NM_CRYPTO_FILE_FORMAT_PKCS12) );
 
 typedef struct {
 	GSList *eap; /* GSList of strings */
@@ -189,512 +115,70 @@ typedef struct {
 	char *phase2_private_key_password;
 	NMSettingSecretFlags phase2_private_key_password_flags;
 	gboolean system_ca_certs;
-	int auth_timeout;
+	gint auth_timeout;
 } NMSetting8021xPrivate;
 
-G_DEFINE_TYPE (NMSetting8021x, nm_setting_802_1x, NM_TYPE_SETTING)
-
-#define NM_SETTING_802_1X_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_802_1X, NMSetting8021xPrivate))
+enum {
+	PROP_0,
+	PROP_EAP,
+	PROP_IDENTITY,
+	PROP_ANONYMOUS_IDENTITY,
+	PROP_PAC_FILE,
+	PROP_CA_CERT,
+	PROP_CA_CERT_PASSWORD,
+	PROP_CA_CERT_PASSWORD_FLAGS,
+	PROP_CA_PATH,
+	PROP_SUBJECT_MATCH,
+	PROP_ALTSUBJECT_MATCHES,
+	PROP_DOMAIN_SUFFIX_MATCH,
+	PROP_CLIENT_CERT,
+	PROP_CLIENT_CERT_PASSWORD,
+	PROP_CLIENT_CERT_PASSWORD_FLAGS,
+	PROP_PHASE1_PEAPVER,
+	PROP_PHASE1_PEAPLABEL,
+	PROP_PHASE1_FAST_PROVISIONING,
+	PROP_PHASE1_AUTH_FLAGS,
+	PROP_PHASE2_AUTH,
+	PROP_PHASE2_AUTHEAP,
+	PROP_PHASE2_CA_CERT,
+	PROP_PHASE2_CA_CERT_PASSWORD,
+	PROP_PHASE2_CA_CERT_PASSWORD_FLAGS,
+	PROP_PHASE2_CA_PATH,
+	PROP_PHASE2_SUBJECT_MATCH,
+	PROP_PHASE2_ALTSUBJECT_MATCHES,
+	PROP_PHASE2_DOMAIN_SUFFIX_MATCH,
+	PROP_PHASE2_CLIENT_CERT,
+	PROP_PHASE2_CLIENT_CERT_PASSWORD,
+	PROP_PHASE2_CLIENT_CERT_PASSWORD_FLAGS,
+	PROP_PASSWORD,
+	PROP_PASSWORD_FLAGS,
+	PROP_PASSWORD_RAW,
+	PROP_PASSWORD_RAW_FLAGS,
+	PROP_PRIVATE_KEY,
+	PROP_PRIVATE_KEY_PASSWORD,
+	PROP_PRIVATE_KEY_PASSWORD_FLAGS,
+	PROP_PHASE2_PRIVATE_KEY,
+	PROP_PHASE2_PRIVATE_KEY_PASSWORD,
+	PROP_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS,
+	PROP_PIN,
+	PROP_PIN_FLAGS,
+	PROP_SYSTEM_CA_CERTS,
+	PROP_AUTH_TIMEOUT,
 
-/*****************************************************************************/
+	LAST_PROP
+};
 
 /**
- * nm_setting_802_1x_check_cert_scheme:
- * @pdata: (allow-none): the data pointer
- * @length: the length of the data
- * @error: (allow-none): (out): validation reason
- *
- * Determines and verifies the blob type.
- * When setting certificate properties of NMSetting8021x
- * the blob must be not UNKNOWN (or NULL).
+ * nm_setting_802_1x_new:
  *
- * Returns: the scheme of the blob or %NM_SETTING_802_1X_CK_SCHEME_UNKNOWN.
- * For NULL it also returns NM_SETTING_802_1X_CK_SCHEME_UNKNOWN.
+ * Creates a new #NMSetting8021x object with default values.
  *
- * Since: 1.2
+ * Returns: the new empty #NMSetting8021x object
  **/
-NMSetting8021xCKScheme
-nm_setting_802_1x_check_cert_scheme (gconstpointer pdata, gsize length, GError **error)
-{
-	const char *data = pdata;
-	NMSetting8021xCKScheme scheme;
-	gsize prefix_length;
-
-	g_return_val_if_fail (!length || data, NM_SETTING_802_1X_CK_SCHEME_UNKNOWN);
-
-	if (!length || !data) {
-		g_set_error_literal (error,
-		                     NM_CONNECTION_ERROR,
-		                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
-		                     _("binary data missing"));
-		return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN;
-	}
-
-	if (   length >= NM_STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH)
-	    && !memcmp (data, NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH, NM_STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH))) {
-		scheme = NM_SETTING_802_1X_CK_SCHEME_PATH;
-		prefix_length = NM_STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH);
-	} else if (   length >= NM_STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PKCS11)
-	           && !memcmp (data, NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PKCS11, NM_STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PKCS11))) {
-		scheme = NM_SETTING_802_1X_CK_SCHEME_PKCS11;
-		prefix_length = NM_STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PKCS11);
-	} else {
-		scheme = NM_SETTING_802_1X_CK_SCHEME_BLOB;
-		prefix_length = 0;
-	}
-
-	if (scheme != NM_SETTING_802_1X_CK_SCHEME_BLOB) {
-		/* An actual URI must be NUL terminated, contain at least
-		 * one non-NUL character, and contain only one trailing NUL
-		 * chracter.
-		 * And ensure it's UTF-8 valid too so we can pass it through
-		 * D-Bus and stuff like that. */
-
-		if (data[length - 1] != '\0') {
-			g_set_error_literal (error,
-			                     NM_CONNECTION_ERROR,
-			                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
-			                     _("URI not NUL terminated"));
-			return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN;
-		}
-		length--;
-
-		if (length <= prefix_length) {
-			g_set_error_literal (error,
-			                     NM_CONNECTION_ERROR,
-			                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
-			                     _("URI is empty"));
-			return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN;
-		}
-
-		if (!g_utf8_validate (data + prefix_length, length - prefix_length, NULL)) {
-			g_set_error_literal (error,
-			                     NM_CONNECTION_ERROR,
-			                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
-			                     _("URI is not valid UTF-8"));
-			return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN;
-		}
-	}
-
-	return scheme;
-}
-
-NMSetting8021xCKScheme
-_nm_setting_802_1x_cert_get_scheme (GBytes *bytes, GError **error)
-{
-	const char *data;
-	gsize length;
-
-	if (!bytes) {
-		g_set_error_literal (error,
-		                     NM_CONNECTION_ERROR,
-		                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
-		                     _("data missing"));
-		return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN;
-	}
-
-	data = g_bytes_get_data (bytes, &length);
-	return nm_setting_802_1x_check_cert_scheme (data, length, error);
-}
-
-static gboolean
-_cert_verify_scheme (NMSetting8021xCKScheme scheme,
-                     GBytes *bytes,
-                     GError **error)
-{
-	GError *local = NULL;
-	NMSetting8021xCKScheme scheme_detected;
-
-	nm_assert (bytes);
-
-	scheme_detected = _nm_setting_802_1x_cert_get_scheme (bytes, &local);
-	if (scheme_detected == NM_SETTING_802_1X_CK_SCHEME_UNKNOWN) {
-		g_set_error (error,
-		             NM_CONNECTION_ERROR,
-		             NM_CONNECTION_ERROR_INVALID_PROPERTY,
-		             _("certificate is invalid: %s"), local->message);
-		return FALSE;
-	}
-
-	if (scheme_detected != scheme) {
-		g_set_error (error,
-		             NM_CONNECTION_ERROR,
-		             NM_CONNECTION_ERROR_INVALID_PROPERTY,
-		             _("certificate detected as invalid scheme"));
-		return FALSE;
-	}
-
-	return TRUE;
-}
-
-GBytes *
-_nm_setting_802_1x_cert_value_to_bytes (NMSetting8021xCKScheme scheme,
-                                        const guint8 *val_bin,
-                                        gssize val_len,
-                                        GError **error)
-{
-	gs_unref_bytes GBytes *bytes = NULL;
-	guint8 *mem;
-	gsize total_len;
-
-	nm_assert (val_bin);
-
-	switch (scheme) {
-	case NM_SETTING_802_1X_CK_SCHEME_PKCS11:
-		if (val_len < 0)
-			val_len = strlen ((char *) val_bin) + 1;
-
-		bytes = g_bytes_new (val_bin, val_len);
-		break;
-	case NM_SETTING_802_1X_CK_SCHEME_PATH:
-		if (val_len < 0)
-			val_len = strlen ((char *) val_bin) + 1;
-
-		total_len = NM_STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH) + ((gsize) val_len);
-
-		mem = g_new (guint8, total_len);
-		memcpy (mem, NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH, NM_STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH));
-		memcpy (&mem[NM_STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH)], val_bin, val_len);
-		bytes = g_bytes_new_take (mem, total_len);
-		break;
-	default:
-		g_return_val_if_reached (NULL);
-	}
-
-	if (!_cert_verify_scheme (scheme, bytes, error))
-		return NULL;
-
-	return g_steal_pointer (&bytes);
-}
-
-static const char *
-_cert_get_path (GBytes *bytes)
-{
-	const guint8 *bin;
-
-	nm_assert (bytes);
-	nm_assert (g_bytes_get_size (bytes) >= NM_STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH));
-
-	bin = g_bytes_get_data (bytes, NULL);
-
-	nm_assert (bin);
-	nm_assert (bin[g_bytes_get_size (bytes) - 1] == '\0');
-	nm_assert (g_str_has_prefix ((const char *) bin, NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH));
-
-	return (const char *) &bin[NM_STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH)];
-}
-
-#define _cert_assert_scheme(cert, check_scheme, ret_val) \
-	G_STMT_START { \
-		NMSetting8021xCKScheme scheme; \
-		\
-		scheme = _nm_setting_802_1x_cert_get_scheme ((cert), NULL); \
-		if (scheme != check_scheme) { \
-			g_return_val_if_fail (scheme == check_scheme, ret_val); \
-			return ret_val; \
-		} \
-	} G_STMT_END
-
-#define _cert_impl_get_scheme(setting, cert_field) \
-	G_STMT_START { \
-		NMSetting8021x *const _setting = (setting); \
-		GBytes *_cert; \
-		\
-		g_return_val_if_fail (NM_IS_SETTING_802_1X (_setting), NM_SETTING_802_1X_CK_SCHEME_UNKNOWN); \
-		\
-		_cert = NM_SETTING_802_1X_GET_PRIVATE (_setting)->cert_field; \
-		\
-		return _nm_setting_802_1x_cert_get_scheme (_cert, NULL); \
-	} G_STMT_END
-
-#define _cert_impl_get_blob(setting, cert_field) \
-	G_STMT_START { \
-		NMSetting8021x *const _setting = (setting); \
-		GBytes *_cert; \
-		\
-		g_return_val_if_fail (NM_IS_SETTING_802_1X (_setting), NULL); \
-		\
-		_cert = NM_SETTING_802_1X_GET_PRIVATE (_setting)->cert_field; \
-		\
-		_cert_assert_scheme (_cert, NM_SETTING_802_1X_CK_SCHEME_BLOB, NULL); \
-		\
-		return _cert; \
-	} G_STMT_END
-
-#define _cert_impl_get_path(setting, cert_field) \
-	G_STMT_START { \
-		NMSetting8021x *const _setting = (setting); \
-		GBytes *_cert; \
-		\
-		g_return_val_if_fail (NM_IS_SETTING_802_1X (_setting), NULL); \
-		\
-		_cert = NM_SETTING_802_1X_GET_PRIVATE (_setting)->cert_field; \
-		\
-		_cert_assert_scheme (_cert, NM_SETTING_802_1X_CK_SCHEME_PATH, NULL); \
-		\
-		return _cert_get_path (_cert); \
-	} G_STMT_END
-
-#define _cert_impl_get_uri(setting, cert_field) \
-	G_STMT_START { \
-		NMSetting8021x *const _setting = (setting); \
-		GBytes *_cert; \
-		\
-		g_return_val_if_fail (NM_IS_SETTING_802_1X (_setting), NULL); \
-		\
-		_cert = NM_SETTING_802_1X_GET_PRIVATE (_setting)->cert_field; \
-		\
-		_cert_assert_scheme (_cert, NM_SETTING_802_1X_CK_SCHEME_PKCS11, NULL); \
-		\
-		return g_bytes_get_data (_cert, NULL); \
-	} G_STMT_END
-
-static gboolean
-_cert_impl_set (NMSetting8021x *setting,
-                _PropertyEnums property,
-                const char *value,
-                const char *password,
-                NMSetting8021xCKScheme scheme,
-                NMSetting8021xCKFormat *out_format,
-                GError **error)
-{
-	NMSetting8021xPrivate *priv;
-	NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
-	gs_unref_bytes GBytes *cert = NULL;
-	GBytes **p_cert = NULL;
-	GBytes **p_client_cert = NULL;
-	char **p_password = NULL;
-	_PropertyEnums notify_cert = property;
-	_PropertyEnums notify_password = PROP_0;
-	_PropertyEnums notify_client_cert = PROP_0;
-
-	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE);
-	g_return_val_if_fail (!error || !*error, FALSE);
-	if (value) {
-		g_return_val_if_fail (g_utf8_validate (value, -1, NULL), FALSE);
-		g_return_val_if_fail (NM_IN_SET (scheme, NM_SETTING_802_1X_CK_SCHEME_BLOB,
-		                                         NM_SETTING_802_1X_CK_SCHEME_PATH,
-		                                         NM_SETTING_802_1X_CK_SCHEME_PKCS11), FALSE);
-	}
-
-	if (!value) {
-		/* coerce password to %NULL. It should be already. */
-		password = NULL;
-	}
-
-	priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
-
-	if (!value) {
-		/* pass. */
-	} else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11) {
-		cert = _nm_setting_802_1x_cert_value_to_bytes (scheme, (guint8 *) value, -1, error);
-		if (!cert)
-			goto err;
-	} else {
-		gs_unref_bytes GBytes *file = NULL;
-
-		if (NM_IN_SET (property, PROP_PRIVATE_KEY,
-		                         PROP_PHASE2_PRIVATE_KEY)) {
-			file = nm_crypto_read_file (value, error);
-			if (!file)
-				goto err;
-			format = nm_crypto_verify_private_key_data (g_bytes_get_data (file, NULL),
-			                                            g_bytes_get_size (file),
-			                                            password,
-			                                            NULL,
-			                                            error);
-			if (format == NM_CRYPTO_FILE_FORMAT_UNKNOWN)
-				goto err;
-		} else {
-			if (!nm_crypto_load_and_verify_certificate (value, &format, &file, error))
-				goto err;
-		}
-
-		nm_assert (format != NM_CRYPTO_FILE_FORMAT_UNKNOWN);
-		nm_assert (file);
-
-		if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) {
-			cert = g_steal_pointer (&file);
-			if (!_cert_verify_scheme (scheme, cert, error))
-				goto err;
-		} else {
-			cert = _nm_setting_802_1x_cert_value_to_bytes (scheme, (guint8 *) value, -1, error);
-			if (!cert)
-				goto err;
-		}
-	}
-
-	switch (property) {
-	case PROP_CA_CERT:
-	case PROP_PHASE2_CA_CERT:
-		if (   value
-		    && scheme != NM_SETTING_802_1X_CK_SCHEME_PKCS11
-		    && format != NM_CRYPTO_FILE_FORMAT_X509) {
-			/* wpa_supplicant can only use raw x509 CA certs */
-			g_set_error_literal (error,
-			             NM_CONNECTION_ERROR,
-			             NM_CONNECTION_ERROR_INVALID_PROPERTY,
-			             _("CA certificate must be in X.509 format"));
-			goto err;
-		}
-		p_cert = (property == PROP_CA_CERT)
-		         ? &priv->ca_cert
-		         : &priv->phase2_ca_cert;
-		break;
-	case PROP_CLIENT_CERT:
-	case PROP_PHASE2_CLIENT_CERT:
-		if (   value
-		    && scheme != NM_SETTING_802_1X_CK_SCHEME_PKCS11
-		    && !NM_IN_SET (format, NM_CRYPTO_FILE_FORMAT_X509,
-		                           NM_CRYPTO_FILE_FORMAT_PKCS12)) {
-			g_set_error_literal (error,
-			                     NM_CONNECTION_ERROR,
-			                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
-			                     _("invalid certificate format"));
-			goto err;
-		}
-		p_cert = (property == PROP_CLIENT_CERT)
-		         ? &priv->client_cert
-		         : &priv->phase2_client_cert;
-		break;
-	case PROP_PRIVATE_KEY:
-		p_cert = &priv->private_key;
-		p_password = &priv->private_key_password;
-		p_client_cert = &priv->client_cert;
-		notify_password = PROP_PRIVATE_KEY_PASSWORD;
-		notify_client_cert = PROP_CLIENT_CERT;
-		break;
-	case PROP_PHASE2_PRIVATE_KEY:
-		p_cert = &priv->phase2_private_key;
-		p_password = &priv->phase2_private_key_password;
-		p_client_cert = &priv->phase2_client_cert;
-		notify_password = PROP_PHASE2_PRIVATE_KEY_PASSWORD;
-		notify_client_cert = PROP_PHASE2_CLIENT_CERT;
-		break;
-	default:
-		nm_assert_not_reached ();
-		break;
-	}
-
-	/* As required by NM and wpa_supplicant, set the client-cert
-	 * property to the same PKCS#12 data.
-	 */
-	if (   cert
-	    && p_client_cert
-	    && format == NM_CRYPTO_FILE_FORMAT_PKCS12
-	    && !nm_gbytes_equal0 (cert, *p_client_cert)) {
-		g_bytes_unref (*p_client_cert);
-		*p_client_cert = g_bytes_ref (cert);
-	} else
-		notify_client_cert = PROP_0;
-
-	if (   p_cert
-	    && !nm_gbytes_equal0 (cert, *p_cert)) {
-		g_bytes_unref (*p_cert);
-		*p_cert = g_steal_pointer (&cert);
-	} else
-		notify_cert = PROP_0;
-
-	if (   p_password
-	    && !nm_streq0 (password, *p_password)) {
-		nm_free_secret (*p_password);
-		*p_password = g_strdup (password);
-	} else
-		notify_password = PROP_0;
-
-	nm_gobject_notify_together (setting, notify_cert,
-	                                     notify_password,
-	                                     notify_client_cert);
-
-	NM_SET_OUT (out_format, _crypto_format_to_ck (format));
-	return TRUE;
-
-err:
-	g_prefix_error (error,
-	                "%s.%s: ",
-	                NM_SETTING_802_1X_SETTING_NAME,
-	                obj_properties[property]->name);
-	NM_SET_OUT (out_format, NM_SETTING_802_1X_CK_FORMAT_UNKNOWN);
-	return FALSE;
-}
-
-static NMSetting8021xCKFormat
-_cert_impl_get_key_format_from_bytes (GBytes *private_key)
-{
-	const char *path;
-	GError *error = NULL;
-
-	if (!private_key)
-		return NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
-
-	switch (_nm_setting_802_1x_cert_get_scheme (private_key, NULL)) {
-	case NM_SETTING_802_1X_CK_SCHEME_BLOB:
-		if (nm_crypto_is_pkcs12_data (g_bytes_get_data (private_key, NULL),
-		                              g_bytes_get_size (private_key),
-		                              NULL))
-			return NM_SETTING_802_1X_CK_FORMAT_PKCS12;
-		return NM_SETTING_802_1X_CK_FORMAT_RAW_KEY;
-	case NM_SETTING_802_1X_CK_SCHEME_PATH:
-		path = _cert_get_path (private_key);
-		if (nm_crypto_is_pkcs12_file (path, &error))
-			return NM_SETTING_802_1X_CK_FORMAT_PKCS12;
-		if (error && error->domain == G_FILE_ERROR) {
-			g_error_free (error);
-			return NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
-		}
-		g_error_free (error);
-		return NM_SETTING_802_1X_CK_FORMAT_RAW_KEY;
-	default:
-		break;
-	}
-
-	return NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
-}
-#define _cert_impl_get_key_format(setting, private_key_field) \
-	({ \
-		NMSetting8021x *_setting = (setting); \
-		NMSetting8021xPrivate *_priv; \
-		\
-		g_return_val_if_fail (NM_IS_SETTING_802_1X (_setting), NM_SETTING_802_1X_CK_FORMAT_UNKNOWN); \
-		\
-		_priv = NM_SETTING_802_1X_GET_PRIVATE (_setting); \
-		_cert_impl_get_key_format_from_bytes (_priv->private_key_field); \
-	})
-
-static gboolean
-_cert_verify_property (GBytes *bytes,
-                       const char *prop_name,
-                       const char *password,
-                       const char *password_prop_name,
-                       GError **error)
+NMSetting *
+nm_setting_802_1x_new (void)
 {
-	GError *local = NULL;
-	NMSetting8021xCKScheme scheme;
-
-	if (!bytes)
-		return TRUE;
-
-	scheme = _nm_setting_802_1x_cert_get_scheme (bytes, &local);
-	if (scheme == NM_SETTING_802_1X_CK_SCHEME_UNKNOWN) {
-		g_set_error (error,
-		             NM_CONNECTION_ERROR,
-		             NM_CONNECTION_ERROR_INVALID_PROPERTY,
-		             _("certificate is invalid: %s"), local->message);
-		g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, prop_name);
-		g_error_free (local);
-		return FALSE;
-	}
-
-	if (password && (scheme != NM_SETTING_802_1X_CK_SCHEME_PKCS11)) {
-		g_set_error (error,
-		             NM_CONNECTION_ERROR,
-		             NM_CONNECTION_ERROR_INVALID_PROPERTY,
-		             _("password is not supported when certificate is not on a PKCS#11 token"));
-		g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, password_prop_name);
-		return FALSE;
-	}
-
-	return TRUE;
+	return (NMSetting *) g_object_new (NM_TYPE_SETTING_802_1X, NULL);
 }
 
 /*****************************************************************************/
@@ -769,7 +253,7 @@ nm_setting_802_1x_add_eap_method (NMSetting8021x *setting, const char *eap)
 	}
 
 	priv->eap = g_slist_append (priv->eap, g_ascii_strdown (eap, -1));
-	_notify (setting, PROP_EAP);
+	g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_EAP);
 	return TRUE;
 }
 
@@ -794,7 +278,7 @@ nm_setting_802_1x_remove_eap_method (NMSetting8021x *setting, guint32 i)
 
 	g_free (elt->data);
 	priv->eap = g_slist_delete_link (priv->eap, elt);
-	_notify (setting, PROP_EAP);
+	g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_EAP);
 }
 
 /**
@@ -820,7 +304,7 @@ nm_setting_802_1x_remove_eap_method_by_value (NMSetting8021x *setting,
 	for (iter = priv->eap; iter; iter = g_slist_next (iter)) {
 		if (!strcmp (eap, (char *) iter->data)) {
 			priv->eap = g_slist_delete_link (priv->eap, iter);
-			_notify (setting, PROP_EAP);
+			g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_EAP);
 			return TRUE;
 		}
 	}
@@ -843,7 +327,7 @@ nm_setting_802_1x_clear_eap_methods (NMSetting8021x *setting)
 	priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
 	g_slist_free_full (priv->eap, g_free);
 	priv->eap = NULL;
-	_notify (setting, PROP_EAP);
+	g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_EAP);
 }
 
 /**
@@ -939,6 +423,134 @@ nm_setting_802_1x_get_system_ca_certs (NMSetting8021x *setting)
 	return NM_SETTING_802_1X_GET_PRIVATE (setting)->system_ca_certs;
 }
 
+static NMSetting8021xCKScheme
+get_cert_scheme (GBytes *bytes, GError **error)
+{
+	const char *data;
+	gsize length;
+
+	if (!bytes) {
+		g_set_error_literal (error,
+		                     NM_CONNECTION_ERROR,
+		                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
+		                     _("data missing"));
+		return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN;
+	}
+
+	data = g_bytes_get_data (bytes, &length);
+	return nm_setting_802_1x_check_cert_scheme (data, length, error);
+}
+
+/**
+ * nm_setting_802_1x_check_cert_scheme:
+ * @pdata: (allow-none): the data pointer
+ * @length: the length of the data
+ * @error: (allow-none): (out): validation reason
+ *
+ * Determines and verifies the blob type.
+ * When setting certificate properties of NMSetting8021x
+ * the blob must be not UNKNOWN (or NULL).
+ *
+ * Returns: the scheme of the blob or %NM_SETTING_802_1X_CK_SCHEME_UNKNOWN.
+ * For NULL it also returns NM_SETTING_802_1X_CK_SCHEME_UNKNOWN.
+ *
+ * Since: 1.2
+ **/
+NMSetting8021xCKScheme
+nm_setting_802_1x_check_cert_scheme (gconstpointer pdata, gsize length, GError **error)
+{
+	const char *data = pdata;
+	NMSetting8021xCKScheme scheme;
+	gsize prefix_length;
+
+	g_return_val_if_fail (!length || data, NM_SETTING_802_1X_CK_SCHEME_UNKNOWN);
+
+	if (!length || !data) {
+		g_set_error_literal (error,
+		                     NM_CONNECTION_ERROR,
+		                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
+		                     _("binary data missing"));
+		return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN;
+	}
+
+	if (   length >= NM_STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH)
+	    && !memcmp (data, NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH, NM_STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH))) {
+		scheme = NM_SETTING_802_1X_CK_SCHEME_PATH;
+		prefix_length = NM_STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH);
+	} else if (   length >= NM_STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PKCS11)
+	           && !memcmp (data, NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PKCS11, NM_STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PKCS11))) {
+		scheme = NM_SETTING_802_1X_CK_SCHEME_PKCS11;
+		prefix_length = NM_STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PKCS11);
+	} else {
+		scheme = NM_SETTING_802_1X_CK_SCHEME_BLOB;
+		prefix_length = 0;
+	}
+
+	if (scheme != NM_SETTING_802_1X_CK_SCHEME_BLOB) {
+		/* An actual URI must be NUL terminated, contain at least
+		 * one non-NUL character, and contain only one trailing NUL
+		 * chracter.
+		 * And ensure it's UTF-8 valid too so we can pass it through
+		 * D-Bus and stuff like that. */
+
+		if (data[length - 1] != '\0') {
+			g_set_error_literal (error,
+			                     NM_CONNECTION_ERROR,
+			                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
+			                     _("URI not NUL terminated"));
+			return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN;
+		}
+		length--;
+
+		if (length <= prefix_length) {
+			g_set_error_literal (error,
+			                     NM_CONNECTION_ERROR,
+			                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
+			                     _("URI is empty"));
+			return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN;
+		}
+
+		if (!g_utf8_validate (data + prefix_length, length - prefix_length, NULL)) {
+			g_set_error_literal (error,
+					     NM_CONNECTION_ERROR,
+					     NM_CONNECTION_ERROR_INVALID_PROPERTY,
+					     _("URI is not valid UTF-8"));
+			return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN;
+		}
+	}
+
+	return scheme;
+}
+
+static GByteArray *
+load_and_verify_certificate (const char *cert_path,
+                             NMSetting8021xCKScheme scheme,
+                             NMCryptoFileFormat *out_file_format,
+                             GError **error)
+{
+	NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
+	GByteArray *array;
+
+	array = crypto_load_and_verify_certificate (cert_path, &format, error);
+
+	if (!array || !array->len || format == NM_CRYPTO_FILE_FORMAT_UNKNOWN) {
+		/* the array is empty or the format is already unknown. */
+		format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
+	} else if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) {
+		/* If we load the file as blob, we must ensure that the binary data does not
+		 * start with file://. NMSetting8021x cannot represent blobs that start with
+		 * file://.
+		 * If that's the case, coerce the format to UNKNOWN. The callers will take care
+		 * of that and not set the blob. */
+		if (nm_setting_802_1x_check_cert_scheme (array->data, array->len, NULL) != NM_SETTING_802_1X_CK_SCHEME_BLOB)
+			format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
+	}
+
+	if (out_file_format)
+		*out_file_format = format;
+	return array;
+}
+
 /**
  * nm_setting_802_1x_get_ca_cert_scheme:
  * @setting: the #NMSetting8021x
@@ -953,7 +565,9 @@ nm_setting_802_1x_get_system_ca_certs (NMSetting8021x *setting)
 NMSetting8021xCKScheme
 nm_setting_802_1x_get_ca_cert_scheme (NMSetting8021x *setting)
 {
-	_cert_impl_get_scheme (setting, ca_cert);
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_SCHEME_UNKNOWN);
+
+	return get_cert_scheme (NM_SETTING_802_1X_GET_PRIVATE (setting)->ca_cert, NULL);
 }
 
 /**
@@ -972,7 +586,14 @@ nm_setting_802_1x_get_ca_cert_scheme (NMSetting8021x *setting)
 GBytes *
 nm_setting_802_1x_get_ca_cert_blob (NMSetting8021x *setting)
 {
-	_cert_impl_get_blob (setting, ca_cert);
+	NMSetting8021xCKScheme scheme;
+
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+	scheme = nm_setting_802_1x_get_ca_cert_scheme (setting);
+	g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB, NULL);
+
+	return NM_SETTING_802_1X_GET_PRIVATE (setting)->ca_cert;
 }
 
 /**
@@ -991,7 +612,16 @@ nm_setting_802_1x_get_ca_cert_blob (NMSetting8021x *setting)
 const char *
 nm_setting_802_1x_get_ca_cert_path (NMSetting8021x *setting)
 {
-	_cert_impl_get_path (setting, ca_cert);
+	NMSetting8021xCKScheme scheme;
+	gconstpointer data;
+
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+	scheme = nm_setting_802_1x_get_ca_cert_scheme (setting);
+	g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH, NULL);
+
+	data = g_bytes_get_data (NM_SETTING_802_1X_GET_PRIVATE (setting)->ca_cert, NULL);
+	return (const char *)data + strlen (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH);
 }
 
 /**
@@ -1013,7 +643,35 @@ nm_setting_802_1x_get_ca_cert_path (NMSetting8021x *setting)
 const char *
 nm_setting_802_1x_get_ca_cert_uri (NMSetting8021x *setting)
 {
-	_cert_impl_get_uri (setting, ca_cert);
+	NMSetting8021xCKScheme scheme;
+	gconstpointer data;
+
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+	scheme = nm_setting_802_1x_get_ca_cert_scheme (setting);
+	g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11, NULL);
+
+	data = g_bytes_get_data (NM_SETTING_802_1X_GET_PRIVATE (setting)->ca_cert, NULL);
+	return (const char *)data;
+}
+
+static GBytes *
+path_to_scheme_value (const char *path)
+{
+	GByteArray *array;
+	gsize len;
+
+	g_return_val_if_fail (path != NULL && path[0], NULL);
+
+	len = strlen (path);
+
+	/* Add the path scheme tag to the front, then the filename */
+	array = g_byte_array_sized_new (len + strlen (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH) + 1);
+	g_byte_array_append (array, (const guint8 *) NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH, strlen (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH));
+	g_byte_array_append (array, (const guint8 *) path, len);
+	g_byte_array_append (array, (const guint8 *) "\0", 1);
+
+	return g_byte_array_free_to_bytes (array);
 }
 
 /**
@@ -1042,7 +700,65 @@ nm_setting_802_1x_set_ca_cert (NMSetting8021x *setting,
                                NMSetting8021xCKFormat *out_format,
                                GError **error)
 {
-	return _cert_impl_set (setting, PROP_CA_CERT, value, NULL, scheme, out_format, error);
+	NMSetting8021xPrivate *priv;
+	NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
+	GByteArray *data;
+
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE);
+
+	if (value) {
+		g_return_val_if_fail (g_utf8_validate (value, -1, NULL), FALSE);
+		g_return_val_if_fail (   scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB
+		                      || scheme == NM_SETTING_802_1X_CK_SCHEME_PATH
+		                      || scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11,
+		                      FALSE);
+	}
+
+	if (out_format)
+		g_return_val_if_fail (*out_format == NM_SETTING_802_1X_CK_FORMAT_UNKNOWN, FALSE);
+
+	priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
+
+	g_clear_pointer (&priv->ca_cert, g_bytes_unref);
+
+	if (!value) {
+		g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_CA_CERT);
+		return TRUE;
+	}
+
+	if (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11) {
+		priv->ca_cert = g_bytes_new (value, strlen (value) + 1);
+		g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_CA_CERT);
+		return TRUE;
+	}
+
+	data = load_and_verify_certificate (value, scheme, &format, error);
+	if (data) {
+		/* wpa_supplicant can only use raw x509 CA certs */
+		if (format == NM_CRYPTO_FILE_FORMAT_X509) {
+			if (out_format)
+				*out_format = NM_SETTING_802_1X_CK_FORMAT_X509;
+
+			if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) {
+				priv->ca_cert = g_byte_array_free_to_bytes (data);
+				data = NULL;
+			} else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH)
+				priv->ca_cert = path_to_scheme_value (value);
+			else
+				g_assert_not_reached ();
+		} else {
+			g_set_error_literal (error,
+			             NM_CONNECTION_ERROR,
+			             NM_CONNECTION_ERROR_INVALID_PROPERTY,
+			             _("CA certificate must be in X.509 format"));
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_CA_CERT);
+		}
+		if (data)
+			g_byte_array_unref (data);
+	}
+
+	g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_CA_CERT);
+	return priv->ca_cert != NULL;
 }
 
 /**
@@ -1166,7 +882,7 @@ nm_setting_802_1x_add_altsubject_match (NMSetting8021x *setting,
 
 	priv->altsubject_matches = g_slist_append (priv->altsubject_matches,
 	                                           g_strdup (altsubject_match));
-	_notify (setting, PROP_ALTSUBJECT_MATCHES);
+	g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_ALTSUBJECT_MATCHES);
 	return TRUE;
 }
 
@@ -1191,7 +907,7 @@ nm_setting_802_1x_remove_altsubject_match (NMSetting8021x *setting, guint32 i)
 
 	g_free (elt->data);
 	priv->altsubject_matches = g_slist_delete_link (priv->altsubject_matches, elt);
-	_notify (setting, PROP_ALTSUBJECT_MATCHES);
+	g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_ALTSUBJECT_MATCHES);
 }
 
 /**
@@ -1218,7 +934,7 @@ nm_setting_802_1x_remove_altsubject_match_by_value (NMSetting8021x *setting,
 	for (iter = priv->altsubject_matches; iter; iter = g_slist_next (iter)) {
 		if (!strcmp (altsubject_match, (char *) iter->data)) {
 			priv->altsubject_matches = g_slist_delete_link (priv->altsubject_matches, iter);
-			_notify (setting, PROP_ALTSUBJECT_MATCHES);
+			g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_ALTSUBJECT_MATCHES);
 			return TRUE;
 		}
 	}
@@ -1241,7 +957,7 @@ nm_setting_802_1x_clear_altsubject_matches (NMSetting8021x *setting)
 	priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
 	g_slist_free_full (priv->altsubject_matches, g_free);
 	priv->altsubject_matches = NULL;
-	_notify (setting, PROP_ALTSUBJECT_MATCHES);
+	g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_ALTSUBJECT_MATCHES);
 }
 
 /**
@@ -1274,7 +990,9 @@ nm_setting_802_1x_get_domain_suffix_match (NMSetting8021x *setting)
 NMSetting8021xCKScheme
 nm_setting_802_1x_get_client_cert_scheme (NMSetting8021x *setting)
 {
-	_cert_impl_get_scheme (setting, client_cert);
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_SCHEME_UNKNOWN);
+
+	return get_cert_scheme (NM_SETTING_802_1X_GET_PRIVATE (setting)->client_cert, NULL);
 }
 
 /**
@@ -1290,7 +1008,14 @@ nm_setting_802_1x_get_client_cert_scheme (NMSetting8021x *setting)
 GBytes *
 nm_setting_802_1x_get_client_cert_blob (NMSetting8021x *setting)
 {
-	_cert_impl_get_blob (setting, client_cert);
+	NMSetting8021xCKScheme scheme;
+
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+	scheme = nm_setting_802_1x_get_client_cert_scheme (setting);
+	g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB, NULL);
+
+	return NM_SETTING_802_1X_GET_PRIVATE (setting)->client_cert;
 }
 
 /**
@@ -1306,7 +1031,16 @@ nm_setting_802_1x_get_client_cert_blob (NMSetting8021x *setting)
 const char *
 nm_setting_802_1x_get_client_cert_path (NMSetting8021x *setting)
 {
-	_cert_impl_get_path (setting, client_cert);
+	NMSetting8021xCKScheme scheme;
+	gconstpointer data;
+
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+	scheme = nm_setting_802_1x_get_client_cert_scheme (setting);
+	g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH, NULL);
+
+	data = g_bytes_get_data (NM_SETTING_802_1X_GET_PRIVATE (setting)->client_cert, NULL);
+	return (const char *)data + strlen (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH);
 }
 
 /**
@@ -1328,7 +1062,16 @@ nm_setting_802_1x_get_client_cert_path (NMSetting8021x *setting)
 const char *
 nm_setting_802_1x_get_client_cert_uri (NMSetting8021x *setting)
 {
-	_cert_impl_get_uri (setting, client_cert);
+	NMSetting8021xCKScheme scheme;
+	gconstpointer data;
+
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+	scheme = nm_setting_802_1x_get_client_cert_scheme (setting);
+	g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11, NULL);
+
+	data = g_bytes_get_data (NM_SETTING_802_1X_GET_PRIVATE (setting)->client_cert, NULL);
+	return (const char *)data;
 }
 
 /**
@@ -1361,7 +1104,77 @@ nm_setting_802_1x_set_client_cert (NMSetting8021x *setting,
                                    NMSetting8021xCKFormat *out_format,
                                    GError **error)
 {
-	return _cert_impl_set (setting, PROP_CLIENT_CERT, value, NULL, scheme, out_format, error);
+	NMSetting8021xPrivate *priv;
+	NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
+	GByteArray *data;
+
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE);
+
+	if (value) {
+		g_return_val_if_fail (g_utf8_validate (value, -1, NULL), FALSE);
+		g_return_val_if_fail (   scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB
+		                      || scheme == NM_SETTING_802_1X_CK_SCHEME_PATH
+		                      || scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11,
+		                      FALSE);
+	}
+
+	if (out_format)
+		g_return_val_if_fail (*out_format == NM_SETTING_802_1X_CK_FORMAT_UNKNOWN, FALSE);
+
+	priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
+
+	g_clear_pointer (&priv->client_cert, g_bytes_unref);
+
+	if (!value) {
+		g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_CLIENT_CERT);
+		return TRUE;
+	}
+
+	if (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11) {
+		priv->client_cert = g_bytes_new (value, strlen (value) + 1);
+		g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_CLIENT_CERT);
+		return TRUE;
+	}
+
+	data = load_and_verify_certificate (value, scheme, &format, error);
+	if (data) {
+		gboolean valid = FALSE;
+
+		switch (format) {
+		case NM_CRYPTO_FILE_FORMAT_X509:
+			if (out_format)
+				*out_format = NM_SETTING_802_1X_CK_FORMAT_X509;
+			valid = TRUE;
+			break;
+		case NM_CRYPTO_FILE_FORMAT_PKCS12:
+			if (out_format)
+				*out_format = NM_SETTING_802_1X_CK_FORMAT_PKCS12;
+			valid = TRUE;
+			break;
+		default:
+			g_set_error_literal (error,
+			                     NM_CONNECTION_ERROR,
+			                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
+			                     _("invalid certificate format"));
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_CLIENT_CERT);
+			break;
+		}
+
+		if (valid) {
+			if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) {
+				priv->client_cert = g_byte_array_free_to_bytes (data);
+				data = NULL;
+			} else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH)
+				priv->client_cert = path_to_scheme_value (value);
+			else
+				g_assert_not_reached ();
+		}
+		if (data)
+			g_byte_array_unref (data);
+	}
+
+	g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_CLIENT_CERT);
+	return priv->client_cert != NULL;
 }
 
 /**
@@ -1530,7 +1343,9 @@ nm_setting_802_1x_get_phase2_ca_path (NMSetting8021x *setting)
 NMSetting8021xCKScheme
 nm_setting_802_1x_get_phase2_ca_cert_scheme (NMSetting8021x *setting)
 {
-	_cert_impl_get_scheme (setting, phase2_ca_cert);
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_SCHEME_UNKNOWN);
+
+	return get_cert_scheme (NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_ca_cert, NULL);
 }
 
 /**
@@ -1549,7 +1364,14 @@ nm_setting_802_1x_get_phase2_ca_cert_scheme (NMSetting8021x *setting)
 GBytes *
 nm_setting_802_1x_get_phase2_ca_cert_blob (NMSetting8021x *setting)
 {
-	_cert_impl_get_blob (setting, phase2_ca_cert);
+	NMSetting8021xCKScheme scheme;
+
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+	scheme = nm_setting_802_1x_get_phase2_ca_cert_scheme (setting);
+	g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB, NULL);
+
+	return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_ca_cert;
 }
 
 /**
@@ -1568,7 +1390,16 @@ nm_setting_802_1x_get_phase2_ca_cert_blob (NMSetting8021x *setting)
 const char *
 nm_setting_802_1x_get_phase2_ca_cert_path (NMSetting8021x *setting)
 {
-	_cert_impl_get_path (setting, phase2_ca_cert);
+	NMSetting8021xCKScheme scheme;
+	gconstpointer data;
+
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+	scheme = nm_setting_802_1x_get_phase2_ca_cert_scheme (setting);
+	g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH, NULL);
+
+	data = g_bytes_get_data (NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_ca_cert, NULL);
+	return (const char *)data + strlen (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH);
 }
 
 /**
@@ -1590,7 +1421,16 @@ nm_setting_802_1x_get_phase2_ca_cert_path (NMSetting8021x *setting)
 const char *
 nm_setting_802_1x_get_phase2_ca_cert_uri (NMSetting8021x *setting)
 {
-	_cert_impl_get_uri (setting, phase2_ca_cert);
+	NMSetting8021xCKScheme scheme;
+	gconstpointer data;
+
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+	scheme = nm_setting_802_1x_get_phase2_ca_cert_scheme (setting);
+	g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11, NULL);
+
+	data = g_bytes_get_data (NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_ca_cert, NULL);
+	return (const char *)data;
 }
 
 /**
@@ -1619,7 +1459,65 @@ nm_setting_802_1x_set_phase2_ca_cert (NMSetting8021x *setting,
                                       NMSetting8021xCKFormat *out_format,
                                       GError **error)
 {
-	return _cert_impl_set (setting, PROP_PHASE2_CA_CERT, value, NULL, scheme, out_format, error);
+	NMSetting8021xPrivate *priv;
+	NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
+	GByteArray *data;
+
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE);
+
+	if (value) {
+		g_return_val_if_fail (g_utf8_validate (value, -1, NULL), FALSE);
+		g_return_val_if_fail (   scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB
+		                      || scheme == NM_SETTING_802_1X_CK_SCHEME_PATH
+		                      || scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11,
+		                      FALSE);
+	}
+
+	if (out_format)
+		g_return_val_if_fail (*out_format == NM_SETTING_802_1X_CK_FORMAT_UNKNOWN, FALSE);
+
+	priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
+
+	g_clear_pointer (&priv->phase2_ca_cert, g_bytes_unref);
+
+	if (!value) {
+		g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_CA_CERT);
+		return TRUE;
+	}
+
+	if (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11) {
+		priv->phase2_ca_cert = g_bytes_new (value, strlen (value) + 1);
+		g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_CA_CERT);
+		return TRUE;
+	}
+
+	data = load_and_verify_certificate (value, scheme, &format, error);
+	if (data) {
+		/* wpa_supplicant can only use raw x509 CA certs */
+		if (format == NM_CRYPTO_FILE_FORMAT_X509) {
+			if (out_format)
+				*out_format = NM_SETTING_802_1X_CK_FORMAT_X509;
+
+			if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) {
+				priv->phase2_ca_cert = g_byte_array_free_to_bytes (data);
+				data = NULL;
+			} else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH)
+				priv->phase2_ca_cert = path_to_scheme_value (value);
+			else
+				g_assert_not_reached ();
+		} else {
+			g_set_error_literal (error,
+			                     NM_CONNECTION_ERROR,
+			                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
+			                     _("invalid certificate format"));
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_PHASE2_CA_CERT);
+		}
+		if (data)
+			g_byte_array_unref (data);
+	}
+
+	g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_CA_CERT);
+	return priv->phase2_ca_cert != NULL;
 }
 
 /**
@@ -1760,7 +1658,7 @@ nm_setting_802_1x_add_phase2_altsubject_match (NMSetting8021x *setting,
 
 	priv->phase2_altsubject_matches = g_slist_append (priv->phase2_altsubject_matches,
 	                                                  g_strdup (phase2_altsubject_match));
-	_notify (setting, PROP_PHASE2_ALTSUBJECT_MATCHES);
+	g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_ALTSUBJECT_MATCHES);
 	return TRUE;
 }
 
@@ -1785,7 +1683,7 @@ nm_setting_802_1x_remove_phase2_altsubject_match (NMSetting8021x *setting, guint
 
 	g_free (elt->data);
 	priv->phase2_altsubject_matches = g_slist_delete_link (priv->phase2_altsubject_matches, elt);
-	_notify (setting, PROP_PHASE2_ALTSUBJECT_MATCHES);
+	g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_ALTSUBJECT_MATCHES);
 }
 
 /**
@@ -1812,7 +1710,7 @@ nm_setting_802_1x_remove_phase2_altsubject_match_by_value (NMSetting8021x *setti
 	for (iter = priv->phase2_altsubject_matches; iter; iter = g_slist_next (iter)) {
 		if (!strcmp (phase2_altsubject_match, (char *) iter->data)) {
 			priv->phase2_altsubject_matches = g_slist_delete_link (priv->phase2_altsubject_matches, iter);
-			_notify (setting, PROP_PHASE2_ALTSUBJECT_MATCHES);
+			g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_ALTSUBJECT_MATCHES);
 			return TRUE;
 		}
 	}
@@ -1835,7 +1733,7 @@ nm_setting_802_1x_clear_phase2_altsubject_matches (NMSetting8021x *setting)
 	priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
 	g_slist_free_full (priv->phase2_altsubject_matches, g_free);
 	priv->phase2_altsubject_matches = NULL;
-	_notify (setting, PROP_PHASE2_ALTSUBJECT_MATCHES);
+	g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_ALTSUBJECT_MATCHES);
 }
 
 /**
@@ -1855,7 +1753,9 @@ nm_setting_802_1x_clear_phase2_altsubject_matches (NMSetting8021x *setting)
 NMSetting8021xCKScheme
 nm_setting_802_1x_get_phase2_client_cert_scheme (NMSetting8021x *setting)
 {
-	_cert_impl_get_scheme (setting, phase2_client_cert);
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_SCHEME_UNKNOWN);
+
+	return get_cert_scheme (NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_client_cert, NULL);
 }
 
 /**
@@ -1871,7 +1771,14 @@ nm_setting_802_1x_get_phase2_client_cert_scheme (NMSetting8021x *setting)
 GBytes *
 nm_setting_802_1x_get_phase2_client_cert_blob (NMSetting8021x *setting)
 {
-	_cert_impl_get_blob (setting, phase2_client_cert);
+	NMSetting8021xCKScheme scheme;
+
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+	scheme = nm_setting_802_1x_get_phase2_client_cert_scheme (setting);
+	g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB, NULL);
+
+	return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_client_cert;
 }
 
 /**
@@ -1887,7 +1794,16 @@ nm_setting_802_1x_get_phase2_client_cert_blob (NMSetting8021x *setting)
 const char *
 nm_setting_802_1x_get_phase2_client_cert_path (NMSetting8021x *setting)
 {
-	_cert_impl_get_path (setting, phase2_client_cert);
+	NMSetting8021xCKScheme scheme;
+	gconstpointer data;
+
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+	scheme = nm_setting_802_1x_get_phase2_client_cert_scheme (setting);
+	g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH, NULL);
+
+	data = g_bytes_get_data (NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_client_cert, NULL);
+	return (const char *)data + strlen (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH);
 }
 
 /**
@@ -1909,7 +1825,16 @@ nm_setting_802_1x_get_phase2_client_cert_path (NMSetting8021x *setting)
 const char *
 nm_setting_802_1x_get_phase2_client_cert_uri (NMSetting8021x *setting)
 {
-	_cert_impl_get_uri (setting, phase2_client_cert);
+	NMSetting8021xCKScheme scheme;
+	gconstpointer data;
+
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+	scheme = nm_setting_802_1x_get_phase2_client_cert_scheme (setting);
+	g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11, NULL);
+
+	data = g_bytes_get_data (NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_client_cert, NULL);
+	return (const char *)data;
 }
 
 /**
@@ -1942,7 +1867,78 @@ nm_setting_802_1x_set_phase2_client_cert (NMSetting8021x *setting,
                                           NMSetting8021xCKFormat *out_format,
                                           GError **error)
 {
-	return _cert_impl_set (setting, PROP_PHASE2_CLIENT_CERT, value, NULL, scheme, out_format, error);
+	NMSetting8021xPrivate *priv;
+	NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
+	GByteArray *data;
+
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE);
+
+	if (value) {
+		g_return_val_if_fail (g_utf8_validate (value, -1, NULL), FALSE);
+		g_return_val_if_fail (   scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB
+		                      || scheme == NM_SETTING_802_1X_CK_SCHEME_PATH
+		                      || scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11,
+		                      FALSE);
+	}
+
+	if (out_format)
+		g_return_val_if_fail (*out_format == NM_SETTING_802_1X_CK_FORMAT_UNKNOWN, FALSE);
+
+	priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
+
+	g_clear_pointer (&priv->phase2_client_cert, g_bytes_unref);
+
+	if (!value) {
+		g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_CLIENT_CERT);
+		return TRUE;
+	}
+
+	if (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11) {
+		priv->phase2_client_cert = g_bytes_new (value, strlen (value) + 1);
+		g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_CLIENT_CERT);
+		return TRUE;
+	}
+
+	data = load_and_verify_certificate (value, scheme, &format, error);
+	if (data) {
+		gboolean valid = FALSE;
+
+		/* wpa_supplicant can only use raw x509 CA certs */
+		switch (format) {
+		case NM_CRYPTO_FILE_FORMAT_X509:
+			if (out_format)
+				*out_format = NM_SETTING_802_1X_CK_FORMAT_X509;
+			valid = TRUE;
+			break;
+		case NM_CRYPTO_FILE_FORMAT_PKCS12:
+			if (out_format)
+				*out_format = NM_SETTING_802_1X_CK_FORMAT_PKCS12;
+			valid = TRUE;
+			break;
+		default:
+			g_set_error_literal (error,
+			                     NM_CONNECTION_ERROR,
+			                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
+			                     _("invalid certificate format"));
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_PHASE2_CLIENT_CERT);
+			break;
+		}
+
+		if (valid) {
+			if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) {
+				priv->phase2_client_cert = g_byte_array_free_to_bytes (data);
+				data = NULL;
+			} else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH)
+				priv->phase2_client_cert = path_to_scheme_value (value);
+			else
+				g_assert_not_reached ();
+		}
+		if (data)
+			g_byte_array_unref (data);
+	}
+
+	g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_CLIENT_CERT);
+	return priv->phase2_client_cert != NULL;
 }
 
 /**
@@ -2087,7 +2083,9 @@ nm_setting_802_1x_get_pin_flags (NMSetting8021x *setting)
 NMSetting8021xCKScheme
 nm_setting_802_1x_get_private_key_scheme (NMSetting8021x *setting)
 {
-	_cert_impl_get_scheme (setting, private_key);
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_SCHEME_UNKNOWN);
+
+	return get_cert_scheme (NM_SETTING_802_1X_GET_PRIVATE (setting)->private_key, NULL);
 }
 
 /**
@@ -2107,7 +2105,14 @@ nm_setting_802_1x_get_private_key_scheme (NMSetting8021x *setting)
 GBytes *
 nm_setting_802_1x_get_private_key_blob (NMSetting8021x *setting)
 {
-	_cert_impl_get_blob (setting, private_key);
+	NMSetting8021xCKScheme scheme;
+
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+	scheme = nm_setting_802_1x_get_private_key_scheme (setting);
+	g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB, NULL);
+
+	return NM_SETTING_802_1X_GET_PRIVATE (setting)->private_key;
 }
 
 /**
@@ -2123,7 +2128,16 @@ nm_setting_802_1x_get_private_key_blob (NMSetting8021x *setting)
 const char *
 nm_setting_802_1x_get_private_key_path (NMSetting8021x *setting)
 {
-	_cert_impl_get_path (setting, private_key);
+	NMSetting8021xCKScheme scheme;
+	gconstpointer data;
+
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+	scheme = nm_setting_802_1x_get_private_key_scheme (setting);
+	g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH, NULL);
+
+	data = g_bytes_get_data (NM_SETTING_802_1X_GET_PRIVATE (setting)->private_key, NULL);
+	return (const char *)data + strlen (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH);
 }
 
 /**
@@ -2145,7 +2159,42 @@ nm_setting_802_1x_get_private_key_path (NMSetting8021x *setting)
 const char *
 nm_setting_802_1x_get_private_key_uri (NMSetting8021x *setting)
 {
-	_cert_impl_get_uri (setting, private_key);
+	NMSetting8021xCKScheme scheme;
+	gconstpointer data;
+
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+	scheme = nm_setting_802_1x_get_private_key_scheme (setting);
+	g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11, NULL);
+
+	data = g_bytes_get_data (NM_SETTING_802_1X_GET_PRIVATE (setting)->private_key, NULL);
+	return (const char *)data;
+}
+
+static void
+free_secure_bytes (gpointer data)
+{
+	GByteArray *array = data;
+
+	memset (array->data, 0, array->len);
+	g_byte_array_unref (array);
+}
+
+static GBytes *
+file_to_secure_bytes (const char *filename)
+{
+	char *contents;
+	GByteArray *array = NULL;
+	gsize length = 0;
+
+	if (g_file_get_contents (filename, &contents, &length, NULL)) {
+		array = g_byte_array_sized_new (length);
+		g_byte_array_append (array, (guint8 *) contents, length);
+		memset (contents, 0, length);
+		g_free (contents);
+		return g_bytes_new_with_free_func (array->data, array->len, free_secure_bytes, array);
+	}
+	return NULL;
 }
 
 /**
@@ -2195,7 +2244,88 @@ nm_setting_802_1x_set_private_key (NMSetting8021x *setting,
                                    NMSetting8021xCKFormat *out_format,
                                    GError **error)
 {
-	return _cert_impl_set (setting, PROP_PRIVATE_KEY, value, password, scheme, out_format, error);
+	NMSetting8021xPrivate *priv;
+	NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
+	gboolean password_changed = FALSE;
+	GError *local_err = NULL;
+
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE);
+
+	if (value) {
+		g_return_val_if_fail (g_utf8_validate (value, -1, NULL), FALSE);
+		g_return_val_if_fail (   scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB
+		                      || scheme == NM_SETTING_802_1X_CK_SCHEME_PATH
+		                      || scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11,
+		                      FALSE);
+	}
+
+	if (out_format)
+		g_return_val_if_fail (*out_format == NM_SETTING_802_1X_CK_FORMAT_UNKNOWN, FALSE);
+
+	/* Ensure the private key is a recognized format and if the password was
+	 * given, that it decrypts the private key.
+	 */
+	if (value && scheme != NM_SETTING_802_1X_CK_SCHEME_PKCS11) {
+		format = crypto_verify_private_key (value, password, NULL, &local_err);
+		if (format == NM_CRYPTO_FILE_FORMAT_UNKNOWN) {
+			g_set_error_literal (error,
+			                     NM_CONNECTION_ERROR,
+			                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
+			                     local_err ? local_err->message : _("invalid private key"));
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_PRIVATE_KEY);
+			g_clear_error (&local_err);
+			return FALSE;
+		}
+	}
+
+	priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
+
+	if (value == NULL) {
+		if (priv->private_key) {
+			g_clear_pointer (&priv->private_key, g_bytes_unref);
+			g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PRIVATE_KEY);
+		}
+		if (nm_clear_g_free (&priv->private_key_password))
+			g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD);
+		return TRUE;
+	}
+
+	/* this makes password self-assignment safe. */
+	if (!nm_streq0 (priv->private_key_password, password)) {
+		g_free (priv->private_key_password);
+		priv->private_key_password = g_strdup (password);
+		password_changed = TRUE;
+	}
+
+	g_bytes_unref (priv->private_key);
+	if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) {
+		/* FIXME: potential race after verifying the private key above */
+		/* FIXME: ensure blob doesn't start with file:// */
+		priv->private_key = file_to_secure_bytes (value);
+		nm_assert (priv->private_key);
+	} else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH)
+		priv->private_key = path_to_scheme_value (value);
+	else {
+		nm_assert (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11);
+		priv->private_key = g_bytes_new (value, strlen (value) + 1);
+	}
+
+	/* As required by NM and wpa_supplicant, set the client-cert
+	 * property to the same PKCS#12 data.
+	 */
+	if (format == NM_CRYPTO_FILE_FORMAT_PKCS12) {
+		if (priv->client_cert)
+			g_bytes_unref (priv->client_cert);
+		priv->client_cert = g_bytes_ref (priv->private_key);
+		g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_CLIENT_CERT);
+	}
+
+	g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PRIVATE_KEY);
+	if (password_changed)
+		g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD);
+
+	NM_SET_OUT (out_format, (NMSetting8021xCKFormat) format);
+	return priv->private_key != NULL;
 }
 
 /**
@@ -2239,7 +2369,38 @@ nm_setting_802_1x_get_private_key_password_flags (NMSetting8021x *setting)
 NMSetting8021xCKFormat
 nm_setting_802_1x_get_private_key_format (NMSetting8021x *setting)
 {
-	return _cert_impl_get_key_format (setting, private_key);
+	NMSetting8021xPrivate *priv;
+	const char *path;
+	GError *error = NULL;
+
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_FORMAT_UNKNOWN);
+	priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
+
+	if (!priv->private_key)
+		return NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+
+	switch (nm_setting_802_1x_get_private_key_scheme (setting)) {
+	case NM_SETTING_802_1X_CK_SCHEME_BLOB:
+		if (crypto_is_pkcs12_data (g_bytes_get_data (priv->private_key, NULL),
+		                           g_bytes_get_size (priv->private_key),
+		                           NULL))
+			return NM_SETTING_802_1X_CK_FORMAT_PKCS12;
+		return NM_SETTING_802_1X_CK_FORMAT_RAW_KEY;
+	case NM_SETTING_802_1X_CK_SCHEME_PATH:
+		path = nm_setting_802_1x_get_private_key_path (setting);
+		if (crypto_is_pkcs12_file (path, &error))
+			return NM_SETTING_802_1X_CK_FORMAT_PKCS12;
+		if (error && error->domain == G_FILE_ERROR) {
+			g_error_free (error);
+			return NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+		}
+		g_error_free (error);
+		return NM_SETTING_802_1X_CK_FORMAT_RAW_KEY;
+	default:
+		break;
+	}
+
+	return NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
 }
 
 /**
@@ -2290,7 +2451,9 @@ nm_setting_802_1x_get_phase2_private_key_password_flags (NMSetting8021x *setting
 NMSetting8021xCKScheme
 nm_setting_802_1x_get_phase2_private_key_scheme (NMSetting8021x *setting)
 {
-	_cert_impl_get_scheme (setting, phase2_private_key);
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_SCHEME_UNKNOWN);
+
+	return get_cert_scheme (NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_private_key, NULL);
 }
 
 /**
@@ -2310,7 +2473,14 @@ nm_setting_802_1x_get_phase2_private_key_scheme (NMSetting8021x *setting)
 GBytes *
 nm_setting_802_1x_get_phase2_private_key_blob (NMSetting8021x *setting)
 {
-	_cert_impl_get_blob (setting, phase2_private_key);
+	NMSetting8021xCKScheme scheme;
+
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+	scheme = nm_setting_802_1x_get_phase2_private_key_scheme (setting);
+	g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB, NULL);
+
+	return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_private_key;
 }
 
 /**
@@ -2326,7 +2496,16 @@ nm_setting_802_1x_get_phase2_private_key_blob (NMSetting8021x *setting)
 const char *
 nm_setting_802_1x_get_phase2_private_key_path (NMSetting8021x *setting)
 {
-	_cert_impl_get_path (setting, phase2_private_key);
+	NMSetting8021xCKScheme scheme;
+	gconstpointer data;
+
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+	scheme = nm_setting_802_1x_get_phase2_private_key_scheme (setting);
+	g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH, NULL);
+
+	data = g_bytes_get_data (NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_private_key, NULL);
+	return (const char *)data + strlen (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH);
 }
 
 /**
@@ -2348,7 +2527,16 @@ nm_setting_802_1x_get_phase2_private_key_path (NMSetting8021x *setting)
 const char *
 nm_setting_802_1x_get_phase2_private_key_uri (NMSetting8021x *setting)
 {
-	_cert_impl_get_uri (setting, phase2_private_key);
+	NMSetting8021xCKScheme scheme;
+	gconstpointer data;
+
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+	scheme = nm_setting_802_1x_get_phase2_private_key_scheme (setting);
+	g_return_val_if_fail (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11, NULL);
+
+	data = g_bytes_get_data (NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_private_key, NULL);
+	return (const char *)data;
 }
 
 /**
@@ -2398,7 +2586,89 @@ nm_setting_802_1x_set_phase2_private_key (NMSetting8021x *setting,
                                           NMSetting8021xCKFormat *out_format,
                                           GError **error)
 {
-	return _cert_impl_set (setting, PROP_PHASE2_PRIVATE_KEY, value, password, scheme, out_format, error);
+	NMSetting8021xPrivate *priv;
+	NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
+	gboolean password_changed = FALSE;
+	GError *local_err = NULL;
+
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE);
+
+	if (value) {
+		g_return_val_if_fail (g_utf8_validate (value, -1, NULL), FALSE);
+		g_return_val_if_fail (   scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB
+		                      || scheme == NM_SETTING_802_1X_CK_SCHEME_PATH
+		                      || scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11,
+		                      FALSE);
+	}
+
+	if (out_format)
+		g_return_val_if_fail (*out_format == NM_SETTING_802_1X_CK_FORMAT_UNKNOWN, FALSE);
+
+	/* Ensure the private key is a recognized format and if the password was
+	 * given, that it decrypts the private key.
+	 */
+	if (value && scheme != NM_SETTING_802_1X_CK_SCHEME_PKCS11) {
+		format = crypto_verify_private_key (value, password, NULL, &local_err);
+		if (format == NM_CRYPTO_FILE_FORMAT_UNKNOWN) {
+			g_set_error_literal (error,
+			                     NM_CONNECTION_ERROR,
+			                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
+			                     local_err ? local_err->message : _("invalid phase2 private key"));
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY);
+			g_clear_error (&local_err);
+			return FALSE;
+		}
+	}
+
+	priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
+
+	if (value == NULL) {
+		if (priv->phase2_private_key) {
+			g_clear_pointer (&priv->phase2_private_key, g_bytes_unref);
+			g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_PRIVATE_KEY);
+		}
+		if (nm_clear_g_free (&priv->phase2_private_key_password))
+			g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD);
+		return TRUE;
+	}
+
+	/* this makes password self-assignment safe. */
+	if (!nm_streq0 (priv->phase2_private_key_password, password)) {
+		g_free (priv->phase2_private_key_password);
+		priv->phase2_private_key_password = g_strdup (password);
+		password_changed = TRUE;
+	}
+
+	g_bytes_unref (priv->phase2_private_key);
+	if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) {
+		/* FIXME: potential race after verifying the private key above */
+		/* FIXME: ensure blob doesn't start with file:// */
+		priv->phase2_private_key = file_to_secure_bytes (value);
+		nm_assert (priv->phase2_private_key);
+	} else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH)
+		priv->phase2_private_key = path_to_scheme_value (value);
+	else {
+		nm_assert (scheme == NM_SETTING_802_1X_CK_SCHEME_PKCS11);
+		priv->phase2_private_key = g_bytes_new (value, strlen (value) + 1);
+	}
+
+	/* As required by NM and wpa_supplicant, set the client-cert
+	 * property to the same PKCS#12 data.
+	 */
+	if (format == NM_CRYPTO_FILE_FORMAT_PKCS12) {
+		if (priv->phase2_client_cert)
+			g_bytes_unref (priv->phase2_client_cert);
+
+		priv->phase2_client_cert = g_bytes_ref (priv->phase2_private_key);
+		g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_CLIENT_CERT);
+	}
+
+	g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_PRIVATE_KEY);
+	if (password_changed)
+		g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD);
+
+	NM_SET_OUT (out_format, (NMSetting8021xCKFormat) format);
+	return priv->phase2_private_key != NULL;
 }
 
 /**
@@ -2411,7 +2681,38 @@ nm_setting_802_1x_set_phase2_private_key (NMSetting8021x *setting,
 NMSetting8021xCKFormat
 nm_setting_802_1x_get_phase2_private_key_format (NMSetting8021x *setting)
 {
-	return _cert_impl_get_key_format (setting, phase2_private_key);
+	NMSetting8021xPrivate *priv;
+	const char *path;
+	GError *error = NULL;
+
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_FORMAT_UNKNOWN);
+	priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
+
+	if (!priv->phase2_private_key)
+		return NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+
+	switch (nm_setting_802_1x_get_phase2_private_key_scheme (setting)) {
+	case NM_SETTING_802_1X_CK_SCHEME_BLOB:
+		if (crypto_is_pkcs12_data (g_bytes_get_data (priv->phase2_private_key, NULL),
+		                           g_bytes_get_size (priv->phase2_private_key),
+		                           NULL))
+			return NM_SETTING_802_1X_CK_FORMAT_PKCS12;
+		return NM_SETTING_802_1X_CK_FORMAT_RAW_KEY;
+	case NM_SETTING_802_1X_CK_SCHEME_PATH:
+		path = nm_setting_802_1x_get_phase2_private_key_path (setting);
+		if (crypto_is_pkcs12_file (path, &error))
+			return NM_SETTING_802_1X_CK_FORMAT_PKCS12;
+		if (error && error->domain == G_FILE_ERROR) {
+			g_error_free (error);
+			return NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+		}
+		g_error_free (error);
+		return NM_SETTING_802_1X_CK_FORMAT_RAW_KEY;
+	default:
+		break;
+	}
+
+	return NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
 }
 
 /**
@@ -2425,7 +2726,7 @@ nm_setting_802_1x_get_phase2_private_key_format (NMSetting8021x *setting)
  *
  * Since: 1.8
  **/
-int
+gint
 nm_setting_802_1x_get_auth_timeout (NMSetting8021x *setting)
 {
 	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), 0);
@@ -2433,8 +2734,6 @@ nm_setting_802_1x_get_auth_timeout (NMSetting8021x *setting)
 	return NM_SETTING_802_1X_GET_PRIVATE (setting)->auth_timeout;
 }
 
-/*****************************************************************************/
-
 static void
 need_secrets_password (NMSetting8021x *self,
                        GPtrArray *secrets,
@@ -2479,11 +2778,11 @@ need_private_key_password (GBytes *blob,
 	/* Private key password is required */
 	if (password) {
 		if (path)
-			format = nm_crypto_verify_private_key (path, password, NULL, NULL);
+			format = crypto_verify_private_key (path, password, NULL, NULL);
 		else if (blob)
-			format = nm_crypto_verify_private_key_data (g_bytes_get_data (blob, NULL),
-			                                            g_bytes_get_size (blob),
-			                                            password, NULL, NULL);
+			format = crypto_verify_private_key_data (g_bytes_get_data (blob, NULL),
+			                                         g_bytes_get_size (blob),
+			                                         password, NULL, NULL);
 		else
 			return FALSE;
 	}
@@ -2598,9 +2897,9 @@ verify_tls (NMSetting8021x *self, gboolean phase2, GError **error)
 		}
 
 		/* If the private key is PKCS#12, check that it matches the client cert */
-		if (nm_crypto_is_pkcs12_data (g_bytes_get_data (priv->phase2_private_key, NULL),
-		                              g_bytes_get_size (priv->phase2_private_key),
-		                              NULL)) {
+		if (crypto_is_pkcs12_data (g_bytes_get_data (priv->phase2_private_key, NULL),
+		                           g_bytes_get_size (priv->phase2_private_key),
+		                           NULL)) {
 			if (!g_bytes_equal (priv->phase2_private_key, priv->phase2_client_cert)) {
 				g_set_error (error,
 				             NM_CONNECTION_ERROR,
@@ -2646,9 +2945,9 @@ verify_tls (NMSetting8021x *self, gboolean phase2, GError **error)
 		}
 
 		/* If the private key is PKCS#12, check that it matches the client cert */
-		if (nm_crypto_is_pkcs12_data (g_bytes_get_data (priv->private_key, NULL),
-		                              g_bytes_get_size (priv->private_key),
-		                              NULL)) {
+		if (crypto_is_pkcs12_data (g_bytes_get_data (priv->private_key, NULL),
+		                           g_bytes_get_size (priv->private_key),
+		                           NULL)) {
 			if (!g_bytes_equal (priv->private_key, priv->client_cert)) {
 				g_set_error (error,
 				             NM_CONNECTION_ERROR,
@@ -2756,6 +3055,43 @@ verify_identity (NMSetting8021x *self, gboolean phase2, GError **error)
 	return TRUE;
 }
 
+/* Implemented below... */
+static void need_secrets_phase2 (NMSetting8021x *self,
+                                 GPtrArray *secrets,
+                                 gboolean phase2);
+
+typedef void (*EAPMethodNeedSecretsFunc) (NMSetting8021x *self,
+                                          GPtrArray *secrets,
+                                          gboolean phase2);
+
+typedef gboolean (*EAPMethodValidateFunc)(NMSetting8021x *self,
+                                          gboolean phase2,
+                                          GError **error);
+
+typedef struct {
+	const char *method;
+	EAPMethodNeedSecretsFunc ns_func;
+	EAPMethodValidateFunc v_func;
+} EAPMethodsTable;
+
+static EAPMethodsTable eap_methods_table[] = {
+	{ "leap", need_secrets_password, verify_identity },
+	{ "pwd", need_secrets_password, verify_identity },
+	{ "md5", need_secrets_password, verify_identity },
+	{ "pap", need_secrets_password, verify_identity },
+	{ "chap", need_secrets_password, verify_identity },
+	{ "mschap", need_secrets_password, verify_identity },
+	{ "mschapv2", need_secrets_password, verify_identity },
+	{ "fast", need_secrets_password, verify_identity },
+	{ "tls", need_secrets_tls, verify_tls },
+	{ "peap", need_secrets_phase2, verify_ttls },
+	{ "ttls", need_secrets_phase2, verify_ttls },
+	{ "sim", need_secrets_sim, NULL },
+	{ "gtc", need_secrets_password, verify_identity },
+	{ "otp", NULL, NULL },  // FIXME: implement
+	{ NULL, NULL, NULL }
+};
+
 static void
 need_secrets_phase2 (NMSetting8021x *self,
                      GPtrArray *secrets,
@@ -2789,31 +3125,91 @@ need_secrets_phase2 (NMSetting8021x *self,
 	}
 }
 
-static EAPMethodsTable eap_methods_table[] = {
-	{ "leap", need_secrets_password, verify_identity },
-	{ "pwd", need_secrets_password, verify_identity },
-	{ "md5", need_secrets_password, verify_identity },
-	{ "pap", need_secrets_password, verify_identity },
-	{ "chap", need_secrets_password, verify_identity },
-	{ "mschap", need_secrets_password, verify_identity },
-	{ "mschapv2", need_secrets_password, verify_identity },
-	{ "fast", need_secrets_password, verify_identity },
-	{ "tls", need_secrets_tls, verify_tls },
-	{ "peap", need_secrets_phase2, verify_ttls },
-	{ "ttls", need_secrets_phase2, verify_ttls },
-	{ "sim", need_secrets_sim, NULL },
-	{ "gtc", need_secrets_password, verify_identity },
-	{ "otp", NULL, NULL },  // FIXME: implement
-	{ "external", NULL, NULL },
-	{ NULL, NULL, NULL }
-};
+static GPtrArray *
+need_secrets (NMSetting *setting)
+{
+	NMSetting8021x *self = NM_SETTING_802_1X (setting);
+	NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self);
+	GSList *iter;
+	GPtrArray *secrets;
+	gboolean eap_method_found = FALSE;
+
+	secrets = g_ptr_array_sized_new (4);
+
+	/* Ask each configured EAP method if it needs secrets */
+	for (iter = priv->eap; iter && !eap_method_found; iter = g_slist_next (iter)) {
+		const char *method = (const char *) iter->data;
+		int i;
+
+		for (i = 0; eap_methods_table[i].method; i++) {
+			if (eap_methods_table[i].ns_func == NULL)
+				continue;
+			if (!strcmp (eap_methods_table[i].method, method)) {
+				(*eap_methods_table[i].ns_func) (self, secrets, FALSE);
+
+				/* Only break out of the outer loop if this EAP method
+				 * needed secrets.
+				 */
+				if (secrets->len > 0)
+					eap_method_found = TRUE;
+				break;
+			}
+		}
+	}
+
+	if (secrets->len == 0) {
+		g_ptr_array_free (secrets, TRUE);
+		secrets = NULL;
+	}
+
+	return secrets;
+}
+
+static gboolean
+verify_cert (GBytes *bytes, const char *prop_name,
+             const char *password, const char *password_prop_name, GError **error)
+{
+	GError *local = NULL;
+	NMSetting8021xCKScheme scheme;
+
+	if (bytes)
+		scheme = get_cert_scheme (bytes, &local);
+	else
+		return TRUE;
+
+	if (scheme == NM_SETTING_802_1X_CK_SCHEME_UNKNOWN) {
+		g_set_error (error,
+		             NM_CONNECTION_ERROR,
+		             NM_CONNECTION_ERROR_INVALID_PROPERTY,
+		             _("certificate is invalid: %s"), local->message);
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, prop_name);
+		g_error_free (local);
+		return FALSE;
+	}
+
+	if (password && (scheme != NM_SETTING_802_1X_CK_SCHEME_PKCS11)) {
+		g_set_error (error,
+		             NM_CONNECTION_ERROR,
+		             NM_CONNECTION_ERROR_INVALID_PROPERTY,
+		             _("password is not supported when certificate is not on a PKCS#11 token"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, password_prop_name);
+		return FALSE;
+	}
+
+	return TRUE;
+}
 
 static gboolean
 verify (NMSetting *setting, NMConnection *connection, GError **error)
 {
 	NMSetting8021x *self = NM_SETTING_802_1X (setting);
 	NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self);
-	const char *valid_eap[] = { "leap", "md5", "tls", "peap", "ttls", "sim", "fast", "pwd", "external", NULL };
+	const char *valid_eap[] = { "leap", "md5", "tls", "peap", "ttls", "sim", "fast", "pwd", NULL };
+	const char *valid_phase1_peapver[] = { "0", "1", NULL };
+	const char *valid_phase1_peaplabel[] = { "0", "1", NULL };
+	const char *valid_phase1_fast_pac[] = { "0", "1", "2", "3", NULL };
+	const char *valid_phase2_auth[] = { "pap", "chap", "mschap", "mschapv2", "gtc", "otp", "md5", "tls", NULL };
+	const char *valid_phase2_autheap[] = { "md5", "mschapv2", "otp", "gtc", "tls", NULL };
 	GSList *iter;
 
 	if (error)
@@ -2853,9 +3249,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
 		}
 	}
 
-	if (!NM_IN_STRSET (priv->phase1_peapver, NULL,
-	                                         "0",
-	                                         "1")) {
+	if (priv->phase1_peapver && !g_strv_contains (valid_phase1_peapver, priv->phase1_peapver)) {
 		g_set_error (error,
 		             NM_CONNECTION_ERROR,
 		             NM_CONNECTION_ERROR_INVALID_PROPERTY,
@@ -2865,9 +3259,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
 		return FALSE;
 	}
 
-	if (!NM_IN_STRSET (priv->phase1_peaplabel, NULL,
-	                                           "0",
-	                                           "1")) {
+	if (priv->phase1_peaplabel && !g_strv_contains (valid_phase1_peaplabel, priv->phase1_peaplabel)) {
 		g_set_error (error,
 		             NM_CONNECTION_ERROR,
 		             NM_CONNECTION_ERROR_INVALID_PROPERTY,
@@ -2877,11 +3269,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
 		return FALSE;
 	}
 
-	if (!NM_IN_STRSET (priv->phase1_fast_provisioning, NULL,
-	                                                   "0",
-	                                                   "1",
-	                                                   "2",
-	                                                   "3")) {
+	if (priv->phase1_fast_provisioning && !g_strv_contains (valid_phase1_fast_pac, priv->phase1_fast_provisioning)) {
 		g_set_error (error,
 		             NM_CONNECTION_ERROR,
 		             NM_CONNECTION_ERROR_INVALID_PROPERTY,
@@ -2900,15 +3288,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
 		return FALSE;
 	}
 
-	if (!NM_IN_STRSET (priv->phase2_auth, NULL,
-	                                      "pap",
-	                                      "chap",
-	                                      "mschap",
-	                                      "mschapv2",
-	                                      "gtc",
-	                                      "otp",
-	                                      "md5",
-	                                      "tls")) {
+	if (priv->phase2_auth && !g_strv_contains (valid_phase2_auth, priv->phase2_auth)) {
 		g_set_error (error,
 		             NM_CONNECTION_ERROR,
 		             NM_CONNECTION_ERROR_INVALID_PROPERTY,
@@ -2918,12 +3298,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
 		return FALSE;
 	}
 
-	if (!NM_IN_STRSET (priv->phase2_autheap, NULL,
-	                                         "md5",
-	                                         "mschapv2",
-	                                         "otp",
-	                                         "gtc",
-	                                         "tls")) {
+	if (priv->phase2_autheap && !g_strv_contains (valid_phase2_autheap, priv->phase2_autheap)) {
 		g_set_error (error,
 		             NM_CONNECTION_ERROR,
 		             NM_CONNECTION_ERROR_INVALID_PROPERTY,
@@ -2933,231 +3308,307 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
 		return FALSE;
 	}
 
-	if (!_cert_verify_property (priv->ca_cert,
-	                            NM_SETTING_802_1X_CA_CERT,
-	                            priv->ca_cert_password,
-	                            NM_SETTING_802_1X_CA_CERT_PASSWORD,
-	                            error))
+	if (!verify_cert (priv->ca_cert, NM_SETTING_802_1X_CA_CERT,
+	                  priv->ca_cert_password, NM_SETTING_802_1X_CA_CERT_PASSWORD, error))
 		return FALSE;
-	if (!_cert_verify_property (priv->phase2_ca_cert,
-	                            NM_SETTING_802_1X_PHASE2_CA_CERT,
-	                            priv->phase2_ca_cert_password,
-	                            NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD,
-	                            error))
+	if (!verify_cert (priv->phase2_ca_cert, NM_SETTING_802_1X_PHASE2_CA_CERT,
+	                  priv->phase2_ca_cert_password, NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD, error))
 		return FALSE;
 
-	if (!_cert_verify_property (priv->client_cert,
-	                            NM_SETTING_802_1X_CLIENT_CERT,
-	                            priv->client_cert_password,
-	                            NM_SETTING_802_1X_CLIENT_CERT_PASSWORD,
-	                            error))
+	if (!verify_cert (priv->client_cert, NM_SETTING_802_1X_CLIENT_CERT,
+	                  priv->client_cert_password, NM_SETTING_802_1X_CLIENT_CERT_PASSWORD, error))
 		return FALSE;
-	if (!_cert_verify_property (priv->phase2_client_cert,
-	                            NM_SETTING_802_1X_PHASE2_CLIENT_CERT,
-	                            priv->phase2_client_cert_password,
-	                            NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD,
-	                            error))
+	if (!verify_cert (priv->phase2_client_cert, NM_SETTING_802_1X_PHASE2_CLIENT_CERT,
+	                  priv->phase2_client_cert_password, NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD, error))
 		return FALSE;
 
-	if (!_cert_verify_property (priv->private_key,
-	                            NM_SETTING_802_1X_PRIVATE_KEY,
-	                            NULL,
-	                            NULL,
-	                            error))
+	if (!verify_cert (priv->private_key, NM_SETTING_802_1X_PRIVATE_KEY, NULL, NULL, error))
 		return FALSE;
-	if (!_cert_verify_property (priv->phase2_private_key,
-	                            NM_SETTING_802_1X_PHASE2_PRIVATE_KEY,
-	                            NULL,
-	                            NULL,
-	                            error))
+	if (!verify_cert (priv->phase2_private_key, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY, NULL, NULL, error))
 		return FALSE;
 
+	/* FIXME: finish */
+
 	return TRUE;
 }
 
-/*****************************************************************************/
+static void
+nm_setting_802_1x_init (NMSetting8021x *setting)
+{
+}
 
-static GPtrArray *
-need_secrets (NMSetting *setting)
+static void
+finalize (GObject *object)
 {
-	NMSetting8021x *self = NM_SETTING_802_1X (setting);
+	NMSetting8021x *self = NM_SETTING_802_1X (object);
 	NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self);
-	GSList *iter;
-	GPtrArray *secrets;
-	gboolean eap_method_found = FALSE;
 
-	secrets = g_ptr_array_sized_new (4);
-
-	/* Ask each configured EAP method if it needs secrets */
-	for (iter = priv->eap; iter && !eap_method_found; iter = g_slist_next (iter)) {
-		const char *method = (const char *) iter->data;
-		int i;
+	/* Strings first. g_free() already checks for NULLs so we don't have to */
 
-		for (i = 0; eap_methods_table[i].method; i++) {
-			if (eap_methods_table[i].ns_func == NULL)
-				continue;
-			if (!strcmp (eap_methods_table[i].method, method)) {
-				(*eap_methods_table[i].ns_func) (self, secrets, FALSE);
+	g_free (priv->identity);
+	g_free (priv->anonymous_identity);
+	g_free (priv->ca_path);
+	g_free (priv->subject_match);
+	g_free (priv->domain_suffix_match);
+	g_free (priv->phase1_peapver);
+	g_free (priv->phase1_peaplabel);
+	g_free (priv->phase1_fast_provisioning);
+	g_free (priv->phase2_auth);
+	g_free (priv->phase2_autheap);
+	g_free (priv->phase2_ca_path);
+	g_free (priv->phase2_subject_match);
+	g_free (priv->phase2_domain_suffix_match);
+	g_free (priv->password);
+	if (priv->password_raw)
+		g_bytes_unref (priv->password_raw);
+	g_free (priv->pin);
 
-				/* Only break out of the outer loop if this EAP method
-				 * needed secrets.
-				 */
-				if (secrets->len > 0)
-					eap_method_found = TRUE;
-				break;
-			}
-		}
-	}
+	g_slist_free_full (priv->eap, g_free);
+	g_slist_free_full (priv->altsubject_matches, g_free);
+	g_slist_free_full (priv->phase2_altsubject_matches, g_free);
 
-	if (secrets->len == 0) {
-		g_ptr_array_free (secrets, TRUE);
-		return NULL;
-	}
+	if (priv->ca_cert)
+		g_bytes_unref (priv->ca_cert);
+	g_free (priv->ca_cert_password);
+	if (priv->client_cert)
+		g_bytes_unref (priv->client_cert);
+	g_free (priv->client_cert_password);
+	if (priv->private_key)
+		g_bytes_unref (priv->private_key);
+	g_free (priv->private_key_password);
+	if (priv->phase2_ca_cert)
+		g_bytes_unref (priv->phase2_ca_cert);
+	g_free (priv->phase2_ca_cert_password);
+	if (priv->phase2_client_cert)
+		g_bytes_unref (priv->phase2_client_cert);
+	g_free (priv->phase2_client_cert_password);
+	if (priv->phase2_private_key)
+		g_bytes_unref (priv->phase2_private_key);
+	g_free (priv->phase2_private_key_password);
 
-	return secrets;
+	G_OBJECT_CLASS (nm_setting_802_1x_parent_class)->finalize (object);
 }
 
-/*****************************************************************************/
+static GBytes *
+set_cert_prop_helper (const GValue *value, const char *prop_name, GError **error)
+{
+	gboolean valid;
+	GBytes *bytes = NULL;
+
+	bytes = g_value_dup_boxed (value);
+	/* Verify the new data */
+	if (bytes) {
+		valid = verify_cert (bytes, prop_name, NULL, NULL, error);
+		if (!valid)
+			g_clear_pointer (&bytes, g_bytes_unref);
+	}
+	return bytes;
+}
 
 static void
-get_property (GObject *object, guint prop_id,
-              GValue *value, GParamSpec *pspec)
+set_property (GObject *object, guint prop_id,
+              const GValue *value, GParamSpec *pspec)
 {
 	NMSetting8021x *setting = NM_SETTING_802_1X (object);
 	NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
+	GError *error = NULL;
 
 	switch (prop_id) {
 	case PROP_EAP:
-		g_value_take_boxed (value, _nm_utils_slist_to_strv (priv->eap, TRUE));
+		g_slist_free_full (priv->eap, g_free);
+		priv->eap = _nm_utils_strv_to_slist (g_value_get_boxed (value), TRUE);
 		break;
 	case PROP_IDENTITY:
-		g_value_set_string (value, priv->identity);
+		g_free (priv->identity);
+		priv->identity = g_value_dup_string (value);
 		break;
 	case PROP_ANONYMOUS_IDENTITY:
-		g_value_set_string (value, priv->anonymous_identity);
+		g_free (priv->anonymous_identity);
+		priv->anonymous_identity = g_value_dup_string (value);
 		break;
 	case PROP_PAC_FILE:
-		g_value_set_string (value, priv->pac_file);
+		g_free (priv->pac_file);
+		priv->pac_file = g_value_dup_string (value);
 		break;
 	case PROP_CA_CERT:
-		g_value_set_boxed (value, priv->ca_cert);
+		if (priv->ca_cert)
+			g_bytes_unref (priv->ca_cert);
+		priv->ca_cert = set_cert_prop_helper (value, NM_SETTING_802_1X_CA_CERT, &error);
+		if (error) {
+			g_warning ("Error setting certificate (invalid data): %s", error->message);
+			g_error_free (error);
+		}
 		break;
 	case PROP_CA_CERT_PASSWORD:
-		g_value_set_string (value, priv->ca_cert_password);
+		g_free (priv->ca_cert_password);
+		priv->ca_cert_password = g_value_dup_string (value);
 		break;
 	case PROP_CA_CERT_PASSWORD_FLAGS:
-		g_value_set_flags (value, priv->ca_cert_password_flags);
+		priv->ca_cert_password_flags = g_value_get_flags (value);
 		break;
 	case PROP_CA_PATH:
-		g_value_set_string (value, priv->ca_path);
+		g_free (priv->ca_path);
+		priv->ca_path = g_value_dup_string (value);
 		break;
 	case PROP_SUBJECT_MATCH:
-		g_value_set_string (value, priv->subject_match);
+		g_free (priv->subject_match);
+		priv->subject_match = nm_strdup_not_empty (g_value_get_string (value));
 		break;
 	case PROP_ALTSUBJECT_MATCHES:
-		g_value_take_boxed (value, _nm_utils_slist_to_strv (priv->altsubject_matches, TRUE));
+		g_slist_free_full (priv->altsubject_matches, g_free);
+		priv->altsubject_matches = _nm_utils_strv_to_slist (g_value_get_boxed (value), TRUE);
 		break;
 	case PROP_DOMAIN_SUFFIX_MATCH:
-		g_value_set_string (value, priv->domain_suffix_match);
+		g_free (priv->domain_suffix_match);
+		priv->domain_suffix_match = nm_strdup_not_empty (g_value_get_string (value));
 		break;
 	case PROP_CLIENT_CERT:
-		g_value_set_boxed (value, priv->client_cert);
+		if (priv->client_cert)
+			g_bytes_unref (priv->client_cert);
+		priv->client_cert = set_cert_prop_helper (value, NM_SETTING_802_1X_CLIENT_CERT, &error);
+		if (error) {
+			g_warning ("Error setting certificate (invalid data): %s", error->message);
+			g_error_free (error);
+		}
 		break;
 	case PROP_CLIENT_CERT_PASSWORD:
-		g_value_set_string (value, priv->client_cert_password);
+		g_free (priv->client_cert_password);
+		priv->client_cert_password = g_value_dup_string (value);
 		break;
 	case PROP_CLIENT_CERT_PASSWORD_FLAGS:
-		g_value_set_flags (value, priv->client_cert_password_flags);
+		priv->client_cert_password_flags = g_value_get_flags (value);
 		break;
 	case PROP_PHASE1_PEAPVER:
-		g_value_set_string (value, priv->phase1_peapver);
+		g_free (priv->phase1_peapver);
+		priv->phase1_peapver = g_value_dup_string (value);
 		break;
 	case PROP_PHASE1_PEAPLABEL:
-		g_value_set_string (value, priv->phase1_peaplabel);
+		g_free (priv->phase1_peaplabel);
+		priv->phase1_peaplabel = g_value_dup_string (value);
 		break;
 	case PROP_PHASE1_FAST_PROVISIONING:
-		g_value_set_string (value, priv->phase1_fast_provisioning);
+		g_free (priv->phase1_fast_provisioning);
+		priv->phase1_fast_provisioning = g_value_dup_string (value);
 		break;
 	case PROP_PHASE1_AUTH_FLAGS:
-		g_value_set_uint (value, priv->phase1_auth_flags);
+		priv->phase1_auth_flags = g_value_get_uint (value);
 		break;
 	case PROP_PHASE2_AUTH:
-		g_value_set_string (value, priv->phase2_auth);
+		g_free (priv->phase2_auth);
+		priv->phase2_auth = g_value_dup_string (value);
 		break;
 	case PROP_PHASE2_AUTHEAP:
-		g_value_set_string (value, priv->phase2_autheap);
+		g_free (priv->phase2_autheap);
+		priv->phase2_autheap = g_value_dup_string (value);
 		break;
 	case PROP_PHASE2_CA_CERT:
-		g_value_set_boxed (value, priv->phase2_ca_cert);
+		if (priv->phase2_ca_cert)
+			g_bytes_unref (priv->phase2_ca_cert);
+		priv->phase2_ca_cert = set_cert_prop_helper (value, NM_SETTING_802_1X_PHASE2_CA_CERT, &error);
+		if (error) {
+			g_warning ("Error setting certificate (invalid data): %s", error->message);
+			g_error_free (error);
+		}
 		break;
 	case PROP_PHASE2_CA_CERT_PASSWORD:
-		g_value_set_string (value, priv->phase2_ca_cert_password);
+		g_free (priv->phase2_ca_cert_password);
+		priv->phase2_ca_cert_password = g_value_dup_string (value);
 		break;
 	case PROP_PHASE2_CA_CERT_PASSWORD_FLAGS:
-		g_value_set_flags (value, priv->phase2_ca_cert_password_flags);
+		priv->phase2_ca_cert_password_flags = g_value_get_flags (value);
 		break;
 	case PROP_PHASE2_CA_PATH:
-		g_value_set_string (value, priv->phase2_ca_path);
+		g_free (priv->phase2_ca_path);
+		priv->phase2_ca_path = g_value_dup_string (value);
 		break;
 	case PROP_PHASE2_SUBJECT_MATCH:
-		g_value_set_string (value, priv->phase2_subject_match);
+		g_free (priv->phase2_subject_match);
+		priv->phase2_subject_match = nm_strdup_not_empty (g_value_get_string (value));
 		break;
 	case PROP_PHASE2_ALTSUBJECT_MATCHES:
-		g_value_take_boxed (value, _nm_utils_slist_to_strv (priv->phase2_altsubject_matches, TRUE));
+		g_slist_free_full (priv->phase2_altsubject_matches, g_free);
+		priv->phase2_altsubject_matches = _nm_utils_strv_to_slist (g_value_get_boxed (value), TRUE);
 		break;
 	case PROP_PHASE2_DOMAIN_SUFFIX_MATCH:
-		g_value_set_string (value, priv->phase2_domain_suffix_match);
+		g_free (priv->phase2_domain_suffix_match);
+		priv->phase2_domain_suffix_match = nm_strdup_not_empty (g_value_get_string (value));
 		break;
 	case PROP_PHASE2_CLIENT_CERT:
-		g_value_set_boxed (value, priv->phase2_client_cert);
+
+		if (priv->phase2_client_cert)
+			g_bytes_unref (priv->phase2_client_cert);
+		priv->phase2_client_cert = set_cert_prop_helper (value, NM_SETTING_802_1X_PHASE2_CLIENT_CERT, &error);
+		if (error) {
+			g_warning ("Error setting certificate (invalid data): %s", error->message);
+			g_error_free (error);
+		}
 		break;
 	case PROP_PHASE2_CLIENT_CERT_PASSWORD:
-		g_value_set_string (value, priv->phase2_client_cert_password);
+		g_free (priv->phase2_client_cert_password);
+		priv->phase2_client_cert_password = g_value_dup_string (value);
 		break;
 	case PROP_PHASE2_CLIENT_CERT_PASSWORD_FLAGS:
-		g_value_set_flags (value, priv->phase2_client_cert_password_flags);
+		priv->phase2_client_cert_password_flags = g_value_get_flags (value);
 		break;
 	case PROP_PASSWORD:
-		g_value_set_string (value, priv->password);
+		g_free (priv->password);
+		priv->password = g_value_dup_string (value);
 		break;
 	case PROP_PASSWORD_FLAGS:
-		g_value_set_flags (value, priv->password_flags);
+		priv->password_flags = g_value_get_flags (value);
 		break;
 	case PROP_PASSWORD_RAW:
-		g_value_set_boxed (value, priv->password_raw);
+		if (priv->password_raw)
+			g_bytes_unref (priv->password_raw);
+		priv->password_raw = g_value_dup_boxed (value);
 		break;
 	case PROP_PASSWORD_RAW_FLAGS:
-		g_value_set_flags (value, priv->password_raw_flags);
+		priv->password_raw_flags = g_value_get_flags (value);
 		break;
 	case PROP_PRIVATE_KEY:
-		g_value_set_boxed (value, priv->private_key);
+		if (priv->private_key)
+			g_bytes_unref (priv->private_key);
+		priv->private_key = set_cert_prop_helper (value, NM_SETTING_802_1X_PRIVATE_KEY, &error);
+		if (error) {
+			g_warning ("Error setting private key (invalid data): %s", error->message);
+			g_error_free (error);
+		}
 		break;
 	case PROP_PRIVATE_KEY_PASSWORD:
-		g_value_set_string (value, priv->private_key_password);
+		g_free (priv->private_key_password);
+		priv->private_key_password = g_value_dup_string (value);
 		break;
 	case PROP_PRIVATE_KEY_PASSWORD_FLAGS:
-		g_value_set_flags (value, priv->private_key_password_flags);
+		priv->private_key_password_flags = g_value_get_flags (value);
 		break;
 	case PROP_PHASE2_PRIVATE_KEY:
-		g_value_set_boxed (value, priv->phase2_private_key);
+		if (priv->phase2_private_key)
+			g_bytes_unref (priv->phase2_private_key);
+		priv->phase2_private_key = set_cert_prop_helper (value, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY, &error);
+		if (error) {
+			g_warning ("Error setting private key (invalid data): %s", error->message);
+			g_error_free (error);
+		}
 		break;
 	case PROP_PHASE2_PRIVATE_KEY_PASSWORD:
-		g_value_set_string (value, priv->phase2_private_key_password);
+		g_free (priv->phase2_private_key_password);
+		priv->phase2_private_key_password = g_value_dup_string (value);
 		break;
 	case PROP_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS:
-		g_value_set_flags (value, priv->phase2_private_key_password_flags);
+		priv->phase2_private_key_password_flags = g_value_get_flags (value);
 		break;
 	case PROP_PIN:
-		g_value_set_string (value, priv->pin);
+		g_free (priv->pin);
+		priv->pin = g_value_dup_string (value);
 		break;
 	case PROP_PIN_FLAGS:
-		g_value_set_flags (value, priv->pin_flags);
+		priv->pin_flags = g_value_get_flags (value);
 		break;
 	case PROP_SYSTEM_CA_CERTS:
-		g_value_set_boolean (value, priv->system_ca_certs);
+		priv->system_ca_certs = g_value_get_boolean (value);
 		break;
 	case PROP_AUTH_TIMEOUT:
-		g_value_set_int (value, priv->auth_timeout);
+		priv->auth_timeout = g_value_get_int (value);
 		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -3166,176 +3617,144 @@ get_property (GObject *object, guint prop_id,
 }
 
 static void
-set_property (GObject *object, guint prop_id,
-              const GValue *value, GParamSpec *pspec)
+get_property (GObject *object, guint prop_id,
+              GValue *value, GParamSpec *pspec)
 {
 	NMSetting8021x *setting = NM_SETTING_802_1X (object);
 	NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
 
 	switch (prop_id) {
 	case PROP_EAP:
-		g_slist_free_full (priv->eap, g_free);
-		priv->eap = _nm_utils_strv_to_slist (g_value_get_boxed (value), TRUE);
+		g_value_take_boxed (value, _nm_utils_slist_to_strv (priv->eap, TRUE));
 		break;
 	case PROP_IDENTITY:
-		g_free (priv->identity);
-		priv->identity = g_value_dup_string (value);
+		g_value_set_string (value, priv->identity);
 		break;
 	case PROP_ANONYMOUS_IDENTITY:
-		g_free (priv->anonymous_identity);
-		priv->anonymous_identity = g_value_dup_string (value);
+		g_value_set_string (value, priv->anonymous_identity);
 		break;
 	case PROP_PAC_FILE:
-		g_free (priv->pac_file);
-		priv->pac_file = g_value_dup_string (value);
+		g_value_set_string (value, priv->pac_file);
 		break;
 	case PROP_CA_CERT:
-		g_bytes_unref (priv->ca_cert);
-		priv->ca_cert = g_value_dup_boxed (value);
+		g_value_set_boxed (value, priv->ca_cert);
 		break;
 	case PROP_CA_CERT_PASSWORD:
-		g_free (priv->ca_cert_password);
-		priv->ca_cert_password = g_value_dup_string (value);
+		g_value_set_string (value, priv->ca_cert_password);
 		break;
 	case PROP_CA_CERT_PASSWORD_FLAGS:
-		priv->ca_cert_password_flags = g_value_get_flags (value);
+		g_value_set_flags (value, priv->ca_cert_password_flags);
 		break;
 	case PROP_CA_PATH:
-		g_free (priv->ca_path);
-		priv->ca_path = g_value_dup_string (value);
+		g_value_set_string (value, priv->ca_path);
 		break;
 	case PROP_SUBJECT_MATCH:
-		g_free (priv->subject_match);
-		priv->subject_match = nm_strdup_not_empty (g_value_get_string (value));
+		g_value_set_string (value, priv->subject_match);
 		break;
 	case PROP_ALTSUBJECT_MATCHES:
-		g_slist_free_full (priv->altsubject_matches, g_free);
-		priv->altsubject_matches = _nm_utils_strv_to_slist (g_value_get_boxed (value), TRUE);
+		g_value_take_boxed (value, _nm_utils_slist_to_strv (priv->altsubject_matches, TRUE));
 		break;
 	case PROP_DOMAIN_SUFFIX_MATCH:
-		g_free (priv->domain_suffix_match);
-		priv->domain_suffix_match = nm_strdup_not_empty (g_value_get_string (value));
+		g_value_set_string (value, priv->domain_suffix_match);
 		break;
 	case PROP_CLIENT_CERT:
-		g_bytes_unref (priv->client_cert);
-		priv->client_cert = g_value_dup_boxed (value);
+		g_value_set_boxed (value, priv->client_cert);
 		break;
 	case PROP_CLIENT_CERT_PASSWORD:
-		g_free (priv->client_cert_password);
-		priv->client_cert_password = g_value_dup_string (value);
+		g_value_set_string (value, priv->client_cert_password);
 		break;
 	case PROP_CLIENT_CERT_PASSWORD_FLAGS:
-		priv->client_cert_password_flags = g_value_get_flags (value);
+		g_value_set_flags (value, priv->client_cert_password_flags);
 		break;
 	case PROP_PHASE1_PEAPVER:
-		g_free (priv->phase1_peapver);
-		priv->phase1_peapver = g_value_dup_string (value);
+		g_value_set_string (value, priv->phase1_peapver);
 		break;
 	case PROP_PHASE1_PEAPLABEL:
-		g_free (priv->phase1_peaplabel);
-		priv->phase1_peaplabel = g_value_dup_string (value);
+		g_value_set_string (value, priv->phase1_peaplabel);
 		break;
 	case PROP_PHASE1_FAST_PROVISIONING:
-		g_free (priv->phase1_fast_provisioning);
-		priv->phase1_fast_provisioning = g_value_dup_string (value);
+		g_value_set_string (value, priv->phase1_fast_provisioning);
 		break;
 	case PROP_PHASE1_AUTH_FLAGS:
-		priv->phase1_auth_flags = g_value_get_uint (value);
+		g_value_set_uint (value, priv->phase1_auth_flags);
 		break;
 	case PROP_PHASE2_AUTH:
-		g_free (priv->phase2_auth);
-		priv->phase2_auth = g_value_dup_string (value);
+		g_value_set_string (value, priv->phase2_auth);
 		break;
 	case PROP_PHASE2_AUTHEAP:
-		g_free (priv->phase2_autheap);
-		priv->phase2_autheap = g_value_dup_string (value);
+		g_value_set_string (value, priv->phase2_autheap);
 		break;
 	case PROP_PHASE2_CA_CERT:
-		g_bytes_unref (priv->phase2_ca_cert);
-		priv->phase2_ca_cert = g_value_dup_boxed (value);
+		g_value_set_boxed (value, priv->phase2_ca_cert);
 		break;
 	case PROP_PHASE2_CA_CERT_PASSWORD:
-		g_free (priv->phase2_ca_cert_password);
-		priv->phase2_ca_cert_password = g_value_dup_string (value);
+		g_value_set_string (value, priv->phase2_ca_cert_password);
 		break;
 	case PROP_PHASE2_CA_CERT_PASSWORD_FLAGS:
-		priv->phase2_ca_cert_password_flags = g_value_get_flags (value);
+		g_value_set_flags (value, priv->phase2_ca_cert_password_flags);
 		break;
 	case PROP_PHASE2_CA_PATH:
-		g_free (priv->phase2_ca_path);
-		priv->phase2_ca_path = g_value_dup_string (value);
+		g_value_set_string (value, priv->phase2_ca_path);
 		break;
 	case PROP_PHASE2_SUBJECT_MATCH:
-		g_free (priv->phase2_subject_match);
-		priv->phase2_subject_match = nm_strdup_not_empty (g_value_get_string (value));
+		g_value_set_string (value, priv->phase2_subject_match);
 		break;
 	case PROP_PHASE2_ALTSUBJECT_MATCHES:
-		g_slist_free_full (priv->phase2_altsubject_matches, g_free);
-		priv->phase2_altsubject_matches = _nm_utils_strv_to_slist (g_value_get_boxed (value), TRUE);
+		g_value_take_boxed (value, _nm_utils_slist_to_strv (priv->phase2_altsubject_matches, TRUE));
 		break;
 	case PROP_PHASE2_DOMAIN_SUFFIX_MATCH:
-		g_free (priv->phase2_domain_suffix_match);
-		priv->phase2_domain_suffix_match = nm_strdup_not_empty (g_value_get_string (value));
+		g_value_set_string (value, priv->phase2_domain_suffix_match);
 		break;
 	case PROP_PHASE2_CLIENT_CERT:
-		g_bytes_unref (priv->phase2_client_cert);
-		priv->phase2_client_cert = g_value_dup_boxed (value);
+		g_value_set_boxed (value, priv->phase2_client_cert);
 		break;
 	case PROP_PHASE2_CLIENT_CERT_PASSWORD:
-		g_free (priv->phase2_client_cert_password);
-		priv->phase2_client_cert_password = g_value_dup_string (value);
+		g_value_set_string (value, priv->phase2_client_cert_password);
 		break;
 	case PROP_PHASE2_CLIENT_CERT_PASSWORD_FLAGS:
-		priv->phase2_client_cert_password_flags = g_value_get_flags (value);
+		g_value_set_flags (value, priv->phase2_client_cert_password_flags);
 		break;
 	case PROP_PASSWORD:
-		g_free (priv->password);
-		priv->password = g_value_dup_string (value);
+		g_value_set_string (value, priv->password);
 		break;
 	case PROP_PASSWORD_FLAGS:
-		priv->password_flags = g_value_get_flags (value);
+		g_value_set_flags (value, priv->password_flags);
 		break;
 	case PROP_PASSWORD_RAW:
-		g_bytes_unref (priv->password_raw);
-		priv->password_raw = g_value_dup_boxed (value);
+		g_value_set_boxed (value, priv->password_raw);
 		break;
 	case PROP_PASSWORD_RAW_FLAGS:
-		priv->password_raw_flags = g_value_get_flags (value);
+		g_value_set_flags (value, priv->password_raw_flags);
 		break;
 	case PROP_PRIVATE_KEY:
-		g_bytes_unref (priv->private_key);
-		priv->private_key = g_value_dup_boxed (value);
+		g_value_set_boxed (value, priv->private_key);
 		break;
 	case PROP_PRIVATE_KEY_PASSWORD:
-		nm_free_secret (priv->private_key_password);
-		priv->private_key_password = g_value_dup_string (value);
+		g_value_set_string (value, priv->private_key_password);
 		break;
 	case PROP_PRIVATE_KEY_PASSWORD_FLAGS:
-		priv->private_key_password_flags = g_value_get_flags (value);
+		g_value_set_flags (value, priv->private_key_password_flags);
 		break;
 	case PROP_PHASE2_PRIVATE_KEY:
-		g_bytes_unref (priv->phase2_private_key);
-		priv->phase2_private_key = g_value_dup_boxed (value);
+		g_value_set_boxed (value, priv->phase2_private_key);
 		break;
 	case PROP_PHASE2_PRIVATE_KEY_PASSWORD:
-		nm_free_secret (priv->phase2_private_key_password);
-		priv->phase2_private_key_password = g_value_dup_string (value);
+		g_value_set_string (value, priv->phase2_private_key_password);
 		break;
 	case PROP_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS:
-		priv->phase2_private_key_password_flags = g_value_get_flags (value);
+		g_value_set_flags (value, priv->phase2_private_key_password_flags);
 		break;
 	case PROP_PIN:
-		g_free (priv->pin);
-		priv->pin = g_value_dup_string (value);
+		g_value_set_string (value, priv->pin);
 		break;
 	case PROP_PIN_FLAGS:
-		priv->pin_flags = g_value_get_flags (value);
+		g_value_set_flags (value, priv->pin_flags);
 		break;
 	case PROP_SYSTEM_CA_CERTS:
-		priv->system_ca_certs = g_value_get_boolean (value);
+		g_value_set_boolean (value, priv->system_ca_certs);
 		break;
 	case PROP_AUTH_TIMEOUT:
-		priv->auth_timeout = g_value_get_int (value);
+		g_value_set_int (value, priv->auth_timeout);
 		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -3343,85 +3762,23 @@ set_property (GObject *object, guint prop_id,
 	}
 }
 
-/*****************************************************************************/
-
-static void
-nm_setting_802_1x_init (NMSetting8021x *setting)
-{
-}
-
-/**
- * nm_setting_802_1x_new:
- *
- * Creates a new #NMSetting8021x object with default values.
- *
- * Returns: the new empty #NMSetting8021x object
- **/
-NMSetting *
-nm_setting_802_1x_new (void)
-{
-	return (NMSetting *) g_object_new (NM_TYPE_SETTING_802_1X, NULL);
-}
-
 static void
-finalize (GObject *object)
+nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
 {
-	NMSetting8021x *self = NM_SETTING_802_1X (object);
-	NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self);
+	GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+	NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
 
-	/* Strings first. g_free() already checks for NULLs so we don't have to */
-
-	g_free (priv->identity);
-	g_free (priv->anonymous_identity);
-	g_free (priv->ca_path);
-	g_free (priv->subject_match);
-	g_free (priv->domain_suffix_match);
-	g_free (priv->phase1_peapver);
-	g_free (priv->phase1_peaplabel);
-	g_free (priv->phase1_fast_provisioning);
-	g_free (priv->phase2_auth);
-	g_free (priv->phase2_autheap);
-	g_free (priv->phase2_ca_path);
-	g_free (priv->phase2_subject_match);
-	g_free (priv->phase2_domain_suffix_match);
-	g_free (priv->password);
-	g_bytes_unref (priv->password_raw);
-	g_free (priv->pin);
-
-	g_slist_free_full (priv->eap, g_free);
-	g_slist_free_full (priv->altsubject_matches, g_free);
-	g_slist_free_full (priv->phase2_altsubject_matches, g_free);
-
-	g_bytes_unref (priv->ca_cert);
-	g_free (priv->ca_cert_password);
-	g_bytes_unref (priv->client_cert);
-	g_free (priv->client_cert_password);
-	g_bytes_unref (priv->private_key);
-	nm_free_secret (priv->private_key_password);
-	g_bytes_unref (priv->phase2_ca_cert);
-	g_free (priv->phase2_ca_cert_password);
-	g_bytes_unref (priv->phase2_client_cert);
-	g_free (priv->phase2_client_cert_password);
-	g_bytes_unref (priv->phase2_private_key);
-	nm_free_secret (priv->phase2_private_key_password);
-
-	G_OBJECT_CLASS (nm_setting_802_1x_parent_class)->finalize (object);
-}
-
-static void
-nm_setting_802_1x_class_init (NMSetting8021xClass *klass)
-{
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	NMSettingClass *setting_class = NM_SETTING_CLASS (klass);
-
-	g_type_class_add_private (klass, sizeof (NMSetting8021xPrivate));
+	g_type_class_add_private (setting_class, sizeof (NMSetting8021xPrivate));
 
+	/* virtual methods */
 	object_class->set_property = set_property;
 	object_class->get_property = get_property;
 	object_class->finalize     = finalize;
 
-	setting_class->verify       = verify;
-	setting_class->need_secrets = need_secrets;
+	parent_class->verify         = verify;
+	parent_class->need_secrets   = need_secrets;
+
+	/* Properties */
 
 	/**
 	 * NMSetting8021x:eap:
@@ -3440,11 +3797,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass)
 	 * example: IEEE_8021X_EAP_METHODS=PEAP
 	 * ---end---
 	 */
-	obj_properties[PROP_EAP] =
-	    g_param_spec_boxed (NM_SETTING_802_1X_EAP, "", "",
-	                        G_TYPE_STRV,
-	                        G_PARAM_READWRITE |
-	                        G_PARAM_STATIC_STRINGS);
+	g_object_class_install_property
+		(object_class, PROP_EAP,
+		 g_param_spec_boxed (NM_SETTING_802_1X_EAP, "", "",
+		                     G_TYPE_STRV,
+		                     G_PARAM_READWRITE |
+		                     G_PARAM_STATIC_STRINGS));
 
 	/**
 	 * NMSetting8021x:identity:
@@ -3459,11 +3817,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass)
 	 * example: IEEE_8021X_IDENTITY=itsme
 	 * ---end---
 	 */
-	obj_properties[PROP_IDENTITY] =
-	    g_param_spec_string (NM_SETTING_802_1X_IDENTITY, "", "",
-	                         NULL,
-	                         G_PARAM_READWRITE |
-	                         G_PARAM_STATIC_STRINGS);
+	g_object_class_install_property
+		(object_class, PROP_IDENTITY,
+		 g_param_spec_string (NM_SETTING_802_1X_IDENTITY, "", "",
+		                      NULL,
+		                      G_PARAM_READWRITE |
+		                      G_PARAM_STATIC_STRINGS));
 
 	/**
 	 * NMSetting8021x:anonymous-identity:
@@ -3478,11 +3837,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass)
 	 * description: Anonymous identity for EAP authentication methods.
 	 * ---end---
 	 */
-	obj_properties[PROP_ANONYMOUS_IDENTITY] =
-	    g_param_spec_string (NM_SETTING_802_1X_ANONYMOUS_IDENTITY, "", "",
-	                         NULL,
-	                         G_PARAM_READWRITE |
-	                         G_PARAM_STATIC_STRINGS);
+	g_object_class_install_property
+		(object_class, PROP_ANONYMOUS_IDENTITY,
+		 g_param_spec_string (NM_SETTING_802_1X_ANONYMOUS_IDENTITY, "", "",
+		                      NULL,
+		                      G_PARAM_READWRITE |
+		                      G_PARAM_STATIC_STRINGS));
 
 	/**
 	 * NMSetting8021x:pac-file:
@@ -3496,11 +3856,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass)
 	 * example: IEEE_8021X_PAC_FILE=/home/joe/my-fast.pac
 	 * ---end---
 	 */
-	obj_properties[PROP_PAC_FILE] =
-	    g_param_spec_string (NM_SETTING_802_1X_PAC_FILE, "", "",
-	                         NULL,
-	                         G_PARAM_READWRITE |
-	                         G_PARAM_STATIC_STRINGS);
+	g_object_class_install_property
+		(object_class, PROP_PAC_FILE,
+		 g_param_spec_string (NM_SETTING_802_1X_PAC_FILE, "", "",
+		                      NULL,
+		                      G_PARAM_READWRITE |
+		                      G_PARAM_STATIC_STRINGS));
 
 	/**
 	 * NMSetting8021x:ca-cert:
@@ -3527,11 +3888,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass)
 	 * example: IEEE_8021X_CA_CERT=/home/joe/cacert.crt
 	 * ---end---
 	 */
-	obj_properties[PROP_CA_CERT] =
-	    g_param_spec_boxed (NM_SETTING_802_1X_CA_CERT, "", "",
-	                        G_TYPE_BYTES,
-	                        G_PARAM_READWRITE |
-	                        G_PARAM_STATIC_STRINGS);
+	g_object_class_install_property
+		(object_class, PROP_CA_CERT,
+		 g_param_spec_boxed (NM_SETTING_802_1X_CA_CERT, "", "",
+		                     G_TYPE_BYTES,
+		                     G_PARAM_READWRITE |
+		                     G_PARAM_STATIC_STRINGS));
 
 	/**
 	 * NMSetting8021x:ca-cert-password:
@@ -3545,12 +3907,13 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass)
 	/* ---ifcfg-rh---
 	 * ---end---
 	 */
-	obj_properties[PROP_CA_CERT_PASSWORD] =
-	    g_param_spec_string (NM_SETTING_802_1X_CA_CERT_PASSWORD, "", "",
-	                         NULL,
-	                         G_PARAM_READWRITE |
-	                         NM_SETTING_PARAM_SECRET |
-	                         G_PARAM_STATIC_STRINGS);
+	g_object_class_install_property
+		(object_class, PROP_CA_CERT_PASSWORD,
+		 g_param_spec_string (NM_SETTING_802_1X_CA_CERT_PASSWORD, "", "",
+		                      NULL,
+		                      G_PARAM_READWRITE |
+		                      NM_SETTING_PARAM_SECRET |
+		                      G_PARAM_STATIC_STRINGS));
 
 	/**
 	 * NMSetting8021x:ca-cert-password-flags:
@@ -3562,12 +3925,13 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass)
 	/* ---ifcfg-rh---
 	 * ---end---
 	 */
-	obj_properties[PROP_CA_CERT_PASSWORD_FLAGS] =
-	    g_param_spec_flags (NM_SETTING_802_1X_CA_CERT_PASSWORD_FLAGS, "", "",
-	                        NM_TYPE_SETTING_SECRET_FLAGS,
-	                        NM_SETTING_SECRET_FLAG_NONE,
-	                        G_PARAM_READWRITE |
-	                        G_PARAM_STATIC_STRINGS);
+	g_object_class_install_property
+		(object_class, PROP_CA_CERT_PASSWORD_FLAGS,
+		 g_param_spec_flags (NM_SETTING_802_1X_CA_CERT_PASSWORD_FLAGS, "", "",
+		                     NM_TYPE_SETTING_SECRET_FLAGS,
+		                     NM_SETTING_SECRET_FLAG_NONE,
+		                     G_PARAM_READWRITE |
+		                     G_PARAM_STATIC_STRINGS));
 
 	/**
 	 * NMSetting8021x:ca-path:
@@ -3582,11 +3946,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass)
 	 * description: The property is not handled by ifcfg-rh plugin.
 	 * ---end---
 	 */
-	obj_properties[PROP_CA_PATH] =
-	    g_param_spec_string (NM_SETTING_802_1X_CA_PATH, "", "",
-	                         NULL,
-	                         G_PARAM_READWRITE |
-	                         G_PARAM_STATIC_STRINGS);
+	g_object_class_install_property
+		(object_class, PROP_CA_PATH,
+		 g_param_spec_string (NM_SETTING_802_1X_CA_PATH, "", "",
+		                      NULL,
+		                      G_PARAM_READWRITE |
+		                      G_PARAM_STATIC_STRINGS));
 
 	/**
 	 * NMSetting8021x:subject-match:
@@ -3604,11 +3969,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass)
 	 * example: IEEE_8021X_SUBJECT_MATCH="Red Hat"
 	 * ---end---
 	 */
-	obj_properties[PROP_SUBJECT_MATCH] =
-	    g_param_spec_string (NM_SETTING_802_1X_SUBJECT_MATCH, "", "",
-	                         NULL,
-	                         G_PARAM_READWRITE |
-	                         G_PARAM_STATIC_STRINGS);
+	g_object_class_install_property
+		(object_class, PROP_SUBJECT_MATCH,
+		 g_param_spec_string (NM_SETTING_802_1X_SUBJECT_MATCH, "", "",
+		                      NULL,
+		                      G_PARAM_READWRITE |
+		                      G_PARAM_STATIC_STRINGS));
 
 	/**
 	 * NMSetting8021x:altsubject-matches:
@@ -3624,11 +3990,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass)
 	 * example: IEEE_8021X_ALTSUBJECT_MATCHES="s1.domain.cc"
 	 * ---end---
 	 */
-	obj_properties[PROP_ALTSUBJECT_MATCHES] =
-	    g_param_spec_boxed (NM_SETTING_802_1X_ALTSUBJECT_MATCHES, "", "",
-	                        G_TYPE_STRV,
-	                        G_PARAM_READWRITE |
-	                        G_PARAM_STATIC_STRINGS);
+	g_object_class_install_property
+		(object_class, PROP_ALTSUBJECT_MATCHES,
+		 g_param_spec_boxed (NM_SETTING_802_1X_ALTSUBJECT_MATCHES, "", "",
+		                     G_TYPE_STRV,
+		                     G_PARAM_READWRITE |
+		                     G_PARAM_STATIC_STRINGS));
 
 	/**
 	 * NMSetting8021x:domain-suffix-match:
@@ -3647,11 +4014,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass)
 	 * variable: IEEE_8021X_DOMAIN_SUFFIX_MATCH(+)
 	 * ---end---
 	 */
-	obj_properties[PROP_DOMAIN_SUFFIX_MATCH] =
-	    g_param_spec_string (NM_SETTING_802_1X_DOMAIN_SUFFIX_MATCH, "", "",
-	                         NULL,
-	                         G_PARAM_READWRITE |
-	                         G_PARAM_STATIC_STRINGS);
+	g_object_class_install_property
+		(object_class, PROP_DOMAIN_SUFFIX_MATCH,
+		 g_param_spec_string (NM_SETTING_802_1X_DOMAIN_SUFFIX_MATCH, "", "",
+		                      NULL,
+		                      G_PARAM_READWRITE |
+		                      G_PARAM_STATIC_STRINGS));
 
 	/**
 	 * NMSetting8021x:client-cert:
@@ -3676,11 +4044,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass)
 	 * example: IEEE_8021X_CLIENT_CERT=/home/joe/mycert.crt
 	 * ---end---
 	 */
-	obj_properties[PROP_CLIENT_CERT] =
-	    g_param_spec_boxed (NM_SETTING_802_1X_CLIENT_CERT, "", "",
-	                        G_TYPE_BYTES,
-	                        G_PARAM_READWRITE |
-	                        G_PARAM_STATIC_STRINGS);
+	g_object_class_install_property
+		(object_class, PROP_CLIENT_CERT,
+		 g_param_spec_boxed (NM_SETTING_802_1X_CLIENT_CERT, "", "",
+		                     G_TYPE_BYTES,
+		                     G_PARAM_READWRITE |
+		                     G_PARAM_STATIC_STRINGS));
 
 	/**
 	 * NMSetting8021x:client-cert-password:
@@ -3694,12 +4063,13 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass)
 	/* ---ifcfg-rh---
 	 * ---end---
 	 */
-	obj_properties[PROP_CLIENT_CERT_PASSWORD] =
-	    g_param_spec_string (NM_SETTING_802_1X_CLIENT_CERT_PASSWORD, "", "",
-	                         NULL,
-	                         G_PARAM_READWRITE |
-	                         NM_SETTING_PARAM_SECRET |
-	                         G_PARAM_STATIC_STRINGS);
+	g_object_class_install_property
+		(object_class, PROP_CLIENT_CERT_PASSWORD,
+		 g_param_spec_string (NM_SETTING_802_1X_CLIENT_CERT_PASSWORD, "", "",
+		                      NULL,
+		                      G_PARAM_READWRITE |
+		                      NM_SETTING_PARAM_SECRET |
+		                      G_PARAM_STATIC_STRINGS));
 
 	/**
 	 * NMSetting8021x:client-cert-password-flags:
@@ -3711,12 +4081,13 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass)
 	/* ---ifcfg-rh---
 	 * ---end---
 	 */
-	obj_properties[PROP_CLIENT_CERT_PASSWORD_FLAGS] =
-	    g_param_spec_flags (NM_SETTING_802_1X_CLIENT_CERT_PASSWORD_FLAGS, "", "",
-	                        NM_TYPE_SETTING_SECRET_FLAGS,
-	                        NM_SETTING_SECRET_FLAG_NONE,
-	                        G_PARAM_READWRITE |
-	                        G_PARAM_STATIC_STRINGS);
+	g_object_class_install_property
+		(object_class, PROP_CLIENT_CERT_PASSWORD_FLAGS,
+		 g_param_spec_flags (NM_SETTING_802_1X_CLIENT_CERT_PASSWORD_FLAGS, "", "",
+		                     NM_TYPE_SETTING_SECRET_FLAGS,
+		                     NM_SETTING_SECRET_FLAG_NONE,
+		                     G_PARAM_READWRITE |
+		                     G_PARAM_STATIC_STRINGS));
 
 	/**
 	 * NMSetting8021x:phase1-peapver:
@@ -3735,11 +4106,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass)
 	 * description: Use to force a specific PEAP version.
 	 * ---end---
 	 */
-	obj_properties[PROP_PHASE1_PEAPVER] =
-	    g_param_spec_string (NM_SETTING_802_1X_PHASE1_PEAPVER, "", "",
-	                         NULL,
-	                         G_PARAM_READWRITE |
-	                         G_PARAM_STATIC_STRINGS);
+	g_object_class_install_property
+		(object_class, PROP_PHASE1_PEAPVER,
+		 g_param_spec_string (NM_SETTING_802_1X_PHASE1_PEAPVER, "", "",
+		                      NULL,
+		                      G_PARAM_READWRITE |
+		                      G_PARAM_STATIC_STRINGS));
 
 	/**
 	 * NMSetting8021x:phase1-peaplabel:
@@ -3757,11 +4129,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass)
 	 * description: Use to force the new PEAP label during key derivation.
 	 * ---end---
 	 */
-	obj_properties[PROP_PHASE1_PEAPLABEL] =
-	    g_param_spec_string (NM_SETTING_802_1X_PHASE1_PEAPLABEL, "", "",
-	                         NULL,
-	                         G_PARAM_READWRITE |
-	                         G_PARAM_STATIC_STRINGS);
+	g_object_class_install_property
+		(object_class, PROP_PHASE1_PEAPLABEL,
+		 g_param_spec_string (NM_SETTING_802_1X_PHASE1_PEAPLABEL, "", "",
+		                      NULL,
+		                      G_PARAM_READWRITE |
+		                      G_PARAM_STATIC_STRINGS));
 
 	/**
 	 * NMSetting8021x:phase1-fast-provisioning:
@@ -3781,11 +4154,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass)
 	 * example: IEEE_8021X_FAST_PROVISIONING="allow-auth allow-unauth"
 	 * ---end---
 	 */
-	obj_properties[PROP_PHASE1_FAST_PROVISIONING] =
-	    g_param_spec_string (NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING, "", "",
-	                         NULL,
-	                         G_PARAM_READWRITE |
-	                         G_PARAM_STATIC_STRINGS);
+	g_object_class_install_property
+		(object_class, PROP_PHASE1_FAST_PROVISIONING,
+		 g_param_spec_string (NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING, "", "",
+		                      NULL,
+		                      G_PARAM_READWRITE |
+		                      G_PARAM_STATIC_STRINGS));
 
 	/**
 	 * NMSetting8021x:phase1-auth-flags:
@@ -3807,12 +4181,13 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass)
 	 * example: IEEE_8021X_PHASE1_AUTH_FLAGS="tls-1-0-disable tls-1-1-disable"
 	 * ---end---
 	 */
-	obj_properties[PROP_PHASE1_AUTH_FLAGS] =
-	    g_param_spec_uint (NM_SETTING_802_1X_PHASE1_AUTH_FLAGS, "", "",
-	                       0, G_MAXUINT32, NM_SETTING_802_1X_AUTH_FLAGS_NONE,
-	                       G_PARAM_CONSTRUCT |
-	                       G_PARAM_READWRITE |
-	                       G_PARAM_STATIC_STRINGS);
+	g_object_class_install_property
+		(object_class, PROP_PHASE1_AUTH_FLAGS,
+		 g_param_spec_uint (NM_SETTING_802_1X_PHASE1_AUTH_FLAGS, "", "",
+		                    0, G_MAXUINT32, NM_SETTING_802_1X_AUTH_FLAGS_NONE,
+		                    G_PARAM_CONSTRUCT |
+		                    G_PARAM_READWRITE |
+		                    G_PARAM_STATIC_STRINGS));
 
 	/**
 	 * NMSetting8021x:phase2-auth:
@@ -3833,11 +4208,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass)
 	 * example: IEEE_8021X_INNER_AUTH_METHODS=PAP
 	 * ---end---
 	 */
-	obj_properties[PROP_PHASE2_AUTH] =
-	    g_param_spec_string (NM_SETTING_802_1X_PHASE2_AUTH, "", "",
-	                         NULL,
-	                         G_PARAM_READWRITE |
-	                         G_PARAM_STATIC_STRINGS);
+	g_object_class_install_property
+		(object_class, PROP_PHASE2_AUTH,
+		 g_param_spec_string (NM_SETTING_802_1X_PHASE2_AUTH, "", "",
+		                      NULL,
+		                      G_PARAM_READWRITE |
+		                      G_PARAM_STATIC_STRINGS));
 
 	/**
 	 * NMSetting8021x:phase2-autheap:
@@ -3858,11 +4234,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass)
 	 * example: IEEE_8021X_INNER_AUTH_METHODS="MSCHAPV2 EAP-TLS"
 	 * ---end---
 	 */
-	obj_properties[PROP_PHASE2_AUTHEAP] =
-	    g_param_spec_string (NM_SETTING_802_1X_PHASE2_AUTHEAP, "", "",
-	                         NULL,
-	                         G_PARAM_READWRITE |
-	                         G_PARAM_STATIC_STRINGS);
+	g_object_class_install_property
+		(object_class, PROP_PHASE2_AUTHEAP,
+		 g_param_spec_string (NM_SETTING_802_1X_PHASE2_AUTHEAP, "", "",
+		                      NULL,
+		                      G_PARAM_READWRITE |
+		                      G_PARAM_STATIC_STRINGS));
 
 	/**
 	 * NMSetting8021x:phase2-ca-cert:
@@ -3883,11 +4260,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass)
 	 * Setting this property directly is discouraged; use the
 	 * nm_setting_802_1x_set_phase2_ca_cert() function instead.
 	 **/
-	obj_properties[PROP_PHASE2_CA_CERT] =
-	    g_param_spec_boxed (NM_SETTING_802_1X_PHASE2_CA_CERT, "", "",
-	                        G_TYPE_BYTES,
-	                        G_PARAM_READWRITE |
-	                        G_PARAM_STATIC_STRINGS);
+	g_object_class_install_property
+		(object_class, PROP_PHASE2_CA_CERT,
+		 g_param_spec_boxed (NM_SETTING_802_1X_PHASE2_CA_CERT, "", "",
+		                     G_TYPE_BYTES,
+		                     G_PARAM_READWRITE |
+		                     G_PARAM_STATIC_STRINGS));
 
 	/**
 	 * NMSetting8021x:phase2-ca-cert-password:
@@ -3901,12 +4279,13 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass)
 	/* ---ifcfg-rh---
 	 * ---end---
 	 */
-	obj_properties[PROP_PHASE2_CA_CERT_PASSWORD] =
-	    g_param_spec_string (NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD, "", "",
-	                         NULL,
-	                         G_PARAM_READWRITE |
-	                         NM_SETTING_PARAM_SECRET |
-	                         G_PARAM_STATIC_STRINGS);
+	g_object_class_install_property
+		(object_class, PROP_PHASE2_CA_CERT_PASSWORD,
+		 g_param_spec_string (NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD, "", "",
+		                      NULL,
+		                      G_PARAM_READWRITE |
+		                      NM_SETTING_PARAM_SECRET |
+		                      G_PARAM_STATIC_STRINGS));
 
 	/**
 	 * NMSetting8021x:phase2-ca-cert-password-flags:
@@ -3918,12 +4297,13 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass)
 	/* ---ifcfg-rh---
 	 * ---end---
 	 */
-	obj_properties[PROP_PHASE2_CA_CERT_PASSWORD_FLAGS] =
-	    g_param_spec_flags (NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD_FLAGS, "", "",
-	                        NM_TYPE_SETTING_SECRET_FLAGS,
-	                        NM_SETTING_SECRET_FLAG_NONE,
-	                        G_PARAM_READWRITE |
-	                        G_PARAM_STATIC_STRINGS);
+	g_object_class_install_property
+		(object_class, PROP_PHASE2_CA_CERT_PASSWORD_FLAGS,
+		 g_param_spec_flags (NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD_FLAGS, "", "",
+		                     NM_TYPE_SETTING_SECRET_FLAGS,
+		                     NM_SETTING_SECRET_FLAG_NONE,
+		                     G_PARAM_READWRITE |
+		                     G_PARAM_STATIC_STRINGS));
 
 	/**
 	 * NMSetting8021x:phase2-ca-path:
@@ -3932,11 +4312,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass)
 	 * certificates to be added to the verification chain in addition to the
 	 * certificate specified in the #NMSetting8021x:phase2-ca-cert property.
 	 **/
-	obj_properties[PROP_PHASE2_CA_PATH] =
-	    g_param_spec_string (NM_SETTING_802_1X_PHASE2_CA_PATH, "", "",
-	                         NULL,
-	                         G_PARAM_READWRITE |
-	                         G_PARAM_STATIC_STRINGS);
+	g_object_class_install_property
+		(object_class, PROP_PHASE2_CA_PATH,
+		 g_param_spec_string (NM_SETTING_802_1X_PHASE2_CA_PATH, "", "",
+		                      NULL,
+		                      G_PARAM_READWRITE |
+		                      G_PARAM_STATIC_STRINGS));
 
 	/**
 	 * NMSetting8021x:phase2-subject-match:
@@ -3955,11 +4336,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass)
 	 * example: IEEE_8021X_PHASE2_SUBJECT_MATCH="Red Hat"
 	 * ---end---
 	 */
-	obj_properties[PROP_PHASE2_SUBJECT_MATCH] =
-	    g_param_spec_string (NM_SETTING_802_1X_PHASE2_SUBJECT_MATCH, "", "",
-	                         NULL,
-	                         G_PARAM_READWRITE |
-	                         G_PARAM_STATIC_STRINGS);
+	g_object_class_install_property
+		(object_class, PROP_PHASE2_SUBJECT_MATCH,
+		 g_param_spec_string (NM_SETTING_802_1X_PHASE2_SUBJECT_MATCH, "", "",
+		                      NULL,
+		                      G_PARAM_READWRITE |
+		                      G_PARAM_STATIC_STRINGS));
 
 	/**
 	 * NMSetting8021x:phase2-altsubject-matches:
@@ -3974,11 +4356,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass)
 	 * variable: IEEE_8021X_PHASE2_ALTSUBJECT_MATCHES(+)
 	 * ---end---
 	 */
-	obj_properties[PROP_PHASE2_ALTSUBJECT_MATCHES] =
-	    g_param_spec_boxed (NM_SETTING_802_1X_PHASE2_ALTSUBJECT_MATCHES, "", "",
-	                        G_TYPE_STRV,
-	                        G_PARAM_READWRITE |
-	                        G_PARAM_STATIC_STRINGS);
+	g_object_class_install_property
+		(object_class, PROP_PHASE2_ALTSUBJECT_MATCHES,
+		 g_param_spec_boxed (NM_SETTING_802_1X_PHASE2_ALTSUBJECT_MATCHES, "", "",
+		                     G_TYPE_STRV,
+		                     G_PARAM_READWRITE |
+		                     G_PARAM_STATIC_STRINGS));
 
 	/**
 	 * NMSetting8021x:phase2-domain-suffix-match:
@@ -3998,11 +4381,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass)
 	 * variable: IEEE_8021X_PHASE2_DOMAIN_SUFFIX_MATCH(+)
 	 * ---end---
 	 */
-	obj_properties[PROP_PHASE2_DOMAIN_SUFFIX_MATCH] =
-	    g_param_spec_string (NM_SETTING_802_1X_PHASE2_DOMAIN_SUFFIX_MATCH, "", "",
-	                         NULL,
-	                         G_PARAM_READWRITE |
-	                         G_PARAM_STATIC_STRINGS);
+	g_object_class_install_property
+		(object_class, PROP_PHASE2_DOMAIN_SUFFIX_MATCH,
+		 g_param_spec_string (NM_SETTING_802_1X_PHASE2_DOMAIN_SUFFIX_MATCH, "", "",
+		                      NULL,
+		                      G_PARAM_READWRITE |
+		                      G_PARAM_STATIC_STRINGS));
 
 	/**
 	 * NMSetting8021x:phase2-client-cert:
@@ -4030,11 +4414,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass)
 	 * example: IEEE_8021X_INNER_CLIENT_CERT=/home/joe/mycert.crt
 	 * ---end---
 	 */
-	obj_properties[PROP_PHASE2_CLIENT_CERT] =
-	    g_param_spec_boxed (NM_SETTING_802_1X_PHASE2_CLIENT_CERT, "", "",
-	                        G_TYPE_BYTES,
-	                        G_PARAM_READWRITE |
-	                        G_PARAM_STATIC_STRINGS);
+	g_object_class_install_property
+		(object_class, PROP_PHASE2_CLIENT_CERT,
+		 g_param_spec_boxed (NM_SETTING_802_1X_PHASE2_CLIENT_CERT, "", "",
+		                     G_TYPE_BYTES,
+		                     G_PARAM_READWRITE |
+		                     G_PARAM_STATIC_STRINGS));
 
 	/**
 	 * NMSetting8021x:phase2-client-cert-password:
@@ -4048,12 +4433,13 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass)
 	/* ---ifcfg-rh---
 	 * ---end---
 	 */
-	obj_properties[PROP_PHASE2_CLIENT_CERT_PASSWORD] =
-	    g_param_spec_string (NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD, "", "",
-	                         NULL,
-	                         G_PARAM_READWRITE |
-	                         NM_SETTING_PARAM_SECRET |
-	                         G_PARAM_STATIC_STRINGS);
+	g_object_class_install_property
+		(object_class, PROP_PHASE2_CLIENT_CERT_PASSWORD,
+		 g_param_spec_string (NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD, "", "",
+		                      NULL,
+		                      G_PARAM_READWRITE |
+		                      NM_SETTING_PARAM_SECRET |
+		                      G_PARAM_STATIC_STRINGS));
 
 	/**
 	 * NMSetting8021x:phase2-client-cert-password-flags:
@@ -4065,12 +4451,13 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass)
 	/* ---ifcfg-rh---
 	 * ---end---
 	 */
-	obj_properties[PROP_PHASE2_CLIENT_CERT_PASSWORD_FLAGS] =
-	    g_param_spec_flags (NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD_FLAGS, "", "",
-	                        NM_TYPE_SETTING_SECRET_FLAGS,
-	                        NM_SETTING_SECRET_FLAG_NONE,
-	                        G_PARAM_READWRITE |
-	                        G_PARAM_STATIC_STRINGS);
+	g_object_class_install_property
+		(object_class, PROP_PHASE2_CLIENT_CERT_PASSWORD_FLAGS,
+		 g_param_spec_flags (NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD_FLAGS, "", "",
+		                     NM_TYPE_SETTING_SECRET_FLAGS,
+		                     NM_SETTING_SECRET_FLAG_NONE,
+		                     G_PARAM_READWRITE |
+		                     G_PARAM_STATIC_STRINGS));
 
 	/**
 	 * NMSetting8021x:password:
@@ -4086,12 +4473,13 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass)
 	 *   lookaside file, or it can be owned by a secret agent.
 	 * ---end---
 	 */
-	obj_properties[PROP_PASSWORD] =
-	    g_param_spec_string (NM_SETTING_802_1X_PASSWORD, "", "",
-	                         NULL,
-	                         G_PARAM_READWRITE |
-	                         NM_SETTING_PARAM_SECRET |
-	                         G_PARAM_STATIC_STRINGS);
+	g_object_class_install_property
+		(object_class, PROP_PASSWORD,
+		 g_param_spec_string (NM_SETTING_802_1X_PASSWORD, "", "",
+		                      NULL,
+		                      G_PARAM_READWRITE |
+		                      NM_SETTING_PARAM_SECRET |
+		                      G_PARAM_STATIC_STRINGS));
 
 	/**
 	 * NMSetting8021x:password-flags:
@@ -4105,12 +4493,13 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass)
 	 * description: Password flags for IEEE_8021X_PASSWORD password.
 	 * ---end---
 	 */
-	obj_properties[PROP_PASSWORD_FLAGS] =
-	    g_param_spec_flags (NM_SETTING_802_1X_PASSWORD_FLAGS, "", "",
-	                        NM_TYPE_SETTING_SECRET_FLAGS,
-	                        NM_SETTING_SECRET_FLAG_NONE,
-	                        G_PARAM_READWRITE |
-	                        G_PARAM_STATIC_STRINGS);
+	g_object_class_install_property
+		(object_class, PROP_PASSWORD_FLAGS,
+		 g_param_spec_flags (NM_SETTING_802_1X_PASSWORD_FLAGS, "", "",
+		                     NM_TYPE_SETTING_SECRET_FLAGS,
+		                     NM_SETTING_SECRET_FLAG_NONE,
+		                     G_PARAM_READWRITE |
+		                     G_PARAM_STATIC_STRINGS));
 
 	/**
 	 * NMSetting8021x:password-raw:
@@ -4128,12 +4517,13 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass)
 	 * example: IEEE_8021X_PASSWORD_RAW=041c8320083aa4bf
 	 * ---end---
 	 */
-	obj_properties[PROP_PASSWORD_RAW] =
-	    g_param_spec_boxed (NM_SETTING_802_1X_PASSWORD_RAW, "", "",
-	                        G_TYPE_BYTES,
-	                        G_PARAM_READWRITE |
-	                        NM_SETTING_PARAM_SECRET |
-	                        G_PARAM_STATIC_STRINGS);
+	g_object_class_install_property
+		(object_class, PROP_PASSWORD_RAW,
+		 g_param_spec_boxed (NM_SETTING_802_1X_PASSWORD_RAW, "", "",
+		                     G_TYPE_BYTES,
+		                     G_PARAM_READWRITE |
+		                     NM_SETTING_PARAM_SECRET |
+		                     G_PARAM_STATIC_STRINGS));
 
 	/**
 	 * NMSetting8021x:password-raw-flags:
@@ -4146,12 +4536,13 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass)
 	 * description: The property is not handled by ifcfg-rh plugin.
 	 * ---end---
 	 */
-	obj_properties[PROP_PASSWORD_RAW_FLAGS] =
-	    g_param_spec_flags (NM_SETTING_802_1X_PASSWORD_RAW_FLAGS, "", "",
-	                        NM_TYPE_SETTING_SECRET_FLAGS,
-	                        NM_SETTING_SECRET_FLAG_NONE,
-	                        G_PARAM_READWRITE |
-	                        G_PARAM_STATIC_STRINGS);
+	g_object_class_install_property
+		(object_class, PROP_PASSWORD_RAW_FLAGS,
+		 g_param_spec_flags (NM_SETTING_802_1X_PASSWORD_RAW_FLAGS, "", "",
+		                     NM_TYPE_SETTING_SECRET_FLAGS,
+		                     NM_SETTING_SECRET_FLAG_NONE,
+		                     G_PARAM_READWRITE |
+		                     G_PARAM_STATIC_STRINGS));
 
 	/**
 	 * NMSetting8021x:private-key:
@@ -4191,11 +4582,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass)
 	 * example: IEEE_8021X_PRIVATE_KEY=/home/joe/mykey.p12
 	 * ---end---
 	 */
-	obj_properties[PROP_PRIVATE_KEY] =
-	    g_param_spec_boxed (NM_SETTING_802_1X_PRIVATE_KEY, "", "",
-	                        G_TYPE_BYTES,
-	                        G_PARAM_READWRITE |
-	                        G_PARAM_STATIC_STRINGS);
+	g_object_class_install_property
+		(object_class, PROP_PRIVATE_KEY,
+		 g_param_spec_boxed (NM_SETTING_802_1X_PRIVATE_KEY, "", "",
+		                     G_TYPE_BYTES,
+		                     G_PARAM_READWRITE |
+		                     G_PARAM_STATIC_STRINGS));
 
 	/**
 	 * NMSetting8021x:private-key-password:
@@ -4214,12 +4606,13 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass)
 	 *   lookaside file, or it can be owned by a secret agent.
 	 * ---end---
 	 */
-	obj_properties[PROP_PRIVATE_KEY_PASSWORD] =
-	    g_param_spec_string (NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD, "", "",
-	                         NULL,
-	                         G_PARAM_READWRITE |
-	                         NM_SETTING_PARAM_SECRET |
-	                         G_PARAM_STATIC_STRINGS);
+	g_object_class_install_property
+		(object_class, PROP_PRIVATE_KEY_PASSWORD,
+		 g_param_spec_string (NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD, "", "",
+		                      NULL,
+		                      G_PARAM_READWRITE |
+		                      NM_SETTING_PARAM_SECRET |
+		                      G_PARAM_STATIC_STRINGS));
 
 	/**
 	 * NMSetting8021x:private-key-password-flags:
@@ -4234,12 +4627,13 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass)
 	 * description: Password flags for IEEE_8021X_PRIVATE_KEY_PASSWORD password.
 	 * ---end---
 	 */
-	obj_properties[PROP_PRIVATE_KEY_PASSWORD_FLAGS] =
-	    g_param_spec_flags (NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD_FLAGS, "", "",
-	                        NM_TYPE_SETTING_SECRET_FLAGS,
-	                        NM_SETTING_SECRET_FLAG_NONE,
-	                        G_PARAM_READWRITE |
-	                        G_PARAM_STATIC_STRINGS);
+	g_object_class_install_property
+		(object_class, PROP_PRIVATE_KEY_PASSWORD_FLAGS,
+		 g_param_spec_flags (NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD_FLAGS, "", "",
+		                     NM_TYPE_SETTING_SECRET_FLAGS,
+		                     NM_SETTING_SECRET_FLAG_NONE,
+		                     G_PARAM_READWRITE |
+		                     G_PARAM_STATIC_STRINGS));
 
 	/**
 	 * NMSetting8021x:phase2-private-key:
@@ -4273,11 +4667,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass)
 	 * description: Private key for inner authentication method for EAP-TLS.
 	 * ---end---
 	 */
-	obj_properties[PROP_PHASE2_PRIVATE_KEY] =
-	    g_param_spec_boxed (NM_SETTING_802_1X_PHASE2_PRIVATE_KEY, "", "",
-	                        G_TYPE_BYTES,
-	                        G_PARAM_READWRITE |
-	                        G_PARAM_STATIC_STRINGS);
+	g_object_class_install_property
+		(object_class, PROP_PHASE2_PRIVATE_KEY,
+		 g_param_spec_boxed (NM_SETTING_802_1X_PHASE2_PRIVATE_KEY, "", "",
+		                     G_TYPE_BYTES,
+		                     G_PARAM_READWRITE |
+		                     G_PARAM_STATIC_STRINGS));
 
 	/**
 	 * NMSetting8021x:phase2-private-key-password:
@@ -4297,12 +4692,13 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass)
 	 *   lookaside file, or it can be owned by a secret agent.
 	 * ---end---
 	 */
-	obj_properties[PROP_PHASE2_PRIVATE_KEY_PASSWORD] =
-	    g_param_spec_string (NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD, "", "",
-	                         NULL,
-	                         G_PARAM_READWRITE |
-	                         NM_SETTING_PARAM_SECRET |
-	                         G_PARAM_STATIC_STRINGS);
+	g_object_class_install_property
+		(object_class, PROP_PHASE2_PRIVATE_KEY_PASSWORD,
+		 g_param_spec_string (NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD, "", "",
+		                      NULL,
+		                      G_PARAM_READWRITE |
+		                      NM_SETTING_PARAM_SECRET |
+		                      G_PARAM_STATIC_STRINGS));
 
 	/**
 	 * NMSetting8021x:phase2-private-key-password-flags:
@@ -4317,12 +4713,13 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass)
 	 * description: Password flags for IEEE_8021X_INNER_PRIVATE_KEY_PASSWORD password.
 	 * ---end---
 	 */
-	obj_properties[PROP_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS] =
-	    g_param_spec_flags (NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS, "", "",
-	                        NM_TYPE_SETTING_SECRET_FLAGS,
-	                        NM_SETTING_SECRET_FLAG_NONE,
-	                        G_PARAM_READWRITE |
-	                        G_PARAM_STATIC_STRINGS);
+	g_object_class_install_property
+		(object_class, PROP_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS,
+		 g_param_spec_flags (NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS, "", "",
+		                     NM_TYPE_SETTING_SECRET_FLAGS,
+		                     NM_SETTING_SECRET_FLAG_NONE,
+		                     G_PARAM_READWRITE |
+		                     G_PARAM_STATIC_STRINGS));
 
 	/**
 	 * NMSetting8021x:pin:
@@ -4335,12 +4732,13 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass)
 	 * description: The property is not handled by ifcfg-rh plugin.
 	 * ---end---
 	 */
-	obj_properties[PROP_PIN] =
-	    g_param_spec_string (NM_SETTING_802_1X_PIN, "", "",
-	                         NULL,
-	                         G_PARAM_READWRITE |
-	                         NM_SETTING_PARAM_SECRET |
-	                         G_PARAM_STATIC_STRINGS);
+	g_object_class_install_property
+		(object_class, PROP_PIN,
+		 g_param_spec_string (NM_SETTING_802_1X_PIN, "", "",
+		                      NULL,
+		                      G_PARAM_READWRITE |
+		                      NM_SETTING_PARAM_SECRET |
+		                      G_PARAM_STATIC_STRINGS));
 
 	/**
 	 * NMSetting8021x:pin-flags:
@@ -4353,12 +4751,13 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass)
 	 * description: The property is not handled by ifcfg-rh plugin.
 	 * ---end---
 	 */
-	obj_properties[PROP_PIN_FLAGS] =
-	    g_param_spec_flags (NM_SETTING_802_1X_PIN_FLAGS, "", "",
-	                        NM_TYPE_SETTING_SECRET_FLAGS,
-	                        NM_SETTING_SECRET_FLAG_NONE,
-	                        G_PARAM_READWRITE |
-	                        G_PARAM_STATIC_STRINGS);
+	g_object_class_install_property
+		(object_class, PROP_PIN_FLAGS,
+		 g_param_spec_flags (NM_SETTING_802_1X_PIN_FLAGS, "", "",
+		                     NM_TYPE_SETTING_SECRET_FLAGS,
+		                     NM_SETTING_SECRET_FLAG_NONE,
+		                     G_PARAM_READWRITE |
+		                     G_PARAM_STATIC_STRINGS));
 
 	/**
 	 * NMSetting8021x:system-ca-certs:
@@ -4379,12 +4778,13 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass)
 	 * description: The property is not handled by ifcfg-rh plugin.
 	 * ---end---
 	 */
-	obj_properties[PROP_SYSTEM_CA_CERTS] =
-	    g_param_spec_boolean (NM_SETTING_802_1X_SYSTEM_CA_CERTS, "", "",
-	                          FALSE,
-	                          G_PARAM_READWRITE |
-	                          G_PARAM_CONSTRUCT |
-	                          G_PARAM_STATIC_STRINGS);
+	g_object_class_install_property
+		(object_class, PROP_SYSTEM_CA_CERTS,
+		 g_param_spec_boolean (NM_SETTING_802_1X_SYSTEM_CA_CERTS, "", "",
+		                       FALSE,
+		                       G_PARAM_READWRITE |
+		                       G_PARAM_CONSTRUCT |
+		                       G_PARAM_STATIC_STRINGS));
 
 	/**
 	 * NMSetting8021x:auth-timeout:
@@ -4401,14 +4801,11 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *klass)
 	 * description: Timeout in seconds for the 802.1X authentication. Zero means the global default or 25.
 	 * ---end---
 	 */
-	obj_properties[PROP_AUTH_TIMEOUT] =
-	    g_param_spec_int (NM_SETTING_802_1X_AUTH_TIMEOUT, "", "",
-	                      0, G_MAXINT32, 0,
-	                      G_PARAM_READWRITE |
-	                      NM_SETTING_PARAM_FUZZY_IGNORE |
-	                      G_PARAM_STATIC_STRINGS);
-
-	g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
-
-	_nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_802_1X);
+	g_object_class_install_property
+		(object_class, PROP_AUTH_TIMEOUT,
+		 g_param_spec_int (NM_SETTING_802_1X_AUTH_TIMEOUT, "", "",
+		                   0, G_MAXINT32, 0,
+		                   G_PARAM_READWRITE |
+		                   NM_SETTING_PARAM_FUZZY_IGNORE |
+		                   G_PARAM_STATIC_STRINGS));
 }
diff --git a/libnm-core/nm-setting-8021x.h b/libnm-core/nm-setting-8021x.h
index 82ef5eba..986d0488 100644
--- a/libnm-core/nm-setting-8021x.h
+++ b/libnm-core/nm-setting-8021x.h
@@ -359,7 +359,7 @@ NMSetting8021xCKFormat nm_setting_802_1x_get_phase2_private_key_format   (NMSett
 NM_AVAILABLE_IN_1_8
 NMSetting8021xAuthFlags nm_setting_802_1x_get_phase1_auth_flags          (NMSetting8021x *setting);
 NM_AVAILABLE_IN_1_8
-int                    nm_setting_802_1x_get_auth_timeout                (NMSetting8021x *setting);
+gint                   nm_setting_802_1x_get_auth_timeout                (NMSetting8021x *setting);
 
 G_END_DECLS
 
diff --git a/libnm-core/nm-setting-adsl.c b/libnm-core/nm-setting-adsl.c
index 9ffff927..c2eb5db4 100644
--- a/libnm-core/nm-setting-adsl.c
+++ b/libnm-core/nm-setting-adsl.c
@@ -37,7 +37,9 @@
  * properties of ADSL connections.
  */
 
-G_DEFINE_TYPE (NMSettingAdsl, nm_setting_adsl, NM_TYPE_SETTING)
+G_DEFINE_TYPE_WITH_CODE (NMSettingAdsl, nm_setting_adsl, NM_TYPE_SETTING,
+                         _nm_register_setting (ADSL, NM_SETTING_PRIORITY_HW_BASE))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_ADSL)
 
 #define NM_SETTING_ADSL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_ADSL, NMSettingAdslPrivate))
 
@@ -344,20 +346,22 @@ get_property (GObject *object, guint prop_id,
 }
 
 static void
-nm_setting_adsl_class_init (NMSettingAdslClass *klass)
+nm_setting_adsl_class_init (NMSettingAdslClass *setting_class)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	NMSettingClass *setting_class = NM_SETTING_CLASS (klass);
+	GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+	NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
 
-	g_type_class_add_private (klass, sizeof (NMSettingAdslPrivate));
+	g_type_class_add_private (setting_class, sizeof (NMSettingAdslPrivate));
 
+	/* virtual methods */
 	object_class->set_property = set_property;
 	object_class->get_property = get_property;
 	object_class->finalize     = finalize;
+	parent_class->verify       = verify;
+	parent_class->verify_secrets = verify_secrets;
+	parent_class->need_secrets = need_secrets;
 
-	setting_class->verify         = verify;
-	setting_class->verify_secrets = verify_secrets;
-	setting_class->need_secrets   = need_secrets;
+	/* Properties */
 
 	/**
 	 * NMSettingAdsl:username:
@@ -444,6 +448,4 @@ nm_setting_adsl_class_init (NMSettingAdslClass *klass)
 		                    0, 65536, 0,
 		                    G_PARAM_READWRITE |
 		                    G_PARAM_STATIC_STRINGS));
-
-	_nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_ADSL);
 }
diff --git a/libnm-core/nm-setting-bluetooth.c b/libnm-core/nm-setting-bluetooth.c
index bbc6a83d..5b6ef3eb 100644
--- a/libnm-core/nm-setting-bluetooth.c
+++ b/libnm-core/nm-setting-bluetooth.c
@@ -43,7 +43,9 @@
  * Point (NAP) profiles.
  **/
 
-G_DEFINE_TYPE (NMSettingBluetooth, nm_setting_bluetooth, NM_TYPE_SETTING)
+G_DEFINE_TYPE_WITH_CODE (NMSettingBluetooth, nm_setting_bluetooth, NM_TYPE_SETTING,
+                         _nm_register_setting (BLUETOOTH, NM_SETTING_PRIORITY_HW_NON_BASE))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_BLUETOOTH)
 
 #define NM_SETTING_BLUETOOTH_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_BLUETOOTH, NMSettingBluetoothPrivate))
 
@@ -281,19 +283,20 @@ get_property (GObject *object, guint prop_id,
 }
 
 static void
-nm_setting_bluetooth_class_init (NMSettingBluetoothClass *klass)
+nm_setting_bluetooth_class_init (NMSettingBluetoothClass *setting_class)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	NMSettingClass *setting_class = NM_SETTING_CLASS (klass);
-	GArray *properties_override = _nm_sett_info_property_override_create_array ();
+	GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+	NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
 
-	g_type_class_add_private (klass, sizeof (NMSettingBluetoothPrivate));
+	g_type_class_add_private (setting_class, sizeof (NMSettingBluetoothPrivate));
 
+	/* virtual methods */
 	object_class->set_property = set_property;
 	object_class->get_property = get_property;
 	object_class->finalize     = finalize;
+	parent_class->verify       = verify;
 
-	setting_class->verify       = verify;
+	/* Properties */
 
 	/**
 	 * NMSettingBluetooth:bdaddr:
@@ -307,13 +310,10 @@ nm_setting_bluetooth_class_init (NMSettingBluetoothClass *klass)
 		                      G_PARAM_READWRITE |
 		                      NM_SETTING_PARAM_INFERRABLE |
 		                      G_PARAM_STATIC_STRINGS));
-
-	_properties_override_add_transform (properties_override,
-	                                    g_object_class_find_property (G_OBJECT_CLASS (setting_class),
-	                                                                  NM_SETTING_BLUETOOTH_BDADDR),
-	                                    G_VARIANT_TYPE_BYTESTRING,
-	                                    _nm_utils_hwaddr_to_dbus,
-	                                    _nm_utils_hwaddr_from_dbus);
+	_nm_setting_class_transform_property (parent_class, NM_SETTING_BLUETOOTH_BDADDR,
+	                                      G_VARIANT_TYPE_BYTESTRING,
+	                                      _nm_utils_hwaddr_to_dbus,
+	                                      _nm_utils_hwaddr_from_dbus);
 
 	/**
 	 * NMSettingBluetooth:type:
@@ -328,7 +328,4 @@ nm_setting_bluetooth_class_init (NMSettingBluetoothClass *klass)
 		                      G_PARAM_READWRITE |
 		                      NM_SETTING_PARAM_INFERRABLE |
 		                      G_PARAM_STATIC_STRINGS));
-
-	_nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_BLUETOOTH,
-	                               NULL, properties_override);
 }
diff --git a/libnm-core/nm-setting-bond.c b/libnm-core/nm-setting-bond.c
index 0c84b3a0..9b4b3641 100644
--- a/libnm-core/nm-setting-bond.c
+++ b/libnm-core/nm-setting-bond.c
@@ -57,7 +57,9 @@ typedef struct {
 	NMUtilsNamedValue *options_idx_cache;
 } NMSettingBondPrivate;
 
-G_DEFINE_TYPE (NMSettingBond, nm_setting_bond, NM_TYPE_SETTING)
+G_DEFINE_TYPE_WITH_CODE (NMSettingBond, nm_setting_bond, NM_TYPE_SETTING,
+                         _nm_register_setting (BOND, NM_SETTING_PRIORITY_HW_BASE))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_BOND)
 
 #define NM_SETTING_BOND_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_BOND, NMSettingBondPrivate))
 
@@ -178,7 +180,7 @@ nm_setting_bond_get_option (NMSettingBond *setting,
 static gboolean
 validate_int (const char *name, const char *value, const BondDefault *def)
 {
-	long num;
+	glong num;
 	guint i;
 
 	for (i = 0; i < strlen (value); i++) {
@@ -871,7 +873,7 @@ compare_property (NMSetting *setting,
                   const GParamSpec *prop_spec,
                   NMSettingCompareFlags flags)
 {
-	NMSettingClass *setting_class;
+	NMSettingClass *parent_class;
 
 	if (nm_streq0 (prop_spec->name, NM_SETTING_BOND_OPTIONS)) {
 		return options_equal (NM_SETTING_BOND (setting),
@@ -880,8 +882,9 @@ compare_property (NMSetting *setting,
 		                      flags);
 	}
 
-	setting_class = NM_SETTING_CLASS (nm_setting_bond_parent_class);
-	return setting_class->compare_property (setting, other, prop_spec, flags);
+	/* Otherwise chain up to parent to handle generic compare */
+	parent_class = NM_SETTING_CLASS (nm_setting_bond_parent_class);
+	return parent_class->compare_property (setting, other, prop_spec, flags);
 }
 
 /*****************************************************************************/
@@ -958,21 +961,21 @@ finalize (GObject *object)
 }
 
 static void
-nm_setting_bond_class_init (NMSettingBondClass *klass)
+nm_setting_bond_class_init (NMSettingBondClass *setting_class)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	NMSettingClass *setting_class = NM_SETTING_CLASS (klass);
-	GArray *properties_override = _nm_sett_info_property_override_create_array ();
+	GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+	NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
 
-	g_type_class_add_private (klass, sizeof (NMSettingBondPrivate));
+	g_type_class_add_private (setting_class, sizeof (NMSettingBondPrivate));
 
+	/* virtual methods */
 	object_class->set_property     = set_property;
 	object_class->get_property     = get_property;
 	object_class->finalize         = finalize;
+	parent_class->verify           = verify;
+	parent_class->compare_property = compare_property;
 
-	setting_class->verify           = verify;
-	setting_class->compare_property = compare_property;
-
+	/* Properties */
 	/**
 	 * NMSettingBond:options: (type GHashTable(utf8,utf8)):
 	 *
@@ -994,13 +997,10 @@ nm_setting_bond_class_init (NMSettingBondClass *klass)
 		                     G_PARAM_READWRITE |
 		                     NM_SETTING_PARAM_INFERRABLE |
 		                     G_PARAM_STATIC_STRINGS));
-
-	_properties_override_add_transform (properties_override,
-	                                    g_object_class_find_property (G_OBJECT_CLASS (setting_class),
-	                                                                  NM_SETTING_BOND_OPTIONS),
-	                                    G_VARIANT_TYPE ("a{ss}"),
-	                                    _nm_utils_strdict_to_dbus,
-	                                    _nm_utils_strdict_from_dbus);
+	 _nm_setting_class_transform_property (parent_class, NM_SETTING_BOND_OPTIONS,
+	                                       G_VARIANT_TYPE ("a{ss}"),
+	                                       _nm_utils_strdict_to_dbus,
+	                                       _nm_utils_strdict_from_dbus);
 
 	 /* ---dbus---
 	  * property: interface-name
@@ -1010,12 +1010,8 @@ nm_setting_bond_class_init (NMSettingBondClass *klass)
 	  *   bond's interface name.
 	  * ---end---
 	  */
-	_properties_override_add_dbus_only (properties_override,
-	                                    "interface-name",
-	                                    G_VARIANT_TYPE_STRING,
-	                                    _nm_setting_get_deprecated_virtual_interface_name,
-	                                    NULL);
-
-	_nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_BOND,
-	                               NULL, properties_override);
+	 _nm_setting_class_add_dbus_only_property (parent_class, "interface-name",
+	                                           G_VARIANT_TYPE_STRING,
+	                                           _nm_setting_get_deprecated_virtual_interface_name,
+	                                           NULL);
 }
diff --git a/libnm-core/nm-setting-bridge-port.c b/libnm-core/nm-setting-bridge-port.c
index 4104f8c5..3fc0e873 100644
--- a/libnm-core/nm-setting-bridge-port.c
+++ b/libnm-core/nm-setting-bridge-port.c
@@ -40,7 +40,9 @@
  * optional properties that apply to bridge ports.
  **/
 
-G_DEFINE_TYPE (NMSettingBridgePort, nm_setting_bridge_port, NM_TYPE_SETTING)
+G_DEFINE_TYPE_WITH_CODE (NMSettingBridgePort, nm_setting_bridge_port, NM_TYPE_SETTING,
+                         _nm_register_setting (BRIDGE_PORT, NM_SETTING_PRIORITY_AUX))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_BRIDGE_PORT)
 
 #define NM_SETTING_BRIDGE_PORT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_BRIDGE_PORT, NMSettingBridgePortPrivate))
 
@@ -210,18 +212,19 @@ get_property (GObject *object, guint prop_id,
 }
 
 static void
-nm_setting_bridge_port_class_init (NMSettingBridgePortClass *klass)
+nm_setting_bridge_port_class_init (NMSettingBridgePortClass *setting_class)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	NMSettingClass *setting_class = NM_SETTING_CLASS (klass);
+	GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+	NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
 
-	g_type_class_add_private (klass, sizeof (NMSettingBridgePortPrivate));
+	g_type_class_add_private (setting_class, sizeof (NMSettingBridgePortPrivate));
 
+	/* virtual methods */
 	object_class->set_property = set_property;
 	object_class->get_property = get_property;
+	parent_class->verify       = verify;
 
-	setting_class->verify = verify;
-
+	/* Properties */
 	/**
 	 * NMSettingBridgePort:priority:
 	 *
@@ -287,6 +290,4 @@ nm_setting_bridge_port_class_init (NMSettingBridgePortClass *klass)
 		                       G_PARAM_READWRITE |
 		                       NM_SETTING_PARAM_INFERRABLE |
 		                       G_PARAM_STATIC_STRINGS));
-
-	_nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_BRIDGE_PORT);
 }
diff --git a/libnm-core/nm-setting-bridge.c b/libnm-core/nm-setting-bridge.c
index 71fe2ed2..112b499f 100644
--- a/libnm-core/nm-setting-bridge.c
+++ b/libnm-core/nm-setting-bridge.c
@@ -38,7 +38,9 @@
  * necessary for bridging connections.
  **/
 
-G_DEFINE_TYPE (NMSettingBridge, nm_setting_bridge, NM_TYPE_SETTING)
+G_DEFINE_TYPE_WITH_CODE (NMSettingBridge, nm_setting_bridge, NM_TYPE_SETTING,
+                         _nm_register_setting (BRIDGE, NM_SETTING_PRIORITY_HW_BASE))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_BRIDGE)
 
 #define NM_SETTING_BRIDGE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_BRIDGE, NMSettingBridgePrivate))
 
@@ -391,20 +393,20 @@ get_property (GObject *object, guint prop_id,
 }
 
 static void
-nm_setting_bridge_class_init (NMSettingBridgeClass *klass)
+nm_setting_bridge_class_init (NMSettingBridgeClass *setting_class)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	NMSettingClass *setting_class = NM_SETTING_CLASS (klass);
-	GArray *properties_override = _nm_sett_info_property_override_create_array ();
+	GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+	NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
 
-	g_type_class_add_private (klass, sizeof (NMSettingBridgePrivate));
+	g_type_class_add_private (setting_class, sizeof (NMSettingBridgePrivate));
 
+	/* virtual methods */
 	object_class->set_property = set_property;
 	object_class->get_property = get_property;
 	object_class->finalize     = finalize;
+	parent_class->verify       = verify;
 
-	setting_class->verify = verify;
-
+	/* Properties */
 	/**
 	 * NMSettingBridge:mac-address:
 	 *
@@ -442,13 +444,10 @@ nm_setting_bridge_class_init (NMSettingBridgeClass *klass)
 		                      G_PARAM_READWRITE |
 		                      NM_SETTING_PARAM_INFERRABLE |
 		                      G_PARAM_STATIC_STRINGS));
-
-	_properties_override_add_transform (properties_override,
-	                                    g_object_class_find_property (G_OBJECT_CLASS (setting_class),
-	                                                                  NM_SETTING_BRIDGE_MAC_ADDRESS),
-	                                    G_VARIANT_TYPE_BYTESTRING,
-	                                    _nm_utils_hwaddr_to_dbus,
-	                                    _nm_utils_hwaddr_from_dbus);
+	_nm_setting_class_transform_property (parent_class, NM_SETTING_BRIDGE_MAC_ADDRESS,
+	                                      G_VARIANT_TYPE_BYTESTRING,
+	                                      _nm_utils_hwaddr_to_dbus,
+	                                      _nm_utils_hwaddr_from_dbus);
 
 	/**
 	 * NMSettingBridge:stp:
@@ -639,12 +638,8 @@ nm_setting_bridge_class_init (NMSettingBridgeClass *klass)
 	 *   bridge's interface name.
 	 * ---end---
 	 */
-	_properties_override_add_dbus_only (properties_override,
-	                                    "interface-name",
-	                                    G_VARIANT_TYPE_STRING,
-	                                    _nm_setting_get_deprecated_virtual_interface_name,
-	                                    NULL);
-
-	_nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_BRIDGE,
-	                               NULL, properties_override);
+	_nm_setting_class_add_dbus_only_property (parent_class, "interface-name",
+	                                          G_VARIANT_TYPE_STRING,
+	                                          _nm_setting_get_deprecated_virtual_interface_name,
+	                                          NULL);
 }
diff --git a/libnm-core/nm-setting-cdma.c b/libnm-core/nm-setting-cdma.c
index a5d5428d..63178951 100644
--- a/libnm-core/nm-setting-cdma.c
+++ b/libnm-core/nm-setting-cdma.c
@@ -37,7 +37,9 @@
  * networks, including those using CDMA2000/EVDO technology.
  */
 
-G_DEFINE_TYPE (NMSettingCdma, nm_setting_cdma, NM_TYPE_SETTING)
+G_DEFINE_TYPE_WITH_CODE (NMSettingCdma, nm_setting_cdma, NM_TYPE_SETTING,
+                         _nm_register_setting (CDMA, NM_SETTING_PRIORITY_HW_BASE))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_CDMA)
 
 #define NM_SETTING_CDMA_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_CDMA, NMSettingCdmaPrivate))
 
@@ -283,20 +285,22 @@ get_property (GObject *object, guint prop_id,
 }
 
 static void
-nm_setting_cdma_class_init (NMSettingCdmaClass *klass)
+nm_setting_cdma_class_init (NMSettingCdmaClass *setting_class)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	NMSettingClass *setting_class = NM_SETTING_CLASS (klass);
+	GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+	NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
 
-	g_type_class_add_private (klass, sizeof (NMSettingCdmaPrivate));
+	g_type_class_add_private (setting_class, sizeof (NMSettingCdmaPrivate));
 
+	/* virtual methods */
 	object_class->set_property = set_property;
 	object_class->get_property = get_property;
 	object_class->finalize     = finalize;
+	parent_class->verify       = verify;
+	parent_class->verify_secrets = verify_secrets;
+	parent_class->need_secrets = need_secrets;
 
-	setting_class->verify         = verify;
-	setting_class->verify_secrets = verify_secrets;
-	setting_class->need_secrets   = need_secrets;
+	/* Properties */
 
 	/**
 	 * NMSettingCdma:number:
@@ -371,5 +375,4 @@ nm_setting_cdma_class_init (NMSettingCdmaClass *klass)
 		                    NM_SETTING_PARAM_FUZZY_IGNORE |
 		                    G_PARAM_STATIC_STRINGS));
 
-	_nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_CDMA);
 }
diff --git a/libnm-core/nm-setting-connection.c b/libnm-core/nm-setting-connection.c
index 50240bc9..689ba794 100644
--- a/libnm-core/nm-setting-connection.c
+++ b/libnm-core/nm-setting-connection.c
@@ -45,7 +45,9 @@
  * a #NMSettingConnection setting.
  **/
 
-G_DEFINE_TYPE (NMSettingConnection, nm_setting_connection, NM_TYPE_SETTING)
+G_DEFINE_TYPE_WITH_CODE (NMSettingConnection, nm_setting_connection, NM_TYPE_SETTING,
+                         _nm_register_setting (CONNECTION, NM_SETTING_PRIORITY_CONNECTION))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_CONNECTION)
 
 #define NM_SETTING_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_CONNECTION, NMSettingConnectionPrivate))
 
@@ -69,9 +71,8 @@ typedef struct {
 	NMSettingConnectionAutoconnectSlaves autoconnect_slaves;
 	GSList *permissions; /* list of Permission structs */
 	gboolean autoconnect;
-	int autoconnect_priority;
-	int autoconnect_retries;
-	int multi_connect;
+	gint autoconnect_priority;
+	gint autoconnect_retries;
 	guint64 timestamp;
 	gboolean read_only;
 	char *zone;
@@ -79,9 +80,8 @@ typedef struct {
 	guint gateway_ping_timeout;
 	NMMetered metered;
 	NMSettingConnectionLldp lldp;
-	int auth_retries;
+	gint auth_retries;
 	int mdns;
-	int llmnr;
 } NMSettingConnectionPrivate;
 
 enum {
@@ -94,7 +94,6 @@ enum {
 	PROP_AUTOCONNECT,
 	PROP_AUTOCONNECT_PRIORITY,
 	PROP_AUTOCONNECT_RETRIES,
-	PROP_MULTI_CONNECT,
 	PROP_TIMESTAMP,
 	PROP_READ_ONLY,
 	PROP_ZONE,
@@ -106,7 +105,6 @@ enum {
 	PROP_METERED,
 	PROP_LLDP,
 	PROP_MDNS,
-	PROP_LLMNR,
 	PROP_STABLE_ID,
 	PROP_AUTH_RETRIES,
 
@@ -530,7 +528,7 @@ nm_setting_connection_get_autoconnect (NMSettingConnection *setting)
  *
  * Returns: the connection's autoconnect priority
  **/
-int
+gint
 nm_setting_connection_get_autoconnect_priority (NMSettingConnection *setting)
 {
 	g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), 0);
@@ -549,7 +547,7 @@ nm_setting_connection_get_autoconnect_priority (NMSettingConnection *setting)
  *
  * Since: 1.6
  **/
-int
+gint
 nm_setting_connection_get_autoconnect_retries (NMSettingConnection *setting)
 {
 	g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), -1);
@@ -558,22 +556,6 @@ nm_setting_connection_get_autoconnect_retries (NMSettingConnection *setting)
 }
 
 /**
- * nm_setting_connection_get_multi_connect:
- * @setting: the #NMSettingConnection
- *
- * Returns: the #NMSettingConnection:multi-connect property of the connection.
- *
- * Since: 1.14
- **/
-NMConnectionMultiConnect
-nm_setting_connection_get_multi_connect (NMSettingConnection *setting)
-{
-	g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), -1);
-
-	return (NMConnectionMultiConnect) NM_SETTING_CONNECTION_GET_PRIVATE (setting)->multi_connect;
-}
-
-/**
  * nm_setting_connection_get_auth_retries:
  * @setting: the #NMSettingConnection
  *
@@ -584,7 +566,7 @@ nm_setting_connection_get_multi_connect (NMSettingConnection *setting)
  *
  * Since: 1.10
  **/
-int
+gint
 nm_setting_connection_get_auth_retries (NMSettingConnection *setting)
 {
 	g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), -1);
@@ -898,23 +880,6 @@ nm_setting_connection_get_mdns (NMSettingConnection *setting)
 	return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->mdns;
 }
 
-/**
- * nm_setting_connection_get_llmnr:
- * @setting: the #NMSettingConnection
- *
- * Returns: the #NMSettingConnection:llmnr property of the setting.
- *
- * Since: 1.14
- **/
-NMSettingConnectionLlmnr
-nm_setting_connection_get_llmnr (NMSettingConnection *setting)
-{
-	g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting),
-	                      NM_SETTING_CONNECTION_LLMNR_DEFAULT);
-
-	return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->llmnr;
-}
-
 static void
 _set_error_missing_base_setting (GError **error, const char *type)
 {
@@ -1112,41 +1077,17 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
 		return FALSE;
 	}
 
-	if (   priv->mdns < (int) NM_SETTING_CONNECTION_MDNS_DEFAULT
-	    || priv->mdns > (int) NM_SETTING_CONNECTION_MDNS_YES) {
+	if (   priv->mdns < NM_SETTING_CONNECTION_MDNS_DEFAULT
+	    || priv->mdns > NM_SETTING_CONNECTION_MDNS_YES) {
 		g_set_error (error,
 		             NM_CONNECTION_ERROR,
 		             NM_CONNECTION_ERROR_INVALID_PROPERTY,
-		             _("value %d is not valid"), priv->mdns);
+		             _("mdns value %d is not valid"), priv->mdns);
 		g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME,
 		                NM_SETTING_CONNECTION_MDNS);
 		return FALSE;
 	}
 
-	if (   priv->llmnr < (int) NM_SETTING_CONNECTION_LLMNR_DEFAULT
-	    || priv->llmnr > (int) NM_SETTING_CONNECTION_LLMNR_YES) {
-		g_set_error (error,
-		             NM_CONNECTION_ERROR,
-		             NM_CONNECTION_ERROR_INVALID_PROPERTY,
-		             _("value %d is not valid"), priv->llmnr);
-		g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME,
-		                NM_SETTING_CONNECTION_LLMNR);
-		return FALSE;
-	}
-
-	if (!NM_IN_SET (priv->multi_connect, (int) NM_CONNECTION_MULTI_CONNECT_DEFAULT,
-	                                     (int) NM_CONNECTION_MULTI_CONNECT_SINGLE,
-	                                     (int) NM_CONNECTION_MULTI_CONNECT_MANUAL_MULTIPLE,
-	                                     (int) NM_CONNECTION_MULTI_CONNECT_MULTIPLE)) {
-		g_set_error (error,
-		             NM_CONNECTION_ERROR,
-		             NM_CONNECTION_ERROR_INVALID_PROPERTY,
-		             _("value %d is not valid"), priv->multi_connect);
-		g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME,
-		                NM_SETTING_CONNECTION_MULTI_CONNECT);
-		return FALSE;
-	}
-
 	/* *** errors above here should be always fatal, below NORMALIZABLE_ERROR *** */
 
 	if (!priv->uuid) {
@@ -1297,6 +1238,7 @@ compare_property (NMSetting *setting,
 	    && g_strcmp0 (prop_spec->name, NM_SETTING_CONNECTION_TIMESTAMP) == 0)
 		return TRUE;
 
+	/* Otherwise chain up to parent to handle generic compare */
 	return NM_SETTING_CLASS (nm_setting_connection_parent_class)->compare_property (setting, other, prop_spec, flags);
 }
 
@@ -1306,7 +1248,6 @@ nm_setting_connection_init (NMSettingConnection *setting)
 	NMSettingConnectionPrivate *priv = NM_SETTING_CONNECTION_GET_PRIVATE (setting);
 
 	priv->mdns = NM_SETTING_CONNECTION_MDNS_DEFAULT;
-	priv->llmnr = NM_SETTING_CONNECTION_LLMNR_DEFAULT;
 }
 
 static void
@@ -1388,9 +1329,6 @@ set_property (GObject *object, guint prop_id,
 	case PROP_AUTOCONNECT_RETRIES:
 		priv->autoconnect_retries = g_value_get_int (value);
 		break;
-	case PROP_MULTI_CONNECT:
-		priv->multi_connect = g_value_get_int (value);
-		break;
 	case PROP_TIMESTAMP:
 		priv->timestamp = g_value_get_uint64 (value);
 		break;
@@ -1431,9 +1369,6 @@ set_property (GObject *object, guint prop_id,
 	case PROP_MDNS:
 		priv->mdns = g_value_get_int (value);
 		break;
-	case PROP_LLMNR:
-		priv->llmnr = g_value_get_int (value);
-		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -1489,9 +1424,6 @@ get_property (GObject *object, guint prop_id,
 	case PROP_AUTOCONNECT_RETRIES:
 		g_value_set_int (value, nm_setting_connection_get_autoconnect_retries (setting));
 		break;
-	case PROP_MULTI_CONNECT:
-		g_value_set_int (value, priv->multi_connect);
-		break;
 	case PROP_TIMESTAMP:
 		g_value_set_uint64 (value, nm_setting_connection_get_timestamp (setting));
 		break;
@@ -1528,9 +1460,6 @@ get_property (GObject *object, guint prop_id,
 	case PROP_MDNS:
 		g_value_set_int (value, priv->mdns);
 		break;
-	case PROP_LLMNR:
-		g_value_set_int (value, priv->llmnr);
-		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -1538,20 +1467,21 @@ get_property (GObject *object, guint prop_id,
 }
 
 static void
-nm_setting_connection_class_init (NMSettingConnectionClass *klass)
+nm_setting_connection_class_init (NMSettingConnectionClass *setting_class)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	NMSettingClass *setting_class = NM_SETTING_CLASS (klass);
-	GArray *properties_override = _nm_sett_info_property_override_create_array ();
+	GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+	NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
 
-	g_type_class_add_private (klass, sizeof (NMSettingConnectionPrivate));
+	g_type_class_add_private (setting_class, sizeof (NMSettingConnectionPrivate));
 
+	/* virtual methods */
 	object_class->set_property = set_property;
 	object_class->get_property = get_property;
 	object_class->finalize     = finalize;
+	parent_class->verify       = verify;
+	parent_class->compare_property = compare_property;
 
-	setting_class->verify           = verify;
-	setting_class->compare_property = compare_property;
+	/* Properties */
 
 	/**
 	 * NMSettingConnection:id:
@@ -1688,14 +1618,11 @@ nm_setting_connection_class_init (NMSettingConnectionClass *klass)
 		                      G_PARAM_READWRITE |
 		                      NM_SETTING_PARAM_INFERRABLE |
 		                      G_PARAM_STATIC_STRINGS));
-
-	_properties_override_add_override (properties_override,
-	                                   g_object_class_find_property (G_OBJECT_CLASS (setting_class),
-	                                                                 NM_SETTING_CONNECTION_INTERFACE_NAME),
-	                                   G_VARIANT_TYPE_STRING,
-	                                   NULL,
-	                                   nm_setting_connection_set_interface_name,
-	                                   nm_setting_connection_no_interface_name);
+	_nm_setting_class_override_property (parent_class, NM_SETTING_CONNECTION_INTERFACE_NAME,
+	                                     G_VARIANT_TYPE_STRING,
+	                                     NULL,
+	                                     nm_setting_connection_set_interface_name,
+	                                     nm_setting_connection_no_interface_name);
 
 	/**
 	 * NMSettingConnection:type:
@@ -1839,30 +1766,6 @@ nm_setting_connection_class_init (NMSettingConnectionClass *klass)
 	                       G_PARAM_STATIC_STRINGS));
 
 	/**
-	 * NMSettingConnection:multi-connect:
-	 *
-	 * Specifies whether the profile can be active multiple times at a particular
-	 * moment. The value is of type #NMConnectionMultiConnect.
-	 *
-	 * Since: 1.14
-	 */
-	/* ---ifcfg-rh---
-	 * property: multi-connect
-	 * variable: MULTI_CONNECT(+)
-	 * description: whether the profile can be active on multiple devices at a given
-	 *   moment. The values are numbers corresponding to #NMConnectionMultiConnect enum.
-	 * example: ZONE=3
-	 * ---end---
-	 */
-	g_object_class_install_property
-	    (object_class, PROP_MULTI_CONNECT,
-	     g_param_spec_int (NM_SETTING_CONNECTION_MULTI_CONNECT, "", "",
-	                       G_MININT32, G_MAXINT32, NM_CONNECTION_MULTI_CONNECT_DEFAULT,
-	                       G_PARAM_READWRITE |
-	                       NM_SETTING_PARAM_FUZZY_IGNORE |
-	                       G_PARAM_STATIC_STRINGS));
-
-	/**
 	 * NMSettingConnection:timestamp:
 	 *
 	 * The time, in seconds since the Unix Epoch, that the connection was last
@@ -2141,6 +2044,8 @@ nm_setting_connection_class_init (NMSettingConnectionClass *klass)
 	 * The permitted values are: yes: register hostname and resolving
 	 * for the connection, no: disable mDNS for the interface, resolve:
 	 * do not register hostname but allow resolving of mDNS host names.
+	 * When updating this property on a currently activated connection,
+	 * the change takes effect immediately.
 	 *
 	 * This feature requires a plugin which supports mDNS. One such
 	 * plugin is dns-systemd-resolved.
@@ -2149,11 +2054,11 @@ nm_setting_connection_class_init (NMSettingConnectionClass *klass)
 	 **/
 	/* ---ifcfg-rh---
 	 * property: mdns
-	 * variable: MDNS(+)
+	 * variable: CONNECTION_MDNS(+)
 	 * values: yes,no,resolve
 	 * default: missing variable means global default
 	 * description: Whether or not mDNS is enabled for the connection
-	 * example: MDNS=yes
+	 * example: CONNECTION_MDNS=yes
 	 * ---end---
 	 */
 	g_object_class_install_property
@@ -2163,41 +2068,4 @@ nm_setting_connection_class_init (NMSettingConnectionClass *klass)
 		                   NM_SETTING_CONNECTION_MDNS_DEFAULT,
 		                   G_PARAM_READWRITE |
 		                   G_PARAM_STATIC_STRINGS));
-
-	/**
-	 * NMSettingConnection:llmnr:
-	 *
-	 * Whether Link-Local Multicast Name Resolution (LLMNR) is enabled
-	 * for the connection. LLMNR is a protocol based on the Domain Name
-	 * System (DNS) packet format that allows both IPv4 and IPv6 hosts
-	 * to perform name resolution for hosts on the same local link.
-	 *
-	 * The permitted values are: yes: register hostname and resolving
-	 * for the connection, no: disable LLMNR for the interface, resolve:
-	 * do not register hostname but allow resolving of LLMNR host names.
-	 *
-	 * This feature requires a plugin which supports LLMNR. One such
-	 * plugin is dns-systemd-resolved.
-	 *
-	 * Since: 1.14
-	 **/
-	/* ---ifcfg-rh---
-	 * property: llmnr
-	 * variable: LLMNR(+)
-	 * values: yes,no,resolve
-	 * default: missing variable means global default
-	 * description: Whether or not LLMNR is enabled for the connection
-	 * example: LLMNR=yes
-	 * ---end---
-	 */
-	g_object_class_install_property
-		(object_class, PROP_LLMNR,
-		 g_param_spec_int (NM_SETTING_CONNECTION_LLMNR, "", "",
-		                   G_MININT32, G_MAXINT32,
-		                   NM_SETTING_CONNECTION_LLMNR_DEFAULT,
-		                   G_PARAM_READWRITE |
-		                   G_PARAM_STATIC_STRINGS));
-
-	_nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_CONNECTION,
-	                               NULL, properties_override);
 }
diff --git a/libnm-core/nm-setting-connection.h b/libnm-core/nm-setting-connection.h
index b65fb67b..cf083a48 100644
--- a/libnm-core/nm-setting-connection.h
+++ b/libnm-core/nm-setting-connection.h
@@ -52,7 +52,6 @@ G_BEGIN_DECLS
 #define NM_SETTING_CONNECTION_AUTOCONNECT    "autoconnect"
 #define NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY "autoconnect-priority"
 #define NM_SETTING_CONNECTION_AUTOCONNECT_RETRIES "autoconnect-retries"
-#define NM_SETTING_CONNECTION_MULTI_CONNECT  "multi-connect"
 #define NM_SETTING_CONNECTION_TIMESTAMP      "timestamp"
 #define NM_SETTING_CONNECTION_READ_ONLY      "read-only"
 #define NM_SETTING_CONNECTION_PERMISSIONS    "permissions"
@@ -66,7 +65,6 @@ G_BEGIN_DECLS
 #define NM_SETTING_CONNECTION_LLDP           "lldp"
 #define NM_SETTING_CONNECTION_AUTH_RETRIES   "auth-retries"
 #define NM_SETTING_CONNECTION_MDNS           "mdns"
-#define NM_SETTING_CONNECTION_LLMNR          "llmnr"
 
 /* Types for property values */
 /**
@@ -119,24 +117,6 @@ typedef enum {
 } NMSettingConnectionMdns;
 
 /**
- * NMSettingConnectionLlmnr:
- * @NM_SETTING_CONNECTION_LLMNR_DEFAULT: default value
- * @NM_SETTING_CONNECTION_LLMNR_NO: disable LLMNR
- * @NM_SETTING_CONNECTION_LLMNR_RESOLVE: support only resolving, do not register hostname
- * @NM_SETTING_CONNECTION_LLMNR_YES: enable LLMNR
- *
- * #NMSettingConnectionLlmnr values indicate whether LLMNR should be enabled.
- *
- * Since: 1.14
- */
-typedef enum {
-	NM_SETTING_CONNECTION_LLMNR_DEFAULT      = -1,
-	NM_SETTING_CONNECTION_LLMNR_NO           = 0,
-	NM_SETTING_CONNECTION_LLMNR_RESOLVE      = 1,
-	NM_SETTING_CONNECTION_LLMNR_YES          = 2,
-} NMSettingConnectionLlmnr;
-
-/**
  * NMSettingConnection:
  *
  * General Connection Profile Settings
@@ -162,11 +142,9 @@ const char *nm_setting_connection_get_stable_id        (NMSettingConnection *set
 const char *nm_setting_connection_get_interface_name   (NMSettingConnection *setting);
 const char *nm_setting_connection_get_connection_type  (NMSettingConnection *setting);
 gboolean    nm_setting_connection_get_autoconnect      (NMSettingConnection *setting);
-int         nm_setting_connection_get_autoconnect_priority (NMSettingConnection *setting);
+gint        nm_setting_connection_get_autoconnect_priority (NMSettingConnection *setting);
 NM_AVAILABLE_IN_1_6
-int         nm_setting_connection_get_autoconnect_retries (NMSettingConnection *setting);
-NM_AVAILABLE_IN_1_14
-NMConnectionMultiConnect nm_setting_connection_get_multi_connect (NMSettingConnection *setting);
+gint        nm_setting_connection_get_autoconnect_retries (NMSettingConnection *setting);
 guint64     nm_setting_connection_get_timestamp        (NMSettingConnection *setting);
 gboolean    nm_setting_connection_get_read_only        (NMSettingConnection *setting);
 
@@ -209,13 +187,10 @@ NM_AVAILABLE_IN_1_2
 NMSettingConnectionLldp nm_setting_connection_get_lldp (NMSettingConnection *setting);
 
 NM_AVAILABLE_IN_1_10
-int         nm_setting_connection_get_auth_retries     (NMSettingConnection *setting);
+gint        nm_setting_connection_get_auth_retries     (NMSettingConnection *setting);
 
 NM_AVAILABLE_IN_1_12
 NMSettingConnectionMdns   nm_setting_connection_get_mdns (NMSettingConnection *setting);
-NM_AVAILABLE_IN_1_14
-NMSettingConnectionLlmnr  nm_setting_connection_get_llmnr (NMSettingConnection *setting);
-
 G_END_DECLS
 
 #endif /* __NM_SETTING_CONNECTION_H__ */
diff --git a/libnm-core/nm-setting-dcb.c b/libnm-core/nm-setting-dcb.c
index dabcbbaf..491d9151 100644
--- a/libnm-core/nm-setting-dcb.c
+++ b/libnm-core/nm-setting-dcb.c
@@ -40,20 +40,22 @@
  * of storage technologies like Fibre Channel over Ethernet (FCoE) and iSCSI.
  **/
 
-G_DEFINE_TYPE (NMSettingDcb, nm_setting_dcb, NM_TYPE_SETTING)
+G_DEFINE_TYPE_WITH_CODE (NMSettingDcb, nm_setting_dcb, NM_TYPE_SETTING,
+                         _nm_register_setting (DCB, NM_SETTING_PRIORITY_HW_AUX))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_DCB)
 
 #define NM_SETTING_DCB_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_DCB, NMSettingDcbPrivate))
 
 typedef struct {
 	NMSettingDcbFlags app_fcoe_flags;
-	int               app_fcoe_priority;
+	gint              app_fcoe_priority;
 	char *            app_fcoe_mode;
 
 	NMSettingDcbFlags app_iscsi_flags;
-	int               app_iscsi_priority;
+	gint              app_iscsi_priority;
 
 	NMSettingDcbFlags app_fip_flags;
-	int               app_fip_priority;
+	gint              app_fip_priority;
 
 	/* Priority Flow Control */
 	NMSettingDcbFlags pfc_flags;
@@ -126,7 +128,7 @@ nm_setting_dcb_get_app_fcoe_flags (NMSettingDcb *setting)
  *
  * Returns: the #NMSettingDcb:app-fcoe-priority property of the setting
  **/
-int
+gint
 nm_setting_dcb_get_app_fcoe_priority (NMSettingDcb *setting)
 {
 	g_return_val_if_fail (NM_IS_SETTING_DCB (setting), 0);
@@ -168,7 +170,7 @@ nm_setting_dcb_get_app_iscsi_flags (NMSettingDcb *setting)
  *
  * Returns: the #NMSettingDcb:app-iscsi-priority property of the setting
  **/
-int
+gint
 nm_setting_dcb_get_app_iscsi_priority (NMSettingDcb *setting)
 {
 	g_return_val_if_fail (NM_IS_SETTING_DCB (setting), 0);
@@ -196,7 +198,7 @@ nm_setting_dcb_get_app_fip_flags (NMSettingDcb *setting)
  *
  * Returns: the #NMSettingDcb:app-fip-priority property of the setting
  **/
-int
+gint
 nm_setting_dcb_get_app_fip_priority (NMSettingDcb *setting)
 {
 	g_return_val_if_fail (NM_IS_SETTING_DCB (setting), 0);
@@ -592,7 +594,7 @@ check_uint_array (const guint *array,
 }
 
 static gboolean
-check_priority (int val,
+check_priority (gint val,
                 NMSettingDcbFlags flags,
                 const char *prop_name,
                 GError **error)
@@ -905,20 +907,20 @@ finalize (GObject *object)
 }
 
 static void
-nm_setting_dcb_class_init (NMSettingDcbClass *klass)
+nm_setting_dcb_class_init (NMSettingDcbClass *setting_class)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	NMSettingClass *setting_class = NM_SETTING_CLASS (klass);
-	GArray *properties_override = _nm_sett_info_property_override_create_array ();
+	GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+	NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
 
-	g_type_class_add_private (klass, sizeof (NMSettingDcbPrivate));
+	g_type_class_add_private (setting_class, sizeof (NMSettingDcbPrivate));
 
+	/* virtual methods */
 	object_class->set_property = set_property;
 	object_class->get_property = get_property;
 	object_class->finalize = finalize;
+	parent_class->verify       = verify;
 
-	setting_class->verify = verify;
-
+	/* Properties */
 	/**
 	 * NMSettingDcb:app-fcoe-flags:
 	 *
@@ -1117,13 +1119,10 @@ nm_setting_dcb_class_init (NMSettingDcbClass *klass)
 		                     G_TYPE_ARRAY,
 		                     G_PARAM_READWRITE |
 		                     G_PARAM_STATIC_STRINGS));
-
-	_properties_override_add_transform (properties_override,
-	                                    g_object_class_find_property (G_OBJECT_CLASS (setting_class),
-	                                                                  NM_SETTING_DCB_PRIORITY_FLOW_CONTROL),
-	                                    G_VARIANT_TYPE ("au"),
-	                                    _nm_setting_dcb_uint_array_to_dbus,
-	                                    _nm_setting_dcb_uint_array_from_dbus);
+	_nm_setting_class_transform_property (parent_class, NM_SETTING_DCB_PRIORITY_FLOW_CONTROL,
+	                                      G_VARIANT_TYPE ("au"),
+	                                      _nm_setting_dcb_uint_array_to_dbus,
+	                                      _nm_setting_dcb_uint_array_from_dbus);
 
 	/**
 	 * NMSettingDcb:priority-group-flags:
@@ -1168,13 +1167,10 @@ nm_setting_dcb_class_init (NMSettingDcbClass *klass)
 		                     G_TYPE_ARRAY,
 		                     G_PARAM_READWRITE |
 		                     G_PARAM_STATIC_STRINGS));
-
-	_properties_override_add_transform (properties_override,
-	                                    g_object_class_find_property (G_OBJECT_CLASS (setting_class),
-	                                                                  NM_SETTING_DCB_PRIORITY_GROUP_ID),
-	                                    G_VARIANT_TYPE ("au"),
-	                                    _nm_setting_dcb_uint_array_to_dbus,
-	                                    _nm_setting_dcb_uint_array_from_dbus);
+	_nm_setting_class_transform_property (parent_class, NM_SETTING_DCB_PRIORITY_GROUP_ID,
+	                                      G_VARIANT_TYPE ("au"),
+	                                      _nm_setting_dcb_uint_array_to_dbus,
+	                                      _nm_setting_dcb_uint_array_from_dbus);
 
 	/**
 	 * NMSettingDcb:priority-group-bandwidth: (type GArray(guint))
@@ -1197,13 +1193,10 @@ nm_setting_dcb_class_init (NMSettingDcbClass *klass)
 		                     G_TYPE_ARRAY,
 		                     G_PARAM_READWRITE |
 		                     G_PARAM_STATIC_STRINGS));
-
-	_properties_override_add_transform (properties_override,
-	                                    g_object_class_find_property (G_OBJECT_CLASS (setting_class),
-	                                                                  NM_SETTING_DCB_PRIORITY_GROUP_BANDWIDTH),
-	                                    G_VARIANT_TYPE ("au"),
-	                                    _nm_setting_dcb_uint_array_to_dbus,
-	                                    _nm_setting_dcb_uint_array_from_dbus);
+	_nm_setting_class_transform_property (parent_class, NM_SETTING_DCB_PRIORITY_GROUP_BANDWIDTH,
+	                                      G_VARIANT_TYPE ("au"),
+	                                      _nm_setting_dcb_uint_array_to_dbus,
+	                                      _nm_setting_dcb_uint_array_from_dbus);
 
 	/**
 	 * NMSettingDcb:priority-bandwidth: (type GArray(guint))
@@ -1228,13 +1221,10 @@ nm_setting_dcb_class_init (NMSettingDcbClass *klass)
 		                     G_TYPE_ARRAY,
 		                     G_PARAM_READWRITE |
 		                     G_PARAM_STATIC_STRINGS));
-
-	_properties_override_add_transform (properties_override,
-	                                    g_object_class_find_property (G_OBJECT_CLASS (setting_class),
-	                                                                  NM_SETTING_DCB_PRIORITY_BANDWIDTH),
-	                                    G_VARIANT_TYPE ("au"),
-	                                    _nm_setting_dcb_uint_array_to_dbus,
-	                                    _nm_setting_dcb_uint_array_from_dbus);
+	_nm_setting_class_transform_property (parent_class, NM_SETTING_DCB_PRIORITY_BANDWIDTH,
+	                                      G_VARIANT_TYPE ("au"),
+	                                      _nm_setting_dcb_uint_array_to_dbus,
+	                                      _nm_setting_dcb_uint_array_from_dbus);
 
 	/**
 	 * NMSettingDcb:priority-strict-bandwidth: (type GArray(gboolean))
@@ -1257,13 +1247,10 @@ nm_setting_dcb_class_init (NMSettingDcbClass *klass)
 		                     G_TYPE_ARRAY,
 		                     G_PARAM_READWRITE |
 		                     G_PARAM_STATIC_STRINGS));
-
-	_properties_override_add_transform (properties_override,
-	                                    g_object_class_find_property (G_OBJECT_CLASS (setting_class),
-	                                                                  NM_SETTING_DCB_PRIORITY_STRICT_BANDWIDTH),
-	                                    G_VARIANT_TYPE ("au"),
-	                                    _nm_setting_dcb_uint_array_to_dbus,
-	                                    _nm_setting_dcb_uint_array_from_dbus);
+	_nm_setting_class_transform_property (parent_class, NM_SETTING_DCB_PRIORITY_STRICT_BANDWIDTH,
+	                                      G_VARIANT_TYPE ("au"),
+	                                      _nm_setting_dcb_uint_array_to_dbus,
+	                                      _nm_setting_dcb_uint_array_from_dbus);
 
 	/**
 	 * NMSettingDcb:priority-traffic-class: (type GArray(guint))
@@ -1285,14 +1272,8 @@ nm_setting_dcb_class_init (NMSettingDcbClass *klass)
 		                     G_TYPE_ARRAY,
 		                     G_PARAM_READWRITE |
 		                     G_PARAM_STATIC_STRINGS));
-
-	_properties_override_add_transform (properties_override,
-	                                    g_object_class_find_property (G_OBJECT_CLASS (setting_class),
-	                                                                  NM_SETTING_DCB_PRIORITY_TRAFFIC_CLASS),
-	                                    G_VARIANT_TYPE ("au"),
-	                                    _nm_setting_dcb_uint_array_to_dbus,
-	                                    _nm_setting_dcb_uint_array_from_dbus);
-
-	_nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_DCB,
-	                               NULL, properties_override);
+	_nm_setting_class_transform_property (parent_class, NM_SETTING_DCB_PRIORITY_TRAFFIC_CLASS,
+	                                      G_VARIANT_TYPE ("au"),
+	                                      _nm_setting_dcb_uint_array_to_dbus,
+	                                      _nm_setting_dcb_uint_array_from_dbus);
 }
diff --git a/libnm-core/nm-setting-dcb.h b/libnm-core/nm-setting-dcb.h
index 92ca2682..51a883fb 100644
--- a/libnm-core/nm-setting-dcb.h
+++ b/libnm-core/nm-setting-dcb.h
@@ -112,14 +112,14 @@ GType nm_setting_dcb_get_type (void);
 NMSetting *       nm_setting_dcb_new                      (void);
 
 NMSettingDcbFlags nm_setting_dcb_get_app_fcoe_flags     (NMSettingDcb *setting);
-int               nm_setting_dcb_get_app_fcoe_priority  (NMSettingDcb *setting);
+gint              nm_setting_dcb_get_app_fcoe_priority  (NMSettingDcb *setting);
 const char *      nm_setting_dcb_get_app_fcoe_mode      (NMSettingDcb *setting);
 
 NMSettingDcbFlags nm_setting_dcb_get_app_iscsi_flags    (NMSettingDcb *setting);
-int               nm_setting_dcb_get_app_iscsi_priority (NMSettingDcb *setting);
+gint              nm_setting_dcb_get_app_iscsi_priority (NMSettingDcb *setting);
 
 NMSettingDcbFlags nm_setting_dcb_get_app_fip_flags      (NMSettingDcb *setting);
-int               nm_setting_dcb_get_app_fip_priority   (NMSettingDcb *setting);
+gint              nm_setting_dcb_get_app_fip_priority   (NMSettingDcb *setting);
 
 /* Priority Flow Control */
 NMSettingDcbFlags nm_setting_dcb_get_priority_flow_control_flags    (NMSettingDcb *setting);
diff --git a/libnm-core/nm-setting-dummy.c b/libnm-core/nm-setting-dummy.c
index 9ae05ec4..4b3c41f0 100644
--- a/libnm-core/nm-setting-dummy.c
+++ b/libnm-core/nm-setting-dummy.c
@@ -34,7 +34,9 @@
  * necessary for connection to dummy devices
  **/
 
-G_DEFINE_TYPE (NMSettingDummy, nm_setting_dummy, NM_TYPE_SETTING)
+G_DEFINE_TYPE_WITH_CODE (NMSettingDummy, nm_setting_dummy, NM_TYPE_SETTING,
+                         _nm_register_setting (DUMMY, NM_SETTING_PRIORITY_HW_BASE))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_DUMMY)
 
 /**
  * nm_setting_dummy_new:
@@ -66,11 +68,9 @@ nm_setting_dummy_init (NMSettingDummy *setting)
 }
 
 static void
-nm_setting_dummy_class_init (NMSettingDummyClass *klass)
+nm_setting_dummy_class_init (NMSettingDummyClass *setting_class)
 {
-	NMSettingClass *setting_class = NM_SETTING_CLASS (klass);
+	NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
 
-	setting_class->verify = verify;
-
-	_nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_DUMMY);
+	parent_class->verify           = verify;
 }
diff --git a/libnm-core/nm-setting-ethtool.c b/libnm-core/nm-setting-ethtool.c
deleted file mode 100644
index 7bdbcb1a..00000000
--- a/libnm-core/nm-setting-ethtool.c
+++ /dev/null
@@ -1,342 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-
-/*
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA.
- *
- * Copyright 2018 Red Hat, Inc.
- */
-
-#include "nm-default.h"
-
-#include "nm-setting-ethtool.h"
-
-#include "nm-setting-private.h"
-#include "nm-ethtool-utils.h"
-
-/*****************************************************************************/
-
-/**
- * SECTION:nm-setting-ethtool
- * @short_description: Describes connection properties for ethtool related options
- *
- * The #NMSettingEthtool object is a #NMSetting subclass that describes properties
- * to control network driver and hardware settings.
- **/
-
-/*****************************************************************************/
-
-/**
- * nm_ethtool_optname_is_feature:
- * @optname: the option name to check
- *
- * Checks whether @optname is a valid option name for an offload feature.
- *
- * %Returns: %TRUE, if @optname is valid
- *
- * Since: 1.14
- */
-gboolean
-nm_ethtool_optname_is_feature (const char *optname)
-{
-	return optname && nm_ethtool_id_is_feature (nm_ethtool_id_get_by_name (optname));
-}
-
-/*****************************************************************************/
-
-/**
- * NMSettingEthtool:
- *
- * Ethtool Ethernet Settings
- *
- * Since: 1.14
- */
-struct _NMSettingEthtool {
-	NMSetting parent;
-};
-
-struct _NMSettingEthtoolClass {
-	NMSettingClass parent;
-};
-
-G_DEFINE_TYPE (NMSettingEthtool, nm_setting_ethtool, NM_TYPE_SETTING)
-
-#define NM_SETTING_ETHTOOL_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMSettingEthtool, NM_IS_SETTING_ETHTOOL, NMSetting)
-
-/*****************************************************************************/
-
-static void
-_notify_attributes (NMSettingEthtool *self)
-{
-	_nm_setting_gendata_notify (NM_SETTING (self), TRUE);
-}
-
-/*****************************************************************************/
-
-/**
- * nm_setting_ethtool_get_feature:
- * @setting: the #NMSettingEthtool
- * @optname: option name of the offload feature to get
- *
- * Gets and offload feature setting. Returns %NM_TERNARY_DEFAULT if the
- * feature is not set.
- *
- * Returns: a #NMTernary value indicating whether the offload feature
- *   is enabled, disabled, or left untouched.
- *
- * Since: 1.14
- */
-NMTernary
-nm_setting_ethtool_get_feature (NMSettingEthtool *setting,
-                                const char *optname)
-{
-	GVariant *v;
-
-	g_return_val_if_fail (NM_IS_SETTING_ETHTOOL (setting), NM_TERNARY_DEFAULT);
-	g_return_val_if_fail (optname && nm_ethtool_optname_is_feature (optname), NM_TERNARY_DEFAULT);
-
-	v = nm_setting_gendata_get (NM_SETTING (setting), optname);
-	if (   v
-	    && g_variant_is_of_type (v, G_VARIANT_TYPE_BOOLEAN)) {
-		return g_variant_get_boolean (v)
-		       ? NM_TERNARY_TRUE
-		       : NM_TERNARY_FALSE;
-	}
-	return NM_TERNARY_DEFAULT;
-}
-
-/**
- * nm_setting_ethtool_set_feature:
- * @setting: the #NMSettingEthtool
- * @optname: option name of the offload feature to get
- * @value: the new value to set. The special value %NM_TERNARY_DEFAULT
- *   means to clear the offload feature setting.
- *
- * Sets and offload feature setting.
- *
- * Since: 1.14
- */
-void
-nm_setting_ethtool_set_feature (NMSettingEthtool *setting,
-                                const char *optname,
-                                NMTernary value)
-{
-	GHashTable *hash;
-	GVariant *v;
-
-	g_return_if_fail (NM_IS_SETTING_ETHTOOL (setting));
-	g_return_if_fail (optname && nm_ethtool_optname_is_feature (optname));
-	g_return_if_fail (NM_IN_SET (value, NM_TERNARY_DEFAULT,
-	                                    NM_TERNARY_FALSE,
-	                                    NM_TERNARY_TRUE));
-
-	hash = _nm_setting_gendata_hash (NM_SETTING (setting),
-	                                 value != NM_TERNARY_DEFAULT);
-
-	if (value == NM_TERNARY_DEFAULT) {
-		if (hash) {
-			if (g_hash_table_remove (hash, optname))
-				_notify_attributes (setting);
-		}
-		return;
-	}
-
-	v = g_hash_table_lookup (hash, optname);
-	if (   v
-	    && g_variant_is_of_type (v, G_VARIANT_TYPE_BOOLEAN)) {
-		if (g_variant_get_boolean (v)) {
-			if (value == NM_TERNARY_TRUE)
-				return;
-		} else {
-			if (value == NM_TERNARY_FALSE)
-				return;
-		}
-	}
-
-	v = g_variant_ref_sink (g_variant_new_boolean (value != NM_TERNARY_FALSE));
-	g_hash_table_insert (hash,
-	                     g_strdup (optname),
-	                     v);
-	_notify_attributes (setting);
-}
-
-/**
- * nm_setting_ethtool_clear_features:
- * @setting: the #NMSettingEthtool
- *
- * Clears all offload features settings
- *
- * Since: 1.14
- */
-void
-nm_setting_ethtool_clear_features (NMSettingEthtool *setting)
-{
-	GHashTable *hash;
-	GHashTableIter iter;
-	const char *name;
-	gboolean changed = FALSE;
-
-	g_return_if_fail (NM_IS_SETTING_ETHTOOL (setting));
-
-	hash = _nm_setting_gendata_hash (NM_SETTING (setting), FALSE);
-	if (!hash)
-		return;
-
-	g_hash_table_iter_init (&iter, hash);
-	while (g_hash_table_iter_next (&iter, (gpointer *) &name, NULL)) {
-		if (nm_ethtool_optname_is_feature (name)) {
-			g_hash_table_iter_remove (&iter);
-			changed = TRUE;
-		}
-	}
-
-	if (changed)
-		_notify_attributes (setting);
-}
-
-guint
-nm_setting_ethtool_init_features (NMSettingEthtool *setting,
-                                  NMTernary *requested /* indexed by NMEthtoolID - _NM_ETHTOOL_ID_FEATURE_FIRST */)
-{
-	GHashTable *hash;
-	GHashTableIter iter;
-	guint i;
-	guint n_req = 0;
-	const char *name;
-	GVariant *variant;
-
-	nm_assert (NM_IS_SETTING_ETHTOOL (setting));
-	nm_assert (requested);
-
-	for (i = 0; i < _NM_ETHTOOL_ID_FEATURE_NUM; i++)
-		requested[i] = NM_TERNARY_DEFAULT;
-
-	hash = _nm_setting_gendata_hash (NM_SETTING (setting), FALSE);
-	if (!hash)
-		return 0;
-
-	g_hash_table_iter_init (&iter, hash);
-	while (g_hash_table_iter_next (&iter, (gpointer *) &name, (gpointer *) &variant)) {
-		NMEthtoolID ethtool_id = nm_ethtool_id_get_by_name (name);
-
-		if (!nm_ethtool_id_is_feature (ethtool_id))
-			continue;
-		if (!g_variant_is_of_type (variant, G_VARIANT_TYPE_BOOLEAN))
-			continue;
-
-		requested[ethtool_id - _NM_ETHTOOL_ID_FEATURE_FIRST] = g_variant_get_boolean (variant)
-		                                                       ? NM_TERNARY_TRUE
-		                                                       : NM_TERNARY_FALSE;
-		n_req++;
-	}
-
-	return n_req;
-}
-
-/*****************************************************************************/
-
-static gboolean
-verify (NMSetting *setting, NMConnection *connection, GError **error)
-{
-	GHashTable *hash;
-	GHashTableIter iter;
-	const char *optname;
-	GVariant *variant;
-
-	hash = _nm_setting_gendata_hash (setting, FALSE);
-
-	if (!hash)
-		goto out;
-
-	g_hash_table_iter_init (&iter, hash);
-	while (g_hash_table_iter_next (&iter, (gpointer *) &optname, (gpointer *) &variant)) {
-		if (!nm_ethtool_optname_is_feature (optname)) {
-			g_set_error_literal (error,
-			                     NM_CONNECTION_ERROR,
-			                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
-			                     _("unsupported offload feature"));
-			g_prefix_error (error, "%s.%s: ", NM_SETTING_ETHTOOL_SETTING_NAME, optname);
-			return FALSE;
-		}
-		if (!g_variant_is_of_type (variant, G_VARIANT_TYPE_BOOLEAN)) {
-			g_set_error_literal (error,
-			                     NM_CONNECTION_ERROR,
-			                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
-			                     _("offload feature has invalid variant type"));
-			g_prefix_error (error, "%s.%s: ", NM_SETTING_ETHTOOL_SETTING_NAME, optname);
-			return FALSE;
-		}
-	}
-
-out:
-	return TRUE;
-}
-
-/*****************************************************************************/
-
-static const GVariantType *
-get_variant_type (const NMSettInfoSetting *sett_info,
-                  const char *name,
-                  GError **error)
-{
-	if (nm_ethtool_optname_is_feature (name))
-		return G_VARIANT_TYPE_BOOLEAN;
-
-	g_set_error (error,
-	             NM_CONNECTION_ERROR,
-	             NM_CONNECTION_ERROR_INVALID_PROPERTY,
-	             _("unknown ethtool option '%s'"),
-	             name);
-	return NULL;
-}
-
-/*****************************************************************************/
-
-static void
-nm_setting_ethtool_init (NMSettingEthtool *setting)
-{
-}
-
-/**
- * nm_setting_ethtool_new:
- *
- * Creates a new #NMSettingEthtool object with default values.
- *
- * Returns: (transfer full): the new empty #NMSettingEthtool object
- *
- * Since: 1.14
- **/
-NMSetting *
-nm_setting_ethtool_new (void)
-{
-	return g_object_new (NM_TYPE_SETTING_ETHTOOL, NULL);
-}
-
-static void
-nm_setting_ethtool_class_init (NMSettingEthtoolClass *klass)
-{
-	NMSettingClass *setting_class = NM_SETTING_CLASS (klass);
-
-	setting_class->verify = verify;
-
-	_nm_setting_class_commit_full (setting_class,
-	                               NM_META_SETTING_TYPE_ETHTOOL,
-	                               NM_SETT_INFO_SETT_DETAIL (
-	                                 .gendata_info = NM_SETT_INFO_SETT_GENDATA (
-	                                     .get_variant_type = get_variant_type,
-	                                 ),
-	                               ),
-	                               NULL);
-}
diff --git a/libnm-core/nm-setting-ethtool.h b/libnm-core/nm-setting-ethtool.h
deleted file mode 100644
index 66a94489..00000000
--- a/libnm-core/nm-setting-ethtool.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-/*
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA.
- *
- * Copyright 2018 Red Hat, Inc.
- */
-
-#ifndef __NM_SETTING_ETHTOOL_H__
-#define __NM_SETTING_ETHTOOL_H__
-
-#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION)
-#error "Only <NetworkManager.h> can be included directly."
-#endif
-
-#include "nm-setting.h"
-
-G_BEGIN_DECLS
-
-/*****************************************************************************/
-
-#define NM_ETHTOOL_OPTNAME_FEATURE_ESP_HW_OFFLOAD               "feature-esp-hw-offload"
-#define NM_ETHTOOL_OPTNAME_FEATURE_ESP_TX_CSUM_HW_OFFLOAD       "feature-esp-tx-csum-hw-offload"
-#define NM_ETHTOOL_OPTNAME_FEATURE_FCOE_MTU                     "feature-fcoe-mtu"
-#define NM_ETHTOOL_OPTNAME_FEATURE_GRO                          "feature-gro"
-#define NM_ETHTOOL_OPTNAME_FEATURE_GSO                          "feature-gso"
-#define NM_ETHTOOL_OPTNAME_FEATURE_HIGHDMA                      "feature-highdma"
-#define NM_ETHTOOL_OPTNAME_FEATURE_HW_TC_OFFLOAD                "feature-hw-tc-offload"
-#define NM_ETHTOOL_OPTNAME_FEATURE_L2_FWD_OFFLOAD               "feature-l2-fwd-offload"
-#define NM_ETHTOOL_OPTNAME_FEATURE_LOOPBACK                     "feature-loopback"
-#define NM_ETHTOOL_OPTNAME_FEATURE_LRO                          "feature-lro"
-#define NM_ETHTOOL_OPTNAME_FEATURE_NTUPLE                       "feature-ntuple"
-#define NM_ETHTOOL_OPTNAME_FEATURE_RX                           "feature-rx"
-#define NM_ETHTOOL_OPTNAME_FEATURE_RXHASH                       "feature-rxhash"
-#define NM_ETHTOOL_OPTNAME_FEATURE_RXVLAN                       "feature-rxvlan"
-#define NM_ETHTOOL_OPTNAME_FEATURE_RX_ALL                       "feature-rx-all"
-#define NM_ETHTOOL_OPTNAME_FEATURE_RX_FCS                       "feature-rx-fcs"
-#define NM_ETHTOOL_OPTNAME_FEATURE_RX_GRO_HW                    "feature-rx-gro-hw"
-#define NM_ETHTOOL_OPTNAME_FEATURE_RX_UDP_TUNNEL_PORT_OFFLOAD   "feature-rx-udp_tunnel-port-offload"
-#define NM_ETHTOOL_OPTNAME_FEATURE_RX_VLAN_FILTER               "feature-rx-vlan-filter"
-#define NM_ETHTOOL_OPTNAME_FEATURE_RX_VLAN_STAG_FILTER          "feature-rx-vlan-stag-filter"
-#define NM_ETHTOOL_OPTNAME_FEATURE_RX_VLAN_STAG_HW_PARSE        "feature-rx-vlan-stag-hw-parse"
-#define NM_ETHTOOL_OPTNAME_FEATURE_SG                           "feature-sg"
-#define NM_ETHTOOL_OPTNAME_FEATURE_TLS_HW_RECORD                "feature-tls-hw-record"
-#define NM_ETHTOOL_OPTNAME_FEATURE_TLS_HW_TX_OFFLOAD            "feature-tls-hw-tx-offload"
-#define NM_ETHTOOL_OPTNAME_FEATURE_TSO                          "feature-tso"
-#define NM_ETHTOOL_OPTNAME_FEATURE_TX                           "feature-tx"
-#define NM_ETHTOOL_OPTNAME_FEATURE_TXVLAN                       "feature-txvlan"
-#define NM_ETHTOOL_OPTNAME_FEATURE_TX_CHECKSUM_FCOE_CRC         "feature-tx-checksum-fcoe-crc"
-#define NM_ETHTOOL_OPTNAME_FEATURE_TX_CHECKSUM_IPV4             "feature-tx-checksum-ipv4"
-#define NM_ETHTOOL_OPTNAME_FEATURE_TX_CHECKSUM_IPV6             "feature-tx-checksum-ipv6"
-#define NM_ETHTOOL_OPTNAME_FEATURE_TX_CHECKSUM_IP_GENERIC       "feature-tx-checksum-ip-generic"
-#define NM_ETHTOOL_OPTNAME_FEATURE_TX_CHECKSUM_SCTP             "feature-tx-checksum-sctp"
-#define NM_ETHTOOL_OPTNAME_FEATURE_TX_ESP_SEGMENTATION          "feature-tx-esp-segmentation"
-#define NM_ETHTOOL_OPTNAME_FEATURE_TX_FCOE_SEGMENTATION         "feature-tx-fcoe-segmentation"
-#define NM_ETHTOOL_OPTNAME_FEATURE_TX_GRE_CSUM_SEGMENTATION     "feature-tx-gre-csum-segmentation"
-#define NM_ETHTOOL_OPTNAME_FEATURE_TX_GRE_SEGMENTATION          "feature-tx-gre-segmentation"
-#define NM_ETHTOOL_OPTNAME_FEATURE_TX_GSO_PARTIAL               "feature-tx-gso-partial"
-#define NM_ETHTOOL_OPTNAME_FEATURE_TX_GSO_ROBUST                "feature-tx-gso-robust"
-#define NM_ETHTOOL_OPTNAME_FEATURE_TX_IPXIP4_SEGMENTATION       "feature-tx-ipxip4-segmentation"
-#define NM_ETHTOOL_OPTNAME_FEATURE_TX_IPXIP6_SEGMENTATION       "feature-tx-ipxip6-segmentation"
-#define NM_ETHTOOL_OPTNAME_FEATURE_TX_NOCACHE_COPY              "feature-tx-nocache-copy"
-#define NM_ETHTOOL_OPTNAME_FEATURE_TX_SCATTER_GATHER            "feature-tx-scatter-gather"
-#define NM_ETHTOOL_OPTNAME_FEATURE_TX_SCATTER_GATHER_FRAGLIST   "feature-tx-scatter-gather-fraglist"
-#define NM_ETHTOOL_OPTNAME_FEATURE_TX_SCTP_SEGMENTATION         "feature-tx-sctp-segmentation"
-#define NM_ETHTOOL_OPTNAME_FEATURE_TX_TCP6_SEGMENTATION         "feature-tx-tcp6-segmentation"
-#define NM_ETHTOOL_OPTNAME_FEATURE_TX_TCP_ECN_SEGMENTATION      "feature-tx-tcp-ecn-segmentation"
-#define NM_ETHTOOL_OPTNAME_FEATURE_TX_TCP_MANGLEID_SEGMENTATION "feature-tx-tcp-mangleid-segmentation"
-#define NM_ETHTOOL_OPTNAME_FEATURE_TX_TCP_SEGMENTATION          "feature-tx-tcp-segmentation"
-#define NM_ETHTOOL_OPTNAME_FEATURE_TX_UDP_SEGMENTATION          "feature-tx-udp-segmentation"
-#define NM_ETHTOOL_OPTNAME_FEATURE_TX_UDP_TNL_CSUM_SEGMENTATION "feature-tx-udp_tnl-csum-segmentation"
-#define NM_ETHTOOL_OPTNAME_FEATURE_TX_UDP_TNL_SEGMENTATION      "feature-tx-udp_tnl-segmentation"
-#define NM_ETHTOOL_OPTNAME_FEATURE_TX_VLAN_STAG_HW_INSERT       "feature-tx-vlan-stag-hw-insert"
-
-NM_AVAILABLE_IN_1_14
-gboolean nm_ethtool_optname_is_feature (const char *optname);
-
-/*****************************************************************************/
-
-#define NM_TYPE_SETTING_ETHTOOL            (nm_setting_ethtool_get_type ())
-#define NM_SETTING_ETHTOOL(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_ETHTOOL, NMSettingEthtool))
-#define NM_SETTING_ETHTOOL_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_ETHTOOL, NMSettingEthtoolClass))
-#define NM_IS_SETTING_ETHTOOL(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_ETHTOOL))
-#define NM_IS_SETTING_ETHTOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_ETHTOOL))
-#define NM_SETTING_ETHTOOL_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_ETHTOOL, NMSettingEthtoolClass))
-
-#define NM_SETTING_ETHTOOL_SETTING_NAME "ethtool"
-
-/*****************************************************************************/
-
-typedef struct _NMSettingEthtoolClass NMSettingEthtoolClass;
-
-NM_AVAILABLE_IN_1_14
-GType nm_setting_ethtool_get_type (void);
-
-NM_AVAILABLE_IN_1_14
-NMSetting        *nm_setting_ethtool_new (void);
-
-/*****************************************************************************/
-
-NM_AVAILABLE_IN_1_14
-NMTernary         nm_setting_ethtool_get_feature (NMSettingEthtool *setting,
-                                                  const char *optname);
-NM_AVAILABLE_IN_1_14
-void              nm_setting_ethtool_set_feature (NMSettingEthtool *setting,
-                                                  const char *optname,
-                                                  NMTernary value);
-NM_AVAILABLE_IN_1_14
-void              nm_setting_ethtool_clear_features (NMSettingEthtool *setting);
-
-G_END_DECLS
-
-#endif /* __NM_SETTING_ETHTOOL_H__ */
diff --git a/libnm-core/nm-setting-generic.c b/libnm-core/nm-setting-generic.c
index 44402e39..96f26ac2 100644
--- a/libnm-core/nm-setting-generic.c
+++ b/libnm-core/nm-setting-generic.c
@@ -36,7 +36,9 @@
  * the "connection type" setting on #NMConnections for generic devices.
  **/
 
-G_DEFINE_TYPE (NMSettingGeneric, nm_setting_generic, NM_TYPE_SETTING)
+G_DEFINE_TYPE_WITH_CODE (NMSettingGeneric, nm_setting_generic, NM_TYPE_SETTING,
+                         _nm_register_setting (GENERIC, NM_SETTING_PRIORITY_HW_BASE))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_GENERIC)
 
 #define NM_SETTING_GENERIC_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_GENERIC, NMSettingGenericPrivate))
 
@@ -65,11 +67,7 @@ nm_setting_generic_init (NMSettingGeneric *setting)
 }
 
 static void
-nm_setting_generic_class_init (NMSettingGenericClass *klass)
+nm_setting_generic_class_init (NMSettingGenericClass *setting_class)
 {
-	NMSettingClass *setting_class = NM_SETTING_CLASS (klass);
-
-	g_type_class_add_private (klass, sizeof (NMSettingGenericPrivate));
-
-	_nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_GENERIC);
+	g_type_class_add_private (setting_class, sizeof (NMSettingGenericPrivate));
 }
diff --git a/libnm-core/nm-setting-gsm.c b/libnm-core/nm-setting-gsm.c
index b31da689..3011d917 100644
--- a/libnm-core/nm-setting-gsm.c
+++ b/libnm-core/nm-setting-gsm.c
@@ -38,7 +38,9 @@
  * networks, including those using GPRS/EDGE and UMTS/HSPA technology.
  */
 
-G_DEFINE_TYPE (NMSettingGsm, nm_setting_gsm, NM_TYPE_SETTING)
+G_DEFINE_TYPE_WITH_CODE (NMSettingGsm, nm_setting_gsm, NM_TYPE_SETTING,
+                         _nm_register_setting (GSM, NM_SETTING_PRIORITY_HW_BASE))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_GSM)
 
 #define NM_SETTING_GSM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_GSM, NMSettingGsmPrivate))
 
@@ -602,21 +604,22 @@ get_property (GObject *object, guint prop_id,
 }
 
 static void
-nm_setting_gsm_class_init (NMSettingGsmClass *klass)
+nm_setting_gsm_class_init (NMSettingGsmClass *setting_class)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	NMSettingClass *setting_class = NM_SETTING_CLASS (klass);
-	GArray *properties_override = _nm_sett_info_property_override_create_array ();
+	GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+	NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
 
-	g_type_class_add_private (klass, sizeof (NMSettingGsmPrivate));
+	g_type_class_add_private (setting_class, sizeof (NMSettingGsmPrivate));
 
+	/* virtual methods */
 	object_class->set_property = set_property;
 	object_class->get_property = get_property;
 	object_class->finalize     = finalize;
+	parent_class->verify       = verify;
+	parent_class->verify_secrets = verify_secrets;
+	parent_class->need_secrets = need_secrets;
 
-	setting_class->verify         = verify;
-	setting_class->verify_secrets = verify_secrets;
-	setting_class->need_secrets   = need_secrets;
+	/* Properties */
 
 	/**
 	 * NMSettingGsm:number:
@@ -819,18 +822,10 @@ nm_setting_gsm_class_init (NMSettingGsmClass *klass)
 		                    G_PARAM_STATIC_STRINGS));
 
 	/* Ignore incoming deprecated properties */
-	_properties_override_add_dbus_only (properties_override,
-	                                    "allowed-bands",
-	                                    G_VARIANT_TYPE_UINT32,
-	                                    NULL,
-	                                    NULL);
-
-	_properties_override_add_dbus_only (properties_override,
-	                                    "network-type",
-	                                    G_VARIANT_TYPE_INT32,
-	                                    NULL,
-	                                    NULL);
-
-	_nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_GSM,
-	                               NULL, properties_override);
+	_nm_setting_class_add_dbus_only_property (parent_class, "allowed-bands",
+	                                          G_VARIANT_TYPE_UINT32,
+	                                          NULL, NULL);
+	_nm_setting_class_add_dbus_only_property (parent_class, "network-type",
+	                                          G_VARIANT_TYPE_INT32,
+	                                          NULL, NULL);
 }
diff --git a/libnm-core/nm-setting-infiniband.c b/libnm-core/nm-setting-infiniband.c
index d5ae7085..8c49849a 100644
--- a/libnm-core/nm-setting-infiniband.c
+++ b/libnm-core/nm-setting-infiniband.c
@@ -37,7 +37,9 @@
  * necessary for connection to IP-over-InfiniBand networks.
  **/
 
-G_DEFINE_TYPE (NMSettingInfiniband, nm_setting_infiniband, NM_TYPE_SETTING)
+G_DEFINE_TYPE_WITH_CODE (NMSettingInfiniband, nm_setting_infiniband, NM_TYPE_SETTING,
+                         _nm_register_setting (INFINIBAND, NM_SETTING_PRIORITY_HW_BASE))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_INFINIBAND)
 
 #define NM_SETTING_INFINIBAND_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_INFINIBAND, NMSettingInfinibandPrivate))
 
@@ -376,20 +378,21 @@ get_property (GObject *object, guint prop_id,
 }
 
 static void
-nm_setting_infiniband_class_init (NMSettingInfinibandClass *klass)
+nm_setting_infiniband_class_init (NMSettingInfinibandClass *setting_class)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	NMSettingClass *setting_class = NM_SETTING_CLASS (klass);
-	GArray *properties_override = _nm_sett_info_property_override_create_array ();
+	GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+	NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
 
-	g_type_class_add_private (klass, sizeof (NMSettingInfinibandPrivate));
+	g_type_class_add_private (setting_class, sizeof (NMSettingInfinibandPrivate));
 
+	/* virtual methods */
 	object_class->set_property = set_property;
 	object_class->get_property = get_property;
 	object_class->finalize     = finalize;
 
-	setting_class->verify = verify;
+	parent_class->verify       = verify;
 
+	/* Properties */
 	/**
 	 * NMSettingInfiniband:mac-address:
 	 *
@@ -422,13 +425,10 @@ nm_setting_infiniband_class_init (NMSettingInfinibandClass *klass)
 		                      G_PARAM_READWRITE |
 		                      NM_SETTING_PARAM_INFERRABLE |
 		                      G_PARAM_STATIC_STRINGS));
-
-	_properties_override_add_transform (properties_override,
-	                                    g_object_class_find_property (G_OBJECT_CLASS (setting_class),
-	                                                                  NM_SETTING_INFINIBAND_MAC_ADDRESS),
-	                                    G_VARIANT_TYPE_BYTESTRING,
-	                                    _nm_utils_hwaddr_to_dbus,
-	                                    _nm_utils_hwaddr_from_dbus);
+	_nm_setting_class_transform_property (parent_class, NM_SETTING_INFINIBAND_MAC_ADDRESS,
+	                                      G_VARIANT_TYPE_BYTESTRING,
+	                                      _nm_utils_hwaddr_to_dbus,
+	                                      _nm_utils_hwaddr_from_dbus);
 
 	/**
 	 * NMSettingInfiniband:mtu:
@@ -526,6 +526,4 @@ nm_setting_infiniband_class_init (NMSettingInfinibandClass *klass)
 		                      NM_SETTING_PARAM_INFERRABLE |
 		                      G_PARAM_STATIC_STRINGS));
 
-	_nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_INFINIBAND,
-	                               NULL, properties_override);
 }
diff --git a/libnm-core/nm-setting-ip-config.c b/libnm-core/nm-setting-ip-config.c
index fa2535b8..c7f8c555 100644
--- a/libnm-core/nm-setting-ip-config.c
+++ b/libnm-core/nm-setting-ip-config.c
@@ -1391,7 +1391,7 @@ typedef struct {
 	GPtrArray *dns;        /* array of IP address strings */
 	GPtrArray *dns_search; /* array of domain name strings */
 	GPtrArray *dns_options;/* array of DNS options */
-	int dns_priority;
+	gint dns_priority;
 	GPtrArray *addresses;  /* array of NMIPAddress */
 	GPtrArray *routes;     /* array of NMIPRoute */
 	gint64 route_metric;
@@ -1403,8 +1403,8 @@ typedef struct {
 	gboolean dhcp_send_hostname;
 	gboolean never_default;
 	gboolean may_fail;
-	int dad_timeout;
-	int dhcp_timeout;
+	gint dad_timeout;
+	gint dhcp_timeout;
 } NMSettingIPConfigPrivate;
 
 enum {
@@ -1589,11 +1589,8 @@ nm_setting_ip_config_clear_dns (NMSettingIPConfig *setting)
 	g_return_if_fail (NM_IS_SETTING_IP_CONFIG (setting));
 
 	priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
-
-	if (priv->dns->len != 0) {
-		g_ptr_array_set_size (priv->dns, 0);
-		g_object_notify (G_OBJECT (setting), NM_SETTING_IP_CONFIG_DNS);
-	}
+	g_ptr_array_set_size (priv->dns, 0);
+	g_object_notify (G_OBJECT (setting), NM_SETTING_IP_CONFIG_DNS);
 }
 
 /**
@@ -1691,6 +1688,8 @@ nm_setting_ip_config_remove_dns_search (NMSettingIPConfig *setting, int idx)
  * Removes the DNS search domain @dns_search.
  *
  * Returns: %TRUE if the DNS search domain was found and removed; %FALSE if it was not.
+ *
+ * Since 0.9.10
  **/
 gboolean
 nm_setting_ip_config_remove_dns_search_by_value (NMSettingIPConfig *setting,
@@ -1728,11 +1727,8 @@ nm_setting_ip_config_clear_dns_searches (NMSettingIPConfig *setting)
 	g_return_if_fail (NM_IS_SETTING_IP_CONFIG (setting));
 
 	priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
-
-	if (priv->dns_search->len != 0) {
-		g_ptr_array_set_size (priv->dns_search, 0);
-		g_object_notify (G_OBJECT (setting), NM_SETTING_IP_CONFIG_DNS_SEARCH);
-	}
+	g_ptr_array_set_size (priv->dns_search, 0);
+	g_object_notify (G_OBJECT (setting), NM_SETTING_IP_CONFIG_DNS_SEARCH);
 }
 
 /**
@@ -1808,7 +1804,7 @@ nm_setting_ip_config_get_dns_option (NMSettingIPConfig *setting, guint idx)
  *
  * Since: 1.2
  **/
-int
+gint
 nm_setting_ip_config_next_valid_dns_option (NMSettingIPConfig *setting, guint idx)
 {
 	NMSettingIPConfigPrivate *priv;
@@ -1970,7 +1966,7 @@ nm_setting_ip_config_clear_dns_options (NMSettingIPConfig *setting, gboolean is_
  *
  * Since: 1.4
  **/
-int
+gint
 nm_setting_ip_config_get_dns_priority (NMSettingIPConfig *setting)
 {
 	g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), 0);
@@ -2111,10 +2107,8 @@ nm_setting_ip_config_clear_addresses (NMSettingIPConfig *setting)
 
 	g_return_if_fail (NM_IS_SETTING_IP_CONFIG (setting));
 
-	if (priv->addresses->len != 0) {
-		g_ptr_array_set_size (priv->addresses, 0);
-		g_object_notify (G_OBJECT (setting), NM_SETTING_IP_CONFIG_ADDRESSES);
-	}
+	g_ptr_array_set_size (priv->addresses, 0);
+	g_object_notify (G_OBJECT (setting), NM_SETTING_IP_CONFIG_ADDRESSES);
 }
 
 /**
@@ -2270,10 +2264,8 @@ nm_setting_ip_config_clear_routes (NMSettingIPConfig *setting)
 
 	g_return_if_fail (NM_IS_SETTING_IP_CONFIG (setting));
 
-	if (priv->routes->len != 0) {
-		g_ptr_array_set_size (priv->routes, 0);
-		g_object_notify (G_OBJECT (setting), NM_SETTING_IP_CONFIG_ROUTES);
-	}
+	g_ptr_array_set_size (priv->routes, 0);
+	g_object_notify (G_OBJECT (setting), NM_SETTING_IP_CONFIG_ROUTES);
 }
 
 /**
@@ -2429,7 +2421,7 @@ nm_setting_ip_config_get_may_fail (NMSettingIPConfig *setting)
  *
  * Since: 1.2
  **/
-int
+gint
 nm_setting_ip_config_get_dad_timeout (NMSettingIPConfig *setting)
 {
 	g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), 0);
@@ -2449,7 +2441,7 @@ nm_setting_ip_config_get_dad_timeout (NMSettingIPConfig *setting)
  *
  * Since: 1.2
  **/
-int
+gint
 nm_setting_ip_config_get_dhcp_timeout (NMSettingIPConfig *setting)
 {
 	g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), 0);
@@ -2619,7 +2611,7 @@ compare_property (NMSetting *setting,
                   NMSettingCompareFlags flags)
 {
 	NMSettingIPConfigPrivate *a_priv, *b_priv;
-	NMSettingClass *setting_class;
+	NMSettingClass *parent_class;
 	guint i;
 
 	if (nm_streq (prop_spec->name, NM_SETTING_IP_CONFIG_ADDRESSES)) {
@@ -2648,8 +2640,9 @@ compare_property (NMSetting *setting,
 		return TRUE;
 	}
 
-	setting_class = NM_SETTING_CLASS (nm_setting_ip_config_parent_class);
-	return setting_class->compare_property (setting, other, prop_spec, flags);
+	/* Otherwise chain up to parent to handle generic compare */
+	parent_class = NM_SETTING_CLASS (nm_setting_ip_config_parent_class);
+	return parent_class->compare_property (setting, other, prop_spec, flags);
 }
 
 /*****************************************************************************/
@@ -2876,37 +2869,22 @@ ip_gateway_set (NMSetting  *setting,
 	return TRUE;
 }
 
-GArray *
-_nm_sett_info_property_override_create_array_ip_config (void)
-{
-	nm_auto_unref_gtypeclass NMSettingClass *setting_class = g_type_class_ref (NM_TYPE_SETTING_IP_CONFIG);
-	GArray *properties_override = _nm_sett_info_property_override_create_array ();
-
-	_properties_override_add_override (properties_override,
-	                                   g_object_class_find_property (G_OBJECT_CLASS (setting_class),
-	                                                                 NM_SETTING_IP_CONFIG_GATEWAY),
-	                                   G_VARIANT_TYPE_STRING,
-	                                   NULL,
-	                                   ip_gateway_set,
-	                                   NULL);
-
-	return properties_override;
-}
-
 static void
-nm_setting_ip_config_class_init (NMSettingIPConfigClass *klass)
+nm_setting_ip_config_class_init (NMSettingIPConfigClass *setting_class)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	NMSettingClass *setting_class = NM_SETTING_CLASS (klass);
+	GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+	NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
 
-	g_type_class_add_private (klass, sizeof (NMSettingIPConfigPrivate));
+	g_type_class_add_private (setting_class, sizeof (NMSettingIPConfigPrivate));
 
+	/* virtual methods */
 	object_class->set_property = set_property;
 	object_class->get_property = get_property;
 	object_class->finalize     = finalize;
+	parent_class->verify       = verify;
+	parent_class->compare_property = compare_property;
 
-	setting_class->verify           = verify;
-	setting_class->compare_property = compare_property;
+	/* Properties */
 
 	/**
 	 * NMSettingIPConfig:method:
@@ -2927,9 +2905,7 @@ nm_setting_ip_config_class_init (NMSettingIPConfigClass *klass)
 	 * "link-local", these properties must be empty.
 	 *
 	 * For IPv4 method "shared", the IP subnet can be configured by adding one
-	 * manual IPv4 address or otherwise 10.42.x.0/24 is chosen. Note that the
-	 * shared method must be configured on the interface which shares the internet
-	 * to a subnet, not on the uplink which is shared.
+	 * manual IPv4 address or otherwise 10.42.x.0/24 is chosen.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_METHOD,
@@ -3058,6 +3034,13 @@ nm_setting_ip_config_class_init (NMSettingIPConfigClass *klass)
 		                      NM_SETTING_PARAM_INFERRABLE |
 		                      G_PARAM_STATIC_STRINGS));
 
+	_nm_setting_class_override_property (parent_class,
+	                                     NM_SETTING_IP_CONFIG_GATEWAY,
+	                                     G_VARIANT_TYPE_STRING,
+	                                     NULL,
+	                                     ip_gateway_set,
+	                                     NULL);
+
 	/**
 	 * NMSettingIPConfig:routes: (type GPtrArray(NMIPRoute))
 	 *
diff --git a/libnm-core/nm-setting-ip-config.h b/libnm-core/nm-setting-ip-config.h
index 882a88b6..8b3c85de 100644
--- a/libnm-core/nm-setting-ip-config.h
+++ b/libnm-core/nm-setting-ip-config.h
@@ -247,7 +247,7 @@ guint         nm_setting_ip_config_get_num_dns_options        (NMSettingIPConfig
 gboolean      nm_setting_ip_config_has_dns_options            (NMSettingIPConfig *setting);
 const char   *nm_setting_ip_config_get_dns_option             (NMSettingIPConfig *setting,
                                                                guint              idx);
-int           nm_setting_ip_config_next_valid_dns_option      (NMSettingIPConfig *setting,
+gint          nm_setting_ip_config_next_valid_dns_option      (NMSettingIPConfig *setting,
                                                                guint              idx);
 gboolean      nm_setting_ip_config_add_dns_option             (NMSettingIPConfig *setting,
                                                                const char        *dns_option);
@@ -258,7 +258,7 @@ gboolean      nm_setting_ip_config_remove_dns_option_by_value (NMSettingIPConfig
 void          nm_setting_ip_config_clear_dns_options          (NMSettingIPConfig *setting, gboolean is_set);
 
 NM_AVAILABLE_IN_1_4
-int           nm_setting_ip_config_get_dns_priority (NMSettingIPConfig *setting);
+gint          nm_setting_ip_config_get_dns_priority (NMSettingIPConfig *setting);
 
 guint         nm_setting_ip_config_get_num_addresses          (NMSettingIPConfig *setting);
 NMIPAddress  *nm_setting_ip_config_get_address                (NMSettingIPConfig *setting,
@@ -298,9 +298,9 @@ gboolean      nm_setting_ip_config_get_dhcp_send_hostname     (NMSettingIPConfig
 gboolean      nm_setting_ip_config_get_never_default          (NMSettingIPConfig *setting);
 gboolean      nm_setting_ip_config_get_may_fail               (NMSettingIPConfig *setting);
 NM_AVAILABLE_IN_1_2
-int           nm_setting_ip_config_get_dad_timeout            (NMSettingIPConfig *setting);
+gint          nm_setting_ip_config_get_dad_timeout            (NMSettingIPConfig *setting);
 NM_AVAILABLE_IN_1_2
-int           nm_setting_ip_config_get_dhcp_timeout           (NMSettingIPConfig *setting);
+gint          nm_setting_ip_config_get_dhcp_timeout           (NMSettingIPConfig *setting);
 
 G_END_DECLS
 
diff --git a/libnm-core/nm-setting-ip-tunnel.c b/libnm-core/nm-setting-ip-tunnel.c
index 41314f58..c9cb97df 100644
--- a/libnm-core/nm-setting-ip-tunnel.c
+++ b/libnm-core/nm-setting-ip-tunnel.c
@@ -30,7 +30,9 @@
  * @short_description: Describes connection properties for IP tunnel devices
  **/
 
-G_DEFINE_TYPE (NMSettingIPTunnel, nm_setting_ip_tunnel, NM_TYPE_SETTING)
+G_DEFINE_TYPE_WITH_CODE (NMSettingIPTunnel, nm_setting_ip_tunnel, NM_TYPE_SETTING,
+                         _nm_register_setting (IP_TUNNEL, NM_SETTING_PRIORITY_HW_BASE))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_IP_TUNNEL)
 
 #define NM_SETTING_IP_TUNNEL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_IP_TUNNEL, NMSettingIPTunnelPrivate))
 
@@ -318,14 +320,12 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
 	case NM_IP_TUNNEL_MODE_ISATAP:
 	case NM_IP_TUNNEL_MODE_GRE:
 	case NM_IP_TUNNEL_MODE_VTI:
-	case NM_IP_TUNNEL_MODE_GRETAP:
 		family = AF_INET;
 		break;
 	case NM_IP_TUNNEL_MODE_IP6IP6:
 	case NM_IP_TUNNEL_MODE_IPIP6:
 	case NM_IP_TUNNEL_MODE_IP6GRE:
 	case NM_IP_TUNNEL_MODE_VTI6:
-	case NM_IP_TUNNEL_MODE_IP6GRETAP:
 		family = AF_INET6;
 		break;
 	case NM_IP_TUNNEL_MODE_UNKNOWN:
@@ -388,11 +388,8 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
 
 	if (   (priv->input_key && priv->input_key[0])
 	    || (priv->output_key && priv->output_key[0])) {
-		if (!NM_IN_SET (priv->mode,
-		                NM_IP_TUNNEL_MODE_GRE,
-		                NM_IP_TUNNEL_MODE_GRETAP,
-		                NM_IP_TUNNEL_MODE_IP6GRE,
-		                NM_IP_TUNNEL_MODE_IP6GRETAP)) {
+		if (   priv->mode != NM_IP_TUNNEL_MODE_GRE
+		    && priv->mode != NM_IP_TUNNEL_MODE_IP6GRE) {
 			g_set_error_literal (error,
 			                     NM_CONNECTION_ERROR,
 			                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
@@ -413,7 +410,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
 			             priv->input_key);
 			g_prefix_error (error, "%s.%s: ", NM_SETTING_IP_TUNNEL_SETTING_NAME,
 			                NM_SETTING_IP_TUNNEL_INPUT_KEY);
-			return FALSE;
+		return FALSE;
 		}
 	}
 
@@ -429,7 +426,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
 			             priv->output_key);
 			g_prefix_error (error, "%s.%s: ", NM_SETTING_IP_TUNNEL_SETTING_NAME,
 			                NM_SETTING_IP_TUNNEL_OUTPUT_KEY);
-			return FALSE;
+		return FALSE;
 		}
 	}
 
@@ -457,20 +454,6 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
 		return FALSE;
 	}
 
-	if (   nm_connection_get_setting_wired (connection)
-	    && !NM_IN_SET (priv->mode,
-	                   NM_IP_TUNNEL_MODE_GRETAP,
-	                   NM_IP_TUNNEL_MODE_IP6GRETAP)) {
-		g_set_error (error,
-		             NM_CONNECTION_ERROR,
-		             NM_CONNECTION_ERROR_INVALID_PROPERTY,
-		             _("wired setting not allowed for mode %s"),
-		             nm_utils_enum_to_str (nm_ip_tunnel_mode_get_type (), priv->mode));
-		g_prefix_error (error, "%s.%s: ", NM_SETTING_IP_TUNNEL_SETTING_NAME,
-		                NM_SETTING_IP_TUNNEL_MODE);
-		return NM_SETTING_VERIFY_NORMALIZABLE_ERROR;
-	}
-
 	return TRUE;
 }
 
@@ -621,18 +604,18 @@ finalize (GObject *object)
 }
 
 static void
-nm_setting_ip_tunnel_class_init (NMSettingIPTunnelClass *klass)
+nm_setting_ip_tunnel_class_init (NMSettingIPTunnelClass *setting_class)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	NMSettingClass *setting_class = NM_SETTING_CLASS (klass);
+	GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+	NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
 
-	g_type_class_add_private (klass, sizeof (NMSettingIPTunnelPrivate));
+	g_type_class_add_private (setting_class, sizeof (NMSettingIPTunnelPrivate));
 
+	/* virtual methods */
 	object_class->set_property = set_property;
 	object_class->get_property = get_property;
 	object_class->finalize     = finalize;
-
-	setting_class->verify = verify;
+	parent_class->verify       = verify;
 
 	/**
 	 * NMSettingIPTunnel:parent:
@@ -850,6 +833,4 @@ nm_setting_ip_tunnel_class_init (NMSettingIPTunnelClass *klass)
 		                    G_PARAM_READWRITE |
 		                    NM_SETTING_PARAM_FUZZY_IGNORE |
 		                    G_PARAM_STATIC_STRINGS));
-
-	_nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_IP_TUNNEL);
 }
diff --git a/libnm-core/nm-setting-ip4-config.c b/libnm-core/nm-setting-ip4-config.c
index 19f1cc8d..d855ccba 100644
--- a/libnm-core/nm-setting-ip4-config.c
+++ b/libnm-core/nm-setting-ip4-config.c
@@ -50,7 +50,9 @@
  * connection.
  **/
 
-G_DEFINE_TYPE (NMSettingIP4Config, nm_setting_ip4_config, NM_TYPE_SETTING_IP_CONFIG)
+G_DEFINE_TYPE_WITH_CODE (NMSettingIP4Config, nm_setting_ip4_config, NM_TYPE_SETTING_IP_CONFIG,
+                         _nm_register_setting (IP4_CONFIG, NM_SETTING_PRIORITY_IP))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_IP4_CONFIG)
 
 #define NM_SETTING_IP4_CONFIG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_IP4_CONFIG, NMSettingIP4ConfigPrivate))
 
@@ -523,20 +525,21 @@ ip4_route_data_set (NMSetting  *setting,
 }
 
 static void
-nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *klass)
+nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *ip4_class)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	NMSettingClass *setting_class = NM_SETTING_CLASS (klass);
-	GArray *properties_override = _nm_sett_info_property_override_create_array_ip_config ();
+	NMSettingClass *setting_class = NM_SETTING_CLASS (ip4_class);
+	GObjectClass *object_class = G_OBJECT_CLASS (ip4_class);
 
 	g_type_class_add_private (setting_class, sizeof (NMSettingIP4ConfigPrivate));
 
+	/* virtual methods */
 	object_class->set_property = set_property;
 	object_class->get_property = get_property;
 	object_class->finalize     = finalize;
-
 	setting_class->verify = verify;
 
+	/* properties */
+
 	/* ---ifcfg-rh---
 	 * property: method
 	 * variable: BOOTPROTO
@@ -744,7 +747,7 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *klass)
 
 	/* ---ifcfg-rh---
 	 * property: dad-timeout
-	 * variable: ACD_TIMEOUT(+), ARPING_WAIT
+	 * variable: ACD_TIMEOUT, ARPING_WAIT
 	 * default: missing variable means global default (config override or zero)
 	 * description: Timeout (in milliseconds for ACD_TIMEOUT or in seconds
 	 *   for ARPING_WAIT) for address conflict detection before configuring
@@ -795,12 +798,11 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *klass)
 	 *   integers)
 	 * ---end---
 	 */
-	_properties_override_add_transform (properties_override,
-	                                    g_object_class_find_property (G_OBJECT_CLASS (setting_class),
-	                                                                  NM_SETTING_IP_CONFIG_DNS),
-	                                    G_VARIANT_TYPE ("au"),
-	                                    ip4_dns_to_dbus,
-	                                    ip4_dns_from_dbus);
+	_nm_setting_class_transform_property (setting_class,
+	                                      NM_SETTING_IP_CONFIG_DNS,
+	                                      G_VARIANT_TYPE ("au"),
+	                                      ip4_dns_to_dbus,
+	                                      ip4_dns_from_dbus);
 
 	/* ---dbus---
 	 * property: addresses
@@ -817,19 +819,18 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *klass)
 	 *   for that subnet.
 	 * ---end---
 	 */
-	_properties_override_add_override (properties_override,
-	                                   g_object_class_find_property (G_OBJECT_CLASS (setting_class),
-	                                                                 NM_SETTING_IP_CONFIG_ADDRESSES),
-	                                   G_VARIANT_TYPE ("aau"),
-	                                   ip4_addresses_get,
-	                                   ip4_addresses_set,
-	                                   NULL);
-
-	_properties_override_add_dbus_only (properties_override,
-	                                    "address-labels",
-	                                    G_VARIANT_TYPE_STRING_ARRAY,
-	                                    ip4_address_labels_get,
-	                                    NULL);
+	_nm_setting_class_override_property (setting_class,
+	                                     NM_SETTING_IP_CONFIG_ADDRESSES,
+	                                     G_VARIANT_TYPE ("aau"),
+	                                     ip4_addresses_get,
+	                                     ip4_addresses_set,
+	                                     NULL);
+
+	_nm_setting_class_add_dbus_only_property (setting_class,
+	                                          "address-labels",
+	                                          G_VARIANT_TYPE_STRING_ARRAY,
+	                                          ip4_address_labels_get,
+	                                          NULL);
 
 	/* ---dbus---
 	 * property: address-data
@@ -840,11 +841,11 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *klass)
 	 *   also exist on some addresses.
 	 * ---end---
 	 */
-	_properties_override_add_dbus_only (properties_override,
-	                                    "address-data",
-	                                    G_VARIANT_TYPE ("aa{sv}"),
-	                                    ip4_address_data_get,
-	                                    ip4_address_data_set);
+	_nm_setting_class_add_dbus_only_property (setting_class,
+	                                          "address-data",
+	                                          G_VARIANT_TYPE ("aa{sv}"),
+	                                          ip4_address_data_get,
+	                                          ip4_address_data_set);
 
 	/* ---dbus---
 	 * property: routes
@@ -863,13 +864,12 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *klass)
 	 *   property.)
 	 * ---end---
 	 */
-	_properties_override_add_override (properties_override,
-	                                   g_object_class_find_property (G_OBJECT_CLASS (setting_class),
-	                                                                 NM_SETTING_IP_CONFIG_ROUTES),
-	                                   G_VARIANT_TYPE ("aau"),
-	                                   ip4_routes_get,
-	                                   ip4_routes_set,
-	                                   NULL);
+	_nm_setting_class_override_property (setting_class,
+	                                     NM_SETTING_IP_CONFIG_ROUTES,
+	                                     G_VARIANT_TYPE ("aau"),
+	                                     ip4_routes_get,
+	                                     ip4_routes_set,
+	                                     NULL);
 
 	/* ---dbus---
 	 * property: route-data
@@ -884,12 +884,10 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *klass)
 	 *   also exist on some routes.
 	 * ---end---
 	 */
-	_properties_override_add_dbus_only (properties_override,
-	                                    "route-data",
-	                                    G_VARIANT_TYPE ("aa{sv}"),
-	                                    ip4_route_data_get,
-	                                    ip4_route_data_set);
-
-	_nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_IP4_CONFIG,
-	                               NULL, properties_override);
+	_nm_setting_class_add_dbus_only_property (setting_class,
+	                                          "route-data",
+	                                          G_VARIANT_TYPE ("aa{sv}"),
+	                                          ip4_route_data_get,
+	                                          ip4_route_data_set);
+
 }
diff --git a/libnm-core/nm-setting-ip6-config.c b/libnm-core/nm-setting-ip6-config.c
index a55fd801..808c88a7 100644
--- a/libnm-core/nm-setting-ip6-config.c
+++ b/libnm-core/nm-setting-ip6-config.c
@@ -52,7 +52,9 @@
  * supported.
  **/
 
-G_DEFINE_TYPE (NMSettingIP6Config, nm_setting_ip6_config, NM_TYPE_SETTING_IP_CONFIG)
+G_DEFINE_TYPE_WITH_CODE (NMSettingIP6Config, nm_setting_ip6_config, NM_TYPE_SETTING_IP_CONFIG,
+                         _nm_register_setting (IP6_CONFIG, NM_SETTING_PRIORITY_IP))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_IP6_CONFIG)
 
 #define NM_SETTING_IP6_CONFIG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_IP6_CONFIG, NMSettingIP6ConfigPrivate))
 
@@ -547,20 +549,21 @@ finalize (GObject *object)
 }
 
 static void
-nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *klass)
+nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *ip6_class)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	NMSettingClass *setting_class = NM_SETTING_CLASS (klass);
-	GArray *properties_override = _nm_sett_info_property_override_create_array_ip_config ();
+	GObjectClass *object_class = G_OBJECT_CLASS (ip6_class);
+	NMSettingClass *setting_class = NM_SETTING_CLASS (ip6_class);
 
-	g_type_class_add_private (klass, sizeof (NMSettingIP6ConfigPrivate));
+	g_type_class_add_private (ip6_class, sizeof (NMSettingIP6ConfigPrivate));
 
+	/* virtual methods */
 	object_class->set_property = set_property;
 	object_class->get_property = get_property;
-	object_class->finalize     = finalize;
-
+	object_class->finalize = finalize;
 	setting_class->verify = verify;
 
+	/* Properties */
+
 	/* ---ifcfg-rh---
 	 * property: method
 	 * variable: IPV6INIT, IPV6FORWARDING, IPV6_AUTOCONF, DHCPV6C
@@ -587,7 +590,7 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *klass)
 
 	/* ---ifcfg-rh---
 	 * property: dns-search
-	 * variable: IPV6_DOMAIN(+)
+	 * variable: IPV6_DOMAIN
 	 * format:   string (space-separated domains)
 	 * description: List of DNS search domains.
 	 * ---end---
@@ -888,12 +891,11 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *klass)
 	 * description: Array of IP addresses of DNS servers (in network byte order)
 	 * ---end---
 	 */
-	_properties_override_add_transform (properties_override,
-	                                    g_object_class_find_property (G_OBJECT_CLASS (setting_class),
-	                                                                  NM_SETTING_IP_CONFIG_DNS),
-	                                    G_VARIANT_TYPE ("aay"),
-	                                    ip6_dns_to_dbus,
-	                                    ip6_dns_from_dbus);
+	_nm_setting_class_transform_property (setting_class,
+	                                      NM_SETTING_IP_CONFIG_DNS,
+	                                      G_VARIANT_TYPE ("aay"),
+	                                      ip6_dns_to_dbus,
+	                                      ip6_dns_from_dbus);
 
 	/* ---dbus---
 	 * property: addresses
@@ -909,13 +911,12 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *klass)
 	 *   that subnet.
 	 * ---end---
 	 */
-	_properties_override_add_override (properties_override,
-	                                   g_object_class_find_property (G_OBJECT_CLASS (setting_class),
-	                                                                 NM_SETTING_IP_CONFIG_ADDRESSES),
-	                                   G_VARIANT_TYPE ("a(ayuay)"),
-	                                   ip6_addresses_get,
-	                                   ip6_addresses_set,
-	                                   NULL);
+	_nm_setting_class_override_property (setting_class,
+	                                     NM_SETTING_IP_CONFIG_ADDRESSES,
+	                                     G_VARIANT_TYPE ("a(ayuay)"),
+	                                     ip6_addresses_get,
+	                                     ip6_addresses_set,
+	                                     NULL);
 
 	/* ---dbus---
 	 * property: address-data
@@ -926,11 +927,11 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *klass)
 	 *   also exist on some addresses.
 	 * ---end---
 	 */
-	_properties_override_add_dbus_only (properties_override,
-	                                    "address-data",
-	                                    G_VARIANT_TYPE ("aa{sv}"),
-	                                    ip6_address_data_get,
-	                                    ip6_address_data_set);
+	_nm_setting_class_add_dbus_only_property (setting_class,
+	                                          "address-data",
+	                                          G_VARIANT_TYPE ("aa{sv}"),
+	                                          ip6_address_data_get,
+	                                          ip6_address_data_set);
 
 	/* ---dbus---
 	 * property: routes
@@ -946,13 +947,12 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *klass)
 	 *   default metric for the device.
 	 * ---end---
 	 */
-	_properties_override_add_override (properties_override,
-	                                   g_object_class_find_property (G_OBJECT_CLASS (setting_class),
-	                                                                 NM_SETTING_IP_CONFIG_ROUTES),
-	                                   G_VARIANT_TYPE ("a(ayuayu)"),
-	                                   ip6_routes_get,
-	                                   ip6_routes_set,
-	                                   NULL);
+	_nm_setting_class_override_property (setting_class,
+	                                     NM_SETTING_IP_CONFIG_ROUTES,
+	                                     G_VARIANT_TYPE ("a(ayuayu)"),
+	                                     ip6_routes_get,
+	                                     ip6_routes_set,
+	                                     NULL);
 
 	/* ---dbus---
 	 * property: route-data
@@ -967,12 +967,9 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *klass)
 	 *   also exist on some routes.
 	 * ---end---
 	 */
-	_properties_override_add_dbus_only (properties_override,
-	                                    "route-data",
-	                                    G_VARIANT_TYPE ("aa{sv}"),
-	                                    ip6_route_data_get,
-	                                    ip6_route_data_set);
-
-	_nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_IP6_CONFIG,
-	                               NULL, properties_override);
+	_nm_setting_class_add_dbus_only_property (setting_class,
+	                                          "route-data",
+	                                          G_VARIANT_TYPE ("aa{sv}"),
+	                                          ip6_route_data_get,
+	                                          ip6_route_data_set);
 }
diff --git a/libnm-core/nm-setting-macsec.c b/libnm-core/nm-setting-macsec.c
index 2c7cff23..92ebafa6 100644
--- a/libnm-core/nm-setting-macsec.c
+++ b/libnm-core/nm-setting-macsec.c
@@ -40,7 +40,9 @@
  * necessary for connection to MACsec (IEEE 802.1AE) interfaces.
  **/
 
-G_DEFINE_TYPE (NMSettingMacsec, nm_setting_macsec, NM_TYPE_SETTING)
+G_DEFINE_TYPE_WITH_CODE (NMSettingMacsec, nm_setting_macsec, NM_TYPE_SETTING,
+                         _nm_register_setting (MACSEC, NM_SETTING_PRIORITY_HW_BASE))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_MACSEC)
 
 #define NM_SETTING_MACSEC_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_MACSEC, NMSettingMacsecPrivate))
 
@@ -472,19 +474,18 @@ finalize (GObject *object)
 }
 
 static void
-nm_setting_macsec_class_init (NMSettingMacsecClass *klass)
+nm_setting_macsec_class_init (NMSettingMacsecClass *setting_class)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	NMSettingClass *setting_class = NM_SETTING_CLASS (klass);
+	GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+	NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
 
-	g_type_class_add_private (klass, sizeof (NMSettingMacsecPrivate));
+	g_type_class_add_private (setting_class, sizeof (NMSettingMacsecPrivate));
 
 	object_class->set_property = set_property;
 	object_class->get_property = get_property;
 	object_class->finalize     = finalize;
-
-	setting_class->verify       = verify;
-	setting_class->need_secrets = need_secrets;
+	parent_class->verify       = verify;
+	parent_class->need_secrets = need_secrets;
 
 	/**
 	 * NMSettingMacsec:parent:
@@ -626,6 +627,4 @@ nm_setting_macsec_class_init (NMSettingMacsecClass *klass)
 	                          G_PARAM_STATIC_STRINGS);
 
 	g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
-
-	_nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_MACSEC);
 }
diff --git a/libnm-core/nm-setting-macvlan.c b/libnm-core/nm-setting-macvlan.c
index 1fc16116..6fea8b0d 100644
--- a/libnm-core/nm-setting-macvlan.c
+++ b/libnm-core/nm-setting-macvlan.c
@@ -39,7 +39,9 @@
  * necessary for connection to macvlan interfaces.
  **/
 
-G_DEFINE_TYPE (NMSettingMacvlan, nm_setting_macvlan, NM_TYPE_SETTING)
+G_DEFINE_TYPE_WITH_CODE (NMSettingMacvlan, nm_setting_macvlan, NM_TYPE_SETTING,
+                         _nm_register_setting (MACVLAN, NM_SETTING_PRIORITY_HW_BASE))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_MACVLAN)
 
 #define NM_SETTING_MACVLAN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_MACVLAN, NMSettingMacvlanPrivate))
 
@@ -258,18 +260,20 @@ finalize (GObject *object)
 }
 
 static void
-nm_setting_macvlan_class_init (NMSettingMacvlanClass *klass)
+nm_setting_macvlan_class_init (NMSettingMacvlanClass *setting_class)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	NMSettingClass *setting_class = NM_SETTING_CLASS (klass);
+	GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+	NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
 
-	g_type_class_add_private (klass, sizeof (NMSettingMacvlanPrivate));
+	g_type_class_add_private (setting_class, sizeof (NMSettingMacvlanPrivate));
 
+	/* virtual methods */
 	object_class->set_property = set_property;
 	object_class->get_property = get_property;
 	object_class->finalize     = finalize;
+	parent_class->verify       = verify;
 
-	setting_class->verify = verify;
+	/* Properties */
 
 	/**
 	 * NMSettingMacvlan:parent:
@@ -338,6 +342,4 @@ nm_setting_macvlan_class_init (NMSettingMacvlanClass *klass)
 		                       G_PARAM_CONSTRUCT |
 		                       NM_SETTING_PARAM_INFERRABLE |
 		                       G_PARAM_STATIC_STRINGS));
-
-	_nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_MACVLAN);
 }
diff --git a/libnm-core/nm-setting-match.c b/libnm-core/nm-setting-match.c
deleted file mode 100644
index 0964c644..00000000
--- a/libnm-core/nm-setting-match.c
+++ /dev/null
@@ -1,295 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-/*
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * Copyright 2018 Red Hat, Inc.
- */
-
-#include "nm-default.h"
-
-#include "nm-setting-match.h"
-#include "nm-setting-private.h"
-#include "nm-utils-private.h"
-
-/**
- * SECTION:nm-setting-match
- * @short_description: Properties to match a connection with a device.
- * @include: nm-setting-match.h
- **/
-
-/**
- * NMSettingMatch:
- *
- * Match settings.
- *
- * Since: 1.14
- */
-struct _NMSettingMatch {
-	NMSetting parent;
-	GPtrArray *interface_name;
-};
-
-struct _NMSettingMatchClass {
-	NMSettingClass parent;
-};
-
-G_DEFINE_TYPE (NMSettingMatch, nm_setting_match, NM_TYPE_SETTING)
-
-NM_GOBJECT_PROPERTIES_DEFINE (NMSettingMatch,
-	PROP_INTERFACE_NAME,
-);
-
-/*****************************************************************************/
-
-/**
- * nm_setting_match_get_num_interface_names:
- * @setting: the #NMSettingMatch
- *
- * Returns: the number of configured interface names
- *
- * Since: 1.14
- **/
-guint
-nm_setting_match_get_num_interface_names (NMSettingMatch *setting)
-{
-	g_return_val_if_fail (NM_IS_SETTING_MATCH (setting), 0);
-
-	return setting->interface_name->len;
-}
-
-/**
- * nm_setting_match_get_interface_name:
- * @setting: the #NMSettingMatch
- * @idx: index number of the DNS search domain to return
- *
- * Returns: the interface name at index @idx
- *
- * Since: 1.14
- **/
-const char *
-nm_setting_match_get_interface_name (NMSettingMatch *setting, int idx)
-{
-	g_return_val_if_fail (NM_IS_SETTING_MATCH (setting), NULL);
-
-	g_return_val_if_fail (idx >= 0 && idx < setting->interface_name->len, NULL);
-
-	return setting->interface_name->pdata[idx];
-}
-
-/**
- * nm_setting_match_add_interface_name:
- * @setting: the #NMSettingMatch
- * @interface_name: the interface name to add
- *
- * Adds a new interface name to the setting.
- *
- * Since: 1.14
- **/
-void
-nm_setting_match_add_interface_name (NMSettingMatch *setting,
-                                     const char *interface_name)
-{
-	g_return_if_fail (NM_IS_SETTING_MATCH (setting));
-	g_return_if_fail (interface_name != NULL);
-	g_return_if_fail (interface_name[0] != '\0');
-
-	g_ptr_array_add (setting->interface_name, g_strdup (interface_name));
-	_notify (setting, PROP_INTERFACE_NAME);
-}
-
-/**
- * nm_setting_match_remove_interface_name:
- * @setting: the #NMSettingMatch
- * @idx: index number of the interface name
- *
- * Removes the interface name at index @idx.
- *
- * Since: 1.14
- **/
-void
-nm_setting_match_remove_interface_name (NMSettingMatch *setting, int idx)
-{
-	g_return_if_fail (NM_IS_SETTING_MATCH (setting));
-
-	g_return_if_fail (idx >= 0 && idx < setting->interface_name->len);
-
-	g_ptr_array_remove_index (setting->interface_name, idx);
-	_notify (setting, PROP_INTERFACE_NAME);
-}
-
-/**
- * nm_setting_match_remove_interface_name_by_value:
- * @setting: the #NMSettingMatch
- * @interface_name: the interface name to remove
- *
- * Removes @interface_name.
- *
- * Returns: %TRUE if the interface name was found and removed; %FALSE if it was not.
- *
- * Since: 1.14
- **/
-gboolean
-nm_setting_match_remove_interface_name_by_value (NMSettingMatch *setting,
-                                                 const char *interface_name)
-{
-	guint i;
-
-	g_return_val_if_fail (NM_IS_SETTING_MATCH (setting), FALSE);
-	g_return_val_if_fail (interface_name != NULL, FALSE);
-	g_return_val_if_fail (interface_name[0] != '\0', FALSE);
-
-	for (i = 0; i < setting->interface_name->len; i++) {
-		if (nm_streq (interface_name, setting->interface_name->pdata[i])) {
-			g_ptr_array_remove_index (setting->interface_name, i);
-			_notify (setting, PROP_INTERFACE_NAME);
-			return TRUE;
-		}
-	}
-	return FALSE;
-}
-
-/**
- * nm_setting_match_clear_interface_names:
- * @setting: the #NMSettingMatch
- *
- * Removes all configured interface names.
- *
- * Since: 1.14
- **/
-void
-nm_setting_match_clear_interface_names (NMSettingMatch *setting)
-{
-	g_return_if_fail (NM_IS_SETTING_MATCH (setting));
-
-	if (setting->interface_name->len != 0) {
-		g_ptr_array_set_size (setting->interface_name, 0);
-		_notify (setting, PROP_INTERFACE_NAME);
-	}
-}
-
-/**
- * nm_setting_match_get_interface_names:
- * @setting: the #NMSettingMatch
- *
- * Returns all the interface names.
- *
- * Returns: (transfer none): the configured interface names.
- *
- * Since: 1.14
- **/
-const char *const *
-nm_setting_match_get_interface_names (NMSettingMatch *setting, guint *length)
-{
-	g_return_val_if_fail (NM_IS_SETTING_MATCH (setting), NULL);
-	g_return_val_if_fail (length, NULL);
-
-	NM_SET_OUT (length, setting->interface_name->len);
-	return (const char *const *) setting->interface_name->pdata;
-}
-
-static void
-get_property (GObject *object, guint prop_id,
-              GValue *value, GParamSpec *pspec)
-{
-	NMSettingMatch *self = NM_SETTING_MATCH (object);
-
-	switch (prop_id) {
-	case PROP_INTERFACE_NAME:
-		g_value_take_boxed (value, _nm_utils_ptrarray_to_strv (self->interface_name));
-		break;
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-		break;
-	}
-}
-
-static void
-set_property (GObject *object, guint prop_id,
-              const GValue *value, GParamSpec *pspec)
-{
-	NMSettingMatch *self = NM_SETTING_MATCH (object);
-
-	switch (prop_id) {
-	case PROP_INTERFACE_NAME:
-		g_ptr_array_unref (self->interface_name);
-		self->interface_name = _nm_utils_strv_to_ptrarray (g_value_get_boxed (value));
-		break;
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-		break;
-	}
-}
-
-static void
-nm_setting_match_init (NMSettingMatch *setting)
-{
-	setting->interface_name = g_ptr_array_new_with_free_func (g_free);
-}
-
-/**
- * nm_setting_match_new:
- *
- * Creates a new #NMSettingMatch object with default values.
- *
- * Returns: (transfer full): the new empty #NMSettingMatch object
- *
- * Since: 1.14
- **/
-NMSetting *
-nm_setting_match_new (void)
-{
-	return (NMSetting *) g_object_new (NM_TYPE_SETTING_MATCH, NULL);
-}
-
-static void
-finalize (GObject *object)
-{
-	NMSettingMatch *self = NM_SETTING_MATCH (object);
-
-	g_ptr_array_unref (self->interface_name);
-
-	G_OBJECT_CLASS (nm_setting_match_parent_class)->finalize (object);
-}
-
-static void
-nm_setting_match_class_init (NMSettingMatchClass *klass)
-{
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	NMSettingClass *setting_class = NM_SETTING_CLASS (klass);
-
-	object_class->finalize     = finalize;
-	object_class->get_property = get_property;
-	object_class->set_property = set_property;
-
-	/**
-	 * NMSettingMatch:interface-name
-	 *
-	 * A list of interface names to match. Each element is a shell wildcard
-	 * pattern.  When an element is prefixed with exclamation mark (!) the
-	 * condition is inverted.
-	 *
-	 * A candidate interface name is considered matching when both these
-	 * conditions are satisfied: (a) any of the elements not prefixed with '!'
-	 * matches or there aren't such elements; (b) none of the elements
-	 * prefixed with '!' match.
-	 *
-	 * Since: 1.14
-	 **/
-	obj_properties[PROP_INTERFACE_NAME] =
-	    g_param_spec_boxed (NM_SETTING_MATCH_INTERFACE_NAME, "", "",
-	                        G_TYPE_STRV,
-	                        NM_SETTING_PARAM_FUZZY_IGNORE |
-	                        G_PARAM_READWRITE |
-	                        G_PARAM_STATIC_STRINGS);
-
-	g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
-
-	_nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_MATCH);
-}
diff --git a/libnm-core/nm-setting-match.h b/libnm-core/nm-setting-match.h
deleted file mode 100644
index a39feca2..00000000
--- a/libnm-core/nm-setting-match.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-/*
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * Copyright 2018 Red Hat, Inc.
- */
-
-#ifndef NM_SETTING_MATCH_H
-#define NM_SETTING_MATCH_H
-
-#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION)
-#error "Only <NetworkManager.h> can be included directly."
-#endif
-
-#include "nm-setting.h"
-
-G_BEGIN_DECLS
-
-#define NM_TYPE_SETTING_MATCH            (nm_setting_match_get_type ())
-#define NM_SETTING_MATCH(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_MATCH, NMSettingMatch))
-#define NM_SETTING_MATCH_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_MATCH, NMSettingMatchClass))
-#define NM_IS_SETTING_MATCH(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_MATCH))
-#define NM_IS_SETTING_MATCH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_MATCH))
-#define NM_SETTING_MATCH_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_MATCH, NMSettingMatchClass))
-
-#define NM_SETTING_MATCH_SETTING_NAME      "match"
-
-#define NM_SETTING_MATCH_INTERFACE_NAME    "interface-name"
-
-typedef struct _NMSettingMatchClass NMSettingMatchClass;
-
-
-NM_AVAILABLE_IN_1_14
-GType nm_setting_match_get_type (void);
-NM_AVAILABLE_IN_1_14
-NMSetting *nm_setting_match_new (void);
-
-NM_AVAILABLE_IN_1_14
-guint nm_setting_match_get_num_interface_names (NMSettingMatch *setting);
-NM_AVAILABLE_IN_1_14
-const char *nm_setting_match_get_interface_name (NMSettingMatch *setting, int idx);
-NM_AVAILABLE_IN_1_14
-void nm_setting_match_remove_interface_name (NMSettingMatch *setting, int idx);
-NM_AVAILABLE_IN_1_14
-gboolean nm_setting_match_remove_interface_name_by_value (NMSettingMatch *setting,
-                                                          const char *interface_name);
-NM_AVAILABLE_IN_1_14
-void nm_setting_match_add_interface_name (NMSettingMatch *setting,
-                                          const char *interface_name);
-NM_AVAILABLE_IN_1_14
-void nm_setting_match_clear_interface_names (NMSettingMatch *setting);
-NM_AVAILABLE_IN_1_14
-const char *const *nm_setting_match_get_interface_names (NMSettingMatch *setting, guint *length);
-G_END_DECLS
-
-#endif /* NM_SETTING_MATCH_H */
diff --git a/libnm-core/nm-setting-olpc-mesh.c b/libnm-core/nm-setting-olpc-mesh.c
index 7f4a1bbf..783d143f 100644
--- a/libnm-core/nm-setting-olpc-mesh.c
+++ b/libnm-core/nm-setting-olpc-mesh.c
@@ -39,7 +39,9 @@
 
 static void nm_setting_olpc_mesh_init (NMSettingOlpcMesh *setting);
 
-G_DEFINE_TYPE (NMSettingOlpcMesh, nm_setting_olpc_mesh, NM_TYPE_SETTING)
+G_DEFINE_TYPE_WITH_CODE (NMSettingOlpcMesh, nm_setting_olpc_mesh, NM_TYPE_SETTING,
+                         _nm_register_setting (OLPC_MESH, NM_SETTING_PRIORITY_HW_BASE))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_OLPC_MESH)
 
 #define NM_SETTING_OLPC_MESH_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_OLPC_MESH, NMSettingOlpcMeshPrivate))
 
@@ -212,20 +214,20 @@ get_property (GObject *object, guint prop_id,
 }
 
 static void
-nm_setting_olpc_mesh_class_init (NMSettingOlpcMeshClass *klass)
+nm_setting_olpc_mesh_class_init (NMSettingOlpcMeshClass *setting_class)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	NMSettingClass *setting_class = NM_SETTING_CLASS (klass);
-	GArray *properties_override = _nm_sett_info_property_override_create_array ();
+	GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+	NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
 
-	g_type_class_add_private (klass, sizeof (NMSettingOlpcMeshPrivate));
+	g_type_class_add_private (setting_class, sizeof (NMSettingOlpcMeshPrivate));
 
+	/* virtual methods */
 	object_class->set_property = set_property;
 	object_class->get_property = get_property;
 	object_class->finalize     = finalize;
+	parent_class->verify       = verify;
 
-	setting_class->verify = verify;
-
+	/* Properties */
 	/**
 	 * NMSettingOlpcMesh:ssid:
 	 *
@@ -266,14 +268,8 @@ nm_setting_olpc_mesh_class_init (NMSettingOlpcMeshClass *klass)
 		                      NULL,
 		                      G_PARAM_READWRITE |
 		                      G_PARAM_STATIC_STRINGS));
-
-	_properties_override_add_transform (properties_override,
-	                                    g_object_class_find_property (G_OBJECT_CLASS (setting_class),
-	                                                                  NM_SETTING_OLPC_MESH_DHCP_ANYCAST_ADDRESS),
-	                                    G_VARIANT_TYPE_BYTESTRING,
-	                                    _nm_utils_hwaddr_to_dbus,
-	                                    _nm_utils_hwaddr_from_dbus);
-
-	_nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_OLPC_MESH,
-	                               NULL, properties_override);
+	_nm_setting_class_transform_property (parent_class, NM_SETTING_OLPC_MESH_DHCP_ANYCAST_ADDRESS,
+	                                      G_VARIANT_TYPE_BYTESTRING,
+	                                      _nm_utils_hwaddr_to_dbus,
+	                                      _nm_utils_hwaddr_from_dbus);
 }
diff --git a/libnm-core/nm-setting-ovs-bridge.c b/libnm-core/nm-setting-ovs-bridge.c
index 9ca5566f..4993d13f 100644
--- a/libnm-core/nm-setting-ovs-bridge.c
+++ b/libnm-core/nm-setting-ovs-bridge.c
@@ -61,7 +61,9 @@ struct _NMSettingOvsBridgeClass {
 	NMSettingClass parent;
 };
 
-G_DEFINE_TYPE (NMSettingOvsBridge, nm_setting_ovs_bridge, NM_TYPE_SETTING)
+G_DEFINE_TYPE_WITH_CODE (NMSettingOvsBridge, nm_setting_ovs_bridge, NM_TYPE_SETTING,
+                         _nm_register_setting (OVS_BRIDGE, NM_SETTING_PRIORITY_HW_BASE))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_OVS_BRIDGE)
 
 /*****************************************************************************/
 
@@ -262,16 +264,15 @@ finalize (GObject *object)
 }
 
 static void
-nm_setting_ovs_bridge_class_init (NMSettingOvsBridgeClass *klass)
+nm_setting_ovs_bridge_class_init (NMSettingOvsBridgeClass *setting_class)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	NMSettingClass *setting_class = NM_SETTING_CLASS (klass);
+	GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+	NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
 
 	object_class->set_property = set_property;
 	object_class->get_property = get_property;
-	object_class->finalize     = finalize;
-
-	setting_class->verify = verify;
+	object_class->finalize = finalize;
+	parent_class->verify = verify;
 
 	/**
 	 * NMSettingOvsBridge:fail-mode:
@@ -333,6 +334,4 @@ nm_setting_ovs_bridge_class_init (NMSettingOvsBridgeClass *klass)
 	                               G_PARAM_READWRITE |
 	                               G_PARAM_CONSTRUCT |
 	                               G_PARAM_STATIC_STRINGS));
-
-	_nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_OVS_BRIDGE);
 }
diff --git a/libnm-core/nm-setting-ovs-interface.c b/libnm-core/nm-setting-ovs-interface.c
index a177098d..ff9e4c1d 100644
--- a/libnm-core/nm-setting-ovs-interface.c
+++ b/libnm-core/nm-setting-ovs-interface.c
@@ -54,7 +54,9 @@ struct _NMSettingOvsInterfaceClass {
 	NMSettingClass parent;
 };
 
-G_DEFINE_TYPE (NMSettingOvsInterface, nm_setting_ovs_interface, NM_TYPE_SETTING)
+G_DEFINE_TYPE_WITH_CODE (NMSettingOvsInterface, nm_setting_ovs_interface, NM_TYPE_SETTING,
+                         _nm_register_setting (OVS_INTERFACE, NM_SETTING_PRIORITY_HW_BASE))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_OVS_INTERFACE)
 
 /*****************************************************************************/
 
@@ -361,16 +363,15 @@ finalize (GObject *object)
 }
 
 static void
-nm_setting_ovs_interface_class_init (NMSettingOvsInterfaceClass *klass)
+nm_setting_ovs_interface_class_init (NMSettingOvsInterfaceClass *setting_class)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	NMSettingClass *setting_class = NM_SETTING_CLASS (klass);
+	GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+	NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
 
 	object_class->set_property = set_property;
 	object_class->get_property = get_property;
-	object_class->finalize     = finalize;
-
-	setting_class->verify = verify;
+	object_class->finalize = finalize;
+	parent_class->verify = verify;
 
 	/**
 	 * NMSettingOvsInterface:type:
@@ -387,6 +388,4 @@ nm_setting_ovs_interface_class_init (NMSettingOvsInterfaceClass *klass)
 	                              G_PARAM_CONSTRUCT |
 	                              NM_SETTING_PARAM_INFERRABLE |
 	                              G_PARAM_STATIC_STRINGS));
-
-	_nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_OVS_INTERFACE);
 }
diff --git a/libnm-core/nm-setting-ovs-patch.c b/libnm-core/nm-setting-ovs-patch.c
index 15005eea..980015f2 100644
--- a/libnm-core/nm-setting-ovs-patch.c
+++ b/libnm-core/nm-setting-ovs-patch.c
@@ -55,7 +55,9 @@ struct _NMSettingOvsPatchClass {
 	NMSettingClass parent;
 };
 
-G_DEFINE_TYPE (NMSettingOvsPatch, nm_setting_ovs_patch, NM_TYPE_SETTING)
+G_DEFINE_TYPE_WITH_CODE (NMSettingOvsPatch, nm_setting_ovs_patch, NM_TYPE_SETTING,
+                         _nm_register_setting (OVS_PATCH, NM_SETTING_PRIORITY_HW_BASE))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_OVS_PATCH)
 
 /*****************************************************************************/
 
@@ -180,16 +182,15 @@ finalize (GObject *object)
 }
 
 static void
-nm_setting_ovs_patch_class_init (NMSettingOvsPatchClass *klass)
+nm_setting_ovs_patch_class_init (NMSettingOvsPatchClass *setting_class)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	NMSettingClass *setting_class = NM_SETTING_CLASS (klass);
+	GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+	NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
 
 	object_class->set_property = set_property;
 	object_class->get_property = get_property;
-	object_class->finalize     = finalize;
-
-	setting_class->verify = verify;
+	object_class->finalize = finalize;
+	parent_class->verify = verify;
 
 	/**
 	 * NMSettingOvsPatch:peer:
@@ -207,6 +208,4 @@ nm_setting_ovs_patch_class_init (NMSettingOvsPatchClass *klass)
 	                              G_PARAM_CONSTRUCT |
 	                              NM_SETTING_PARAM_INFERRABLE |
 	                              G_PARAM_STATIC_STRINGS));
-
-	_nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_OVS_PATCH);
 }
diff --git a/libnm-core/nm-setting-ovs-port.c b/libnm-core/nm-setting-ovs-port.c
index 10e542e7..b61df0ce 100644
--- a/libnm-core/nm-setting-ovs-port.c
+++ b/libnm-core/nm-setting-ovs-port.c
@@ -65,7 +65,9 @@ struct _NMSettingOvsPortClass {
 	NMSettingClass parent;
 };
 
-G_DEFINE_TYPE (NMSettingOvsPort, nm_setting_ovs_port, NM_TYPE_SETTING)
+G_DEFINE_TYPE_WITH_CODE (NMSettingOvsPort, nm_setting_ovs_port, NM_TYPE_SETTING,
+                         _nm_register_setting (OVS_PORT, NM_SETTING_PRIORITY_HW_BASE))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_OVS_PORT)
 
 /*****************************************************************************/
 
@@ -359,16 +361,15 @@ finalize (GObject *object)
 }
 
 static void
-nm_setting_ovs_port_class_init (NMSettingOvsPortClass *klass)
+nm_setting_ovs_port_class_init (NMSettingOvsPortClass *setting_class)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	NMSettingClass *setting_class = NM_SETTING_CLASS (klass);
+	GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+	NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
 
 	object_class->set_property = set_property;
 	object_class->get_property = get_property;
-	object_class->finalize     = finalize;
-
-	setting_class->verify = verify;
+	object_class->finalize = finalize;
+	parent_class->verify = verify;
 
 	/**
 	 * NMSettingOvsPort:vlan-mode:
@@ -466,6 +467,4 @@ nm_setting_ovs_port_class_init (NMSettingOvsPortClass *klass)
 	                            G_PARAM_CONSTRUCT |
 	                            NM_SETTING_PARAM_INFERRABLE |
 	                            G_PARAM_STATIC_STRINGS));
-
-	_nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_OVS_PORT);
 }
diff --git a/libnm-core/nm-setting-ppp.c b/libnm-core/nm-setting-ppp.c
index 7425da19..32900c84 100644
--- a/libnm-core/nm-setting-ppp.c
+++ b/libnm-core/nm-setting-ppp.c
@@ -35,7 +35,9 @@
  * cable and DSL modems and some mobile broadband devices.
  **/
 
-G_DEFINE_TYPE (NMSettingPpp, nm_setting_ppp, NM_TYPE_SETTING)
+G_DEFINE_TYPE_WITH_CODE (NMSettingPpp, nm_setting_ppp, NM_TYPE_SETTING,
+                         _nm_register_setting (PPP, NM_SETTING_PRIORITY_AUX))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_PPP)
 
 #define NM_SETTING_PPP_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_PPP, NMSettingPppPrivate))
 
@@ -523,18 +525,19 @@ get_property (GObject *object, guint prop_id,
 }
 
 static void
-nm_setting_ppp_class_init (NMSettingPppClass *klass)
+nm_setting_ppp_class_init (NMSettingPppClass *setting_class)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	NMSettingClass *setting_class = NM_SETTING_CLASS (klass);
+	GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+	NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
 
-	g_type_class_add_private (klass, sizeof (NMSettingPppPrivate));
+	g_type_class_add_private (setting_class, sizeof (NMSettingPppPrivate));
 
+	/* virtual methods */
 	object_class->set_property = set_property;
 	object_class->get_property = get_property;
+	parent_class->verify       = verify;
 
-	setting_class->verify = verify;
-
+	/* Properties */
 	/**
 	 * NMSettingPpp:noauth:
 	 *
@@ -795,6 +798,4 @@ nm_setting_ppp_class_init (NMSettingPppClass *klass)
 		                    G_PARAM_CONSTRUCT |
 		                    NM_SETTING_PARAM_FUZZY_IGNORE |
 		                    G_PARAM_STATIC_STRINGS));
-
-	_nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_PPP);
 }
diff --git a/libnm-core/nm-setting-pppoe.c b/libnm-core/nm-setting-pppoe.c
index 793d93ce..d7a1a0db 100644
--- a/libnm-core/nm-setting-pppoe.c
+++ b/libnm-core/nm-setting-pppoe.c
@@ -38,7 +38,9 @@
  * to provide IP transport, for example cable or DSL modems.
  **/
 
-G_DEFINE_TYPE (NMSettingPppoe, nm_setting_pppoe, NM_TYPE_SETTING)
+G_DEFINE_TYPE_WITH_CODE (NMSettingPppoe, nm_setting_pppoe, NM_TYPE_SETTING,
+                         _nm_register_setting (PPPOE, NM_SETTING_PRIORITY_AUX))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_PPPOE)
 
 #define NM_SETTING_PPPOE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_PPPOE, NMSettingPppoePrivate))
 
@@ -286,20 +288,21 @@ finalize (GObject *object)
 }
 
 static void
-nm_setting_pppoe_class_init (NMSettingPppoeClass *klass)
+nm_setting_pppoe_class_init (NMSettingPppoeClass *setting_class)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	NMSettingClass *setting_class = NM_SETTING_CLASS (klass);
+	GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+	NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
 
-	g_type_class_add_private (klass, sizeof (NMSettingPppoePrivate));
+	g_type_class_add_private (setting_class, sizeof (NMSettingPppoePrivate));
 
+	/* virtual methods */
 	object_class->set_property = set_property;
 	object_class->get_property = get_property;
 	object_class->finalize     = finalize;
+	parent_class->verify       = verify;
+	parent_class->need_secrets = need_secrets;
 
-	setting_class->verify       = verify;
-	setting_class->need_secrets = need_secrets;
-
+	/* Properties */
 	/**
 	 * NMSettingPppoe:parent:
 	 *
@@ -371,6 +374,4 @@ nm_setting_pppoe_class_init (NMSettingPppoeClass *klass)
 		                     NM_SETTING_SECRET_FLAG_NONE,
 		                     G_PARAM_READWRITE |
 		                     G_PARAM_STATIC_STRINGS));
-
-	_nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_PPPOE);
 }
diff --git a/libnm-core/nm-setting-private.h b/libnm-core/nm-setting-private.h
index 1e25226e..863ea9f3 100644
--- a/libnm-core/nm-setting-private.h
+++ b/libnm-core/nm-setting-private.h
@@ -31,13 +31,18 @@
 
 #include "nm-core-internal.h"
 
-/*****************************************************************************/
+void _nm_register_setting_impl (const char *name,
+                                GType type,
+                                NMSettingPriority priority);
+
+#define _nm_register_setting(name, priority) \
+	G_STMT_START { \
+		_nm_register_setting_impl ("" NM_SETTING_ ## name ## _SETTING_NAME "", g_define_type_id, priority); \
+	} G_STMT_END
 
 NMSettingPriority _nm_setting_get_base_type_priority (NMSetting *setting);
 NMSettingPriority _nm_setting_type_get_base_type_priority (GType type);
-int _nm_setting_compare_priority (gconstpointer a, gconstpointer b);
-
-/*****************************************************************************/
+gint _nm_setting_compare_priority (gconstpointer a, gconstpointer b);
 
 typedef enum NMSettingUpdateSecretResult {
 	NM_SETTING_UPDATE_SECRET_ERROR              = FALSE,
@@ -80,7 +85,10 @@ gboolean _nm_setting_clear_secrets_with_flags (NMSetting *setting,
  */
 #define NM_SETTING_PARAM_REAPPLY_IMMEDIATELY (1 << (6 + G_PARAM_USER_SHIFT))
 
-#define NM_SETTING_PARAM_GENDATA_BACKED (1 << (7 + G_PARAM_USER_SHIFT))
+/* Ensure the setting's GType is registered at library load time */
+#define NM_SETTING_REGISTER_TYPE(x) \
+static void __attribute__((constructor)) register_setting (void) \
+{ g_type_ensure (x); }
 
 GVariant *_nm_setting_get_deprecated_virtual_interface_name (NMSetting *setting,
                                                              NMConnection *connection,
@@ -107,78 +115,44 @@ NMSetting  *_nm_setting_new_from_dbus (GType setting_type,
                                        NMSettingParseFlags parse_flags,
                                        GError **error);
 
-/*****************************************************************************/
-
-static inline GArray *
-_nm_sett_info_property_override_create_array (void)
-{
-	return g_array_new (FALSE, FALSE, sizeof (NMSettInfoProperty));
-}
-
-GArray *_nm_sett_info_property_override_create_array_ip_config (void);
-
-void _nm_setting_class_commit_full (NMSettingClass *setting_class,
-                                    NMMetaSettingType meta_type,
-                                    const NMSettInfoSettDetail *detail,
-                                    GArray *properties_override);
-
-static inline void
-_nm_setting_class_commit (NMSettingClass *setting_class,
-                          NMMetaSettingType meta_type)
-{
-	_nm_setting_class_commit_full (setting_class, meta_type, NULL, NULL);
-}
-
-#define NM_SETT_INFO_SETT_GENDATA(...) \
-	({ \
-		static const NMSettInfoSettGendata _g = { \
-			__VA_ARGS__ \
-		}; \
-		\
-		&_g; \
-	})
-
-#define NM_SETT_INFO_SETT_DETAIL(...) \
-	(&((const NMSettInfoSettDetail) { \
-		__VA_ARGS__ \
-	}))
-
-#define NM_SETT_INFO_PROPERTY(...) \
-	(&((const NMSettInfoProperty) { \
-		__VA_ARGS__ \
-	}))
-
-void _properties_override_add_struct (GArray *properties_override,
-                                      const NMSettInfoProperty *prop_info);
-
-void _properties_override_add__helper (GArray *properties_override,
-                                       NMSettInfoProperty *prop_info);
-
-#define _properties_override_add(properties_override, \
-                                 ...) \
-	(_properties_override_add_struct (properties_override, \
-	                                  NM_SETT_INFO_PROPERTY (__VA_ARGS__)))
-
-void _properties_override_add_dbus_only (GArray *properties_override,
-                                         const char *property_name,
-                                         const GVariantType *dbus_type,
-                                         NMSettingPropertySynthFunc synth_func,
-                                         NMSettingPropertySetFunc set_func);
-
-void _properties_override_add_override (GArray *properties_override,
-                                        GParamSpec *param_spec,
-                                        const GVariantType *dbus_type,
-                                        NMSettingPropertyGetFunc get_func,
-                                        NMSettingPropertySetFunc set_func,
-                                        NMSettingPropertyNotSetFunc not_set_func);
-
-void _properties_override_add_transform (GArray *properties_override,
-                                         GParamSpec *param_spec,
-                                         const GVariantType *dbus_type,
-                                         NMSettingPropertyTransformToFunc to_dbus,
-                                         NMSettingPropertyTransformFromFunc from_dbus);
-
-/*****************************************************************************/
+typedef GVariant * (*NMSettingPropertyGetFunc)    (NMSetting     *setting,
+                                                   const char    *property);
+typedef GVariant * (*NMSettingPropertySynthFunc)  (NMSetting     *setting,
+                                                   NMConnection  *connection,
+                                                   const char    *property);
+typedef gboolean   (*NMSettingPropertySetFunc)    (NMSetting     *setting,
+                                                   GVariant      *connection_dict,
+                                                   const char    *property,
+                                                   GVariant      *value,
+                                                   NMSettingParseFlags parse_flags,
+                                                   GError       **error);
+typedef gboolean   (*NMSettingPropertyNotSetFunc) (NMSetting     *setting,
+                                                   GVariant      *connection_dict,
+                                                   const char    *property,
+                                                   NMSettingParseFlags parse_flags,
+                                                   GError       **error);
+
+void _nm_setting_class_add_dbus_only_property (NMSettingClass *setting_class,
+                                               const char *property_name,
+                                               const GVariantType *dbus_type,
+                                               NMSettingPropertySynthFunc synth_func,
+                                               NMSettingPropertySetFunc set_func);
+
+void _nm_setting_class_override_property (NMSettingClass *setting_class,
+                                          const char *property_name,
+                                          const GVariantType *dbus_type,
+                                          NMSettingPropertyGetFunc get_func,
+                                          NMSettingPropertySetFunc set_func,
+                                          NMSettingPropertyNotSetFunc not_set_func);
+
+typedef GVariant * (*NMSettingPropertyTransformToFunc) (const GValue *from);
+typedef void (*NMSettingPropertyTransformFromFunc) (GVariant *from, GValue *to);
+
+void _nm_setting_class_transform_property (NMSettingClass *setting_class,
+                                           const char *property_name,
+                                           const GVariantType *dbus_type,
+                                           NMSettingPropertyTransformToFunc to_dbus,
+                                           NMSettingPropertyTransformFromFunc from_dbus);
 
 gboolean _nm_setting_use_legacy_property (NMSetting *setting,
                                           GVariant *connection_dict,
@@ -187,6 +161,4 @@ gboolean _nm_setting_use_legacy_property (NMSetting *setting,
 
 GPtrArray  *_nm_setting_need_secrets (NMSetting *setting);
 
-/*****************************************************************************/
-
 #endif  /* NM_SETTING_PRIVATE_H */
diff --git a/libnm-core/nm-setting-proxy.c b/libnm-core/nm-setting-proxy.c
index d544c7fa..58a22080 100644
--- a/libnm-core/nm-setting-proxy.c
+++ b/libnm-core/nm-setting-proxy.c
@@ -39,7 +39,9 @@
  * to fulfill client queries.
  **/
 
-G_DEFINE_TYPE (NMSettingProxy, nm_setting_proxy, NM_TYPE_SETTING)
+G_DEFINE_TYPE_WITH_CODE (NMSettingProxy, nm_setting_proxy, NM_TYPE_SETTING,
+                         _nm_register_setting (PROXY, NM_SETTING_PRIORITY_IP))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_PROXY)
 
 #define NM_SETTING_PROXY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_PROXY, NMSettingProxyPrivate))
 
@@ -283,18 +285,18 @@ set_property (GObject *object, guint prop_id,
 }
 
 static void
-nm_setting_proxy_class_init (NMSettingProxyClass *klass)
+nm_setting_proxy_class_init (NMSettingProxyClass *setting_class)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	NMSettingClass *setting_class = NM_SETTING_CLASS (klass);
+	GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+	NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
 
-	g_type_class_add_private (klass, sizeof (NMSettingProxyPrivate));
+	g_type_class_add_private (setting_class, sizeof (NMSettingProxyPrivate));
 
+	/* virtual methods */
 	object_class->set_property = set_property;
 	object_class->get_property = get_property;
-	object_class->finalize     = finalize;
-
-	setting_class->verify = verify;
+	object_class->finalize = finalize;
+	parent_class->verify = verify;
 
 	/**
 	 * NMSettingProxy:method:
@@ -382,6 +384,4 @@ nm_setting_proxy_class_init (NMSettingProxyClass *klass)
 	                          NULL,
 	                          G_PARAM_READWRITE |
 	                          G_PARAM_STATIC_STRINGS));
-
-	_nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_PROXY);
 }
diff --git a/libnm-core/nm-setting-serial.c b/libnm-core/nm-setting-serial.c
index b173197d..e86988b5 100644
--- a/libnm-core/nm-setting-serial.c
+++ b/libnm-core/nm-setting-serial.c
@@ -16,7 +16,7 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * Copyright 2007 - 2018 Red Hat, Inc.
+ * Copyright 2007 - 2011 Red Hat, Inc.
  * Copyright 2007 - 2008 Novell, Inc.
  */
 
@@ -37,7 +37,9 @@
  * such as mobile broadband or analog telephone connections.
  **/
 
-G_DEFINE_TYPE (NMSettingSerial, nm_setting_serial, NM_TYPE_SETTING)
+G_DEFINE_TYPE_WITH_CODE (NMSettingSerial, nm_setting_serial, NM_TYPE_SETTING,
+                         _nm_register_setting (SERIAL, NM_SETTING_PRIORITY_HW_AUX))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_SERIAL)
 
 #define NM_SETTING_SERIAL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_SERIAL, NMSettingSerialPrivate))
 
@@ -143,6 +145,12 @@ nm_setting_serial_get_send_delay (NMSettingSerial *setting)
 	return NM_SETTING_SERIAL_GET_PRIVATE (setting)->send_delay;
 }
 
+static gboolean
+verify (NMSetting *setting, NMConnection *connection, GError **error)
+{
+	return TRUE;
+}
+
 static void
 nm_setting_serial_init (NMSettingSerial *setting)
 {
@@ -236,16 +244,19 @@ get_property (GObject *object, guint prop_id,
 }
 
 static void
-nm_setting_serial_class_init (NMSettingSerialClass *klass)
+nm_setting_serial_class_init (NMSettingSerialClass *setting_class)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	NMSettingClass *setting_class = NM_SETTING_CLASS (klass);
-	GArray *properties_override = _nm_sett_info_property_override_create_array ();
+	GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+	NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
 
-	g_type_class_add_private (klass, sizeof (NMSettingSerialPrivate));
+	g_type_class_add_private (setting_class, sizeof (NMSettingSerialPrivate));
 
+	/* virtual methods */
 	object_class->set_property = set_property;
 	object_class->get_property = get_property;
+	parent_class->verify       = verify;
+
+	/* Properties */
 
 	/**
 	 * NMSettingSerial:baud:
@@ -303,13 +314,11 @@ nm_setting_serial_class_init (NMSettingSerialClass *klass)
 		                    G_PARAM_READWRITE |
 		                    G_PARAM_CONSTRUCT |
 		                    G_PARAM_STATIC_STRINGS));
-
-	_properties_override_add_transform (properties_override,
-	                                    g_object_class_find_property (G_OBJECT_CLASS (setting_class),
-	                                                                  NM_SETTING_SERIAL_PARITY),
-	                                    G_VARIANT_TYPE_BYTE,
-	                                    parity_to_dbus,
-	                                    parity_from_dbus);
+	_nm_setting_class_transform_property (parent_class,
+	                                      NM_SETTING_SERIAL_PARITY,
+	                                      G_VARIANT_TYPE_BYTE,
+	                                      parity_to_dbus,
+	                                      parity_from_dbus);
 
 	/**
 	 * NMSettingSerial:stopbits:
@@ -337,7 +346,4 @@ nm_setting_serial_class_init (NMSettingSerialClass *klass)
 		                      G_PARAM_READWRITE |
 		                      G_PARAM_CONSTRUCT |
 		                      G_PARAM_STATIC_STRINGS));
-
-	_nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_SERIAL,
-	                               NULL, properties_override);
 }
diff --git a/libnm-core/nm-setting-sriov.c b/libnm-core/nm-setting-sriov.c
deleted file mode 100644
index 45b3a1d2..00000000
--- a/libnm-core/nm-setting-sriov.c
+++ /dev/null
@@ -1,1357 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-/*
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * Copyright 2018 Red Hat, Inc.
- */
-
-#include "nm-default.h"
-
-#include "nm-setting-sriov.h"
-#include "nm-setting-private.h"
-#include "nm-utils-private.h"
-
-/**
- * SECTION:nm-setting-sriov
- * @short_description: Describes SR-IOV connection properties
- * @include: nm-setting-sriov.h
- **/
-
-/**
- * NMSettingSriov:
- *
- * SR-IOV settings.
- *
- * Since: 1.14
- */
-struct _NMSettingSriov {
-	NMSetting parent;
-	GPtrArray *vfs;
-	guint total_vfs;
-	NMTernary autoprobe_drivers;
-};
-
-struct _NMSettingSriovClass {
-	NMSettingClass parent;
-};
-
-G_DEFINE_TYPE (NMSettingSriov, nm_setting_sriov, NM_TYPE_SETTING)
-
-enum {
-	PROP_0,
-	PROP_TOTAL_VFS,
-	PROP_VFS,
-	PROP_AUTOPROBE_DRIVERS,
-
-	LAST_PROP
-};
-
-/*****************************************************************************/
-
-G_DEFINE_BOXED_TYPE (NMSriovVF, nm_sriov_vf, nm_sriov_vf_dup, nm_sriov_vf_unref)
-
-struct _NMSriovVF {
-	guint refcount;
-	guint index;
-	GHashTable *attributes;
-	GHashTable *vlans;
-	guint *vlan_ids;
-};
-
-typedef struct {
-	guint id;
-	guint qos;
-	NMSriovVFVlanProtocol protocol;
-} VFVlan;
-
-static guint
-_vf_vlan_hash (gconstpointer ptr)
-{
-	return nm_hash_val (1348254767u, *((guint *) ptr));
-}
-
-static gboolean
-_vf_vlan_equal (gconstpointer a, gconstpointer b)
-{
-	return *((guint *) a) == *((guint *) b);
-}
-
-static GHashTable *
-_vf_vlan_create_hash (void)
-{
-	G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (VFVlan, id) == 0);
-	return g_hash_table_new_full (_vf_vlan_hash,
-	                              _vf_vlan_equal,
-	                              NULL,
-	                              nm_g_slice_free_fcn (VFVlan));
-}
-
-/**
- * nm_srio_vf_new:
- * @index: the VF index
- *
- * Creates a new #NMSriovVF object.
- *
- * Returns: (transfer full): the new #NMSriovVF object.
- *
- * Since: 1.14
- **/
-NMSriovVF *
-nm_sriov_vf_new (guint index)
-{
-	NMSriovVF *vf;
-
-	vf = g_slice_new0 (NMSriovVF);
-	vf->refcount = 1;
-	vf->index = index;
-	vf->attributes = g_hash_table_new_full (nm_str_hash,
-	                                        g_str_equal,
-	                                        g_free,
-	                                        (GDestroyNotify) g_variant_unref);
-	return vf;
-}
-
-/**
- * nm_sriov_vf_ref:
- * @vf: the #NMSriovVF
- *
- * Increases the reference count of the object.
- *
- * Since: 1.14
- **/
-void
-nm_sriov_vf_ref (NMSriovVF *vf)
-{
-	g_return_if_fail (vf);
-	g_return_if_fail (vf->refcount > 0);
-
-	vf->refcount++;
-}
-
-/**
- * nm_sriov_vf_unref:
- * @vf: the #NMSriovVF
- *
- * Decreases the reference count of the object.  If the reference count
- * reaches zero, the object will be destroyed.
- *
- * Since: 1.14
- **/
-void
-nm_sriov_vf_unref (NMSriovVF *vf)
-{
-	g_return_if_fail (vf);
-	g_return_if_fail (vf->refcount > 0);
-
-	vf->refcount--;
-	if (vf->refcount == 0) {
-		g_hash_table_unref (vf->attributes);
-		if (vf->vlans)
-			g_hash_table_unref (vf->vlans);
-		g_free (vf->vlan_ids);
-		g_slice_free (NMSriovVF, vf);
-	}
-}
-
-/**
- * nm_sriov_vf_equal:
- * @vf: the #NMSriovVF
- * @other: the #NMSriovVF to compare @vf to.
- *
- * Determines if two #NMSriovVF objects have the same index,
- * attributes and VLANs.
- *
- * Returns: %TRUE if the objects contain the same values, %FALSE
- *    if they do not.
- *
- * Since: 1.14
- **/
-gboolean
-nm_sriov_vf_equal (const NMSriovVF *vf, const NMSriovVF *other)
-{
-	GHashTableIter iter;
-	const char *key;
-	GVariant *value, *value2;
-	VFVlan *vlan, *vlan2;
-	guint n_vlans;
-
-	g_return_val_if_fail (vf, FALSE);
-	g_return_val_if_fail (vf->refcount > 0, FALSE);
-	g_return_val_if_fail (other, FALSE);
-	g_return_val_if_fail (other->refcount > 0, FALSE);
-
-	if (vf == other)
-		return TRUE;
-
-	if (vf->index != other->index)
-		return FALSE;
-
-	if (g_hash_table_size (vf->attributes) != g_hash_table_size (other->attributes))
-		return FALSE;
-	g_hash_table_iter_init (&iter, vf->attributes);
-	while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &value)) {
-		value2 = g_hash_table_lookup (other->attributes, key);
-		if (!value2)
-			return FALSE;
-		if (!g_variant_equal (value, value2))
-			return FALSE;
-	}
-
-	n_vlans = vf->vlans ? g_hash_table_size (vf->vlans) : 0u;
-	if (n_vlans != (other->vlans ? g_hash_table_size (other->vlans) : 0u))
-		return FALSE;
-	if (n_vlans > 0) {
-		g_hash_table_iter_init (&iter, vf->vlans);
-		while (g_hash_table_iter_next (&iter, (gpointer *) &vlan, NULL)) {
-			vlan2 = g_hash_table_lookup (other->vlans, vlan);
-			if (!vlan2)
-				return FALSE;
-			if (   vlan->qos != vlan2->qos
-			    || vlan->protocol != vlan2->protocol)
-				return FALSE;
-		}
-	}
-
-	return TRUE;
-}
-
-static void
-vf_add_vlan (NMSriovVF *vf,
-             guint vlan_id,
-             guint qos,
-             NMSriovVFVlanProtocol protocol)
-{
-	VFVlan *vlan;
-
-	vlan = g_slice_new0 (VFVlan);
-	vlan->id = vlan_id;
-	vlan->qos = qos;
-	vlan->protocol = protocol;
-
-	if (!vf->vlans)
-		vf->vlans = _vf_vlan_create_hash ();
-
-	g_hash_table_add (vf->vlans, vlan);
-	g_clear_pointer (&vf->vlan_ids, g_free);
-}
-
-/**
- * nm_sriov_vf_dup:
- * @vf: the #NMSriovVF
- *
- * Creates a copy of @vf.
- *
- * Returns: (transfer full): a copy of @vf
- *
- * Since: 1.14
- **/
-NMSriovVF *
-nm_sriov_vf_dup (const NMSriovVF *vf)
-{
-	NMSriovVF *copy;
-	GHashTableIter iter;
-	const char *name;
-	GVariant *variant;
-	VFVlan *vlan;
-
-	g_return_val_if_fail (vf, NULL);
-	g_return_val_if_fail (vf->refcount > 0, NULL);
-
-	copy = nm_sriov_vf_new (vf->index);
-
-	g_hash_table_iter_init (&iter, vf->attributes);
-	while (g_hash_table_iter_next (&iter, (gpointer *) &name, (gpointer *) &variant))
-		nm_sriov_vf_set_attribute (copy, name, variant);
-
-	if (vf->vlans) {
-		g_hash_table_iter_init (&iter, vf->vlans);
-		while (g_hash_table_iter_next (&iter, (gpointer *) &vlan, NULL))
-			vf_add_vlan (copy, vlan->id, vlan->qos, vlan->protocol);
-	}
-
-	return copy;
-}
-
-/**
- * nm_sriov_vf_get_index:
- * @vf: the #NMSriovVF
- *
- * Gets the index property of this VF object.
- *
- * Returns: the VF index
- *
- * Since: 1.14
- **/
-guint
-nm_sriov_vf_get_index (const NMSriovVF *vf)
-{
-	g_return_val_if_fail (vf, 0);
-	g_return_val_if_fail (vf->refcount > 0, 0);
-
-	return vf->index;
-}
-
-/**
- * nm_sriov_vf_set_attribute:
- * @vf: the #NMSriovVF
- * @name: the name of a route attribute
- * @value: (transfer none) (allow-none): the value
- *
- * Sets the named attribute on @vf to the given value.
- *
- * Since: 1.14
- **/
-void
-nm_sriov_vf_set_attribute (NMSriovVF *vf, const char *name, GVariant *value)
-{
-	g_return_if_fail (vf);
-	g_return_if_fail (vf->refcount > 0);
-	g_return_if_fail (name && *name != '\0');
-	g_return_if_fail (!nm_streq (name, "index"));
-
-	if (value) {
-		g_hash_table_insert (vf->attributes,
-		                     g_strdup (name),
-		                     g_variant_ref_sink (value));
-	} else
-		g_hash_table_remove (vf->attributes, name);
-}
-
-/**
- * nm_sriov_vf_get_attribute_names:
- * @vf: the #NMSriovVF
- *
- * Gets an array of attribute names defined on @vf.
- *
- * Returns: (transfer container): a %NULL-terminated array of attribute names
- *
- * Since: 1.14
- **/
-const char **
-nm_sriov_vf_get_attribute_names (const NMSriovVF *vf)
-{
-	g_return_val_if_fail (vf, NULL);
-	g_return_val_if_fail (vf->refcount > 0, NULL);
-
-	return nm_utils_strdict_get_keys (vf->attributes, TRUE, NULL);
-}
-
-/**
- * nm_sriov_vf_get_attribute:
- * @vf: the #NMSriovVF
- * @name: the name of a VF attribute
- *
- * Gets the value of the attribute with name @name on @vf
- *
- * Returns: (transfer none): the value of the attribute with name @name on
- *   @vf, or %NULL if @vf has no such attribute.
- *
- * Since: 1.14
- **/
-GVariant *
-nm_sriov_vf_get_attribute (const NMSriovVF *vf, const char *name)
-{
-	g_return_val_if_fail (vf, NULL);
-	g_return_val_if_fail (vf->refcount > 0, NULL);
-	g_return_val_if_fail (name && *name != '\0', NULL);
-
-	return g_hash_table_lookup (vf->attributes, name);
-}
-
-#define SRIOV_ATTR_SPEC_PTR(name, type, str_type) \
-	&(NMVariantAttributeSpec) { name, type, FALSE, FALSE, FALSE, FALSE, str_type }
-
-const NMVariantAttributeSpec * const _nm_sriov_vf_attribute_spec[] = {
-	SRIOV_ATTR_SPEC_PTR (NM_SRIOV_VF_ATTRIBUTE_MAC,          G_VARIANT_TYPE_STRING,  'm'),
-	SRIOV_ATTR_SPEC_PTR (NM_SRIOV_VF_ATTRIBUTE_SPOOF_CHECK,  G_VARIANT_TYPE_BOOLEAN,  0),
-	SRIOV_ATTR_SPEC_PTR (NM_SRIOV_VF_ATTRIBUTE_TRUST,        G_VARIANT_TYPE_BOOLEAN,  0),
-	SRIOV_ATTR_SPEC_PTR (NM_SRIOV_VF_ATTRIBUTE_MIN_TX_RATE,  G_VARIANT_TYPE_UINT32,   0),
-	SRIOV_ATTR_SPEC_PTR (NM_SRIOV_VF_ATTRIBUTE_MAX_TX_RATE,  G_VARIANT_TYPE_UINT32,   0),
-	/* D-Bus only, synthetic attributes */
-	SRIOV_ATTR_SPEC_PTR ("vlans",                            G_VARIANT_TYPE_STRING,  'd'),
-	NULL,
-};
-
-/**
- * nm_sriov_vf_attribute_validate:
- * @name: the attribute name
- * @value: the attribute value
- * @known: (out): on return, whether the attribute name is a known one
- * @error: (allow-none): return location for a #GError, or %NULL
- *
- * Validates a VF attribute, i.e. checks that the attribute is a known one,
- * the value is of the correct type and well-formed.
- *
- * Returns: %TRUE if the attribute is valid, %FALSE otherwise
- *
- * Since: 1.14
- */
-gboolean
-nm_sriov_vf_attribute_validate  (const char *name,
-                                 GVariant *value,
-                                 gboolean *known,
-                                 GError **error)
-{
-	const NMVariantAttributeSpec *const *iter;
-	const NMVariantAttributeSpec *spec = NULL;
-
-	g_return_val_if_fail (name, FALSE);
-	g_return_val_if_fail (value, FALSE);
-	g_return_val_if_fail (!error || !*error, FALSE);
-
-	for (iter = _nm_sriov_vf_attribute_spec; *iter; iter++) {
-		if (nm_streq (name, (*iter)->name)) {
-			spec = *iter;
-			break;
-		}
-	}
-
-	if (!spec || spec->str_type == 'd') {
-		NM_SET_OUT (known, FALSE);
-		g_set_error_literal (error,
-		                     NM_CONNECTION_ERROR,
-		                     NM_CONNECTION_ERROR_FAILED,
-		                     _("unknown attribute"));
-		return FALSE;
-	}
-
-	NM_SET_OUT (known, TRUE);
-
-	if (!g_variant_is_of_type (value, spec->type)) {
-		g_set_error (error,
-		             NM_CONNECTION_ERROR,
-		             NM_CONNECTION_ERROR_FAILED,
-		             _("invalid attribute type '%s'"),
-		             g_variant_get_type_string (value));
-		return FALSE;
-	}
-
-	if (spec->type == G_VARIANT_TYPE_STRING) {
-		const char *string;
-
-		switch (spec->str_type) {
-		case 'm': /* MAC address */
-			string = g_variant_get_string (value, NULL);
-			if (!nm_utils_hwaddr_valid (string, -1)) {
-				g_set_error (error,
-				             NM_CONNECTION_ERROR,
-				             NM_CONNECTION_ERROR_FAILED,
-				             _("'%s' is not a valid MAC address"),
-				             string);
-				return FALSE;
-			}
-			break;
-		default:
-			break;
-		}
-	}
-
-	return TRUE;
-}
-
-gboolean
-_nm_sriov_vf_attribute_validate_all (const NMSriovVF *vf, GError **error)
-{
-	GHashTableIter iter;
-	const char *name;
-	GVariant *variant;
-	GVariant *min, *max;
-
-	g_return_val_if_fail (vf, FALSE);
-	g_return_val_if_fail (vf->refcount > 0, FALSE);
-
-	g_hash_table_iter_init (&iter, vf->attributes);
-	while (g_hash_table_iter_next (&iter, (gpointer *) &name, (gpointer *) &variant)) {
-		if (!nm_sriov_vf_attribute_validate (name, variant, NULL, error)) {
-			g_prefix_error (error, "attribute '%s':", name);
-			return FALSE;
-		}
-	}
-
-	min = g_hash_table_lookup (vf->attributes, NM_SRIOV_VF_ATTRIBUTE_MIN_TX_RATE);
-	max = g_hash_table_lookup (vf->attributes, NM_SRIOV_VF_ATTRIBUTE_MAX_TX_RATE);
-	if (   min
-	    && max
-	    && g_variant_get_uint32 (min) > g_variant_get_uint32 (max)) {
-		g_set_error (error,
-		             NM_CONNECTION_ERROR,
-		             NM_CONNECTION_ERROR_FAILED,
-		             "min_tx_rate is greater than max_tx_rate");
-		return FALSE;
-	}
-
-	return TRUE;
-}
-
-/**
- * nm_sriov_vf_add_vlan:
- * @vf: the #NMSriovVF
- * @vlan_id: the VLAN id
- *
- * Adds a VLAN to the VF.
- *
- * Returns: %TRUE if the VLAN was added; %FALSE if it already existed
- *
- * Since: 1.14
- **/
-gboolean
-nm_sriov_vf_add_vlan (NMSriovVF *vf, guint vlan_id)
-{
-	g_return_val_if_fail (vf, FALSE);
-	g_return_val_if_fail (vf->refcount > 0, FALSE);
-
-	if (   vf->vlans
-	    && g_hash_table_contains (vf->vlans, &vlan_id))
-		return FALSE;
-
-	vf_add_vlan (vf, vlan_id, 0, NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q);
-
-	return TRUE;
-}
-
-/**
- * nm_sriov_vf_remove_vlan:
- * @vf: the #NMSriovVF
- * @vlan_id: the VLAN id
- *
- * Removes a VLAN from a VF.
- *
- * Returns: %TRUE if the VLAN was removed, %FALSE if the VLAN @vlan_id
- *     did not belong to the VF.
- *
- * Since: 1.14
- */
-gboolean
-nm_sriov_vf_remove_vlan (NMSriovVF *vf, guint vlan_id)
-{
-	g_return_val_if_fail (vf, FALSE);
-	g_return_val_if_fail (vf->refcount > 0, FALSE);
-
-	if (   !vf->vlans
-	    || !g_hash_table_remove (vf->vlans, &vlan_id))
-		return FALSE;
-
-	g_clear_pointer (&vf->vlan_ids, g_free);
-	return TRUE;
-}
-
-static int
-vlan_id_compare (gconstpointer a, gconstpointer b, gpointer user_data)
-{
-	guint id_a  = *(guint *) a;
-	guint id_b  = *(guint *) b;
-
-	if (id_a < id_b)
-		return -1;
-	else if (id_a > id_b)
-		return 1;
-	else return 0;
-}
-
-/**
- * nm_sriov_vf_get_vlan_ids:
- * @vf: the #NMSriovVF
- * @length: (out) (allow-none): on return, the number of VLANs configured
- *
- * Returns the VLANs currently configured on the VF.
- *
- * Returns: (transfer none): a list of VLAN ids configured on the VF.
- *
- * Since: 1.14
- */
-const guint *
-nm_sriov_vf_get_vlan_ids (const NMSriovVF *vf, guint *length)
-{
-	GHashTableIter iter;
-	VFVlan *vlan;
-	guint num, i;
-
-	g_return_val_if_fail (vf, NULL);
-	g_return_val_if_fail (vf->refcount > 0, NULL);
-
-	num = vf->vlans ? g_hash_table_size (vf->vlans) : 0u;
-	NM_SET_OUT (length, num);
-
-	if (vf->vlan_ids)
-		return vf->vlan_ids;
-	if (num == 0)
-		return NULL;
-
-	/* vf is const, however, vlan_ids is a mutable field caching the
-	 * result ("mutable" in C++ terminology) */
-	((NMSriovVF *) vf)->vlan_ids = g_new0 (guint, num);
-
-	i = 0;
-	g_hash_table_iter_init (&iter, vf->vlans);
-	while (g_hash_table_iter_next (&iter, (gpointer *) &vlan, NULL))
-		vf->vlan_ids[i++] = vlan->id;
-
-	nm_assert (num == i);
-
-	g_qsort_with_data (vf->vlan_ids, num, sizeof (guint), vlan_id_compare, NULL);
-
-	return vf->vlan_ids;
-}
-
-/**
- * nm_sriov_vf_set_vlan_qos:
- * @vf: the #NMSriovVF
- * @vlan_id: the VLAN id
- * @qos: a QoS (priority) value
- *
- * Sets a QoS value for the given VLAN.
- *
- * Since: 1.14
- */
-void
-nm_sriov_vf_set_vlan_qos (NMSriovVF *vf, guint vlan_id, guint32 qos)
-{
-	VFVlan *vlan;
-
-	g_return_if_fail (vf);
-	g_return_if_fail (vf->refcount > 0);
-
-	if (   !vf->vlans
-	    || !(vlan = g_hash_table_lookup (vf->vlans, &vlan_id)))
-		g_return_if_reached ();
-
-	vlan->qos = qos;
-}
-
-/**
- * nm_sriov_vf_set_vlan_protocol:
- * @vf: the #NMSriovVF
- * @vlan_id: the VLAN id
- * @protocol: the VLAN protocol
- *
- * Sets the protocol for the given VLAN.
- *
- * Since: 1.14
- */
-void
-nm_sriov_vf_set_vlan_protocol (NMSriovVF *vf, guint vlan_id, NMSriovVFVlanProtocol protocol)
-{
-	VFVlan *vlan;
-
-	g_return_if_fail (vf);
-	g_return_if_fail (vf->refcount > 0);
-
-	if (   !vf->vlans
-	    || !(vlan = g_hash_table_lookup (vf->vlans, &vlan_id)))
-		g_return_if_reached ();
-
-	vlan->protocol = protocol;
-}
-
-/**
- * nm_sriov_vf_get_vlan_qos:
- * @vf: the #NMSriovVF
- * @vlan_id: the VLAN id
- *
- * Returns the QoS value for the given VLAN.
- *
- * Returns: the QoS value
- *
- * Since: 1.14
- */
-guint32
-nm_sriov_vf_get_vlan_qos (const NMSriovVF *vf, guint vlan_id)
-{
-	VFVlan *vlan;
-
-	g_return_val_if_fail (vf, 0);
-	g_return_val_if_fail (vf->refcount > 0, 0);
-
-	if (   !vf->vlans
-	    || !(vlan = g_hash_table_lookup (vf->vlans, &vlan_id)))
-		g_return_val_if_reached (0);
-
-	return vlan->qos;
-}
-
-/*
- * nm_sriov_vf_get_vlan_protocol:
- * @vf: the #NMSriovVF
- * @vlan_id: the VLAN id
- *
- * Returns the configured protocol for the given VLAN.
- *
- * Returns: the configured protocol
- *
- * Since: 1.14
- */
-NMSriovVFVlanProtocol
-nm_sriov_vf_get_vlan_protocol (const NMSriovVF *vf, guint vlan_id)
-{
-	VFVlan *vlan;
-
-	g_return_val_if_fail (vf, NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q);
-	g_return_val_if_fail (vf->refcount > 0, NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q);
-
-	if (   !vf->vlans
-	    || !(vlan = g_hash_table_lookup (vf->vlans, &vlan_id)))
-		g_return_val_if_reached (NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q);
-
-	return vlan->protocol;
-}
-
-/*****************************************************************************/
-
-/**
- * nm_setting_sriov_new:
- *
- * Creates a new #NMSettingSriov object with default values.
- *
- * Returns: (transfer full): the new empty #NMSettingSriov object
- *
- * Since: 1.14
- **/
-NMSetting *
-nm_setting_sriov_new (void)
-{
-	return (NMSetting *) g_object_new (NM_TYPE_SETTING_SRIOV, NULL);
-}
-
-/**
- * nm_setting_sriov_get_total_vfs:
- * @setting: the #NMSettingSriov
- *
- * Returns the value contained in the #NMSettingSriov:total-vfs
- * property.
- *
- * Returns: the total number of SR-IOV virtual functions to create
- *
- * Since: 1.14
- **/
-guint
-nm_setting_sriov_get_total_vfs (NMSettingSriov *setting)
-{
-	g_return_val_if_fail (NM_IS_SETTING_SRIOV (setting), 0);
-
-	return setting->total_vfs;
-}
-
-/**
- * nm_setting_sriov_get_num_vfs:
- * @setting: the #NMSettingSriov
- *
- * Returns: the number of configured VFs
- *
- * Since: 1.14
- **/
-guint
-nm_setting_sriov_get_num_vfs (NMSettingSriov *setting)
-{
-	g_return_val_if_fail (NM_IS_SETTING_SRIOV (setting), 0);
-
-	return setting->vfs->len;
-}
-
-/**
- * nm_setting_sriov_get_vf:
- * @setting: the #NMSettingSriov
- * @idx: index number of the VF to return
- *
- * Returns: (transfer none): the VF at index @idx
- *
- * Since: 1.14
- **/
-NMSriovVF *
-nm_setting_sriov_get_vf (NMSettingSriov *setting, guint idx)
-{
-	g_return_val_if_fail (NM_IS_SETTING_SRIOV (setting), NULL);
-	g_return_val_if_fail (idx < setting->vfs->len, NULL);
-
-	return setting->vfs->pdata[idx];
-}
-
-/**
- * nm_setting_sriov_add_vf:
- * @setting: the #NMSettingSriov
- * @vf: the VF to add
- *
- * Appends a new VF and associated information to the setting.  The
- * given VF is duplicated internally and is not changed by this function.
- *
- * Since: 1.14
- **/
-void
-nm_setting_sriov_add_vf (NMSettingSriov *setting, NMSriovVF *vf)
-{
-	g_return_if_fail (NM_IS_SETTING_SRIOV (setting));
-	g_return_if_fail (vf);
-	g_return_if_fail (vf->refcount > 0);
-
-	g_ptr_array_add (setting->vfs, nm_sriov_vf_dup (vf));
-	g_object_notify (G_OBJECT (setting), NM_SETTING_SRIOV_VFS);
-}
-
-/**
- * nm_setting_sriov_remove_vf:
- * @setting: the #NMSettingSriov
- * @idx: index number of the VF
- *
- * Removes the VF at index @idx.
- *
- * Since: 1.14
- **/
-void
-nm_setting_sriov_remove_vf (NMSettingSriov *setting, guint idx)
-{
-	g_return_if_fail (NM_IS_SETTING_SRIOV (setting));
-	g_return_if_fail (idx < setting->vfs->len);
-
-	g_ptr_array_remove_index (setting->vfs, idx);
-	g_object_notify (G_OBJECT (setting), NM_SETTING_SRIOV_VFS);
-}
-
-/**
- * nm_setting_sriov_remove_vf_by_index:
- * @setting: the #NMSettingSriov
- * @index: the VF index of the VF to remove
- *
- * Removes the VF with VF index @index.
- *
- * Returns: %TRUE if the VF was found and removed; %FALSE if it was not
- *
- * Since: 1.14
- **/
-gboolean
-nm_setting_sriov_remove_vf_by_index (NMSettingSriov *setting,
-                                     guint index)
-{
-	guint i;
-
-	g_return_val_if_fail (NM_IS_SETTING_SRIOV (setting), FALSE);
-
-	for (i = 0; i < setting->vfs->len; i++) {
-		if (nm_sriov_vf_get_index  (setting->vfs->pdata[i]) == index) {
-			g_ptr_array_remove_index (setting->vfs, i);
-			g_object_notify (G_OBJECT (setting), NM_SETTING_SRIOV_VFS);
-			return TRUE;
-		}
-	}
-	return FALSE;
-}
-
-/**
- * nm_setting_sriov_clear_vfs:
- * @setting: the #NMSettingSriov
- *
- * Removes all configured VFs.
- *
- * Since: 1.14
- **/
-void
-nm_setting_sriov_clear_vfs (NMSettingSriov *setting)
-{
-	g_return_if_fail (NM_IS_SETTING_SRIOV (setting));
-
-	if (setting->vfs->len != 0) {
-		g_ptr_array_set_size (setting->vfs, 0);
-		g_object_notify (G_OBJECT (setting), NM_SETTING_SRIOV_VFS);
-	}
-}
-
-/**
- * nm_setting_sriov_get_autoprobe_drivers:
- * @setting: the #NMSettingSriov
- *
- * Returns the value contained in the #NMSettingSriov:autoprobe-drivers
- * property.
- *
- * Returns: the autoprobe-drivers property value
- *
- * Since: 1.14
- **/
-NMTernary
-nm_setting_sriov_get_autoprobe_drivers (NMSettingSriov *setting)
-{
-	g_return_val_if_fail (NM_IS_SETTING_SRIOV (setting), NM_TERNARY_DEFAULT);
-
-	return setting->autoprobe_drivers;
-}
-
-static gint
-vf_index_compare (gconstpointer a, gconstpointer b)
-{
-	NMSriovVF *vf_a = *(NMSriovVF **) a;
-	NMSriovVF *vf_b = *(NMSriovVF **) b;
-
-	if (vf_a->index < vf_b->index)
-		return -1;
-	else if (vf_a->index > vf_b->index)
-		return 1;
-	else
-		return 0;
-}
-
-gboolean
-_nm_setting_sriov_sort_vfs (NMSettingSriov *setting)
-{
-	gboolean need_sort = FALSE;
-	guint i;
-
-	for (i = 1; i < setting->vfs->len; i++) {
-		NMSriovVF *vf_prev = setting->vfs->pdata[i - 1];
-		NMSriovVF *vf = setting->vfs->pdata[i];
-
-		if (vf->index <= vf_prev->index) {
-			need_sort = TRUE;
-			break;
-		}
-	}
-
-	if (need_sort)
-		g_ptr_array_sort (setting->vfs, vf_index_compare);
-
-	return need_sort;
-}
-
-/*****************************************************************************/
-
-static GVariant *
-vfs_to_dbus (NMSetting *setting, const char *property)
-{
-	gs_unref_ptrarray GPtrArray *vfs = NULL;
-	GVariantBuilder builder;
-	guint i;
-
-	g_object_get (setting, NM_SETTING_SRIOV_VFS, &vfs, NULL);
-	g_variant_builder_init (&builder, G_VARIANT_TYPE ("aa{sv}"));
-
-	if (vfs) {
-		for (i = 0; i < vfs->len; i++) {
-			gs_free const char **attr_names = NULL;
-			NMSriovVF *vf = vfs->pdata[i];
-			GVariantBuilder vf_builder;
-			const guint *vlan_ids;
-			const char **name;
-			guint num_vlans;
-
-			g_variant_builder_init (&vf_builder, G_VARIANT_TYPE_VARDICT);
-			g_variant_builder_add (&vf_builder, "{sv}", "index",
-			                       g_variant_new_uint32 (nm_sriov_vf_get_index (vf)));
-
-			attr_names = nm_utils_strdict_get_keys (vf->attributes, TRUE, NULL);
-			if (attr_names) {
-				for (name = attr_names; *name; name++) {
-					g_variant_builder_add (&vf_builder,
-					                       "{sv}",
-					                       *name,
-					                       nm_sriov_vf_get_attribute (vf, *name));
-				}
-			}
-
-			/* VLANs are translated into an array of maps, where each map has
-			 * keys 'id', 'qos' and 'proto'. This guarantees enough flexibility
-			 * to accomodate any future new option. */
-			vlan_ids = nm_sriov_vf_get_vlan_ids (vf, &num_vlans);
-			if (num_vlans) {
-				GVariantBuilder vlans_builder;
-				guint j;
-
-				g_variant_builder_init (&vlans_builder, G_VARIANT_TYPE ("aa{sv}"));
-				for (j = 0; j < num_vlans; j++) {
-					GVariantBuilder vlan_builder;
-
-					g_variant_builder_init (&vlan_builder, G_VARIANT_TYPE ("a{sv}"));
-					g_variant_builder_add (&vlan_builder,
-					                       "{sv}", "id",
-					                       g_variant_new_uint32 (vlan_ids[j]));
-					g_variant_builder_add (&vlan_builder,
-					                       "{sv}", "qos",
-					                       g_variant_new_uint32 (nm_sriov_vf_get_vlan_qos (vf,
-					                                                                       vlan_ids[j])));
-					g_variant_builder_add (&vlan_builder,
-					                       "{sv}", "protocol",
-					                       g_variant_new_uint32 (nm_sriov_vf_get_vlan_protocol (vf,
-					                                                                            vlan_ids[j])));
-					g_variant_builder_add (&vlans_builder,
-					                       "a{sv}",
-					                       &vlan_builder);
-				}
-				g_variant_builder_add (&vf_builder , "{sv}", "vlans", g_variant_builder_end (&vlans_builder));
-			}
-			g_variant_builder_add (&builder, "a{sv}", &vf_builder);
-		}
-	}
-
-	return g_variant_builder_end (&builder);
-}
-
-static gboolean
-vfs_from_dbus (NMSetting *setting,
-               GVariant *connection_dict,
-               const char *property,
-               GVariant *value,
-               NMSettingParseFlags parse_flags,
-               GError **error)
-{
-	GPtrArray *vfs;
-	GVariantIter vf_iter;
-	GVariant *vf_var;
-
-	g_return_val_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE ("aa{sv}")), FALSE);
-
-	vfs = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_sriov_vf_unref);
-	g_variant_iter_init (&vf_iter, value);
-	while (g_variant_iter_next (&vf_iter, "@a{sv}", &vf_var)) {
-		NMSriovVF *vf;
-		guint32 index;
-		GVariantIter attr_iter;
-		const char *attr_name;
-		GVariant *attr_var, *vlans_var;
-
-		if (!g_variant_lookup (vf_var, "index", "u", &index))
-			goto next;
-
-		vf = nm_sriov_vf_new (index);
-
-		g_variant_iter_init (&attr_iter, vf_var);
-		while (g_variant_iter_next (&attr_iter, "{&sv}", &attr_name, &attr_var)) {
-			if (!NM_IN_STRSET (attr_name, "index", "vlans"))
-				nm_sriov_vf_set_attribute (vf, attr_name, attr_var);
-			g_variant_unref (attr_var);
-		}
-
-		if (g_variant_lookup (vf_var, "vlans", "@aa{sv}", &vlans_var)) {
-			GVariantIter vlan_iter;
-			GVariant *vlan_var;
-
-			g_variant_iter_init (&vlan_iter, vlans_var);
-			while (g_variant_iter_next (&vlan_iter, "@a{sv}", &vlan_var)) {
-				NMSriovVFVlanProtocol proto = NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q;
-				gint64 vlan_id = -1;
-				guint qos = 0;
-
-				g_variant_iter_init (&attr_iter, vlan_var);
-				while (g_variant_iter_next (&attr_iter, "{&sv}", &attr_name, &attr_var)) {
-					if (   nm_streq (attr_name, "id")
-					    && g_variant_is_of_type (attr_var, G_VARIANT_TYPE_UINT32))
-						vlan_id = g_variant_get_uint32 (attr_var);
-					else if (   nm_streq (attr_name, "qos")
-					         && g_variant_is_of_type (attr_var, G_VARIANT_TYPE_UINT32))
-						qos = g_variant_get_uint32 (attr_var);
-					else if (   nm_streq (attr_name, "protocol")
-					         && g_variant_is_of_type (attr_var, G_VARIANT_TYPE_UINT32))
-						proto = g_variant_get_uint32 (attr_var);
-					g_variant_unref (attr_var);
-				}
-				if (vlan_id != -1)
-					vf_add_vlan (vf, vlan_id, qos, proto);
-				g_variant_unref (vlan_var);
-			}
-			g_variant_unref (vlans_var);
-		}
-
-		g_ptr_array_add (vfs, vf);
-next:
-		g_variant_unref (vf_var);
-	}
-
-	g_object_set (setting, NM_SETTING_SRIOV_VFS, vfs, NULL);
-	g_ptr_array_unref (vfs);
-
-	return TRUE;
-}
-
-/*****************************************************************************/
-
-static gboolean
-verify (NMSetting *setting, NMConnection *connection, GError **error)
-{
-	NMSettingSriov *self = NM_SETTING_SRIOV (setting);
-	guint i;
-
-	if (self->vfs->len) {
-		gs_unref_hashtable GHashTable *h = NULL;
-
-		h = g_hash_table_new (nm_direct_hash, NULL);
-		for (i = 0; i < self->vfs->len; i++) {
-			NMSriovVF *vf = self->vfs->pdata[i];
-			gs_free_error GError *local = NULL;
-
-			if (vf->index >= self->total_vfs) {
-				g_set_error (error,
-				             NM_CONNECTION_ERROR,
-				             NM_CONNECTION_ERROR_INVALID_PROPERTY,
-				             _("VF with index %u, but the total number of VFs is %u"),
-				             vf->index, self->total_vfs);
-				g_prefix_error (error, "%s.%s: ", NM_SETTING_SRIOV_SETTING_NAME,
-				                NM_SETTING_SRIOV_VFS);
-				return FALSE;
-			}
-
-			if (!_nm_sriov_vf_attribute_validate_all (vf, &local)) {
-				g_set_error (error,
-				             NM_CONNECTION_ERROR,
-				             NM_CONNECTION_ERROR_INVALID_PROPERTY,
-				             _("invalid VF %u: %s"),
-				             vf->index,
-				             local->message);
-				g_prefix_error (error, "%s.%s: ", NM_SETTING_SRIOV_SETTING_NAME,
-				                NM_SETTING_SRIOV_VFS);
-				return FALSE;
-			}
-
-			if (g_hash_table_contains (h, GUINT_TO_POINTER (vf->index))) {
-				g_set_error (error,
-				             NM_CONNECTION_ERROR,
-				             NM_CONNECTION_ERROR_INVALID_PROPERTY,
-				             _("duplicate VF index %u"), vf->index);
-				g_prefix_error (error, "%s.%s: ", NM_SETTING_SRIOV_SETTING_NAME,
-				                NM_SETTING_SRIOV_VFS);
-				return FALSE;
-			}
-
-			g_hash_table_add (h, GUINT_TO_POINTER (vf->index));
-		}
-	}
-
-	/* Failures from here on are NORMALIZABLE... */
-
-	if (self->vfs->len) {
-		for (i = 1; i < self->vfs->len; i++) {
-			NMSriovVF *vf_prev = self->vfs->pdata[i - 1];
-			NMSriovVF *vf = self->vfs->pdata[i];
-
-			if (vf->index <= vf_prev->index) {
-				g_set_error (error,
-				             NM_CONNECTION_ERROR,
-				             NM_CONNECTION_ERROR_INVALID_PROPERTY,
-				             _("VFs %d and %d are not sorted by ascending index"),
-				             vf_prev->index, vf->index);
-				g_prefix_error (error, "%s.%s: ", NM_SETTING_SRIOV_SETTING_NAME,
-				                NM_SETTING_SRIOV_VFS);
-				return NM_SETTING_VERIFY_NORMALIZABLE;
-			}
-		}
-	}
-
-	return TRUE;
-}
-
-static void
-set_property (GObject *object, guint prop_id,
-              const GValue *value, GParamSpec *pspec)
-{
-	NMSettingSriov *self = NM_SETTING_SRIOV (object);
-
-	switch (prop_id) {
-	case PROP_TOTAL_VFS:
-		self->total_vfs = g_value_get_uint (value);
-		break;
-	case PROP_VFS:
-		g_ptr_array_unref (self->vfs);
-		self->vfs = _nm_utils_copy_array (g_value_get_boxed (value),
-		                                  (NMUtilsCopyFunc) nm_sriov_vf_dup,
-		                                  (GDestroyNotify) nm_sriov_vf_unref);
-		break;
-	case PROP_AUTOPROBE_DRIVERS:
-		self->autoprobe_drivers = g_value_get_enum (value);
-		break;
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-		break;
-	}
-}
-
-static void
-get_property (GObject *object, guint prop_id,
-              GValue *value, GParamSpec *pspec)
-{
-	NMSettingSriov *self = NM_SETTING_SRIOV (object);
-
-	switch (prop_id) {
-	case PROP_TOTAL_VFS:
-		g_value_set_uint (value, self->total_vfs);
-		break;
-	case PROP_VFS:
-		g_value_take_boxed (value, _nm_utils_copy_array (self->vfs,
-		                                                 (NMUtilsCopyFunc) nm_sriov_vf_dup,
-		                                                 (GDestroyNotify) nm_sriov_vf_unref));
-		break;
-	case PROP_AUTOPROBE_DRIVERS:
-		g_value_set_enum (value, self->autoprobe_drivers);
-		break;
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-		break;
-	}
-}
-
-static gboolean
-compare_property (NMSetting *setting,
-                  NMSetting *other,
-                  const GParamSpec *prop_spec,
-                  NMSettingCompareFlags flags)
-{
-	NMSettingSriov *a = NM_SETTING_SRIOV (setting);
-	NMSettingSriov *b = NM_SETTING_SRIOV (other);
-	NMSettingClass *setting_class;
-	guint i;
-
-	if (nm_streq (prop_spec->name, NM_SETTING_SRIOV_VFS)) {
-		if (a->vfs->len != b->vfs->len)
-			return FALSE;
-		for (i = 0; i < a->vfs->len; i++) {
-			if (!nm_sriov_vf_equal (a->vfs->pdata[i], b->vfs->pdata[i]))
-				return FALSE;
-		}
-		return TRUE;
-	}
-
-	setting_class = NM_SETTING_CLASS (nm_setting_sriov_parent_class);
-	return setting_class->compare_property (setting, other, prop_spec, flags);
-}
-
-static void
-nm_setting_sriov_init (NMSettingSriov *setting)
-{
-	setting->vfs = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_sriov_vf_unref);
-}
-
-static void
-finalize (GObject *object)
-{
-	NMSettingSriov *self = NM_SETTING_SRIOV (object);
-
-	g_ptr_array_unref (self->vfs);
-
-	G_OBJECT_CLASS (nm_setting_sriov_parent_class)->finalize (object);
-}
-
-static void
-nm_setting_sriov_class_init (NMSettingSriovClass *klass)
-{
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	NMSettingClass *setting_class = NM_SETTING_CLASS (klass);
-	GArray *properties_override = _nm_sett_info_property_override_create_array ();
-
-	object_class->get_property     = get_property;
-	object_class->set_property     = set_property;
-	object_class->finalize         = finalize;
-
-	setting_class->compare_property = compare_property;
-	setting_class->verify           = verify;
-
-	/**
-	 * NMSettingSriov:total-vfs
-	 *
-	 * The total number of virtual functions to create.
-	 *
-	 * Since: 1.14
-	 **/
-	/* ---ifcfg-rh---
-	 * property: total-vfs
-	 * variable: SRIOV_TOTAL_VFS(+)
-	 * description: The total number of virtual functions to create
-	 * example: SRIOV_TOTAL_VFS=16
-	 * ---end---
-	 */
-	g_object_class_install_property
-		(object_class, PROP_TOTAL_VFS,
-		 g_param_spec_uint (NM_SETTING_SRIOV_TOTAL_VFS, "", "",
-		                    0, G_MAXUINT32, 0,
-		                    NM_SETTING_PARAM_FUZZY_IGNORE |
-		                    G_PARAM_READWRITE |
-		                    G_PARAM_CONSTRUCT |
-		                    G_PARAM_STATIC_STRINGS));
-
-	/**
-	 * NMSettingSriov:vfs: (type GPtrArray(NMSriovVF))
-	 *
-	 * Array of virtual function descriptors.
-	 *
-	 * Each VF descriptor is a dictionary mapping attribute names
-	 * to GVariant values. The 'index' entry is mandatory for
-	 * each VF.
-	 *
-	 * When represented as string a VF is in the form:
-	 *
-	 *   "INDEX [ATTR=VALUE[ ATTR=VALUE]...]".
-	 *
-	 * for example:
-	 *
-	 *   "2 mac=00:11:22:33:44:55 spoof-check=true".
-	 *
-	 * The "vlans" attribute is represented as a semicolor-separated
-	 * list of VLAN descriptors, where each descriptor has the form
-	 *
-	 *   "ID[.PRIORITY[.PROTO]]".
-	 *
-	 * PROTO can be either 'q' for 802.1Q (the default) or 'ad' for
-	 * 802.1ad.
-	 *
-	 * Since: 1.14
-	 **/
-	/* ---ifcfg-rh---
-	 * property: vfs
-	 * variable: SRIOV_VF1(+), SRIOV_VF2(+), ...
-	 * description: SR-IOV virtual function descriptors
-	 * example: SRIOV_VF10="mac=00:11:22:33:44:55", ...
-	 * ---end---
-	 */
-	g_object_class_install_property
-		(object_class, PROP_VFS,
-		 g_param_spec_boxed (NM_SETTING_SRIOV_VFS, "", "",
-		                     G_TYPE_PTR_ARRAY,
-		                     G_PARAM_READWRITE |
-		                     NM_SETTING_PARAM_INFERRABLE |
-		                     G_PARAM_STATIC_STRINGS));
-
-	_properties_override_add_override (properties_override,
-	                                   g_object_class_find_property (G_OBJECT_CLASS (setting_class),
-	                                                                 NM_SETTING_SRIOV_VFS),
-	                                   G_VARIANT_TYPE ("aa{sv}"),
-	                                   vfs_to_dbus,
-	                                   vfs_from_dbus,
-	                                   NULL);
-
-	/**
-	 * NMSettingSriov:autoprobe-drivers
-	 *
-	 * Whether to autoprobe virtual functions by a compatible driver.
-	 *
-	 * If set to %NM_TERNARY_TRUE, the kernel will try to bind VFs to
-	 * a compatible driver and if this succeeds a new network
-	 * interface will be instantiated for each VF.
-	 *
-	 * If set to %NM_TERNARY_FALSE, VFs will not be claimed and no
-	 * network interfaces will be created for them.
-	 *
-	 * When set to %NM_TERNARY_DEFAULT, the global default is used; in
-	 * case the global default is unspecified it is assumed to be
-	 * %NM_TERNARY_TRUE.
-	 *
-	 * Since: 1.14
-	 **/
-	/* ---ifcfg-rh---
-	 * property: autoprobe-drivers
-	 * variable: SRIOV_AUTOPROBE_DRIVERS(+)
-	 * default: missing variable means global default
-	 * description: Whether to autoprobe virtual functions by a compatible driver
-	 * example: SRIOV_AUTOPROBE_DRIVERS=0,1
-	 * ---end---
-	 */
-	g_object_class_install_property
-		(object_class, PROP_AUTOPROBE_DRIVERS,
-		 g_param_spec_enum (NM_SETTING_SRIOV_AUTOPROBE_DRIVERS, "", "",
-		                    nm_ternary_get_type (),
-		                    NM_TERNARY_DEFAULT,
-		                    NM_SETTING_PARAM_FUZZY_IGNORE |
-		                    G_PARAM_READWRITE |
-		                    G_PARAM_CONSTRUCT |
-		                    G_PARAM_STATIC_STRINGS));
-
-	_nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_SRIOV,
-	                               NULL, properties_override);
-}
diff --git a/libnm-core/nm-setting-sriov.h b/libnm-core/nm-setting-sriov.h
deleted file mode 100644
index 2e209964..00000000
--- a/libnm-core/nm-setting-sriov.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-/*
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * Copyright 2018 Red Hat, Inc.
- */
-
-#ifndef NM_SETTING_SRIOV_H
-#define NM_SETTING_SRIOV_H
-
-#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION)
-#error "Only <NetworkManager.h> can be included directly."
-#endif
-
-#include "nm-setting.h"
-
-G_BEGIN_DECLS
-
-#define NM_TYPE_SETTING_SRIOV            (nm_setting_sriov_get_type ())
-#define NM_SETTING_SRIOV(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_SRIOV, NMSettingSriov))
-#define NM_SETTING_SRIOV_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_SRIOV, NMSettingSriovClass))
-#define NM_IS_SETTING_SRIOV(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_SRIOV))
-#define NM_IS_SETTING_SRIOV_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_SRIOV))
-#define NM_SETTING_SRIOV_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_SRIOV, NMSettingSriovClass))
-
-#define NM_SETTING_SRIOV_SETTING_NAME          "sriov"
-
-#define NM_SETTING_SRIOV_TOTAL_VFS             "total-vfs"
-#define NM_SETTING_SRIOV_VFS                   "vfs"
-#define NM_SETTING_SRIOV_AUTOPROBE_DRIVERS     "autoprobe-drivers"
-
-#define NM_SRIOV_VF_ATTRIBUTE_MAC              "mac"
-#define NM_SRIOV_VF_ATTRIBUTE_SPOOF_CHECK      "spoof-check"
-#define NM_SRIOV_VF_ATTRIBUTE_TRUST            "trust"
-#define NM_SRIOV_VF_ATTRIBUTE_MIN_TX_RATE      "min-tx-rate"
-#define NM_SRIOV_VF_ATTRIBUTE_MAX_TX_RATE      "max-tx-rate"
-
-typedef struct _NMSettingSriovClass NMSettingSriovClass;
-typedef struct _NMSriovVF NMSriovVF;
-
-/**
- * NMSriovVFVlanProtocol:
- * @NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q:  use 802.1Q
- * @NM_SRIOV_VF_VLAN_PROTOCOL_802_1AD: use 802.1ad
- *
- * #NMSriovVFVlanProtocol indicates the VLAN protocol to use.
- *
- * Since: 1.14
- */
-typedef enum {
-	NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q = 0,
-	NM_SRIOV_VF_VLAN_PROTOCOL_802_1AD = 1,
-} NMSriovVFVlanProtocol;
-
-NM_AVAILABLE_IN_1_14
-GType nm_setting_sriov_get_type (void);
-NM_AVAILABLE_IN_1_14
-NMSetting *nm_setting_sriov_new (void);
-NM_AVAILABLE_IN_1_14
-guint nm_setting_sriov_get_total_vfs (NMSettingSriov *setting);
-NM_AVAILABLE_IN_1_14
-guint nm_setting_sriov_get_num_vfs (NMSettingSriov *setting);
-NM_AVAILABLE_IN_1_14
-NMSriovVF *nm_setting_sriov_get_vf (NMSettingSriov *setting, guint idx);
-NM_AVAILABLE_IN_1_14
-void nm_setting_sriov_add_vf (NMSettingSriov *setting, NMSriovVF *vf);
-NM_AVAILABLE_IN_1_14
-void nm_setting_sriov_remove_vf (NMSettingSriov *setting, guint idx);
-NM_AVAILABLE_IN_1_14
-gboolean nm_setting_sriov_remove_vf_by_index (NMSettingSriov *setting, guint index);
-NM_AVAILABLE_IN_1_14
-void nm_setting_sriov_clear_vfs (NMSettingSriov *setting);
-NM_AVAILABLE_IN_1_14
-NMTernary nm_setting_sriov_get_autoprobe_drivers (NMSettingSriov *setting);
-
-NM_AVAILABLE_IN_1_14
-gboolean nm_sriov_vf_add_vlan (NMSriovVF *vf, guint vlan_id);
-NM_AVAILABLE_IN_1_14
-gboolean nm_sriov_vf_remove_vlan (NMSriovVF *vf, guint vlan_id);
-NM_AVAILABLE_IN_1_14
-const guint *nm_sriov_vf_get_vlan_ids (const NMSriovVF *vf, guint *length);
-NM_AVAILABLE_IN_1_14
-void nm_sriov_vf_set_vlan_qos (NMSriovVF *vf, guint vlan_id, guint32 qos);
-NM_AVAILABLE_IN_1_14
-void nm_sriov_vf_set_vlan_protocol (NMSriovVF *vf, guint vlan_id, NMSriovVFVlanProtocol protocol);
-NM_AVAILABLE_IN_1_14
-guint32 nm_sriov_vf_get_vlan_qos (const NMSriovVF *vf, guint vlan_id);
-NM_AVAILABLE_IN_1_14
-NMSriovVFVlanProtocol nm_sriov_vf_get_vlan_protocol (const NMSriovVF *vf, guint vlan_id);
-
-NM_AVAILABLE_IN_1_14
-GType nm_sriov_vf_get_type (void);
-NM_AVAILABLE_IN_1_14
-NMSriovVF *nm_sriov_vf_new (guint index);
-NM_AVAILABLE_IN_1_14
-void nm_sriov_vf_ref (NMSriovVF *vf);
-NM_AVAILABLE_IN_1_14
-void nm_sriov_vf_unref (NMSriovVF *vf);
-NM_AVAILABLE_IN_1_14
-gboolean nm_sriov_vf_equal (const NMSriovVF *vf, const NMSriovVF *other);
-NM_AVAILABLE_IN_1_14
-NMSriovVF *nm_sriov_vf_dup (const NMSriovVF *vf);
-NM_AVAILABLE_IN_1_14
-guint nm_sriov_vf_get_index (const NMSriovVF *vf);
-NM_AVAILABLE_IN_1_14
-void nm_sriov_vf_set_attribute (NMSriovVF *vf, const char *name, GVariant *value);
-NM_AVAILABLE_IN_1_14
-const char **nm_sriov_vf_get_attribute_names (const NMSriovVF *vf);
-NM_AVAILABLE_IN_1_14
-GVariant *nm_sriov_vf_get_attribute (const NMSriovVF *vf, const char *name);
-NM_AVAILABLE_IN_1_14
-gboolean nm_sriov_vf_attribute_validate  (const char *name, GVariant *value, gboolean *known, GError **error);
-
-G_END_DECLS
-
-#endif /* NM_SETTING_SRIOV_H */
diff --git a/libnm-core/nm-setting-tc-config.c b/libnm-core/nm-setting-tc-config.c
index 43015d37..f50969fb 100644
--- a/libnm-core/nm-setting-tc-config.c
+++ b/libnm-core/nm-setting-tc-config.c
@@ -820,21 +820,23 @@ enum {
 /**
  * NMSettingTCConfig:
  *
- * Linux Traffic Control Settings.
+ * Linux Traffic Contril Settings.
  *
  * Since: 1.12
  */
 struct _NMSettingTCConfig {
-	NMSetting parent;
+        NMSetting parent;
 	GPtrArray *qdiscs;
 	GPtrArray *tfilters;
 };
 
 struct _NMSettingTCConfigClass {
-	NMSettingClass parent;
+        NMSettingClass parent;
 };
 
-G_DEFINE_TYPE (NMSettingTCConfig, nm_setting_tc_config, NM_TYPE_SETTING)
+G_DEFINE_TYPE_WITH_CODE (NMSettingTCConfig, nm_setting_tc_config, NM_TYPE_SETTING,
+                         _nm_register_setting (TC_CONFIG, NM_SETTING_PRIORITY_IP))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_TC_CONFIG)
 
 /**
  * nm_setting_tc_config_new:
@@ -981,10 +983,8 @@ nm_setting_tc_config_clear_qdiscs (NMSettingTCConfig *self)
 {
 	g_return_if_fail (NM_IS_SETTING_TC_CONFIG (self));
 
-	if (self->qdiscs->len != 0) {
-		g_ptr_array_set_size (self->qdiscs, 0);
-		g_object_notify (G_OBJECT (self), NM_SETTING_TC_CONFIG_QDISCS);
-	}
+	g_ptr_array_set_size (self->qdiscs, 0);
+	g_object_notify (G_OBJECT (self), NM_SETTING_TC_CONFIG_QDISCS);
 }
 
 /*****************************************************************************/
@@ -1117,10 +1117,8 @@ nm_setting_tc_config_clear_tfilters (NMSettingTCConfig *self)
 {
 	g_return_if_fail (NM_IS_SETTING_TC_CONFIG (self));
 
-	if (self->tfilters->len != 0) {
-		g_ptr_array_set_size (self->tfilters, 0);
-		g_object_notify (G_OBJECT (self), NM_SETTING_TC_CONFIG_TFILTERS);
-	}
+	g_ptr_array_set_size (self->tfilters, 0);
+	g_object_notify (G_OBJECT (self), NM_SETTING_TC_CONFIG_TFILTERS);
 }
 
 /*****************************************************************************/
@@ -1241,7 +1239,7 @@ compare_property (NMSetting *setting,
 {
 	NMSettingTCConfig *a_tc_config = NM_SETTING_TC_CONFIG (setting);
 	NMSettingTCConfig *b_tc_config = NM_SETTING_TC_CONFIG (other);
-	NMSettingClass *setting_class;
+	NMSettingClass *parent_class;
 	guint i;
 
 	if (nm_streq (prop_spec->name, NM_SETTING_TC_CONFIG_QDISCS)) {
@@ -1264,8 +1262,9 @@ compare_property (NMSetting *setting,
 		return TRUE;
 	}
 
-	setting_class = NM_SETTING_CLASS (nm_setting_tc_config_parent_class);
-	return setting_class->compare_property (setting, other, prop_spec, flags);
+	/* Otherwise chain up to parent to handle generic compare */
+	parent_class = NM_SETTING_CLASS (nm_setting_tc_config_parent_class);
+	return parent_class->compare_property (setting, other, prop_spec, flags);
 }
 
 static void
@@ -1587,27 +1586,28 @@ tc_tfilters_set (NMSetting *setting,
 }
 
 static void
-nm_setting_tc_config_class_init (NMSettingTCConfigClass *klass)
+nm_setting_tc_config_class_init (NMSettingTCConfigClass *setting_class)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	NMSettingClass *setting_class = NM_SETTING_CLASS (klass);
-	GArray *properties_override = _nm_sett_info_property_override_create_array ();
+	GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+	NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
 
+	/* virtual methods */
 	object_class->set_property     = set_property;
 	object_class->get_property     = get_property;
 	object_class->finalize         = finalize;
+	parent_class->compare_property = compare_property;
+	parent_class->verify           = verify;
 
-	setting_class->compare_property = compare_property;
-	setting_class->verify           = verify;
+	/* Properties */
 
 	/**
 	 * NMSettingTCConfig:qdiscs: (type GPtrArray(NMTCQdisc))
 	 *
-	 * Array of TC queueing disciplines.
+	 * Array of TC queuening disciplines.
 	 **/
 	/* ---ifcfg-rh---
 	 * property: qdiscs
-	 * variable: QDISC1(+), QDISC2(+), ...
+	 * variable: QDISC1, QDISC2, ...
 	 * description: Queueing disciplines
 	 * example: QDISC1=ingress, QDISC2="root handle 1234: fq_codel"
 	 * ---end---
@@ -1620,13 +1620,12 @@ nm_setting_tc_config_class_init (NMSettingTCConfigClass *klass)
 		                     NM_SETTING_PARAM_INFERRABLE |
 		                     G_PARAM_STATIC_STRINGS));
 
-	_properties_override_add_override (properties_override,
-	                                   g_object_class_find_property (G_OBJECT_CLASS (setting_class),
-	                                                                 NM_SETTING_TC_CONFIG_QDISCS),
-	                                   G_VARIANT_TYPE ("aa{sv}"),
-	                                   tc_qdiscs_get,
-	                                   tc_qdiscs_set,
-	                                   NULL);
+	_nm_setting_class_override_property (parent_class,
+	                                     NM_SETTING_TC_CONFIG_QDISCS,
+	                                     G_VARIANT_TYPE ("aa{sv}"),
+	                                     tc_qdiscs_get,
+	                                     tc_qdiscs_set,
+	                                     NULL);
 
 	/**
 	 * NMSettingTCConfig:tfilters: (type GPtrArray(NMTCTfilter))
@@ -1635,7 +1634,7 @@ nm_setting_tc_config_class_init (NMSettingTCConfigClass *klass)
 	 **/
 	/* ---ifcfg-rh---
 	 * property: qdiscs
-	 * variable: FILTER1(+), FILTER2(+), ...
+	 * variable: FILTER1, FILTER2, ...
 	 * description: Traffic filters
 	 * example: FILTER1="parent ffff: matchall action simple sdata Input", ...
 	 * ---end---
@@ -1648,14 +1647,10 @@ nm_setting_tc_config_class_init (NMSettingTCConfigClass *klass)
 		                     NM_SETTING_PARAM_INFERRABLE |
 		                     G_PARAM_STATIC_STRINGS));
 
-	_properties_override_add_override (properties_override,
-	                                   g_object_class_find_property (G_OBJECT_CLASS (setting_class),
-	                                                                 NM_SETTING_TC_CONFIG_TFILTERS),
-	                                   G_VARIANT_TYPE ("aa{sv}"),
-	                                   tc_tfilters_get,
-	                                   tc_tfilters_set,
-	                                   NULL);
-
-	_nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_TC_CONFIG,
-	                               NULL, properties_override);
+	_nm_setting_class_override_property (parent_class,
+	                                     NM_SETTING_TC_CONFIG_TFILTERS,
+	                                     G_VARIANT_TYPE ("aa{sv}"),
+	                                     tc_tfilters_get,
+	                                     tc_tfilters_set,
+	                                     NULL);
 }
diff --git a/libnm-core/nm-setting-team-port.c b/libnm-core/nm-setting-team-port.c
index ee84aaf7..b902b822 100644
--- a/libnm-core/nm-setting-team-port.c
+++ b/libnm-core/nm-setting-team-port.c
@@ -39,7 +39,9 @@
  * optional properties that apply to team ports.
  **/
 
-G_DEFINE_TYPE (NMSettingTeamPort, nm_setting_team_port, NM_TYPE_SETTING)
+G_DEFINE_TYPE_WITH_CODE (NMSettingTeamPort, nm_setting_team_port, NM_TYPE_SETTING,
+                         _nm_register_setting (TEAM_PORT, NM_SETTING_PRIORITY_AUX))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_TEAM_PORT)
 
 #define NM_SETTING_TEAM_PORT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_TEAM_PORT, NMSettingTeamPortPrivate))
 
@@ -113,7 +115,7 @@ nm_setting_team_port_get_config (NMSettingTeamPort *setting)
  *
  * Since: 1.12
  **/
-int
+gint
 nm_setting_team_port_get_queue_id (NMSettingTeamPort *setting)
 {
 	g_return_val_if_fail (NM_IS_SETTING_TEAM_PORT (setting), -1);
@@ -129,7 +131,7 @@ nm_setting_team_port_get_queue_id (NMSettingTeamPort *setting)
  *
  * Since: 1.12
  **/
-int
+gint
 nm_setting_team_port_get_prio (NMSettingTeamPort *setting)
 {
 	g_return_val_if_fail (NM_IS_SETTING_TEAM_PORT (setting), 0);
@@ -161,7 +163,7 @@ nm_setting_team_port_get_sticky (NMSettingTeamPort *setting)
  *
  * Since: 1.12
  **/
-int
+gint
 nm_setting_team_port_get_lacp_prio (NMSettingTeamPort *setting)
 {
 	g_return_val_if_fail (NM_IS_SETTING_TEAM_PORT (setting), 0);
@@ -177,7 +179,7 @@ nm_setting_team_port_get_lacp_prio (NMSettingTeamPort *setting)
  *
  * Since: 1.12
  **/
-int
+gint
 nm_setting_team_port_get_lacp_key (NMSettingTeamPort *setting)
 {
 	g_return_val_if_fail (NM_IS_SETTING_TEAM_PORT (setting), 0);
@@ -321,10 +323,8 @@ nm_setting_team_port_clear_link_watchers (NMSettingTeamPort *setting)
 
 	g_return_if_fail (NM_IS_SETTING_TEAM_PORT (setting));
 
-	if (priv->link_watchers->len != 0) {
-		g_ptr_array_set_size (priv->link_watchers, 0);
-		g_object_notify (G_OBJECT (setting), NM_SETTING_TEAM_PORT_LINK_WATCHERS);
-	}
+	g_ptr_array_set_size (priv->link_watchers, 0);
+	g_object_notify (G_OBJECT (setting), NM_SETTING_TEAM_PORT_LINK_WATCHERS);
 }
 
 static GVariant *
@@ -407,7 +407,7 @@ compare_property (NMSetting *setting,
                   const GParamSpec *prop_spec,
                   NMSettingCompareFlags flags)
 {
-	NMSettingClass *setting_class;
+	NMSettingClass *parent_class;
 	NMSettingTeamPortPrivate *a_priv, *b_priv;
 	guint i, j;
 
@@ -441,8 +441,9 @@ compare_property (NMSetting *setting,
 		return TRUE;
 	}
 
-	setting_class = NM_SETTING_CLASS (nm_setting_team_port_parent_class);
-	return setting_class->compare_property (setting, other, prop_spec, flags);
+	/* Otherwise chain up to parent to handle generic compare */
+	parent_class = NM_SETTING_CLASS (nm_setting_team_port_parent_class);
+	return parent_class->compare_property (setting, other, prop_spec, flags);
 }
 
 static void
@@ -585,21 +586,21 @@ finalize (GObject *object)
 }
 
 static void
-nm_setting_team_port_class_init (NMSettingTeamPortClass *klass)
+nm_setting_team_port_class_init (NMSettingTeamPortClass *setting_class)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	NMSettingClass *setting_class = NM_SETTING_CLASS (klass);
-	GArray *properties_override = _nm_sett_info_property_override_create_array ();
+	GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+	NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
 
-	g_type_class_add_private (klass, sizeof (NMSettingTeamPortPrivate));
+	g_type_class_add_private (setting_class, sizeof (NMSettingTeamPortPrivate));
 
+	/* virtual methods */
 	object_class->set_property     = set_property;
 	object_class->get_property     = get_property;
 	object_class->finalize         = finalize;
+	parent_class->compare_property = compare_property;
+	parent_class->verify           = verify;
 
-	setting_class->compare_property = compare_property;
-	setting_class->verify           = verify;
-
+	/* Properties */
 	/**
 	 * NMSettingTeamPort:config:
 	 *
@@ -713,14 +714,10 @@ nm_setting_team_port_class_init (NMSettingTeamPortClass *klass)
 		                     G_TYPE_PTR_ARRAY,
 		                     G_PARAM_READWRITE |
 		                     G_PARAM_STATIC_STRINGS));
+	_nm_setting_class_transform_property (parent_class,
+	                                      NM_SETTING_TEAM_PORT_LINK_WATCHERS,
+	                                      G_VARIANT_TYPE ("aa{sv}"),
+	                                      team_link_watchers_to_dbus,
+	                                      team_link_watchers_from_dbus);
 
-	_properties_override_add_transform (properties_override,
-	                                    g_object_class_find_property (G_OBJECT_CLASS (setting_class),
-	                                                                  NM_SETTING_TEAM_PORT_LINK_WATCHERS),
-	                                    G_VARIANT_TYPE ("aa{sv}"),
-	                                    team_link_watchers_to_dbus,
-	                                    team_link_watchers_from_dbus);
-
-	_nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_TEAM_PORT,
-	                               NULL, properties_override);
 }
diff --git a/libnm-core/nm-setting-team-port.h b/libnm-core/nm-setting-team-port.h
index 57611750..4ecb1838 100644
--- a/libnm-core/nm-setting-team-port.h
+++ b/libnm-core/nm-setting-team-port.h
@@ -72,15 +72,15 @@ NMSetting *  nm_setting_team_port_new (void);
 
 const char * nm_setting_team_port_get_config (NMSettingTeamPort *setting);
 NM_AVAILABLE_IN_1_12
-int nm_setting_team_port_get_queue_id (NMSettingTeamPort *setting);
+gint nm_setting_team_port_get_queue_id (NMSettingTeamPort *setting);
 NM_AVAILABLE_IN_1_12
-int nm_setting_team_port_get_prio (NMSettingTeamPort *setting);
+gint nm_setting_team_port_get_prio (NMSettingTeamPort *setting);
 NM_AVAILABLE_IN_1_12
 gboolean nm_setting_team_port_get_sticky (NMSettingTeamPort *setting);
 NM_AVAILABLE_IN_1_12
-int nm_setting_team_port_get_lacp_prio (NMSettingTeamPort *setting);
+gint nm_setting_team_port_get_lacp_prio (NMSettingTeamPort *setting);
 NM_AVAILABLE_IN_1_12
-int nm_setting_team_port_get_lacp_key (NMSettingTeamPort *setting);
+gint nm_setting_team_port_get_lacp_key (NMSettingTeamPort *setting);
 NM_AVAILABLE_IN_1_12
 guint nm_setting_team_port_get_num_link_watchers (NMSettingTeamPort *setting);
 NM_AVAILABLE_IN_1_12
diff --git a/libnm-core/nm-setting-team.c b/libnm-core/nm-setting-team.c
index e6737e48..195e509c 100644
--- a/libnm-core/nm-setting-team.c
+++ b/libnm-core/nm-setting-team.c
@@ -118,8 +118,8 @@ struct NMTeamLinkWatcher {
  * Since: 1.12
  **/
 NMTeamLinkWatcher *
-nm_team_link_watcher_new_ethtool (int delay_up,
-                                  int delay_down,
+nm_team_link_watcher_new_ethtool (gint delay_up,
+                                  gint delay_down,
                                   GError **error)
 {
 	NMTeamLinkWatcher *watcher;
@@ -161,9 +161,9 @@ nm_team_link_watcher_new_ethtool (int delay_up,
  * Since: 1.12
  **/
 NMTeamLinkWatcher *
-nm_team_link_watcher_new_nsna_ping (int init_wait,
-                                    int interval,
-                                    int missed_max,
+nm_team_link_watcher_new_nsna_ping (gint init_wait,
+                                    gint interval,
+                                    gint missed_max,
                                     const char *target_host,
                                     GError **error)
 {
@@ -225,9 +225,9 @@ nm_team_link_watcher_new_nsna_ping (int init_wait,
  * Since: 1.12
  **/
 NMTeamLinkWatcher *
-nm_team_link_watcher_new_arp_ping (int init_wait,
-                                   int interval,
-                                   int missed_max,
+nm_team_link_watcher_new_arp_ping (gint init_wait,
+                                   gint interval,
+                                   gint missed_max,
                                    const char *target_host,
                                    const char *source_host,
                                    NMTeamLinkWatcherArpPingFlags flags,
@@ -557,25 +557,27 @@ nm_team_link_watcher_get_flags (NMTeamLinkWatcher *watcher)
 
 /*****************************************************************************/
 
-G_DEFINE_TYPE (NMSettingTeam, nm_setting_team, NM_TYPE_SETTING)
+G_DEFINE_TYPE_WITH_CODE (NMSettingTeam, nm_setting_team, NM_TYPE_SETTING,
+                         _nm_register_setting (TEAM, NM_SETTING_PRIORITY_HW_BASE))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_TEAM)
 
 #define NM_SETTING_TEAM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_TEAM, NMSettingTeamPrivate))
 
 typedef struct {
 	char *config;
-	int notify_peers_count;
-	int notify_peers_interval;
-	int mcast_rejoin_count;
-	int mcast_rejoin_interval;
+	gint notify_peers_count;
+	gint notify_peers_interval;
+	gint mcast_rejoin_count;
+	gint mcast_rejoin_interval;
 	char *runner;
 	char *runner_hwaddr_policy;
 	GPtrArray *runner_tx_hash;
 	char *runner_tx_balancer;
-	int runner_tx_balancer_interval;
+	gint runner_tx_balancer_interval;
 	gboolean runner_active;
 	gboolean runner_fast_rate;
-	int runner_sys_prio;
-	int runner_min_ports;
+	gint runner_sys_prio;
+	gint runner_min_ports;
 	char *runner_agg_select_policy;
 	GPtrArray *link_watchers; /* Array of NMTeamLinkWatcher */
 } NMSettingTeamPrivate;
@@ -659,7 +661,7 @@ nm_setting_team_get_config (NMSettingTeam *setting)
  *
  * Since: 1.12
  **/
-int
+gint
 nm_setting_team_get_notify_peers_count (NMSettingTeam *setting)
 {
 	g_return_val_if_fail (NM_IS_SETTING_TEAM (setting), 0);
@@ -675,7 +677,7 @@ nm_setting_team_get_notify_peers_count (NMSettingTeam *setting)
  *
  * Since: 1.12
  **/
-int
+gint
 nm_setting_team_get_notify_peers_interval (NMSettingTeam *setting)
 {
 	g_return_val_if_fail (NM_IS_SETTING_TEAM (setting), 0);
@@ -691,7 +693,7 @@ nm_setting_team_get_notify_peers_interval (NMSettingTeam *setting)
  *
  * Since: 1.12
  **/
-int
+gint
 nm_setting_team_get_mcast_rejoin_count (NMSettingTeam *setting)
 {
 	g_return_val_if_fail (NM_IS_SETTING_TEAM (setting), 0);
@@ -707,7 +709,7 @@ nm_setting_team_get_mcast_rejoin_count (NMSettingTeam *setting)
  *
  * Since: 1.12
  **/
-int
+gint
 nm_setting_team_get_mcast_rejoin_interval (NMSettingTeam *setting)
 {
 	g_return_val_if_fail (NM_IS_SETTING_TEAM (setting), 0);
@@ -771,7 +773,7 @@ nm_setting_team_get_runner_tx_balancer (NMSettingTeam *setting)
  *
  * Since: 1.12
  **/
-int
+gint
 nm_setting_team_get_runner_tx_balancer_interval (NMSettingTeam *setting)
 {
 	g_return_val_if_fail (NM_IS_SETTING_TEAM (setting), 0);
@@ -819,7 +821,7 @@ nm_setting_team_get_runner_fast_rate (NMSettingTeam *setting)
  *
  * Since: 1.12
  **/
-int
+gint
 nm_setting_team_get_runner_sys_prio (NMSettingTeam *setting)
 {
 	g_return_val_if_fail (NM_IS_SETTING_TEAM (setting), 0);
@@ -835,7 +837,7 @@ nm_setting_team_get_runner_sys_prio (NMSettingTeam *setting)
  *
  * Since: 1.12
  **/
-int
+gint
 nm_setting_team_get_runner_min_ports (NMSettingTeam *setting)
 {
 	g_return_val_if_fail (NM_IS_SETTING_TEAM (setting), 0);
@@ -1119,10 +1121,8 @@ nm_setting_team_clear_link_watchers (NMSettingTeam *setting) {
 
 	g_return_if_fail (NM_IS_SETTING_TEAM (setting));
 
-	if (priv->link_watchers->len != 0) {
-		g_ptr_array_set_size (priv->link_watchers, 0);
-		g_object_notify (G_OBJECT (setting), NM_SETTING_TEAM_LINK_WATCHERS);
-	}
+	g_ptr_array_set_size (priv->link_watchers, 0);
+	g_object_notify (G_OBJECT (setting), NM_SETTING_TEAM_LINK_WATCHERS);
 }
 
 static GVariant *
@@ -1237,7 +1237,7 @@ compare_property (NMSetting *setting,
                   NMSettingCompareFlags flags)
 {
 	NMSettingTeamPrivate *a_priv, *b_priv;
-	NMSettingClass *setting_class;
+	NMSettingClass *parent_class;
 	guint i, j;
 
 	/* If we are trying to match a connection in order to assume it (and thus
@@ -1270,8 +1270,9 @@ compare_property (NMSetting *setting,
 		return TRUE;
 	}
 
-	setting_class = NM_SETTING_CLASS (nm_setting_team_parent_class);
-	return setting_class->compare_property (setting, other, prop_spec, flags);
+	/* Otherwise chain up to parent to handle generic compare */
+	parent_class = NM_SETTING_CLASS (nm_setting_team_parent_class);
+	return parent_class->compare_property (setting, other, prop_spec, flags);
 }
 
 static void
@@ -1556,21 +1557,21 @@ get_property (GObject *object, guint prop_id,
 }
 
 static void
-nm_setting_team_class_init (NMSettingTeamClass *klass)
+nm_setting_team_class_init (NMSettingTeamClass *setting_class)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	NMSettingClass *setting_class = NM_SETTING_CLASS (klass);
-	GArray *properties_override = _nm_sett_info_property_override_create_array ();
+	GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+	NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
 
-	g_type_class_add_private (klass, sizeof (NMSettingTeamPrivate));
+	g_type_class_add_private (setting_class, sizeof (NMSettingTeamPrivate));
 
+	/* virtual methods */
 	object_class->set_property     = set_property;
 	object_class->get_property     = get_property;
 	object_class->finalize         = finalize;
+	parent_class->compare_property = compare_property;
+	parent_class->verify           = verify;
 
-	setting_class->compare_property = compare_property;
-	setting_class->verify           = verify;
-
+	/* Properties */
 	/**
 	 * NMSettingTeam:config:
 	 *
@@ -1816,13 +1817,11 @@ nm_setting_team_class_init (NMSettingTeamClass *klass)
 		                     G_TYPE_PTR_ARRAY,
 		                     G_PARAM_READWRITE |
 		                     G_PARAM_STATIC_STRINGS));
-
-	_properties_override_add_transform (properties_override,
-	                                    g_object_class_find_property (G_OBJECT_CLASS (setting_class),
-	                                                                  NM_SETTING_TEAM_LINK_WATCHERS),
-	                                    G_VARIANT_TYPE ("aa{sv}"),
-	                                    team_link_watchers_to_dbus,
-	                                    team_link_watchers_from_dbus);
+	_nm_setting_class_transform_property (parent_class,
+	                                     NM_SETTING_TEAM_LINK_WATCHERS,
+	                                     G_VARIANT_TYPE ("aa{sv}"),
+	                                     team_link_watchers_to_dbus,
+	                                     team_link_watchers_from_dbus);
 
 	/* ---dbus---
 	 * property: interface-name
@@ -1832,12 +1831,8 @@ nm_setting_team_class_init (NMSettingTeamClass *klass)
 	 *   team's interface name.
 	 * ---end---
 	 */
-	_properties_override_add_dbus_only (properties_override,
-	                                    "interface-name",
-	                                    G_VARIANT_TYPE_STRING,
-	                                    _nm_setting_get_deprecated_virtual_interface_name,
-	                                    NULL);
-
-	_nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_TEAM,
-	                               NULL, properties_override);
+	_nm_setting_class_add_dbus_only_property (parent_class, "interface-name",
+	                                          G_VARIANT_TYPE_STRING,
+	                                          _nm_setting_get_deprecated_virtual_interface_name,
+	                                          NULL);
 }
diff --git a/libnm-core/nm-setting-team.h b/libnm-core/nm-setting-team.h
index a600053a..cd766d8e 100644
--- a/libnm-core/nm-setting-team.h
+++ b/libnm-core/nm-setting-team.h
@@ -57,19 +57,19 @@ typedef struct NMTeamLinkWatcher NMTeamLinkWatcher;
 GType nm_team_link_watcher_get_type              (void);
 
 NM_AVAILABLE_IN_1_12
-NMTeamLinkWatcher *nm_team_link_watcher_new_ethtool (int delay_up,
-                                                     int delay_down,
+NMTeamLinkWatcher *nm_team_link_watcher_new_ethtool (gint delay_up,
+                                                     gint delay_down,
                                                      GError **error);
 NM_AVAILABLE_IN_1_12
-NMTeamLinkWatcher *nm_team_link_watcher_new_nsna_ping (int init_wait,
-                                                       int interval,
-                                                       int missed_max,
+NMTeamLinkWatcher *nm_team_link_watcher_new_nsna_ping (gint init_wait,
+                                                       gint interval,
+                                                       gint missed_max,
                                                        const char *target_host,
                                                        GError **error);
 NM_AVAILABLE_IN_1_12
-NMTeamLinkWatcher *nm_team_link_watcher_new_arp_ping (int init_wait,
-                                                      int interval,
-                                                      int missed_max,
+NMTeamLinkWatcher *nm_team_link_watcher_new_arp_ping (gint init_wait,
+                                                      gint interval,
+                                                      gint missed_max,
                                                       const char *target_host,
                                                       const char *source_host,
                                                       NMTeamLinkWatcherArpPingFlags flags,
@@ -174,13 +174,13 @@ NMSetting *  nm_setting_team_new                (void);
 
 const char * nm_setting_team_get_config (NMSettingTeam *setting);
 NM_AVAILABLE_IN_1_12
-int nm_setting_team_get_notify_peers_count (NMSettingTeam *setting);
+gint nm_setting_team_get_notify_peers_count (NMSettingTeam *setting);
 NM_AVAILABLE_IN_1_12
-int nm_setting_team_get_notify_peers_interval (NMSettingTeam *setting);
+gint nm_setting_team_get_notify_peers_interval (NMSettingTeam *setting);
 NM_AVAILABLE_IN_1_12
-int nm_setting_team_get_mcast_rejoin_count (NMSettingTeam *setting);
+gint nm_setting_team_get_mcast_rejoin_count (NMSettingTeam *setting);
 NM_AVAILABLE_IN_1_12
-int nm_setting_team_get_mcast_rejoin_interval (NMSettingTeam *setting);
+gint nm_setting_team_get_mcast_rejoin_interval (NMSettingTeam *setting);
 NM_AVAILABLE_IN_1_12
 const char * nm_setting_team_get_runner (NMSettingTeam *setting);
 NM_AVAILABLE_IN_1_12
@@ -188,15 +188,15 @@ const char * nm_setting_team_get_runner_hwaddr_policy (NMSettingTeam *setting);
 NM_AVAILABLE_IN_1_12
 const char * nm_setting_team_get_runner_tx_balancer (NMSettingTeam *setting);
 NM_AVAILABLE_IN_1_12
-int nm_setting_team_get_runner_tx_balancer_interval (NMSettingTeam *setting);
+gint nm_setting_team_get_runner_tx_balancer_interval (NMSettingTeam *setting);
 NM_AVAILABLE_IN_1_12
 gboolean nm_setting_team_get_runner_active (NMSettingTeam *setting);
 NM_AVAILABLE_IN_1_12
 gboolean nm_setting_team_get_runner_fast_rate (NMSettingTeam *setting);
 NM_AVAILABLE_IN_1_12
-int nm_setting_team_get_runner_sys_prio (NMSettingTeam *setting);
+gint nm_setting_team_get_runner_sys_prio (NMSettingTeam *setting);
 NM_AVAILABLE_IN_1_12
-int nm_setting_team_get_runner_min_ports (NMSettingTeam *setting);
+gint nm_setting_team_get_runner_min_ports (NMSettingTeam *setting);
 NM_AVAILABLE_IN_1_12
 const char * nm_setting_team_get_runner_agg_select_policy (NMSettingTeam *setting);
 NM_AVAILABLE_IN_1_12
diff --git a/libnm-core/nm-setting-tun.c b/libnm-core/nm-setting-tun.c
index 3e033e25..edcb3ffd 100644
--- a/libnm-core/nm-setting-tun.c
+++ b/libnm-core/nm-setting-tun.c
@@ -38,7 +38,9 @@
  * necessary for connection to TUN/TAP interfaces.
  **/
 
-G_DEFINE_TYPE (NMSettingTun, nm_setting_tun, NM_TYPE_SETTING)
+G_DEFINE_TYPE_WITH_CODE (NMSettingTun, nm_setting_tun, NM_TYPE_SETTING,
+                         _nm_register_setting (TUN, NM_SETTING_PRIORITY_HW_BASE))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_TUN)
 
 #define NM_SETTING_TUN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_TUN, NMSettingTunPrivate))
 
@@ -290,19 +292,20 @@ finalize (GObject *object)
 }
 
 static void
-nm_setting_tun_class_init (NMSettingTunClass *klass)
+nm_setting_tun_class_init (NMSettingTunClass *setting_class)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	NMSettingClass *setting_class = NM_SETTING_CLASS (klass);
+	GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+	NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
 
-	g_type_class_add_private (klass, sizeof (NMSettingTunPrivate));
+	g_type_class_add_private (setting_class, sizeof (NMSettingTunPrivate));
 
+	/* virtual methods */
 	object_class->set_property = set_property;
 	object_class->get_property = get_property;
 	object_class->finalize     = finalize;
+	parent_class->verify       = verify;
 
-	setting_class->verify = verify;
-
+	/* Properties */
 	/**
 	 * NMSettingTun:mode:
 	 *
@@ -403,6 +406,4 @@ nm_setting_tun_class_init (NMSettingTunClass *klass)
 		                       G_PARAM_READWRITE |
 		                       NM_SETTING_PARAM_INFERRABLE |
 		                       G_PARAM_STATIC_STRINGS));
-
-	_nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_TUN);
 }
diff --git a/libnm-core/nm-setting-user.c b/libnm-core/nm-setting-user.c
index d72c9094..ccc030aa 100644
--- a/libnm-core/nm-setting-user.c
+++ b/libnm-core/nm-setting-user.c
@@ -63,7 +63,9 @@ struct _NMSettingUserClass {
 	NMSettingClass parent;
 };
 
-G_DEFINE_TYPE (NMSettingUser, nm_setting_user, NM_TYPE_SETTING)
+G_DEFINE_TYPE_WITH_CODE (NMSettingUser, nm_setting_user, NM_TYPE_SETTING,
+                         _nm_register_setting (USER, NM_SETTING_PRIORITY_USER))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_USER)
 
 #define NM_SETTING_USER_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMSettingUser, NM_IS_SETTING_USER)
 
@@ -396,6 +398,29 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
 }
 
 static gboolean
+hash_table_equal (GHashTable *a, GHashTable *b)
+{
+	guint n;
+	GHashTableIter iter;
+	const char *key, *value, *valu2;
+
+	n = a ? g_hash_table_size (a) : 0;
+	if (n != (b ? g_hash_table_size (b) : 0))
+		return FALSE;
+	if (n > 0) {
+		g_hash_table_iter_init (&iter, a);
+		while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &value)) {
+			if (!g_hash_table_lookup_extended (b, key, NULL, (gpointer *) &valu2))
+				return FALSE;
+			if (!nm_streq (value, valu2))
+				return FALSE;
+		}
+	}
+	return TRUE;
+
+}
+
+static gboolean
 compare_property (NMSetting *setting,
                   NMSetting *other,
                   const GParamSpec *prop_spec,
@@ -412,10 +437,10 @@ compare_property (NMSetting *setting,
 	priv = NM_SETTING_USER_GET_PRIVATE (NM_SETTING_USER (setting));
 	pri2 = NM_SETTING_USER_GET_PRIVATE (NM_SETTING_USER (other));
 
-	if (!nm_utils_hash_table_equal (priv->data, pri2->data, TRUE, g_str_equal))
+	if (!hash_table_equal (priv->data, pri2->data))
 		return FALSE;
 
-	if (!nm_utils_hash_table_equal (priv->data_invalid, pri2->data_invalid, TRUE, g_str_equal))
+	if (!hash_table_equal (priv->data_invalid, pri2->data_invalid))
 		return FALSE;
 
 	return TRUE;
@@ -547,14 +572,12 @@ nm_setting_user_class_init (NMSettingUserClass *klass)
 {
 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
 	NMSettingClass *setting_class = NM_SETTING_CLASS (klass);
-	GArray *properties_override = _nm_sett_info_property_override_create_array ();
 
 	object_class->set_property = set_property;
 	object_class->get_property = get_property;
 	object_class->finalize     = finalize;
-
 	setting_class->compare_property = compare_property;
-	setting_class->verify           = verify;
+	setting_class->verify = verify;
 
 	/**
 	 * NMSettingUser:data: (type GHashTable(utf8,utf8))
@@ -585,13 +608,8 @@ nm_setting_user_class_init (NMSettingUserClass *klass)
 
 	g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
 
-	_properties_override_add_transform (properties_override,
-	                                    g_object_class_find_property (G_OBJECT_CLASS (setting_class),
-	                                                                  NM_SETTING_USER_DATA),
-	                                    G_VARIANT_TYPE ("a{ss}"),
-	                                    _nm_utils_strdict_to_dbus,
-	                                    _nm_utils_strdict_from_dbus);
-
-	_nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_USER,
-	                               NULL, properties_override);
+	_nm_setting_class_transform_property (setting_class, NM_SETTING_USER_DATA,
+	                                      G_VARIANT_TYPE ("a{ss}"),
+	                                      _nm_utils_strdict_to_dbus,
+	                                      _nm_utils_strdict_from_dbus);
 }
diff --git a/libnm-core/nm-setting-vlan.c b/libnm-core/nm-setting-vlan.c
index 1b61da55..f9c6e02d 100644
--- a/libnm-core/nm-setting-vlan.c
+++ b/libnm-core/nm-setting-vlan.c
@@ -41,7 +41,9 @@
  * necessary for connection to VLAN interfaces.
  **/
 
-G_DEFINE_TYPE (NMSettingVlan, nm_setting_vlan, NM_TYPE_SETTING)
+G_DEFINE_TYPE_WITH_CODE (NMSettingVlan, nm_setting_vlan, NM_TYPE_SETTING,
+                         _nm_register_setting (VLAN, NM_SETTING_PRIORITY_HW_BASE))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_VLAN)
 
 #define NM_SETTING_VLAN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_VLAN, NMSettingVlanPrivate))
 
@@ -132,7 +134,7 @@ static NMVlanQosMapping *
 priority_map_new_from_str (NMVlanPriorityMap map, const char *str)
 {
 	NMVlanQosMapping *p = NULL;
-	char **t = NULL;
+	gchar **t = NULL;
 	guint32 len;
 	guint64 from, to;
 
@@ -174,7 +176,7 @@ get_map (NMSettingVlan *self, NMVlanPriorityMap map)
 	return NULL;
 }
 
-static int
+static gint
 prio_map_compare (gconstpointer p_a, gconstpointer p_b)
 {
 	const NMVlanQosMapping *a = p_a;
@@ -829,19 +831,20 @@ finalize (GObject *object)
 }
 
 static void
-nm_setting_vlan_class_init (NMSettingVlanClass *klass)
+nm_setting_vlan_class_init (NMSettingVlanClass *setting_class)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	NMSettingClass *setting_class = NM_SETTING_CLASS (klass);
-	GArray *properties_override = _nm_sett_info_property_override_create_array ();
+	GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+	NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
 
-	g_type_class_add_private (klass, sizeof (NMSettingVlanPrivate));
+	g_type_class_add_private (setting_class, sizeof (NMSettingVlanPrivate));
 
+	/* virtual methods */
 	object_class->set_property = set_property;
 	object_class->get_property = get_property;
 	object_class->finalize     = finalize;
+	parent_class->verify       = verify;
 
-	setting_class->verify = verify;
+	/* Properties */
 
 	/**
 	 * NMSettingVlan:parent:
@@ -918,14 +921,11 @@ nm_setting_vlan_class_init (NMSettingVlanClass *klass)
 		                     G_PARAM_CONSTRUCT |
 		                     NM_SETTING_PARAM_INFERRABLE |
 		                     G_PARAM_STATIC_STRINGS));
-
-	_properties_override_add_override (properties_override,
-	                                   g_object_class_find_property (G_OBJECT_CLASS (setting_class),
-	                                                                 NM_SETTING_VLAN_FLAGS),
-	                                   NULL,
-	                                   _override_flags_get,
-	                                   NULL,
-	                                   _override_flags_not_set);
+	_nm_setting_class_override_property (parent_class, NM_SETTING_VLAN_FLAGS,
+	                                     NULL,
+	                                     _override_flags_get,
+	                                     NULL,
+	                                     _override_flags_not_set);
 
 	/**
 	 * NMSettingVlan:ingress-priority-map:
@@ -987,12 +987,8 @@ nm_setting_vlan_class_init (NMSettingVlanClass *klass)
 	 *   vlan's interface name.
 	 * ---end---
 	 */
-	_properties_override_add_dbus_only (properties_override,
-	                                    "interface-name",
-	                                    G_VARIANT_TYPE_STRING,
-	                                    _nm_setting_get_deprecated_virtual_interface_name,
-	                                    NULL);
-
-	_nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_VLAN,
-	                               NULL, properties_override);
+	_nm_setting_class_add_dbus_only_property (parent_class, "interface-name",
+	                                          G_VARIANT_TYPE_STRING,
+	                                          _nm_setting_get_deprecated_virtual_interface_name,
+	                                          NULL);
 }
diff --git a/libnm-core/nm-setting-vpn.c b/libnm-core/nm-setting-vpn.c
index fcbeec68..a921f51f 100644
--- a/libnm-core/nm-setting-vpn.c
+++ b/libnm-core/nm-setting-vpn.c
@@ -25,8 +25,6 @@
 #include <errno.h>
 #include <stdlib.h>
 
-#include "nm-utils/nm-secret-utils.h"
-
 #include "nm-setting-vpn.h"
 #include "nm-utils.h"
 #include "nm-utils-private.h"
@@ -45,7 +43,9 @@
  * properties.
  **/
 
-G_DEFINE_TYPE (NMSettingVpn, nm_setting_vpn, NM_TYPE_SETTING)
+G_DEFINE_TYPE_WITH_CODE (NMSettingVpn, nm_setting_vpn, NM_TYPE_SETTING,
+                         _nm_register_setting (VPN, NM_SETTING_PRIORITY_HW_BASE))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_VPN)
 
 #define NM_SETTING_VPN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_VPN, NMSettingVpnPrivate))
 
@@ -481,7 +481,6 @@ static gboolean
 verify (NMSetting *setting, NMConnection *connection, GError **error)
 {
 	NMSettingVpnPrivate *priv = NM_SETTING_VPN_GET_PRIVATE (setting);
-	NMSettingConnection *s_con;
 
 	if (!priv->service_type) {
 		g_set_error_literal (error,
@@ -511,16 +510,6 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
 		return FALSE;
 	}
 
-	if (   connection
-	    && (s_con = nm_connection_get_setting_connection (connection))
-	    && nm_setting_connection_get_multi_connect (s_con) != NM_CONNECTION_MULTI_CONNECT_DEFAULT) {
-		g_set_error_literal (error,
-		                     NM_CONNECTION_ERROR,
-		                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
-		                     _("cannot set connection.multi-connect for VPN setting"));
-		return FALSE;
-	}
-
 	return TRUE;
 }
 
@@ -889,26 +878,27 @@ get_property (GObject *object, guint prop_id,
 }
 
 static void
-nm_setting_vpn_class_init (NMSettingVpnClass *klass)
+nm_setting_vpn_class_init (NMSettingVpnClass *setting_class)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	NMSettingClass *setting_class = NM_SETTING_CLASS (klass);
-	GArray *properties_override = _nm_sett_info_property_override_create_array ();
+	GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+	NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
 
-	g_type_class_add_private (klass, sizeof (NMSettingVpnPrivate));
+	g_type_class_add_private (setting_class, sizeof (NMSettingVpnPrivate));
 
+	/* virtual methods */
 	object_class->set_property = set_property;
 	object_class->get_property = get_property;
 	object_class->finalize     = finalize;
 
-	setting_class->verify                   = verify;
-	setting_class->update_one_secret        = update_one_secret;
-	setting_class->get_secret_flags         = get_secret_flags;
-	setting_class->set_secret_flags         = set_secret_flags;
-	setting_class->need_secrets             = need_secrets;
-	setting_class->compare_property         = compare_property;
-	setting_class->clear_secrets_with_flags = clear_secrets_with_flags;
+	parent_class->verify            = verify;
+	parent_class->update_one_secret = update_one_secret;
+	parent_class->get_secret_flags  = get_secret_flags;
+	parent_class->set_secret_flags  = set_secret_flags;
+	parent_class->need_secrets      = need_secrets;
+	parent_class->compare_property  = compare_property;
+	parent_class->clear_secrets_with_flags = clear_secrets_with_flags;
 
+	/* Properties */
 	/**
 	 * NMSettingVpn:service-type:
 	 *
@@ -974,13 +964,10 @@ nm_setting_vpn_class_init (NMSettingVpnClass *klass)
 		                     G_TYPE_HASH_TABLE,
 		                     G_PARAM_READWRITE |
 		                     G_PARAM_STATIC_STRINGS));
-
-	_properties_override_add_transform (properties_override,
-	                                    g_object_class_find_property (G_OBJECT_CLASS (setting_class),
-	                                                                  NM_SETTING_VPN_DATA),
-	                                    G_VARIANT_TYPE ("a{ss}"),
-	                                    _nm_utils_strdict_to_dbus,
-	                                    _nm_utils_strdict_from_dbus);
+	_nm_setting_class_transform_property (parent_class, NM_SETTING_VPN_DATA,
+	                                      G_VARIANT_TYPE ("a{ss}"),
+	                                      _nm_utils_strdict_to_dbus,
+	                                      _nm_utils_strdict_from_dbus);
 
 	/**
 	 * NMSettingVpn:secrets: (type GHashTable(utf8,utf8)):
@@ -1003,13 +990,10 @@ nm_setting_vpn_class_init (NMSettingVpnClass *klass)
 		                     G_PARAM_READWRITE |
 		                     NM_SETTING_PARAM_SECRET |
 		                     G_PARAM_STATIC_STRINGS));
-
-	_properties_override_add_transform (properties_override,
-	                                    g_object_class_find_property (G_OBJECT_CLASS (setting_class),
-	                                                                  NM_SETTING_VPN_SECRETS),
-	                                    G_VARIANT_TYPE ("a{ss}"),
-	                                    _nm_utils_strdict_to_dbus,
-	                                    _nm_utils_strdict_from_dbus);
+	_nm_setting_class_transform_property (parent_class, NM_SETTING_VPN_SECRETS,
+	                                      G_VARIANT_TYPE ("a{ss}"),
+	                                      _nm_utils_strdict_to_dbus,
+	                                      _nm_utils_strdict_from_dbus);
 
 	/**
 	 * NMSettingVpn:timeout:
@@ -1028,7 +1012,4 @@ nm_setting_vpn_class_init (NMSettingVpnClass *klass)
 		                    0, G_MAXUINT32, 0,
 		                    G_PARAM_READWRITE |
 		                    G_PARAM_STATIC_STRINGS));
-
-	_nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_VPN,
-	                               NULL, properties_override);
 }
diff --git a/libnm-core/nm-setting-vxlan.c b/libnm-core/nm-setting-vxlan.c
index d00c5a7a..4be6a236 100644
--- a/libnm-core/nm-setting-vxlan.c
+++ b/libnm-core/nm-setting-vxlan.c
@@ -36,7 +36,9 @@
  * necessary for connection to VXLAN interfaces.
  **/
 
-G_DEFINE_TYPE (NMSettingVxlan, nm_setting_vxlan, NM_TYPE_SETTING)
+G_DEFINE_TYPE_WITH_CODE (NMSettingVxlan, nm_setting_vxlan, NM_TYPE_SETTING,
+                         _nm_register_setting (VXLAN, NM_SETTING_PRIORITY_HW_BASE))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_VXLAN)
 
 #define NM_SETTING_VXLAN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_VXLAN, NMSettingVxlanPrivate))
 
@@ -563,18 +565,20 @@ finalize (GObject *object)
 }
 
 static void
-nm_setting_vxlan_class_init (NMSettingVxlanClass *klass)
+nm_setting_vxlan_class_init (NMSettingVxlanClass *setting_class)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	NMSettingClass *setting_class = NM_SETTING_CLASS (klass);
+	GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+	NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
 
-	g_type_class_add_private (klass, sizeof (NMSettingVxlanPrivate));
+	g_type_class_add_private (setting_class, sizeof (NMSettingVxlanPrivate));
 
+	/* virtual methods */
 	object_class->set_property = set_property;
 	object_class->get_property = get_property;
 	object_class->finalize     = finalize;
+	parent_class->verify       = verify;
 
-	setting_class->verify = verify;
+	/* Properties */
 
 	/**
 	 * NMSettingVxlan:parent:
@@ -836,6 +840,4 @@ nm_setting_vxlan_class_init (NMSettingVxlanClass *klass)
 		                       G_PARAM_CONSTRUCT |
 		                       NM_SETTING_PARAM_INFERRABLE |
 		                       G_PARAM_STATIC_STRINGS));
-
-	_nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_VXLAN);
 }
diff --git a/libnm-core/nm-setting-wimax.c b/libnm-core/nm-setting-wimax.c
index 4c1a572e..dbfb46e4 100644
--- a/libnm-core/nm-setting-wimax.c
+++ b/libnm-core/nm-setting-wimax.c
@@ -42,7 +42,9 @@
  * connections cannot be activated.
  **/
 
-G_DEFINE_TYPE (NMSettingWimax, nm_setting_wimax, NM_TYPE_SETTING)
+G_DEFINE_TYPE_WITH_CODE (NMSettingWimax, nm_setting_wimax, NM_TYPE_SETTING,
+                         _nm_register_setting (WIMAX, NM_SETTING_PRIORITY_HW_BASE))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_WIMAX)
 
 #define NM_SETTING_WIMAX_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_WIMAX, NMSettingWimaxPrivate))
 
@@ -205,20 +207,20 @@ get_property (GObject *object, guint prop_id,
 }
 
 static void
-nm_setting_wimax_class_init (NMSettingWimaxClass *klass)
+nm_setting_wimax_class_init (NMSettingWimaxClass *setting_class)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	NMSettingClass *setting_class = NM_SETTING_CLASS (klass);
-	GArray *properties_override = _nm_sett_info_property_override_create_array ();
+	GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+	NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
 
-	g_type_class_add_private (klass, sizeof (NMSettingWimaxPrivate));
+	g_type_class_add_private (setting_class, sizeof (NMSettingWimaxPrivate));
 
+	/* virtual methods */
 	object_class->set_property = set_property;
 	object_class->get_property = get_property;
 	object_class->finalize     = finalize;
+	parent_class->verify       = verify;
 
-	setting_class->verify = verify;
-
+	/* Properties */
 	/**
 	 * NMSettingWimax:network-name:
 	 *
@@ -249,14 +251,8 @@ nm_setting_wimax_class_init (NMSettingWimaxClass *klass)
 		                      NULL,
 		                      G_PARAM_READWRITE |
 		                      G_PARAM_STATIC_STRINGS));
-
-	_properties_override_add_transform (properties_override,
-	                                    g_object_class_find_property (G_OBJECT_CLASS (setting_class),
-	                                                                  NM_SETTING_WIMAX_MAC_ADDRESS),
-	                                    G_VARIANT_TYPE_BYTESTRING,
-	                                    _nm_utils_hwaddr_to_dbus,
-	                                    _nm_utils_hwaddr_from_dbus);
-
-	_nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_WIMAX,
-	                               NULL, properties_override);
+	_nm_setting_class_transform_property (parent_class, NM_SETTING_WIMAX_MAC_ADDRESS,
+	                                      G_VARIANT_TYPE_BYTESTRING,
+	                                      _nm_utils_hwaddr_to_dbus,
+	                                      _nm_utils_hwaddr_from_dbus);
 }
diff --git a/libnm-core/nm-setting-wired.c b/libnm-core/nm-setting-wired.c
index baa40cc4..5da9ce7d 100644
--- a/libnm-core/nm-setting-wired.c
+++ b/libnm-core/nm-setting-wired.c
@@ -40,7 +40,9 @@
  * necessary for connection to Ethernet networks.
  **/
 
-G_DEFINE_TYPE (NMSettingWired, nm_setting_wired, NM_TYPE_SETTING)
+G_DEFINE_TYPE_WITH_CODE (NMSettingWired, nm_setting_wired, NM_TYPE_SETTING,
+                         _nm_register_setting (WIRED, NM_SETTING_PRIORITY_HW_BASE))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_WIRED)
 
 #define NM_SETTING_WIRED_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_WIRED, NMSettingWiredPrivate))
 
@@ -764,8 +766,8 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
 	    || ((!priv->speed) && (priv->duplex))) {
 
 		g_set_error_literal (error,
-		                     NM_CONNECTION_ERROR,
-		                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
+				     NM_CONNECTION_ERROR,
+				     NM_CONNECTION_ERROR_INVALID_PROPERTY,
 		                     priv->auto_negotiate ?
 		                       _("both speed and duplex should have a valid value or both should be unset")
 		                     : _("both speed and duplex are required for static link configuration"));
@@ -781,15 +783,15 @@ compare_property (NMSetting *setting,
                   const GParamSpec *prop_spec,
                   NMSettingCompareFlags flags)
 {
-	NMSettingClass *setting_class;
+	NMSettingClass *parent_class;
 
 	if (nm_streq (prop_spec->name, NM_SETTING_WIRED_CLONED_MAC_ADDRESS)) {
 		return nm_streq0 (NM_SETTING_WIRED_GET_PRIVATE (setting)->cloned_mac_address,
 		                  NM_SETTING_WIRED_GET_PRIVATE (other)->cloned_mac_address);
 	}
 
-	setting_class = NM_SETTING_CLASS (nm_setting_wired_parent_class);
-	return setting_class->compare_property (setting, other, prop_spec, flags);
+	parent_class = NM_SETTING_CLASS (nm_setting_wired_parent_class);
+	return parent_class->compare_property (setting, other, prop_spec, flags);
 }
 
 static GVariant *
@@ -976,21 +978,21 @@ get_property (GObject *object, guint prop_id,
 }
 
 static void
-nm_setting_wired_class_init (NMSettingWiredClass *klass)
+nm_setting_wired_class_init (NMSettingWiredClass *setting_wired_class)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	NMSettingClass *setting_class = NM_SETTING_CLASS (klass);
-	GArray *properties_override = _nm_sett_info_property_override_create_array ();
+	GObjectClass *object_class = G_OBJECT_CLASS (setting_wired_class);
+	NMSettingClass *setting_class = NM_SETTING_CLASS (setting_wired_class);
 
-	g_type_class_add_private (klass, sizeof (NMSettingWiredPrivate));
+	g_type_class_add_private (setting_wired_class, sizeof (NMSettingWiredPrivate));
 
+	/* virtual methods */
 	object_class->set_property = set_property;
 	object_class->get_property = get_property;
 	object_class->finalize     = finalize;
-
-	setting_class->verify           = verify;
+	setting_class->verify      = verify;
 	setting_class->compare_property = compare_property;
 
+	/* Properties */
 	/**
 	 * NMSettingWired:port:
 	 *
@@ -1101,14 +1103,12 @@ nm_setting_wired_class_init (NMSettingWiredClass *klass)
 		                       G_PARAM_READWRITE |
 		                       G_PARAM_CONSTRUCT |
 		                       G_PARAM_STATIC_STRINGS));
-
-	_properties_override_add_override (properties_override,
-	                                   g_object_class_find_property (G_OBJECT_CLASS (setting_class),
-	                                                                 NM_SETTING_WIRED_AUTO_NEGOTIATE),
-	                                   G_VARIANT_TYPE_BOOLEAN,
-	                                   _override_autoneg_get,
-	                                   NULL,
-	                                   NULL);
+	_nm_setting_class_override_property (setting_class,
+	                                     NM_SETTING_WIRED_AUTO_NEGOTIATE,
+	                                     G_VARIANT_TYPE_BOOLEAN,
+	                                     _override_autoneg_get,
+	                                     NULL,
+	                                     NULL);
 
 	/**
 	 * NMSettingWired:mac-address:
@@ -1141,13 +1141,10 @@ nm_setting_wired_class_init (NMSettingWiredClass *klass)
 		                      G_PARAM_READWRITE |
 		                      NM_SETTING_PARAM_INFERRABLE |
 		                      G_PARAM_STATIC_STRINGS));
-
-	_properties_override_add_transform (properties_override,
-	                                    g_object_class_find_property (G_OBJECT_CLASS (setting_class),
-	                                                                  NM_SETTING_WIRED_MAC_ADDRESS),
-	                                    G_VARIANT_TYPE_BYTESTRING,
-	                                    _nm_utils_hwaddr_to_dbus,
-	                                    _nm_utils_hwaddr_from_dbus);
+	_nm_setting_class_transform_property (setting_class, NM_SETTING_WIRED_MAC_ADDRESS,
+	                                      G_VARIANT_TYPE_BYTESTRING,
+	                                      _nm_utils_hwaddr_to_dbus,
+	                                      _nm_utils_hwaddr_from_dbus);
 
 	/**
 	 * NMSettingWired:cloned-mac-address:
@@ -1199,10 +1196,8 @@ nm_setting_wired_class_init (NMSettingWiredClass *klass)
 		                      G_PARAM_READWRITE |
 		                      NM_SETTING_PARAM_INFERRABLE |
 		                      G_PARAM_STATIC_STRINGS));
-
-	_properties_override_add_override (properties_override,
-	                                     g_object_class_find_property (G_OBJECT_CLASS (setting_class),
-	                                                                   NM_SETTING_WIRED_CLONED_MAC_ADDRESS),
+	_nm_setting_class_override_property (setting_class,
+	                                     NM_SETTING_WIRED_CLONED_MAC_ADDRESS,
 	                                     G_VARIANT_TYPE_BYTESTRING,
 	                                     _nm_utils_hwaddr_cloned_get,
 	                                     _nm_utils_hwaddr_cloned_set,
@@ -1220,11 +1215,11 @@ nm_setting_wired_class_init (NMSettingWiredClass *klass)
 	 *   "cloned-mac-address".
 	 * ---end---
 	 */
-	_properties_override_add_dbus_only (properties_override,
-	                                    "assigned-mac-address",
-	                                    G_VARIANT_TYPE_STRING,
-	                                    _nm_utils_hwaddr_cloned_data_synth,
-	                                    _nm_utils_hwaddr_cloned_data_set);
+	_nm_setting_class_add_dbus_only_property (setting_class,
+	                                          "assigned-mac-address",
+	                                          G_VARIANT_TYPE_STRING,
+	                                          _nm_utils_hwaddr_cloned_data_synth,
+	                                          _nm_utils_hwaddr_cloned_data_set);
 
 	/**
 	 * NMSettingWired:generate-mac-address-mask:
@@ -1394,13 +1389,10 @@ nm_setting_wired_class_init (NMSettingWiredClass *klass)
 		                     G_PARAM_READWRITE |
 		                     NM_SETTING_PARAM_INFERRABLE |
 		                     G_PARAM_STATIC_STRINGS));
-
-	_properties_override_add_transform (properties_override,
-	                                    g_object_class_find_property (G_OBJECT_CLASS (setting_class),
-	                                                                  NM_SETTING_WIRED_S390_OPTIONS),
-	                                    G_VARIANT_TYPE ("a{ss}"),
-	                                    _nm_utils_strdict_to_dbus,
-	                                    _nm_utils_strdict_from_dbus);
+	_nm_setting_class_transform_property (setting_class, NM_SETTING_WIRED_S390_OPTIONS,
+	                                      G_VARIANT_TYPE ("a{ss}"),
+	                                      _nm_utils_strdict_to_dbus,
+	                                      _nm_utils_strdict_from_dbus);
 
 	/**
 	 * NMSettingWired:wake-on-lan:
@@ -1439,7 +1431,4 @@ nm_setting_wired_class_init (NMSettingWiredClass *klass)
 		                      NULL,
 		                      G_PARAM_READWRITE |
 		                      G_PARAM_STATIC_STRINGS));
-
-	_nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_WIRED,
-	                               NULL, properties_override);
 }
diff --git a/libnm-core/nm-setting-wireless-security.c b/libnm-core/nm-setting-wireless-security.c
index d1527821..31e386f3 100644
--- a/libnm-core/nm-setting-wireless-security.c
+++ b/libnm-core/nm-setting-wireless-security.c
@@ -53,7 +53,9 @@
  *       ISBN: 978-1587051548
  **/
 
-G_DEFINE_TYPE (NMSettingWirelessSecurity, nm_setting_wireless_security, NM_TYPE_SETTING)
+G_DEFINE_TYPE_WITH_CODE (NMSettingWirelessSecurity, nm_setting_wireless_security, NM_TYPE_SETTING,
+                         _nm_register_setting (WIRELESS_SECURITY, NM_SETTING_PRIORITY_HW_AUX))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_WIRELESS_SECURITY)
 
 #define NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_WIRELESS_SECURITY, NMSettingWirelessSecurityPrivate))
 
@@ -1429,24 +1431,25 @@ get_property (GObject *object, guint prop_id,
 }
 
 static void
-nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *klass)
+nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *setting_class)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	NMSettingClass *setting_class = NM_SETTING_CLASS (klass);
-	GArray *properties_override = _nm_sett_info_property_override_create_array ();
+	GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+	NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
 
-	g_type_class_add_private (klass, sizeof (NMSettingWirelessSecurityPrivate));
+	g_type_class_add_private (setting_class, sizeof (NMSettingWirelessSecurityPrivate));
 
+	/* virtual methods */
 	object_class->set_property = set_property;
 	object_class->get_property = get_property;
 	object_class->finalize     = finalize;
 
-	setting_class->verify           = verify;
-	setting_class->verify_secrets   = verify_secrets;
-	setting_class->need_secrets     = need_secrets;
-	setting_class->get_secret_flags = get_secret_flags;
-	setting_class->set_secret_flags = set_secret_flags;
+	parent_class->verify           = verify;
+	parent_class->verify_secrets   = verify_secrets;
+	parent_class->need_secrets     = need_secrets;
+	parent_class->get_secret_flags = get_secret_flags;
+	parent_class->set_secret_flags = set_secret_flags;
 
+	/* Properties */
 	/**
 	 * NMSettingWirelessSecurity:key-mgmt:
 	 *
@@ -1853,13 +1856,11 @@ nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *klass)
 		                    G_PARAM_READWRITE |
 		                    G_PARAM_CONSTRUCT |
 		                    G_PARAM_STATIC_STRINGS));
-
-	_properties_override_add_transform (properties_override,
-	                                    g_object_class_find_property (G_OBJECT_CLASS (setting_class),
-	                                                                  NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE),
-	                                    G_VARIANT_TYPE_UINT32,
-	                                    wep_key_type_to_dbus,
-	                                    NULL);
+	_nm_setting_class_transform_property (parent_class,
+	                                      NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE,
+	                                      G_VARIANT_TYPE_UINT32,
+	                                      wep_key_type_to_dbus,
+	                                      NULL);
 	/**
 	 * NMSettingWirelessSecurity:wps-method:
 	 *
@@ -1921,7 +1922,4 @@ nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *klass)
 		                   G_PARAM_CONSTRUCT |
 		                   NM_SETTING_PARAM_FUZZY_IGNORE |
 		                   G_PARAM_STATIC_STRINGS));
-
-	_nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_WIRELESS_SECURITY,
-	                               NULL, properties_override);
 }
diff --git a/libnm-core/nm-setting-wireless.c b/libnm-core/nm-setting-wireless.c
index a9cae6c0..89a2df8e 100644
--- a/libnm-core/nm-setting-wireless.c
+++ b/libnm-core/nm-setting-wireless.c
@@ -40,7 +40,9 @@
  * necessary for connection to 802.11 Wi-Fi networks.
  **/
 
-G_DEFINE_TYPE (NMSettingWireless, nm_setting_wireless, NM_TYPE_SETTING)
+G_DEFINE_TYPE_WITH_CODE (NMSettingWireless, nm_setting_wireless, NM_TYPE_SETTING,
+                         _nm_register_setting (WIRELESS, NM_SETTING_PRIORITY_HW_BASE))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_WIRELESS)
 
 #define NM_SETTING_WIRELESS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_WIRELESS, NMSettingWirelessPrivate))
 
@@ -935,15 +937,15 @@ compare_property (NMSetting *setting,
                   const GParamSpec *prop_spec,
                   NMSettingCompareFlags flags)
 {
-	NMSettingClass *setting_class;
+	NMSettingClass *parent_class;
 
 	if (nm_streq (prop_spec->name, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS)) {
 		return nm_streq0 (NM_SETTING_WIRELESS_GET_PRIVATE (setting)->cloned_mac_address,
 		                  NM_SETTING_WIRELESS_GET_PRIVATE (other)->cloned_mac_address);
 	}
 
-	setting_class = NM_SETTING_CLASS (nm_setting_wireless_parent_class);
-	return setting_class->compare_property (setting, other, prop_spec, flags);
+	parent_class = NM_SETTING_CLASS (nm_setting_wireless_parent_class);
+	return parent_class->compare_property (setting, other, prop_spec, flags);
 }
 
 /*****************************************************************************/
@@ -1174,21 +1176,21 @@ get_property (GObject *object, guint prop_id,
 }
 
 static void
-nm_setting_wireless_class_init (NMSettingWirelessClass *klass)
+nm_setting_wireless_class_init (NMSettingWirelessClass *setting_wireless_class)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	NMSettingClass *setting_class = NM_SETTING_CLASS (klass);
-	GArray *properties_override = _nm_sett_info_property_override_create_array ();
+	GObjectClass *object_class = G_OBJECT_CLASS (setting_wireless_class);
+	NMSettingClass *setting_class = NM_SETTING_CLASS (setting_wireless_class);
 
-	g_type_class_add_private (klass, sizeof (NMSettingWirelessPrivate));
+	g_type_class_add_private (setting_wireless_class, sizeof (NMSettingWirelessPrivate));
 
+	/* virtual methods */
 	object_class->set_property = set_property;
 	object_class->get_property = get_property;
 	object_class->finalize     = finalize;
-
-	setting_class->verify           = verify;
+	setting_class->verify      = verify;
 	setting_class->compare_property = compare_property;
 
+	/* Properties */
 	/**
 	 * NMSettingWireless:ssid:
 	 *
@@ -1306,13 +1308,10 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *klass)
 		                      NULL,
 		                      G_PARAM_READWRITE |
 		                      G_PARAM_STATIC_STRINGS));
-
-	_properties_override_add_transform (properties_override,
-	                                    g_object_class_find_property (G_OBJECT_CLASS (setting_class),
-	                                                                  NM_SETTING_WIRELESS_BSSID),
-	                                    G_VARIANT_TYPE_BYTESTRING,
-	                                    _nm_utils_hwaddr_to_dbus,
-	                                    _nm_utils_hwaddr_from_dbus);
+	_nm_setting_class_transform_property (setting_class, NM_SETTING_WIRELESS_BSSID,
+	                                      G_VARIANT_TYPE_BYTESTRING,
+	                                      _nm_utils_hwaddr_to_dbus,
+	                                      _nm_utils_hwaddr_from_dbus);
 
 	/**
 	 * NMSettingWireless:rate:
@@ -1389,13 +1388,10 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *klass)
 		                      NULL,
 		                      G_PARAM_READWRITE |
 		                      G_PARAM_STATIC_STRINGS));
-
-	_properties_override_add_transform (properties_override,
-	                                    g_object_class_find_property (G_OBJECT_CLASS (setting_class),
-	                                                                  NM_SETTING_WIRELESS_MAC_ADDRESS),
-	                                    G_VARIANT_TYPE_BYTESTRING,
-	                                    _nm_utils_hwaddr_to_dbus,
-	                                    _nm_utils_hwaddr_from_dbus);
+	_nm_setting_class_transform_property (setting_class, NM_SETTING_WIRELESS_MAC_ADDRESS,
+	                                      G_VARIANT_TYPE_BYTESTRING,
+	                                      _nm_utils_hwaddr_to_dbus,
+	                                      _nm_utils_hwaddr_from_dbus);
 
 	/**
 	 * NMSettingWireless:cloned-mac-address:
@@ -1445,14 +1441,12 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *klass)
 		                      NULL,
 		                      G_PARAM_READWRITE |
 		                      G_PARAM_STATIC_STRINGS));
-
-	_properties_override_add_override (properties_override,
-	                                   g_object_class_find_property (G_OBJECT_CLASS (setting_class),
-	                                                                 NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS),
-	                                   G_VARIANT_TYPE_BYTESTRING,
-	                                   _nm_utils_hwaddr_cloned_get,
-	                                   _nm_utils_hwaddr_cloned_set,
-	                                   _nm_utils_hwaddr_cloned_not_set);
+	_nm_setting_class_override_property (setting_class,
+	                                     NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS,
+	                                     G_VARIANT_TYPE_BYTESTRING,
+	                                     _nm_utils_hwaddr_cloned_get,
+	                                     _nm_utils_hwaddr_cloned_set,
+	                                     _nm_utils_hwaddr_cloned_not_set);
 
 	/* ---dbus---
 	 * property: assigned-mac-address
@@ -1466,11 +1460,11 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *klass)
 	 *   "cloned-mac-address".
 	 * ---end---
 	 */
-	_properties_override_add_dbus_only (properties_override,
-	                                    "assigned-mac-address",
-	                                    G_VARIANT_TYPE_STRING,
-	                                    _nm_utils_hwaddr_cloned_data_synth,
-	                                    _nm_utils_hwaddr_cloned_data_set);
+	_nm_setting_class_add_dbus_only_property (setting_class,
+	                                          "assigned-mac-address",
+	                                          G_VARIANT_TYPE_STRING,
+	                                          _nm_utils_hwaddr_cloned_data_synth,
+	                                          _nm_utils_hwaddr_cloned_data_set);
 
 	/**
 	 * NMSettingWireless:generate-mac-address-mask:
@@ -1685,11 +1679,9 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *klass)
 	 *   NetworkManager daemons.
 	 * ---end---
 	 */
-	_properties_override_add_dbus_only (properties_override,
-	                                    "security",
-	                                    G_VARIANT_TYPE_STRING,
-	                                    nm_setting_wireless_get_security,
-	                                    NULL);
+	_nm_setting_class_add_dbus_only_property (setting_class, "security",
+	                                          G_VARIANT_TYPE_STRING,
+	                                          nm_setting_wireless_get_security, NULL);
 
 	/**
 	 * NMSettingWireless:wake-on-wlan:
@@ -1716,7 +1708,4 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *klass)
 		                    G_PARAM_CONSTRUCT |
 		                    G_PARAM_READWRITE |
 		                    G_PARAM_STATIC_STRINGS));
-
-	_nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_WIRELESS,
-	                               NULL, properties_override);
 }
diff --git a/libnm-core/nm-setting-wpan.c b/libnm-core/nm-setting-wpan.c
deleted file mode 100644
index 6e1aaadc..00000000
--- a/libnm-core/nm-setting-wpan.c
+++ /dev/null
@@ -1,274 +0,0 @@
-/*
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA.
- *
- * Copyright 2018 Lubomir Rintel <lkundrak@v3.sk>
- */
-
-#include "nm-default.h"
-
-#include "nm-setting-wpan.h"
-
-#include "nm-connection-private.h"
-#include "nm-setting-connection.h"
-#include "nm-setting-private.h"
-#include "nm-utils-private.h"
-
-/* Ideally we'll be able to get this from a public header. */
-#ifndef IEEE802154_ADDR_LEN
-#define IEEE802154_ADDR_LEN 8
-#endif
-
-enum {
-	PROP_0,
-	PROP_MAC_ADDRESS,
-	PROP_PAN_ID,
-	PROP_SHORT_ADDRESS,
-};
-
-typedef struct {
-	char *mac_address;
-	guint16 pan_id;
-	guint16 short_address;
-} NMSettingWpanPrivate;
-
-/**
- * NMSettingWpan:
- *
- * IEEE 802.15.4 (WPAN) MAC Settings
- */
-struct _NMSettingWpan {
-        NMSetting parent;
-};
-
-struct _NMSettingWpanClass {
-        NMSettingClass parent;
-};
-
-/**
- * SECTION:nm-setting-wpan
- * @short_description: Describes connection properties for IEEE 802.15.4 (WPAN) MAC
- *
- * The #NMSettingWpan object is a #NMSetting subclass that describes properties
- * necessary for configuring IEEE 802.15.4 (WPAN) MAC layer devices.
- **/
-
-G_DEFINE_TYPE (NMSettingWpan, nm_setting_wpan, NM_TYPE_SETTING)
-
-#define NM_SETTING_WPAN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_WPAN, NMSettingWpanPrivate))
-
-/**
- * nm_setting_wpan_get_mac_address:
- * @setting: the #NMSettingWpan
- *
- * Returns: the #NMSettingWpan:mac-address property of the setting
- *
- * Since: 1.14
- **/
-const char *
-nm_setting_wpan_get_mac_address (NMSettingWpan *setting)
-{
-	g_return_val_if_fail (NM_IS_SETTING_WPAN (setting), NULL);
-
-	return NM_SETTING_WPAN_GET_PRIVATE (setting)->mac_address;
-}
-
-/**
- * nm_setting_wpan_get_pan_id:
- * @setting: the #NMSettingWpan
- *
- * Returns: the #NMSettingWpan:pan-id property of the setting
- *
- * Since: 1.14
- **/
-guint16
-nm_setting_wpan_get_pan_id (NMSettingWpan *setting)
-{
-	g_return_val_if_fail (NM_IS_SETTING_WPAN (setting), G_MAXUINT16);
-
-	return NM_SETTING_WPAN_GET_PRIVATE (setting)->pan_id;
-}
-
-/**
- * nm_setting_wpan_get_short_address:
- * @setting: the #NMSettingWpan
- *
- * Returns: the #NMSettingWpan:short-address property of the setting
- *
- * Since: 1.14
- **/
-guint16
-nm_setting_wpan_get_short_address (NMSettingWpan *setting)
-{
-	g_return_val_if_fail (NM_IS_SETTING_WPAN (setting), G_MAXUINT16);
-
-	return NM_SETTING_WPAN_GET_PRIVATE (setting)->short_address;
-}
-
-static gboolean
-verify (NMSetting *setting, NMConnection *connection, GError **error)
-{
-	NMSettingWpanPrivate *priv = NM_SETTING_WPAN_GET_PRIVATE (setting);
-
-	if (priv->mac_address && !nm_utils_hwaddr_valid (priv->mac_address, IEEE802154_ADDR_LEN)) {
-		g_set_error_literal (error,
-		                     NM_CONNECTION_ERROR,
-		                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
-		                     _("property is invalid"));
-		g_prefix_error (error, "%s.%s: ", NM_SETTING_WPAN_SETTING_NAME, NM_SETTING_WPAN_MAC_ADDRESS);
-		return FALSE;
-	}
-
-	return TRUE;
-}
-
-static void
-get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
-{
-	NMSettingWpan *setting = NM_SETTING_WPAN (object);
-
-	switch (prop_id) {
-	case PROP_MAC_ADDRESS:
-		g_value_set_string (value, nm_setting_wpan_get_mac_address (setting));
-		break;
-	case PROP_PAN_ID:
-		g_value_set_uint (value, nm_setting_wpan_get_pan_id (setting));
-		break;
-	case PROP_SHORT_ADDRESS:
-		g_value_set_uint (value, nm_setting_wpan_get_short_address (setting));
-		break;
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-		break;
-	}
-}
-
-static void
-set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
-{
-	NMSettingWpanPrivate *priv = NM_SETTING_WPAN_GET_PRIVATE (object);
-
-	switch (prop_id) {
-	case PROP_MAC_ADDRESS:
-		g_free (priv->mac_address);
-		priv->mac_address = _nm_utils_hwaddr_canonical_or_invalid (g_value_get_string (value),
-		                                                           IEEE802154_ADDR_LEN);
-		break;
-	case PROP_PAN_ID:
-		priv->pan_id = g_value_get_uint (value);
-		break;
-	case PROP_SHORT_ADDRESS:
-		priv->short_address = g_value_get_uint (value);
-		break;
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-		break;
-	}
-}
-
-static void
-nm_setting_wpan_init (NMSettingWpan *setting)
-{
-	NMSettingWpanPrivate *priv = NM_SETTING_WPAN_GET_PRIVATE (setting);
-
-	priv->short_address = G_MAXUINT16;
-	priv->pan_id = G_MAXUINT16;
-}
-
-/**
- * nm_setting_wpan_new:
- *
- * Creates a new #NMSettingWpan object with default values.
- *
- * Returns: (transfer full): the new empty #NMSettingWpan object
- *
- * Since: 1.14
- **/
-NMSetting *
-nm_setting_wpan_new (void)
-{
-	return (NMSetting *) g_object_new (NM_TYPE_SETTING_WPAN, NULL);
-}
-
-static void
-finalize (GObject *object)
-{
-	NMSettingWpanPrivate *priv = NM_SETTING_WPAN_GET_PRIVATE (object);
-
-	g_free (priv->mac_address);
-
-	G_OBJECT_CLASS (nm_setting_wpan_parent_class)->finalize (object);
-}
-
-static void
-nm_setting_wpan_class_init (NMSettingWpanClass *klass)
-{
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	NMSettingClass *setting_class = NM_SETTING_CLASS (klass);
-
-	g_type_class_add_private (setting_class, sizeof (NMSettingWpanPrivate));
-
-	object_class->set_property = set_property;
-	object_class->get_property = get_property;
-	object_class->finalize     = finalize;
-
-	setting_class->verify = verify;
-
-	/**
-	 * NMSettingWpan:mac-address:
-	 *
-	 * If specified, this connection will only apply to the IEEE 802.15.4 (WPAN)
-	 * MAC layer device whose permanent MAC address matches.
-	 **/
-	/* ---keyfile---
-	 * property: mac-address
-	 * format: usual hex-digits-and-colons notation
-	 * description: MAC address in hex-digits-and-colons notation
-	 *   (e.g. 76:d8:9b:87:66:60:84:ee).
-	 * ---end---
-	 */
-	g_object_class_install_property
-	        (object_class, PROP_MAC_ADDRESS,
-	         g_param_spec_string (NM_SETTING_WPAN_MAC_ADDRESS, "", "",
-	                              NULL,
-	                              G_PARAM_READWRITE |
-	                              G_PARAM_STATIC_STRINGS));
-
-	/**
-	 * NMSettingWpan:pan-id:
-	 *
-	 * IEEE 802.15.4 Personal Area Network (PAN) identifier.
-	 **/
-	g_object_class_install_property
-	        (object_class, PROP_PAN_ID,
-	         g_param_spec_uint (NM_SETTING_WPAN_PAN_ID, "", "",
-	                            0, G_MAXUINT16, G_MAXUINT16,
-	                            G_PARAM_READWRITE |
-	                            G_PARAM_STATIC_STRINGS));
-
-	/**
-	 * NMSettingWpan:short-address:
-	 *
-	 * Short IEEE 802.15.4 address to be used within a restricted environment.
-	 **/
-	g_object_class_install_property
-	        (object_class, PROP_SHORT_ADDRESS,
-	         g_param_spec_uint (NM_SETTING_WPAN_SHORT_ADDRESS, "", "",
-	                            0, G_MAXUINT16, G_MAXUINT16,
-	                            G_PARAM_READWRITE |
-	                            G_PARAM_STATIC_STRINGS));
-
-	_nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_WPAN);
-}
diff --git a/libnm-core/nm-setting-wpan.h b/libnm-core/nm-setting-wpan.h
deleted file mode 100644
index a39e377e..00000000
--- a/libnm-core/nm-setting-wpan.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA.
- *
- * Copyright 2018 Lubomir Rintel <lkundrak@v3.sk>
- */
-
-#ifndef __NM_SETTING_WPAN_H__
-#define __NM_SETTING_WPAN_H__
-
-#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION)
-#error "Only <NetworkManager.h> can be included directly."
-#endif
-
-#include "nm-setting.h"
-
-G_BEGIN_DECLS
-
-#define NM_TYPE_SETTING_WPAN            (nm_setting_wpan_get_type ())
-#define NM_SETTING_WPAN(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_WPAN, NMSettingWpan))
-#define NM_SETTING_WPAN_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_WPANCONFIG, NMSettingWpanClass))
-#define NM_IS_SETTING_WPAN(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_WPAN))
-#define NM_IS_SETTING_WPAN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_WPAN))
-#define NM_SETTING_WPAN_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_WPAN, NMSettingWpanClass))
-
-#define NM_SETTING_WPAN_SETTING_NAME       "wpan"
-#define NM_SETTING_WPAN_MAC_ADDRESS        "mac-address"
-#define NM_SETTING_WPAN_PAN_ID             "pan-id"
-#define NM_SETTING_WPAN_SHORT_ADDRESS      "short-address"
-
-typedef struct _NMSettingWpanClass NMSettingWpanClass;
-
-NM_AVAILABLE_IN_1_14
-GType nm_setting_wpan_get_type (void);
-NM_AVAILABLE_IN_1_14
-NMSetting *nm_setting_wpan_new (void);
-
-NM_AVAILABLE_IN_1_14
-const char *nm_setting_wpan_get_mac_address        (NMSettingWpan *setting);
-NM_AVAILABLE_IN_1_14
-guint16     nm_setting_wpan_get_pan_id             (NMSettingWpan *setting);
-NM_AVAILABLE_IN_1_14
-guint16     nm_setting_wpan_get_short_address      (NMSettingWpan *setting);
-
-G_END_DECLS
-
-#endif /* __NM_SETTING_WPAN_H__ */
diff --git a/libnm-core/nm-setting.c b/libnm-core/nm-setting.c
index 0cec5165..218f0dad 100644
--- a/libnm-core/nm-setting.c
+++ b/libnm-core/nm-setting.c
@@ -53,13 +53,9 @@
  * of properties and allowed values.
  */
 
-/*****************************************************************************/
+G_DEFINE_ABSTRACT_TYPE (NMSetting, nm_setting, G_TYPE_OBJECT)
 
-typedef struct {
-	GHashTable *hash;
-	const char **names;
-	GVariant **values;
-} GenData;
+#define NM_SETTING_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING, NMSettingPrivate))
 
 typedef struct {
 	const char *name;
@@ -67,6 +63,10 @@ typedef struct {
 	NMSettingPriority priority;
 } SettingInfo;
 
+typedef struct {
+	const SettingInfo *info;
+} NMSettingPrivate;
+
 enum {
 	PROP_0,
 	PROP_NAME,
@@ -74,66 +74,136 @@ enum {
 	PROP_LAST
 };
 
-typedef struct {
-	GenData *gendata;
-} NMSettingPrivate;
+/*****************************************************************************/
 
-G_DEFINE_ABSTRACT_TYPE (NMSetting, nm_setting, G_TYPE_OBJECT)
+static GHashTable *registered_settings = NULL;
+static GHashTable *registered_settings_by_type = NULL;
 
-#define NM_SETTING_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING, NMSettingPrivate))
+static gboolean
+_nm_gtype_equal (gconstpointer v1, gconstpointer v2)
+{
+	return *((const GType *) v1) == *((const GType *) v2);
+}
+static guint
+_nm_gtype_hash (gconstpointer v)
+{
+	return *((const GType *) v);
+}
 
-/*****************************************************************************/
+static void
+_ensure_registered (void)
+{
+	if (G_UNLIKELY (registered_settings == NULL)) {
+		registered_settings = g_hash_table_new (nm_str_hash, g_str_equal);
+		registered_settings_by_type = g_hash_table_new (_nm_gtype_hash, _nm_gtype_equal);
+	}
+}
 
-static GenData *_gendata_hash (NMSetting *setting, gboolean create_if_necessary);
+static void __attribute__((constructor))
+_ensure_registered_constructor (void)
+{
+	_ensure_registered ();
+}
+
+#define _ensure_setting_info(self, priv) \
+	G_STMT_START { \
+		NMSettingPrivate *_priv_esi = (priv); \
+		if (G_UNLIKELY (!_priv_esi->info)) { \
+			_priv_esi->info = _nm_setting_lookup_setting_by_type (G_OBJECT_TYPE (self)); \
+			g_assert (_priv_esi->info); \
+		} \
+	} G_STMT_END
 
 /*****************************************************************************/
 
+/*
+ * _nm_register_setting_impl:
+ * @name: the name of the #NMSetting object to register
+ * @type: the #GType of the #NMSetting
+ * @priority: the sort priority of the setting, see #NMSettingPriority
+ *
+ * INTERNAL ONLY: registers a setting's internal properties with libnm.
+ */
+void
+_nm_register_setting_impl (const char *name,
+                           GType type,
+                           NMSettingPriority priority)
+{
+	SettingInfo *info;
+
+	nm_assert (name && *name);
+	nm_assert (!NM_IN_SET (type, G_TYPE_INVALID, G_TYPE_NONE));
+	nm_assert (priority != NM_SETTING_PRIORITY_INVALID);
+
+	_ensure_registered ();
+
+	nm_assert (!g_hash_table_lookup (registered_settings, name));
+	nm_assert (!g_hash_table_lookup (registered_settings_by_type, &type));
+
+	nm_assert (   priority != NM_SETTING_PRIORITY_CONNECTION
+	           || nm_streq (name, NM_SETTING_CONNECTION_SETTING_NAME));
+
+	info = g_slice_new0 (SettingInfo);
+	info->type = type;
+	info->priority = priority;
+	info->name = name;
+	g_hash_table_insert (registered_settings, (void *) info->name, info);
+	g_hash_table_insert (registered_settings_by_type, &info->type, info);
+}
+
+static const SettingInfo *
+_nm_setting_lookup_setting_by_type (GType type)
+{
+	_ensure_registered ();
+	return g_hash_table_lookup (registered_settings_by_type, &type);
+}
+
 static NMSettingPriority
-_get_base_type_priority (const NMMetaSettingInfo *setting_info,
-                         GType gtype)
+_get_setting_type_priority (GType type)
 {
-	/* Historical oddity: PPPoE is a base-type even though it's not
-	 * priority 1.  It needs to be sorted *after* lower-level stuff like
-	 * Wi-Fi security or 802.1x for secrets, but it's still allowed as a
-	 * base type.
-	 */
+	const SettingInfo *info;
 
-	if (setting_info) {
-		if (   NM_IN_SET (setting_info->setting_priority,
-		                  NM_SETTING_PRIORITY_HW_BASE,
-		                  NM_SETTING_PRIORITY_HW_NON_BASE)
-		    || gtype == NM_TYPE_SETTING_PPPOE)
-			return setting_info->setting_priority;
-	}
+	g_return_val_if_fail (g_type_is_a (type, NM_TYPE_SETTING), G_MAXUINT32);
 
-	return NM_SETTING_PRIORITY_INVALID;
+	info = _nm_setting_lookup_setting_by_type (type);
+	return info->priority;
 }
 
 NMSettingPriority
 _nm_setting_get_setting_priority (NMSetting *setting)
 {
-	const NMMetaSettingInfo *setting_info;
-
-	g_return_val_if_fail (NM_IS_SETTING (setting), NM_SETTING_PRIORITY_INVALID);
+	NMSettingPrivate *priv;
 
-	setting_info = NM_SETTING_GET_CLASS (setting)->setting_info;
-	return setting_info ? setting_info->setting_priority : NM_SETTING_PRIORITY_INVALID;
+	g_return_val_if_fail (NM_IS_SETTING (setting), G_MAXUINT32);
+	priv = NM_SETTING_GET_PRIVATE (setting);
+	_ensure_setting_info (setting, priv);
+	return priv->info->priority;
 }
 
 NMSettingPriority
 _nm_setting_type_get_base_type_priority (GType type)
 {
-	return _get_base_type_priority (nm_meta_setting_infos_by_gtype (type),
-	                                type);
+	NMSettingPriority priority;
+
+	/* Historical oddity: PPPoE is a base-type even though it's not
+	 * priority 1.  It needs to be sorted *after* lower-level stuff like
+	 * Wi-Fi security or 802.1x for secrets, but it's still allowed as a
+	 * base type.
+	 */
+	priority = _get_setting_type_priority (type);
+	if (   NM_IN_SET (priority,
+	                  NM_SETTING_PRIORITY_HW_BASE,
+	                  NM_SETTING_PRIORITY_HW_NON_BASE)
+	    || type == NM_TYPE_SETTING_PPPOE)
+		return priority;
+	else
+		return NM_SETTING_PRIORITY_INVALID;
 }
 
 NMSettingPriority
 _nm_setting_get_base_type_priority (NMSetting *setting)
 {
-	g_return_val_if_fail (NM_IS_SETTING (setting), NM_SETTING_PRIORITY_INVALID);
-
-	return _get_base_type_priority (NM_SETTING_GET_CLASS (setting)->setting_info,
-	                                G_OBJECT_TYPE (setting));
+	return _nm_setting_type_get_base_type_priority (G_OBJECT_TYPE (setting));
 }
 
 /**
@@ -148,15 +218,17 @@ _nm_setting_get_base_type_priority (NMSetting *setting)
 GType
 nm_setting_lookup_type (const char *name)
 {
-	const NMMetaSettingInfo *setting_info;
+	const SettingInfo *info;
 
 	g_return_val_if_fail (name, G_TYPE_INVALID);
 
-	setting_info = nm_meta_setting_infos_by_name (name);
-	return setting_info ? setting_info->get_setting_gtype () : G_TYPE_INVALID;
+	_ensure_registered ();
+
+	info = g_hash_table_lookup (registered_settings, name);
+	return info ? info->type : G_TYPE_INVALID;
 }
 
-int
+gint
 _nm_setting_compare_priority (gconstpointer a, gconstpointer b)
 {
 	NMSettingPriority prio_a, prio_b;
@@ -201,53 +273,90 @@ _nm_setting_slave_type_is_valid (const char *slave_type, const char **out_port_t
 
 /*****************************************************************************/
 
-static const NMSettInfoProperty *
-_nm_sett_info_property_find_in_array (const NMSettInfoProperty *properties, guint len, const char *name)
+typedef struct {
+	const char *name;
+	GParamSpec *param_spec;
+	const GVariantType *dbus_type;
+
+	NMSettingPropertyGetFunc get_func;
+	NMSettingPropertySynthFunc synth_func;
+	NMSettingPropertySetFunc set_func;
+	NMSettingPropertyNotSetFunc not_set_func;
+
+	NMSettingPropertyTransformToFunc to_dbus;
+	NMSettingPropertyTransformFromFunc from_dbus;
+} NMSettingProperty;
+
+static NM_CACHED_QUARK_FCN ("nm-setting-property-overrides", setting_property_overrides_quark)
+static NM_CACHED_QUARK_FCN ("nm-setting-properties", setting_properties_quark)
+
+static NMSettingProperty *
+find_property (GArray *properties, const char *name)
 {
-	guint i;
+	NMSettingProperty *property;
+	int i;
 
-	for (i = 0; i < len; i++) {
-		if (nm_streq (name, properties[i].name))
-			return &properties[i];
+	if (!properties)
+		return NULL;
+
+	for (i = 0; i < properties->len; i++) {
+		property = &g_array_index (properties, NMSettingProperty, i);
+		if (strcmp (name, property->name) == 0)
+			return property;
 	}
+
 	return NULL;
 }
 
-void
-_properties_override_add_struct (GArray *properties_override,
-                                 const NMSettInfoProperty *prop_info)
+static void
+add_property_override (NMSettingClass *setting_class,
+                       const char *property_name,
+                       GParamSpec *param_spec,
+                       const GVariantType *dbus_type,
+                       NMSettingPropertyGetFunc get_func,
+                       NMSettingPropertySynthFunc synth_func,
+                       NMSettingPropertySetFunc set_func,
+                       NMSettingPropertyNotSetFunc not_set_func,
+                       NMSettingPropertyTransformToFunc to_dbus,
+                       NMSettingPropertyTransformFromFunc from_dbus)
 {
-	nm_assert (properties_override);
-	nm_assert (prop_info);
-	nm_assert (prop_info->name || prop_info->param_spec);
-	nm_assert (!prop_info->param_spec || !prop_info->name || nm_streq0 (prop_info->name, prop_info->param_spec->name));
-	nm_assert (!_nm_sett_info_property_find_in_array ((NMSettInfoProperty *) properties_override->data,
-	                                                  properties_override->len,
-	                                                  prop_info->name ?: prop_info->param_spec->name));
-
-	nm_assert (!prop_info->from_dbus || prop_info->dbus_type);
-	nm_assert (!prop_info->set_func || prop_info->dbus_type);
-
-	g_array_append_vals (properties_override, prop_info, 1);
-
-	if (!prop_info->name) {
-		/* for convenience, allow omitting "name" if "param_spec" is given. */
-		g_array_index (properties_override,
-		               NMSettInfoProperty,
-		               properties_override->len - 1).name = prop_info->param_spec->name;
+	GType setting_type = G_TYPE_FROM_CLASS (setting_class);
+	GArray *overrides;
+	NMSettingProperty override;
+
+	g_return_if_fail (g_type_get_qdata (setting_type, setting_properties_quark ()) == NULL);
+
+	memset (&override, 0, sizeof (override));
+	override.name = property_name;
+	override.param_spec = param_spec;
+	override.dbus_type = dbus_type;
+	override.get_func = get_func;
+	override.synth_func = synth_func;
+	override.set_func = set_func;
+	override.not_set_func = not_set_func;
+	override.to_dbus = to_dbus;
+	override.from_dbus = from_dbus;
+
+	overrides = g_type_get_qdata (setting_type, setting_property_overrides_quark ());
+	if (!overrides) {
+		overrides = g_array_new (FALSE, FALSE, sizeof (NMSettingProperty));
+		g_type_set_qdata (setting_type, setting_property_overrides_quark (), overrides);
 	}
+	g_return_if_fail (find_property (overrides, property_name) == NULL);
+
+	g_array_append_val (overrides, override);
 }
 
 /**
- * _properties_override_add_dbus_only:
- * @properties_override: an array collecting the overrides
+ * _nm_setting_class_add_dbus_only_property:
+ * @setting_class: the setting class
  * @property_name: the name of the property to override
  * @dbus_type: the type of the property (in its D-Bus representation)
  * @synth_func: (allow-none): function to call to synthesize a value for the property
  * @set_func: (allow-none): function to call to set the value of the property
  *
  * Registers a property named @property_name, which will be used in the D-Bus
- * serialization of objects of this setting type, but which does not correspond to
+ * serialization of objects of @setting_class, but which does not correspond to
  * a #GObject property.
  *
  * When serializing a setting to D-Bus, @synth_func will be called to synthesize
@@ -260,30 +369,35 @@ _properties_override_add_struct (GArray *properties_override,
  * then the property will be ignored when deserializing.)
  */
 void
-_properties_override_add_dbus_only (GArray *properties_override,
-                                    const char *property_name,
-                                    const GVariantType *dbus_type,
-                                    NMSettingPropertySynthFunc synth_func,
-                                    NMSettingPropertySetFunc set_func)
+_nm_setting_class_add_dbus_only_property (NMSettingClass *setting_class,
+                                          const char *property_name,
+                                          const GVariantType *dbus_type,
+                                          NMSettingPropertySynthFunc synth_func,
+                                          NMSettingPropertySetFunc set_func)
 {
-	_properties_override_add (properties_override,
-	                          .name = property_name,
-	                          .dbus_type = dbus_type,
-	                          .synth_func = synth_func,
-	                          .set_func = set_func);
+	g_return_if_fail (NM_IS_SETTING_CLASS (setting_class));
+	g_return_if_fail (property_name != NULL);
+
+	/* Must not match any GObject property. */
+	g_return_if_fail (!g_object_class_find_property (G_OBJECT_CLASS (setting_class), property_name));
+
+	add_property_override (setting_class,
+	                       property_name, NULL, dbus_type,
+	                       NULL, synth_func, set_func, NULL,
+	                       NULL, NULL);
 }
 
 /**
- * _properties_override_add_override:
- * @properties_override: an array collecting the overrides
- * @param_spec: the name of the property to override
+ * _nm_setting_class_override_property:
+ * @setting_class: the setting class
+ * @property_name: the name of the property to override
  * @dbus_type: the type of the property (in its D-Bus representation)
  * @get_func: (allow-none): function to call to get the value of the property
  * @set_func: (allow-none): function to call to set the value of the property
  * @not_set_func: (allow-none): function to call to indicate the property was not set
  *
- * Overrides the D-Bus representation of the #GObject property that shares the
- * same name as @param_spec.
+ * Overrides the D-Bus representation of the #GObject property named
+ * @property_name on @setting_class.
  *
  * When serializing a setting to D-Bus, if @get_func is non-%NULL, then it will
  * be called to get the property's value. If it returns a #GVariant, the
@@ -292,38 +406,38 @@ _properties_override_add_dbus_only (GArray *properties_override,
  * with g_object_get_property(), and added to the hash if it is not the default
  * value.)
  *
- * When deserializing a D-Bus representation into a setting, if a value with
- * the name of @param_spec is present, then @set_func will be called to set it.
- * (If @set_func is %NULL then the property will be set normally with
- * g_object_set_property().)
+ * When deserializing a D-Bus representation into a setting, if @property_name
+ * is present, then @set_func will be called to set it. (If @set_func is %NULL
+ * then the property will be set normally with g_object_set_property().)
  *
  * If @not_set_func is non-%NULL, then it will be called when deserializing a
- * representation that does NOT contain a value for the property. This can be used,
- * eg, if a new property needs to be initialized from some older deprecated property
+ * representation that does NOT contain @property_name. This can be used, eg, if
+ * a new property needs to be initialized from some older deprecated property
  * when it is not present.
  */
 void
-_properties_override_add_override (GArray *properties_override,
-                                   GParamSpec *param_spec,
-                                   const GVariantType *dbus_type,
-                                   NMSettingPropertyGetFunc get_func,
-                                   NMSettingPropertySetFunc set_func,
-                                   NMSettingPropertyNotSetFunc not_set_func)
+_nm_setting_class_override_property (NMSettingClass *setting_class,
+                                     const char *property_name,
+                                     const GVariantType *dbus_type,
+                                     NMSettingPropertyGetFunc get_func,
+                                     NMSettingPropertySetFunc set_func,
+                                     NMSettingPropertyNotSetFunc not_set_func)
 {
-	nm_assert (param_spec);
-
-	_properties_override_add (properties_override,
-	                          .param_spec = param_spec,
-	                          .dbus_type = dbus_type,
-	                          .get_func = get_func,
-	                          .set_func = set_func,
-	                          .not_set_func = not_set_func);
+	GParamSpec *param_spec;
+
+	param_spec = g_object_class_find_property (G_OBJECT_CLASS (setting_class), property_name);
+	g_return_if_fail (param_spec != NULL);
+
+	add_property_override (setting_class,
+	                       property_name, param_spec, dbus_type,
+	                       get_func, NULL, set_func, not_set_func,
+	                       NULL, NULL);
 }
 
 /**
- * _properties_override_add_transform:
- * @properties_override: an array collecting the overrides
- * @param_spec: the param spec of the property to transform.
+ * _nm_setting_class_transform_property:
+ * @setting_class: the setting class
+ * @property: the name of the property to transform
  * @dbus_type: the type of the property (in its D-Bus representation)
  * @to_dbus: function to convert from object to D-Bus format
  * @from_dbus: function to convert from D-Bus to object format
@@ -337,143 +451,23 @@ _properties_override_add_override (GArray *properties_override,
  * nm_property_compare() recognizes, as long as it recognizes @dbus_type.
  */
 void
-_properties_override_add_transform (GArray *properties_override,
-                                    GParamSpec *param_spec,
-                                    const GVariantType *dbus_type,
-                                    NMSettingPropertyTransformToFunc to_dbus,
-                                    NMSettingPropertyTransformFromFunc from_dbus)
-{
-	nm_assert (param_spec);
-
-	_properties_override_add (properties_override,
-	                          .param_spec = param_spec,
-	                          .dbus_type = dbus_type,
-	                          .to_dbus = to_dbus,
-	                          .from_dbus = from_dbus);
-}
-
-static NMSettInfoSetting _sett_info_settings[_NM_META_SETTING_TYPE_NUM];
-
-void
-_nm_setting_class_commit_full (NMSettingClass *setting_class,
-                               NMMetaSettingType meta_type,
-                               const NMSettInfoSettDetail *detail,
-                               GArray *properties_override)
-{
-	NMSettInfoSetting *sett_info;
-	gs_free GParamSpec **property_specs = NULL;
-	guint i, n_property_specs, override_len;
-
-	nm_assert (NM_IS_SETTING_CLASS (setting_class));
-	nm_assert (!setting_class->setting_info);
-
-	nm_assert (meta_type < G_N_ELEMENTS (_sett_info_settings));
-
-	sett_info = &_sett_info_settings[meta_type];
-
-	nm_assert (!sett_info->setting_class);
-	nm_assert (!sett_info->property_infos_len);
-	nm_assert (!sett_info->property_infos);
-
-	if (!properties_override) {
-		override_len = 0;
-		properties_override = _nm_sett_info_property_override_create_array ();
-	} else
-		override_len = properties_override->len;
-
-	property_specs = g_object_class_list_properties (G_OBJECT_CLASS (setting_class),
-	                                                 &n_property_specs);
-
-#if NM_MORE_ASSERTS > 10
-	/* assert that properties_override is constructed consistently. */
-	for (i = 0; i < override_len; i++) {
-		guint j;
-		const NMSettInfoProperty *p = &g_array_index (properties_override, NMSettInfoProperty, i);
-
-		nm_assert (!_nm_sett_info_property_find_in_array ((NMSettInfoProperty *) properties_override->data,
-		                                                  i,
-		                                                  p->name));
-		for (j = 0; j < n_property_specs; j++) {
-			if (nm_streq (property_specs[j]->name, p->name)) {
-				nm_assert (p->param_spec == property_specs[j]);
-				break;
-			}
-		}
-		nm_assert ((j == n_property_specs) == (p->param_spec == NULL));
-	}
-#endif
-
-	for (i = 0; i < n_property_specs; i++) {
-		const char *name = property_specs[i]->name;
-		NMSettInfoProperty *p;
-
-		if (_nm_sett_info_property_find_in_array ((NMSettInfoProperty *) properties_override->data,
-		                                           override_len,
-		                                           name))
-			continue;
-
-		g_array_set_size (properties_override, properties_override->len + 1);
-		p = &g_array_index (properties_override, NMSettInfoProperty, properties_override->len - 1);
-		memset (p, 0, sizeof (*p));
-		p->name = name;
-		p->param_spec = property_specs[i];
-	}
-
-	G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (NMSettInfoProperty, name) == 0);
-	g_array_sort (properties_override, nm_strcmp_p);
-
-	setting_class->setting_info = &nm_meta_setting_infos[meta_type];
-	sett_info->setting_class = setting_class;
-	if (detail)
-		sett_info->detail = *detail;
-	sett_info->property_infos_len = properties_override->len;
-	sett_info->property_infos = (const NMSettInfoProperty *) g_array_free (properties_override,
-	                                                                       properties_override->len == 0);
-}
-
-const NMSettInfoSetting *
-_nm_sett_info_setting_get (NMSettingClass *setting_class)
+_nm_setting_class_transform_property (NMSettingClass *setting_class,
+                                      const char *property,
+                                      const GVariantType *dbus_type,
+                                      NMSettingPropertyTransformToFunc to_dbus,
+                                      NMSettingPropertyTransformFromFunc from_dbus)
 {
-	if (   NM_IS_SETTING_CLASS (setting_class)
-	    && setting_class->setting_info) {
-		nm_assert (setting_class->setting_info->meta_type < G_N_ELEMENTS (_sett_info_settings));
-		return &_sett_info_settings[setting_class->setting_info->meta_type];
-	}
-	return NULL;
-}
-
-const NMSettInfoProperty *
-_nm_sett_info_property_get (NMSettingClass *setting_class,
-                            const char *property_name)
-{
-	const NMSettInfoSetting *sett_info = _nm_sett_info_setting_get (setting_class);
-	const NMSettInfoProperty *property;
-	gssize idx;
-
-	if (!sett_info)
-		return NULL;
-
-	G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (NMSettInfoProperty, name) == 0);
-	idx = nm_utils_array_find_binary_search (sett_info->property_infos,
-	                                         sizeof (NMSettInfoProperty),
-	                                         sett_info->property_infos_len,
-	                                         &property_name,
-	                                         nm_strcmp_p_with_data,
-	                                         NULL);
-
-	if (idx < 0)
-		return NULL;
-
-	property = &sett_info->property_infos[idx];
+	GParamSpec *param_spec;
 
-	nm_assert (idx == 0 || strcmp (property[-1].name, property[0].name) < 0);
-	nm_assert (idx == sett_info->property_infos_len - 1 || strcmp (property[0].name, property[1].name) < 0);
+	param_spec = g_object_class_find_property (G_OBJECT_CLASS (setting_class), property);
+	g_return_if_fail (param_spec != NULL);
 
-	return property;
+	add_property_override (setting_class,
+	                       property, param_spec, dbus_type,
+	                       NULL, NULL, NULL, NULL,
+	                       to_dbus, from_dbus);
 }
 
-/*****************************************************************************/
-
 gboolean
 _nm_setting_use_legacy_property (NMSetting *setting,
                                  GVariant *connection_dict,
@@ -510,6 +504,77 @@ _nm_setting_use_legacy_property (NMSetting *setting,
 		return FALSE;
 }
 
+static GArray *
+nm_setting_class_ensure_properties (NMSettingClass *setting_class)
+{
+	GType type = G_TYPE_FROM_CLASS (setting_class), otype;
+	NMSettingProperty property, *override;
+	GArray *overrides, *type_overrides, *properties;
+	GParamSpec **property_specs;
+	guint n_property_specs, i;
+
+	properties = g_type_get_qdata (type, setting_properties_quark ());
+	if (properties)
+		return properties;
+
+	/* Build overrides array from @setting_class and its superclasses */
+	overrides = g_array_new (FALSE, FALSE, sizeof (NMSettingProperty));
+	for (otype = type; otype != G_TYPE_OBJECT; otype = g_type_parent (otype)) {
+		type_overrides = g_type_get_qdata (otype, setting_property_overrides_quark ());
+		if (type_overrides)
+			g_array_append_vals (overrides, (NMSettingProperty *)type_overrides->data, type_overrides->len);
+	}
+
+	/* Build the properties array from the GParamSpecs, obeying overrides */
+	properties = g_array_new (FALSE, FALSE, sizeof (NMSettingProperty));
+
+	property_specs = g_object_class_list_properties (G_OBJECT_CLASS (setting_class),
+	                                                 &n_property_specs);
+	for (i = 0; i < n_property_specs; i++) {
+		override = find_property (overrides, property_specs[i]->name);
+		if (override)
+			property = *override;
+		else {
+			memset (&property, 0, sizeof (property));
+			property.name = property_specs[i]->name;
+			property.param_spec = property_specs[i];
+		}
+		g_array_append_val (properties, property);
+	}
+	g_free (property_specs);
+
+	/* Add any remaining overrides not corresponding to GObject properties */
+	for (i = 0; i < overrides->len; i++) {
+		override = &g_array_index (overrides, NMSettingProperty, i);
+		if (!g_object_class_find_property (G_OBJECT_CLASS (setting_class), override->name))
+			g_array_append_val (properties, *override);
+	}
+	g_array_unref (overrides);
+
+	g_type_set_qdata (type, setting_properties_quark (), properties);
+	return properties;
+}
+
+static const NMSettingProperty *
+nm_setting_class_get_properties (NMSettingClass *setting_class, guint *n_properties)
+{
+	GArray *properties;
+
+	properties = nm_setting_class_ensure_properties (setting_class);
+
+	*n_properties = properties->len;
+	return (NMSettingProperty *) properties->data;
+}
+
+static const NMSettingProperty *
+nm_setting_class_find_property (NMSettingClass *setting_class, const char *property_name)
+{
+	GArray *properties;
+
+	properties = nm_setting_class_ensure_properties (setting_class);
+	return find_property (properties, property_name);
+}
+
 /*****************************************************************************/
 
 static const GVariantType *
@@ -545,7 +610,7 @@ variant_type_for_gtype (GType type)
 
 static GVariant *
 get_property_for_dbus (NMSetting *setting,
-                       const NMSettInfoProperty *property,
+                       const NMSettingProperty *property,
                        gboolean ignore_default)
 {
 	GValue prop_value = { 0, };
@@ -573,7 +638,7 @@ get_property_for_dbus (NMSetting *setting,
 	else if (g_type_is_a (prop_value.g_type, G_TYPE_FLAGS))
 		dbus_value = g_variant_new_uint32 (g_value_get_flags (&prop_value));
 	else if (prop_value.g_type == G_TYPE_BYTES)
-		dbus_value = nm_utils_gbytes_to_variant_ay (g_value_get_boxed (&prop_value));
+		dbus_value = _nm_utils_bytes_to_dbus (&prop_value);
 	else
 		dbus_value = g_dbus_gvalue_to_gvariant (&prop_value, variant_type_for_gtype (prop_value.g_type));
 	g_value_unset (&prop_value);
@@ -582,7 +647,7 @@ get_property_for_dbus (NMSetting *setting,
 }
 
 static gboolean
-set_property_from_dbus (const NMSettInfoProperty *property,
+set_property_from_dbus (const NMSettingProperty *property,
                         GVariant *src_value,
                         GValue *dst_value)
 {
@@ -633,57 +698,40 @@ set_property_from_dbus (const NMSettInfoProperty *property,
 GVariant *
 _nm_setting_to_dbus (NMSetting *setting, NMConnection *connection, NMConnectionSerializationFlags flags)
 {
-	NMSettingPrivate *priv;
 	GVariantBuilder builder;
 	GVariant *dbus_value;
-	const NMSettInfoSetting *sett_info;
+	const NMSettingProperty *properties;
 	guint n_properties, i;
-	const char *const*gendata_keys;
 
 	g_return_val_if_fail (NM_IS_SETTING (setting), NULL);
 
-	priv = NM_SETTING_GET_PRIVATE (setting);
+	properties = nm_setting_class_get_properties (NM_SETTING_GET_CLASS (setting), &n_properties);
 
 	g_variant_builder_init (&builder, NM_VARIANT_TYPE_SETTING);
 
-	n_properties = _nm_setting_gendata_get_all (setting, &gendata_keys, NULL);
 	for (i = 0; i < n_properties; i++) {
-		g_variant_builder_add (&builder,
-		                       "{sv}",
-		                       gendata_keys[i],
-		                       g_hash_table_lookup (priv->gendata->hash, gendata_keys[i]));
-	}
-
-	sett_info = _nm_sett_info_setting_get (NM_SETTING_GET_CLASS (setting));
-	for (i = 0; i < sett_info->property_infos_len; i++) {
-		const NMSettInfoProperty *property = &sett_info->property_infos[i];
+		const NMSettingProperty *property = &properties[i];
 		GParamSpec *prop_spec = property->param_spec;
 
-		if (!prop_spec) {
-			if (!property->synth_func)
-				continue;
-
-			if (flags & NM_CONNECTION_SERIALIZE_ONLY_SECRETS)
-				continue;
-		} else {
-			if (!(prop_spec->flags & G_PARAM_WRITABLE))
-				continue;
+		if (!prop_spec && !property->synth_func) {
+			/* D-Bus-only property with no synth_func, so we skip it. */
+			continue;
+		}
 
-			if (NM_FLAGS_ANY (prop_spec->flags, NM_SETTING_PARAM_GENDATA_BACKED))
-				continue;
+		if (prop_spec && !(prop_spec->flags & G_PARAM_WRITABLE))
+			continue;
 
-			if (   (prop_spec->flags & NM_SETTING_PARAM_LEGACY)
-			    && !_nm_utils_is_manager_process)
-				continue;
+		if (   prop_spec && (prop_spec->flags & NM_SETTING_PARAM_LEGACY)
+		    && !_nm_utils_is_manager_process)
+			continue;
 
-			if (   (flags & NM_CONNECTION_SERIALIZE_NO_SECRETS)
-			    && (prop_spec->flags & NM_SETTING_PARAM_SECRET))
-				continue;
+		if (   (flags & NM_CONNECTION_SERIALIZE_NO_SECRETS)
+		    && (prop_spec && (prop_spec->flags & NM_SETTING_PARAM_SECRET)))
+			continue;
 
-			if (   (flags & NM_CONNECTION_SERIALIZE_ONLY_SECRETS)
-			    && !(prop_spec->flags & NM_SETTING_PARAM_SECRET))
-				continue;
-		}
+		if (   (flags & NM_CONNECTION_SERIALIZE_ONLY_SECRETS)
+		    && !(prop_spec && (prop_spec->flags & NM_SETTING_PARAM_SECRET)))
+			continue;
 
 		if (property->synth_func)
 			dbus_value = property->synth_func (setting, connection, property->name);
@@ -730,8 +778,8 @@ _nm_setting_new_from_dbus (GType setting_type,
 {
 	gs_unref_object NMSetting *setting = NULL;
 	gs_unref_hashtable GHashTable *keys = NULL;
-	const NMSettInfoSetting *sett_info;
-	guint i;
+	const NMSettingProperty *properties;
+	guint i, n_properties;
 
 	g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (setting_type), NULL);
 	g_return_val_if_fail (g_variant_is_of_type (setting_dict, NM_VARIANT_TYPE_SETTING), NULL);
@@ -775,29 +823,9 @@ _nm_setting_new_from_dbus (GType setting_type,
 		}
 	}
 
-	sett_info = _nm_sett_info_setting_get (NM_SETTING_GET_CLASS (setting));
-
-	if (sett_info->detail.gendata_info) {
-		GHashTable *hash;
-		GVariantIter iter;
-		char *key;
-		GVariant *val;
-
-		hash = _gendata_hash (setting, TRUE)->hash;
-
-		g_variant_iter_init (&iter, setting_dict);
-		while (g_variant_iter_next (&iter, "{sv}", &key, &val)) {
-			g_hash_table_insert (hash,
-			                     key,
-			                     val);
-		}
-
-		_nm_setting_gendata_notify (setting, TRUE);
-		return g_steal_pointer (&setting);
-	}
-
-	for (i = 0; i < sett_info->property_infos_len; i++) {
-		const NMSettInfoProperty *property = &sett_info->property_infos[i];
+	properties = nm_setting_class_get_properties (NM_SETTING_GET_CLASS (setting), &n_properties);
+	for (i = 0; i < n_properties; i++) {
+		const NMSettingProperty *property = &properties[i];
 		gs_unref_variant GVariant *value = NULL;
 		gs_free_error GError *local = NULL;
 
@@ -916,12 +944,12 @@ const GVariantType *
 nm_setting_get_dbus_property_type (NMSetting *setting,
                                    const char *property_name)
 {
-	const NMSettInfoProperty *property;
+	const NMSettingProperty *property;
 
 	g_return_val_if_fail (NM_IS_SETTING (setting), NULL);
 	g_return_val_if_fail (property_name != NULL, NULL);
 
-	property = _nm_sett_info_property_get (NM_SETTING_GET_CLASS (setting), property_name);
+	property = nm_setting_class_find_property (NM_SETTING_GET_CLASS (setting), property_name);
 	g_return_val_if_fail (property != NULL, NULL);
 
 	if (property->dbus_type)
@@ -933,32 +961,14 @@ nm_setting_get_dbus_property_type (NMSetting *setting,
 gboolean
 _nm_setting_get_property (NMSetting *setting, const char *property_name, GValue *value)
 {
-	const NMSettInfoSetting *sett_info;
 	GParamSpec *prop_spec;
 
 	g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
 	g_return_val_if_fail (property_name, FALSE);
 	g_return_val_if_fail (value, FALSE);
 
-	sett_info = _nm_sett_info_setting_get (NM_SETTING_GET_CLASS (setting));
-
-	if (sett_info->detail.gendata_info) {
-		GVariant *variant;
-		GenData *gendata = _gendata_hash (setting, FALSE);
-
-		variant = gendata ? g_hash_table_lookup (gendata->hash, property_name) : NULL;
-
-		if (!variant) {
-			g_value_unset (value);
-			return FALSE;
-		}
-
-		g_value_init (value, G_TYPE_VARIANT);
-		g_value_set_variant (value, variant);
-		return TRUE;
-	}
-
 	prop_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (setting), property_name);
+
 	if (!prop_spec) {
 		g_value_unset (value);
 		return FALSE;
@@ -992,37 +1002,16 @@ duplicate_setting (NMSetting *setting,
 NMSetting *
 nm_setting_duplicate (NMSetting *setting)
 {
-	const NMSettInfoSetting *sett_info;
 	GObject *dup;
 
 	g_return_val_if_fail (NM_IS_SETTING (setting), NULL);
 
 	dup = g_object_new (G_OBJECT_TYPE (setting), NULL);
 
-	sett_info = _nm_sett_info_setting_get (NM_SETTING_GET_CLASS (setting));
-
-	if (sett_info->detail.gendata_info) {
-		GenData *gendata = _gendata_hash (setting, FALSE);
-
-		if (   gendata
-		    && g_hash_table_size (gendata->hash) > 0) {
-			GHashTableIter iter;
-			GHashTable *h = _gendata_hash (NM_SETTING (dup), TRUE)->hash;
-			const char *key;
-			GVariant *val;
+	g_object_freeze_notify (dup);
+	nm_setting_enumerate_values (setting, duplicate_setting, dup);
+	g_object_thaw_notify (dup);
 
-			g_hash_table_iter_init (&iter, gendata->hash);
-			while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &val)) {
-				g_hash_table_insert (h,
-				                     g_strdup (key),
-				                     g_variant_ref (val));
-			}
-		}
-	} else {
-		g_object_freeze_notify (dup);
-		nm_setting_enumerate_values (setting, duplicate_setting, dup);
-		g_object_thaw_notify (dup);
-	}
 	return NM_SETTING (dup);
 }
 
@@ -1038,12 +1027,12 @@ nm_setting_duplicate (NMSetting *setting)
 const char *
 nm_setting_get_name (NMSetting *setting)
 {
-	const NMMetaSettingInfo *setting_info;
+	NMSettingPrivate *priv;
 
 	g_return_val_if_fail (NM_IS_SETTING (setting), NULL);
-
-	setting_info = NM_SETTING_GET_CLASS (setting)->setting_info;
-	return setting_info ? setting_info->setting_name : NULL;
+	priv = NM_SETTING_GET_PRIVATE (setting);
+	_ensure_setting_info (setting, priv);
+	return priv->info->name;
 }
 
 /**
@@ -1137,7 +1126,7 @@ compare_property (NMSetting *setting,
                   const GParamSpec *prop_spec,
                   NMSettingCompareFlags flags)
 {
-	const NMSettInfoProperty *property;
+	const NMSettingProperty *property;
 	GVariant *value1, *value2;
 	int cmp;
 
@@ -1169,7 +1158,7 @@ compare_property (NMSetting *setting,
 			return TRUE;
 	}
 
-	property = _nm_sett_info_property_get (NM_SETTING_GET_CLASS (setting), prop_spec->name);
+	property = nm_setting_class_find_property (NM_SETTING_GET_CLASS (setting), prop_spec->name);
 	g_return_val_if_fail (property != NULL, FALSE);
 
 	value1 = get_property_for_dbus (setting, property, TRUE);
@@ -1202,10 +1191,9 @@ nm_setting_compare (NMSetting *a,
                     NMSetting *b,
                     NMSettingCompareFlags flags)
 {
-	const NMSettInfoSetting *sett_info;
 	GParamSpec **property_specs;
 	guint n_property_specs;
-	int same = TRUE;
+	gint same = TRUE;
 	guint i;
 
 	g_return_val_if_fail (NM_IS_SETTING (a), FALSE);
@@ -1215,18 +1203,6 @@ nm_setting_compare (NMSetting *a,
 	if (G_OBJECT_TYPE (a) != G_OBJECT_TYPE (b))
 		return FALSE;
 
-	sett_info = _nm_sett_info_setting_get (NM_SETTING_GET_CLASS (a));
-
-	if (sett_info->detail.gendata_info) {
-		GenData *a_gendata = _gendata_hash (a, FALSE);
-		GenData *b_gendata = _gendata_hash (b, FALSE);
-
-		return nm_utils_hash_table_equal (a_gendata ? a_gendata->hash : NULL,
-		                                  b_gendata ? b_gendata->hash : NULL,
-		                                  TRUE,
-		                                  g_variant_equal);
-	}
-
 	/* And now all properties */
 	property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (a), &n_property_specs);
 	for (i = 0; i < n_property_specs && same; i++) {
@@ -1312,21 +1288,6 @@ should_compare_prop (NMSetting *setting,
 	return TRUE;
 }
 
-static void
-_setting_diff_add_result (GHashTable *results, const char *prop_name, NMSettingDiffResult r)
-{
-	void *p;
-
-	if (r == NM_SETTING_DIFF_RESULT_UNKNOWN)
-		return;
-
-	if (g_hash_table_lookup_extended (results, prop_name, NULL, &p)) {
-		if (!NM_FLAGS_ALL ((guint) r, GPOINTER_TO_UINT (p)))
-			g_hash_table_insert (results, g_strdup (prop_name), GUINT_TO_POINTER (((guint) r) | GPOINTER_TO_UINT (p)));
-	} else
-		g_hash_table_insert (results, g_strdup (prop_name), GUINT_TO_POINTER (r));
-}
-
 /**
  * nm_setting_diff:
  * @a: a #NMSetting
@@ -1355,7 +1316,8 @@ nm_setting_diff (NMSetting *a,
                  gboolean invert_results,
                  GHashTable **results)
 {
-	const NMSettInfoSetting *sett_info;
+	GParamSpec **property_specs;
+	guint n_property_specs;
 	guint i;
 	NMSettingDiffResult a_result = NM_SETTING_DIFF_RESULT_IN_A;
 	NMSettingDiffResult b_result = NM_SETTING_DIFF_RESULT_IN_B;
@@ -1399,117 +1361,78 @@ nm_setting_diff (NMSetting *a,
 		results_created = TRUE;
 	}
 
-	sett_info = _nm_sett_info_setting_get (NM_SETTING_GET_CLASS (a));
+	/* And now all properties */
+	property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (a), &n_property_specs);
 
-	if (sett_info->detail.gendata_info) {
-		const char *key;
-		GVariant *val, *val2;
-		GHashTableIter iter;
-		GenData *a_gendata = _gendata_hash (a, FALSE);
-		GenData *b_gendata = b ? _gendata_hash (b, FALSE) : NULL;
-
-		if (!a_gendata || !b_gendata) {
-			if (a_gendata || b_gendata) {
-				NMSettingDiffResult one_sided_result;
-
-				one_sided_result = a_gendata ? a_result : b_result;
-				g_hash_table_iter_init (&iter, a_gendata ? a_gendata->hash : b_gendata->hash);
-				while (g_hash_table_iter_next (&iter, (gpointer *) &key, NULL)) {
-					diff_found = TRUE;
-					_setting_diff_add_result (*results, key, one_sided_result);
-				}
-			}
-		} else {
-			g_hash_table_iter_init (&iter, a_gendata->hash);
-			while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &val)) {
-				val2 = b_gendata ? g_hash_table_lookup (b_gendata->hash, key) : NULL;
-				compared_any = TRUE;
-				if (   !val2
-				    || !g_variant_equal (val, val2)) {
-					diff_found = TRUE;
-					_setting_diff_add_result (*results, key, a_result);
-				}
-			}
-			g_hash_table_iter_init (&iter, b_gendata->hash);
-			while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &val)) {
-				val2 = a_gendata ? g_hash_table_lookup (a_gendata->hash, key) : NULL;
-				compared_any = TRUE;
-				if (   !val2
-				    || !g_variant_equal (val, val2)) {
-					diff_found = TRUE;
-					_setting_diff_add_result (*results, key, b_result);
-				}
-			}
-		}
-	} else {
-		gs_free GParamSpec **property_specs = NULL;
-		guint n_property_specs;
-
-		property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (a), &n_property_specs);
-
-		for (i = 0; i < n_property_specs; i++) {
-			GParamSpec *prop_spec = property_specs[i];
-			NMSettingDiffResult r = NM_SETTING_DIFF_RESULT_UNKNOWN;
-
-			/* Handle compare flags */
-			if (!should_compare_prop (a, prop_spec->name, flags, prop_spec->flags))
-				continue;
-			if (strcmp (prop_spec->name, NM_SETTING_NAME) == 0)
-				continue;
-
-			compared_any = TRUE;
-
-			if (b) {
-				gboolean different;
-
-				different = !NM_SETTING_GET_CLASS (a)->compare_property (a, b, prop_spec, flags);
-				if (different) {
-					gboolean a_is_default, b_is_default;
-					GValue value = G_VALUE_INIT;
-
-					g_value_init (&value, prop_spec->value_type);
-					g_object_get_property (G_OBJECT (a), prop_spec->name, &value);
-					a_is_default = g_param_value_defaults (prop_spec, &value);
-
-					g_value_reset (&value);
-					g_object_get_property (G_OBJECT (b), prop_spec->name, &value);
-					b_is_default = g_param_value_defaults (prop_spec, &value);
-
-					g_value_unset (&value);
-					if ((flags & NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT) == 0) {
-						if (!a_is_default)
-							r |= a_result;
-						if (!b_is_default)
-							r |= b_result;
-					} else {
-						r |= a_result | b_result;
-						if (a_is_default)
-							r |= a_result_default;
-						if (b_is_default)
-							r |= b_result_default;
-					}
-				}
-			} else if ((flags & (NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT | NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT)) == 0)
-				r = a_result;  /* only in A */
-			else {
+	for (i = 0; i < n_property_specs; i++) {
+		GParamSpec *prop_spec = property_specs[i];
+		NMSettingDiffResult r = NM_SETTING_DIFF_RESULT_UNKNOWN;
+
+		/* Handle compare flags */
+		if (!should_compare_prop (a, prop_spec->name, flags, prop_spec->flags))
+			continue;
+		if (strcmp (prop_spec->name, NM_SETTING_NAME) == 0)
+			continue;
+
+		compared_any = TRUE;
+
+		if (b) {
+			gboolean different;
+
+			different = !NM_SETTING_GET_CLASS (a)->compare_property (a, b, prop_spec, flags);
+			if (different) {
+				gboolean a_is_default, b_is_default;
 				GValue value = G_VALUE_INIT;
 
 				g_value_init (&value, prop_spec->value_type);
 				g_object_get_property (G_OBJECT (a), prop_spec->name, &value);
-				if (!g_param_value_defaults (prop_spec, &value))
-					r |= a_result;
-				else if (flags & NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT)
-					r |= a_result | a_result_default;
+				a_is_default = g_param_value_defaults (prop_spec, &value);
+
+				g_value_reset (&value);
+				g_object_get_property (G_OBJECT (b), prop_spec->name, &value);
+				b_is_default = g_param_value_defaults (prop_spec, &value);
 
 				g_value_unset (&value);
+				if ((flags & NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT) == 0) {
+					if (!a_is_default)
+						r |= a_result;
+					if (!b_is_default)
+						r |= b_result;
+				} else {
+					r |= a_result | b_result;
+					if (a_is_default)
+						r |= a_result_default;
+					if (b_is_default)
+						r |= b_result_default;
+				}
 			}
+		} else if ((flags & (NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT | NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT)) == 0)
+			r = a_result;  /* only in A */
+		else {
+			GValue value = G_VALUE_INIT;
 
-			if (r != NM_SETTING_DIFF_RESULT_UNKNOWN) {
-				diff_found = TRUE;
-				_setting_diff_add_result (*results, prop_spec->name, r);
-			}
+			g_value_init (&value, prop_spec->value_type);
+			g_object_get_property (G_OBJECT (a), prop_spec->name, &value);
+			if (!g_param_value_defaults (prop_spec, &value))
+				r |= a_result;
+			else if (flags & NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT)
+				r |= a_result | a_result_default;
+
+			g_value_unset (&value);
+		}
+
+		if (r != NM_SETTING_DIFF_RESULT_UNKNOWN) {
+			void *p;
+
+			diff_found = TRUE;
+			if (g_hash_table_lookup_extended (*results, prop_spec->name, NULL, &p)) {
+				if ((r & GPOINTER_TO_UINT (p)) != r)
+					g_hash_table_insert (*results, g_strdup (prop_spec->name), GUINT_TO_POINTER (r | GPOINTER_TO_UINT (p)));
+			} else
+				g_hash_table_insert (*results, g_strdup (prop_spec->name), GUINT_TO_POINTER (r));
 		}
 	}
+	g_free (property_specs);
 
 	if (!compared_any && !b) {
 		/* special case: the setting has no properties, and the opposite
@@ -1520,7 +1443,7 @@ nm_setting_diff (NMSetting *a,
 
 	if (diff_found) {
 		/* if there is a difference, we always return FALSE. It also means, we might
-		 * have allocated a new @results hash, and return it to the caller. */
+		 * have allocated a new @results hash, and return if to the caller. */
 		return FALSE;
 	} else {
 		if (results_created) {
@@ -1576,57 +1499,23 @@ nm_setting_enumerate_values (NMSetting *setting,
                              NMSettingValueIterFn func,
                              gpointer user_data)
 {
-	const NMSettInfoSetting *sett_info;
 	GParamSpec **property_specs;
-	guint n_properties;
-	guint i;
+	guint n_property_specs;
+	int i;
 	GType type;
 
 	g_return_if_fail (NM_IS_SETTING (setting));
 	g_return_if_fail (func != NULL);
 
-	sett_info = _nm_sett_info_setting_get (NM_SETTING_GET_CLASS (setting));
-
-	if (sett_info->detail.gendata_info) {
-		const char *const*names;
-
-		/* the properties of this setting are not real GObject properties.
-		 * Hence, this API makes little sense (or does it?). Still, call
-		 * @func with each value. */
-		n_properties = _nm_setting_gendata_get_all (setting, &names, NULL);
-		if (n_properties > 0) {
-			gs_strfreev char **keys = g_strdupv ((char **) names);
-			GHashTable *h = _gendata_hash (setting, FALSE)->hash;
-
-			for (i = 0; i < n_properties; i++) {
-				GValue value = G_VALUE_INIT;
-				GVariant *val = g_hash_table_lookup (h, keys[i]);
-
-				if (!val) {
-					/* was deleted in the meantime? Skip */
-					continue;
-				}
-
-				g_value_init (&value, G_TYPE_VARIANT);
-				g_value_set_variant (&value, val);
-				/* call it will GParamFlags 0. It shall indicate that this
-				 * is not a "real" GObject property. */
-				func (setting, keys[i], &value, 0, user_data);
-				g_value_unset (&value);
-			}
-		}
-		return;
-	}
-
-	property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_properties);
+	property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_property_specs);
 
 	/* sort the properties. This has an effect on the order in which keyfile
 	 * prints them. */
 	type = G_OBJECT_TYPE (setting);
-	g_qsort_with_data (property_specs, n_properties, sizeof (gpointer),
+	g_qsort_with_data (property_specs, n_property_specs, sizeof (gpointer),
 	                   (GCompareDataFunc) _enumerate_values_sort, &type);
 
-	for (i = 0; i < n_properties; i++) {
+	for (i = 0; i < n_property_specs; i++) {
 		GParamSpec *prop_spec = property_specs[i];
 		GValue value = G_VALUE_INIT;
 
@@ -1652,7 +1541,7 @@ nm_setting_enumerate_values (NMSetting *setting,
 gboolean
 _nm_setting_clear_secrets (NMSetting *setting)
 {
-	gs_free GParamSpec **property_specs = NULL;
+	GParamSpec **property_specs;
 	guint n_property_specs;
 	guint i;
 	gboolean changed = FALSE;
@@ -1660,6 +1549,7 @@ _nm_setting_clear_secrets (NMSetting *setting)
 	g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
 
 	property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_property_specs);
+
 	for (i = 0; i < n_property_specs; i++) {
 		GParamSpec *prop_spec = property_specs[i];
 
@@ -1676,6 +1566,9 @@ _nm_setting_clear_secrets (NMSetting *setting)
 			g_value_unset (&value);
 		}
 	}
+
+	g_free (property_specs);
+
 	return changed;
 }
 
@@ -1726,7 +1619,7 @@ _nm_setting_clear_secrets_with_flags (NMSetting *setting,
                                       NMSettingClearSecretsWithFlagsFn func,
                                       gpointer user_data)
 {
-	gs_free GParamSpec **property_specs = NULL;
+	GParamSpec **property_specs;
 	guint n_property_specs;
 	guint i;
 	gboolean changed = FALSE;
@@ -1744,6 +1637,8 @@ _nm_setting_clear_secrets_with_flags (NMSetting *setting,
 			                                                                     user_data);
 		}
 	}
+
+	g_free (property_specs);
 	return changed;
 }
 
@@ -1777,11 +1672,11 @@ _nm_setting_need_secrets (NMSetting *setting)
 static int
 update_one_secret (NMSetting *setting, const char *key, GVariant *value, GError **error)
 {
-	const NMSettInfoProperty *property;
+	const NMSettingProperty *property;
 	GParamSpec *prop_spec;
 	GValue prop_value = { 0, };
 
-	property = _nm_sett_info_property_get (NM_SETTING_GET_CLASS (setting), key);
+	property = nm_setting_class_find_property (NM_SETTING_GET_CLASS (setting), key);
 	if (!property) {
 		g_set_error_literal (error,
 		                     NM_CONNECTION_ERROR,
@@ -1870,10 +1765,10 @@ _nm_setting_update_secrets (NMSetting *setting, GVariant *secrets, GError **erro
 static gboolean
 is_secret_prop (NMSetting *setting, const char *secret_name, GError **error)
 {
-	const NMSettInfoProperty *property;
+	const NMSettingProperty *property;
 	GParamSpec *pspec;
 
-	property = _nm_sett_info_property_get (NM_SETTING_GET_CLASS (setting), secret_name);
+	property = nm_setting_class_find_property (NM_SETTING_GET_CLASS (setting), secret_name);
 	if (!property) {
 		g_set_error_literal (error,
 		                     NM_CONNECTION_ERROR,
@@ -1993,40 +1888,59 @@ nm_setting_set_secret_flags (NMSetting *setting,
  * nm_setting_to_string:
  * @setting: the #NMSetting
  *
- * Convert the setting (including secrets!) into a string. For debugging
- * purposes ONLY, should NOT be used for serialization of the setting,
- * or machine-parsed in any way. The output format is not guaranteed to
- * be stable and may change at any time.
+ * Convert the setting into a string.  For debugging purposes ONLY, should NOT
+ * be used for serialization of the setting, or machine-parsed in any way. The
+ * output format is not guaranteed to be stable and may change at any time.
  *
  * Returns: an allocated string containing a textual representation of the
- * setting's properties and values, which the caller should
+ * setting's properties and values (including secrets!), which the caller should
  * free with g_free()
  **/
 char *
 nm_setting_to_string (NMSetting *setting)
 {
 	GString *string;
-	gs_unref_variant GVariant *variant = NULL;
-	GVariant *child;
-	GVariantIter iter;
+	GParamSpec **property_specs;
+	guint n_property_specs;
+	guint i;
+
+	g_return_val_if_fail (NM_IS_SETTING (setting), NULL);
+
+	property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_property_specs);
 
 	string = g_string_new (nm_setting_get_name (setting));
 	g_string_append_c (string, '\n');
 
-	variant = _nm_setting_to_dbus (setting, NULL, NM_CONNECTION_SERIALIZE_ALL);
+	for (i = 0; i < n_property_specs; i++) {
+		GParamSpec *prop_spec = property_specs[i];
+		GValue value = G_VALUE_INIT;
+		char *value_str;
+		gboolean is_default;
+
+		if (strcmp (prop_spec->name, NM_SETTING_NAME) == 0)
+			continue;
 
-	g_variant_iter_init (&iter, variant);
-	while ((child = g_variant_iter_next_value (&iter))) {
-		gs_free char *name = NULL;
-		gs_free char *value_str = NULL;
-		gs_unref_variant GVariant *value = NULL;
+		g_value_init (&value, prop_spec->value_type);
+		g_object_get_property (G_OBJECT (setting), prop_spec->name, &value);
 
-		g_variant_get (child, "{sv}", &name, &value);
-		value_str = g_variant_print (value, FALSE);
+		value_str = g_strdup_value_contents (&value);
+		g_string_append_printf (string, "\t%s : %s", prop_spec->name, value_str);
+		g_free (value_str);
 
-		g_string_append_printf (string, "\t%s : %s\n", name, value_str);
+		is_default = g_param_value_defaults (prop_spec, &value);
+		g_value_unset (&value);
+
+		g_string_append (string, " (");
+		g_string_append_c (string, 's');
+		if (is_default)
+			g_string_append_c (string, 'd');
+		g_string_append_c (string, ')');
+		g_string_append_c (string, '\n');
 	}
 
+	g_free (property_specs);
+	g_string_append_c (string, '\n');
+
 	return g_string_free (string, FALSE);
 }
 
@@ -2048,257 +1962,17 @@ _nm_setting_get_deprecated_virtual_interface_name (NMSetting *setting,
 
 /*****************************************************************************/
 
-static GenData *
-_gendata_hash (NMSetting *setting, gboolean create_if_necessary)
-{
-	NMSettingPrivate *priv;
-
-	nm_assert (NM_IS_SETTING (setting));
-
-	priv = NM_SETTING_GET_PRIVATE (setting);
-
-	if (G_UNLIKELY (!priv->gendata)) {
-		if (!create_if_necessary)
-			return NULL;
-		priv->gendata = g_slice_new (GenData);
-		priv->gendata->hash = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, (GDestroyNotify) g_variant_unref);
-		priv->gendata->names = NULL;
-		priv->gendata->values = NULL;
-	}
-
-	return priv->gendata;
-}
-
-GHashTable *
-_nm_setting_gendata_hash (NMSetting *setting, gboolean create_if_necessary)
-{
-	GenData *gendata;
-
-	gendata = _gendata_hash (setting, create_if_necessary);
-	return gendata ? gendata->hash : NULL;
-}
-
-void
-_nm_setting_gendata_notify (NMSetting *setting,
-                            gboolean names_changed)
-{
-	GenData *gendata;
-
-	gendata = _gendata_hash (setting, FALSE);
-	if (!gendata)
-		return;
-
-	nm_clear_g_free (&gendata->values);
-
-	if (names_changed) {
-		/* if only the values changed, it's sufficient to invalidate the
-		 * values cache. Otherwise, the names cache must be invalidated too. */
-		nm_clear_g_free (&gendata->names);
-	}
-
-	/* Note, that currently there is now way to notify the subclass when gendata changed.
-	 * gendata is only changed in two situations:
-	 *   1) from within NMSetting itself, for example when creating a NMSetting instance
-	 *      from keyfile or a D-Bus GVariant.
-	 *   2) actively from the subclass itself
-	 * For 2), we don't need the notification, because the subclass knows that something
-	 * changed.
-	 * For 1), we currently don't need the notification either, because all that the subclass
-	 * currently would do, is emit a g_object_notify() signal. However, 1) only happens when
-	 * the setting instance is newly created, at that point, nobody listens to the signal.
-	 *
-	 * If we ever need it, then we would need to call a virtual function to notify the subclass
-	 * that gendata changed. */
-}
-
-GVariant *
-nm_setting_gendata_get (NMSetting *setting,
-                        const char *name)
-{
-	GenData *gendata;
-
-	g_return_val_if_fail (NM_IS_SETTING (setting), NULL);
-	g_return_val_if_fail (name, NULL);
-
-	gendata = _gendata_hash (setting, FALSE);
-	return gendata ? g_hash_table_lookup (gendata->hash, name) : NULL;
-}
-
-guint
-_nm_setting_gendata_get_all (NMSetting *setting,
-                             const char *const**out_names,
-                             GVariant *const**out_values)
-{
-	GenData *gendata;
-	GHashTable *hash;
-	guint i, len;
-
-	nm_assert (NM_IS_SETTING (setting));
-
-	gendata = _gendata_hash (setting, FALSE);
-	if (!gendata)
-		goto out_zero;
-
-	hash = gendata->hash;
-	len = g_hash_table_size (hash);
-	if (len == 0)
-		goto out_zero;
-
-	if (!out_names && !out_values)
-		return len;
-
-	if (G_UNLIKELY (!gendata->names)) {
-		gendata->names = nm_utils_strdict_get_keys (hash,
-		                                            TRUE,
-		                                            NULL);
-	}
-
-	if (out_values) {
-		if (G_UNLIKELY (!gendata->values)) {
-			gendata->values = g_new (GVariant *, len + 1);
-			for (i = 0; i < len; i++)
-				gendata->values[i] = g_hash_table_lookup (hash, gendata->names[i]);
-			gendata->values[i] = NULL;
-		}
-		*out_values = gendata->values;
-	}
-
-	NM_SET_OUT (out_names, (const char *const*) gendata->names);
-	return len;
-
-out_zero:
-	NM_SET_OUT (out_names, NULL);
-	NM_SET_OUT (out_values, NULL);
-	return 0;
-}
-
-/**
- * nm_setting_gendata_get_all_names:
- * @setting: the #NMSetting
- * @out_len: (allow-none): (out):
- *
- * Gives the number of generic data elements and optionally returns all their
- * key names and values. This API is low level access and unless you know what you
- * are doing, it might not be what you want.
- *
- * Returns: (array length=out_len zero-terminated=1) (transfer none):
- *   A %NULL terminated array of key names. If no names are present, this returns
- *   %NULL. The returned array and the names are owned by %NMSetting and might be invalidated
- *   soon.
- *
- * Since: 1.14
- **/
-const char *const*
-nm_setting_gendata_get_all_names (NMSetting *setting,
-                                  guint *out_len)
-{
-	const char *const*names;
-	guint len;
-
-	g_return_val_if_fail (NM_IS_SETTING (setting), NULL);
-
-	len = _nm_setting_gendata_get_all (setting, &names, NULL);
-	NM_SET_OUT (out_len, len);
-	return names;
-}
-
-/**
- * nm_setting_gendata_get_all_values:
- * @setting: the #NMSetting
- *
- * Gives the number of generic data elements and optionally returns all their
- * key names and values. This API is low level access and unless you know what you
- * are doing, it might not be what you want.
- *
- * Returns: (array zero-terminated=1) (transfer none):
- *   A %NULL terminated array of #GVariant. If no data is present, this returns
- *   %NULL. The returned array and the variants are owned by %NMSetting and might be invalidated
- *   soon. The sort order of nm_setting_gendata_get_all_names() and nm_setting_gendata_get_all_values()
- *   is consistent. That means, the nth value has the nth name returned by nm_setting_gendata_get_all_names().
- *
- * Since: 1.14
- **/
-GVariant *const*
-nm_setting_gendata_get_all_values (NMSetting *setting)
-{
-	GVariant *const*values;
-
-	g_return_val_if_fail (NM_IS_SETTING (setting), NULL);
-
-	_nm_setting_gendata_get_all (setting, NULL, &values);
-	return values;
-}
-
-void
-_nm_setting_gendata_to_gvalue (NMSetting *setting,
-                                GValue *value)
-{
-	GenData *gendata;
-	GHashTable *new;
-	const char *key;
-	GVariant *val;
-	GHashTableIter iter;
-
-	nm_assert (NM_IS_SETTING (setting));
-	nm_assert (value);
-	nm_assert (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_HASH_TABLE));
-
-	new = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, (GDestroyNotify) g_variant_unref);
-
-	gendata = _gendata_hash (setting, FALSE);
-	if (gendata) {
-		g_hash_table_iter_init (&iter, gendata->hash);
-		while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &val))
-			g_hash_table_insert (new, g_strdup (key), g_variant_ref (val));
-	}
-
-	g_value_take_boxed (value, new);
-}
-
-gboolean
-_nm_setting_gendata_reset_from_hash (NMSetting *setting,
-                                     GHashTable *new)
+static void
+nm_setting_init (NMSetting *setting)
 {
-	GenData *gendata;
-	GHashTableIter iter;
-	const char *key;
-	GVariant *val;
-	guint num;
-
-	nm_assert (NM_IS_SETTING (setting));
-	nm_assert (new);
-
-	num = new ? g_hash_table_size (new) : 0;
-
-	gendata = _gendata_hash (setting, num > 0);
-
-	if (num == 0) {
-		if (   !gendata
-		    || g_hash_table_size (gendata->hash) == 0)
-			return FALSE;
-
-		g_hash_table_remove_all (gendata->hash);
-		_nm_setting_gendata_notify (setting, TRUE);
-		return TRUE;
-	}
-
-	/* let's not bother to find out whether the new hash has any different
-	 * content the the current gendata. Just replace it. */
-	g_hash_table_remove_all (gendata->hash);
-	if (num > 0) {
-		g_hash_table_iter_init (&iter, new);
-		while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &val))
-			g_hash_table_insert (gendata->hash, g_strdup (key), g_variant_ref (val));
-	}
-	_nm_setting_gendata_notify (setting, TRUE);
-	return TRUE;
 }
 
-/*****************************************************************************/
-
 static void
-nm_setting_init (NMSetting *setting)
+constructed (GObject *object)
 {
+	_ensure_setting_info (object, NM_SETTING_GET_PRIVATE (object));
+
+	G_OBJECT_CLASS (nm_setting_parent_class)->constructed (object);
 }
 
 static void
@@ -2318,44 +1992,15 @@ get_property (GObject *object, guint prop_id,
 }
 
 static void
-finalize (GObject *object)
-{
-	NMSettingPrivate *priv = NM_SETTING_GET_PRIVATE (object);
-
-	if (priv->gendata) {
-		g_free (priv->gendata->names);
-		g_free (priv->gendata->values);
-		g_hash_table_unref (priv->gendata->hash);
-		g_slice_free (GenData, priv->gendata);
-	}
-
-	G_OBJECT_CLASS (nm_setting_parent_class)->finalize (object);
-}
-
-static void
 nm_setting_class_init (NMSettingClass *setting_class)
 {
 	GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
-	GModule *self_module;
-	gpointer func;
-
-	/* loading libnm and legacy libraries libnm-util/libnm-glib at the same
-	 * time is not supported. The reason is, that both libraries use the same
-	 * glib type names ("NMSetting"), and glib does not support namespacing
-	 * to allow for that.
-	 *
-	 * Arbitrarily, add a check here, see whether a known symbol from libnm-util
-	 * is present. If it is, it indicates that the process is borked and we
-	 * abort. */
-	self_module = g_module_open (NULL, 0);
-	if (g_module_symbol (self_module, "nm_util_get_private", &func))
-		g_error ("libnm-util symbols detected; Mixing libnm with libnm-util/libnm-glib is not supported");
-	g_module_close (self_module);
 
 	g_type_class_add_private (setting_class, sizeof (NMSettingPrivate));
 
+	/* virtual methods */
+	object_class->constructed  = constructed;
 	object_class->get_property = get_property;
-	object_class->finalize     = finalize;
 
 	setting_class->update_one_secret = update_one_secret;
 	setting_class->get_secret_flags = get_secret_flags;
@@ -2363,12 +2008,14 @@ nm_setting_class_init (NMSettingClass *setting_class)
 	setting_class->compare_property = compare_property;
 	setting_class->clear_secrets_with_flags = clear_secrets_with_flags;
 
+	/* Properties */
+
 	/**
 	 * NMSetting:name:
 	 *
 	 * The setting's name, which uniquely identifies the setting within the
 	 * connection.  Each setting type has a name unique to that type, for
-	 * example "ppp" or "802-11-wireless" or "802-3-ethernet".
+	 * example "ppp" or "wireless" or "wired".
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_NAME,
diff --git a/libnm-core/nm-setting.h b/libnm-core/nm-setting.h
index a7a0f81f..47a2fdc1 100644
--- a/libnm-core/nm-setting.h
+++ b/libnm-core/nm-setting.h
@@ -168,13 +168,11 @@ typedef gboolean (*NMSettingClearSecretsWithFlagsFn) (NMSetting *setting,
                                                       NMSettingSecretFlags flags,
                                                       gpointer user_data);
 
-struct _NMMetaSettingInfo;
-
 typedef struct {
 	GObjectClass parent;
 
 	/* Virtual functions */
-	int         (*verify)            (NMSetting     *setting,
+	gint        (*verify)            (NMSetting     *setting,
 	                                  NMConnection  *connection,
 	                                  GError       **error);
 
@@ -213,10 +211,7 @@ typedef struct {
 	                                  NMSettingCompareFlags flags);
 
 	/*< private >*/
-	const struct _NMMetaSettingInfo *setting_info;
-
-	/*< private >*/
-	gpointer padding[6];
+	gpointer padding[7];
 } NMSettingClass;
 
 /**
@@ -287,8 +282,7 @@ void        nm_setting_enumerate_values (NMSetting *setting,
 
 char       *nm_setting_to_string      (NMSetting *setting);
 
-/*****************************************************************************/
-
+/* Secrets */
 gboolean    nm_setting_get_secret_flags (NMSetting *setting,
                                          const char *secret_name,
                                          NMSettingSecretFlags *out_flags,
@@ -299,13 +293,10 @@ gboolean    nm_setting_set_secret_flags (NMSetting *setting,
                                          NMSettingSecretFlags flags,
                                          GError **error);
 
-/*****************************************************************************/
-
+/* Properties */
 const GVariantType *nm_setting_get_dbus_property_type (NMSetting *setting,
                                                        const char *property_name);
 
-/*****************************************************************************/
-
 G_END_DECLS
 
 #endif /* __NM_SETTING_H__ */
diff --git a/libnm-core/nm-utils-private.h b/libnm-core/nm-utils-private.h
index b886730a..5d0f8386 100644
--- a/libnm-core/nm-utils-private.h
+++ b/libnm-core/nm-utils-private.h
@@ -74,6 +74,7 @@ GVariant *  _nm_utils_strdict_to_dbus   (const GValue *prop_value);
 void        _nm_utils_strdict_from_dbus (GVariant *dbus_value,
                                          GValue *prop_value);
 
+GVariant *  _nm_utils_bytes_to_dbus     (const GValue *prop_value);
 void        _nm_utils_bytes_from_dbus   (GVariant *dbus_value,
                                          GValue *prop_value);
 
@@ -82,13 +83,6 @@ char *      _nm_utils_hwaddr_canonical_or_invalid (const char *mac, gssize lengt
 GPtrArray * _nm_utils_team_link_watchers_from_variant (GVariant *value);
 GVariant *  _nm_utils_team_link_watchers_to_variant (GPtrArray *link_watchers);
 
-void        _nm_utils_format_variant_attributes_full (GString *str,
-                                                      const NMUtilsNamedValue *values,
-                                                      guint num_values,
-                                                      char attr_separator,
-                                                      char key_value_separator);
-gboolean    _nm_sriov_vf_parse_vlans (NMSriovVF *vf, const char *str, GError **error);
-
 /* JSON to GValue conversion macros */
 
 typedef struct {
diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c
index f6e1555e..b700c7f5 100644
--- a/libnm-core/nm-utils.c
+++ b/libnm-core/nm-utils.c
@@ -43,7 +43,7 @@
 #include "nm-common-macros.h"
 #include "nm-utils-private.h"
 #include "nm-setting-private.h"
-#include "nm-crypto.h"
+#include "crypto.h"
 #include "nm-setting-bond.h"
 #include "nm-setting-bridge.h"
 #include "nm-setting-infiniband.h"
@@ -230,33 +230,31 @@ get_system_encodings (void)
 	return cached_encodings;
 }
 
-/*****************************************************************************/
+/* init libnm */
+
+static gboolean initialized = FALSE;
 
 static void __attribute__((constructor))
 _nm_utils_init (void)
 {
-	static int initialized = 0;
+	GModule *self;
+	gpointer func;
 
-	if (g_atomic_int_get (&initialized) != 0)
+	if (initialized)
 		return;
+	initialized = TRUE;
 
-	/* we don't expect this code to run multiple times, nor on multiple threads.
-	 *
-	 * In practice, it would not be a problem if two threads concurrently try to
-	 * run the initialization code below, all code below itself is thread-safe,
-	 * Hence, a poor-man guard "initialized" above is more than sufficient,
-	 * although it does not guarantee that the code is not run concurrently. */
+	self = g_module_open (NULL, 0);
+	if (g_module_symbol (self, "nm_util_get_private", &func))
+		g_error ("libnm-util symbols detected; Mixing libnm with libnm-util/libnm-glib is not supported");
+	g_module_close (self);
 
 	bindtextdomain (GETTEXT_PACKAGE, NMLOCALEDIR);
 	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
 
 	_nm_dbus_errors_init ();
-
-	g_atomic_int_set (&initialized, 1);
 }
 
-/*****************************************************************************/
-
 gboolean _nm_utils_is_manager_process;
 
 /* ssid helpers */
@@ -302,19 +300,19 @@ nm_utils_ssid_to_utf8 (const guint8 *ssid, gsize len)
 
 	g_return_val_if_fail (ssid != NULL, NULL);
 
-	if (g_utf8_validate ((const char *) ssid, len, NULL))
-		return g_strndup ((const char *) ssid, len);
+	if (g_utf8_validate ((const gchar *) ssid, len, NULL))
+		return g_strndup ((const gchar *) ssid, len);
 
 	encodings = get_system_encodings ();
 
 	for (e = encodings; *e; e++) {
-		converted = g_convert ((const char *) ssid, len, "UTF-8", *e, NULL, NULL, NULL);
+		converted = g_convert ((const gchar *) ssid, len, "UTF-8", *e, NULL, NULL, NULL);
 		if (converted)
 			break;
 	}
 
 	if (!converted) {
-		converted = g_convert_with_fallback ((const char *) ssid, len,
+		converted = g_convert_with_fallback ((const gchar *) ssid, len,
 		                                     "UTF-8", encodings[0], "?", NULL, NULL, NULL);
 	}
 
@@ -325,7 +323,7 @@ nm_utils_ssid_to_utf8 (const guint8 *ssid, gsize len)
 		 */
 
 		/* Use the printable range of 0x20-0x7E */
-		char *valid_chars = " !\"#$%&'()*+,-./0123456789:;<=>?@"
+		gchar *valid_chars = " !\"#$%&'()*+,-./0123456789:;<=>?@"
 		                     "ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`"
 		                     "abcdefghijklmnopqrstuvwxyz{|}~";
 
@@ -336,18 +334,6 @@ nm_utils_ssid_to_utf8 (const guint8 *ssid, gsize len)
 	return converted;
 }
 
-char *
-_nm_utils_ssid_to_utf8 (GBytes *ssid)
-{
-	const guint8 *p;
-	gsize l;
-
-	g_return_val_if_fail (ssid, NULL);
-
-	p = g_bytes_get_data (ssid, &l);
-	return nm_utils_ssid_to_utf8 (p, l);
-}
-
 /* Shamelessly ripped from the Linux kernel ieee80211 stack */
 /**
  * nm_utils_is_empty_ssid:
@@ -375,18 +361,6 @@ nm_utils_is_empty_ssid (const guint8 *ssid, gsize len)
 	return TRUE;
 }
 
-gboolean
-_nm_utils_is_empty_ssid (GBytes *ssid)
-{
-	const guint8 *p;
-	gsize l;
-
-	g_return_val_if_fail (ssid, FALSE);
-
-	p = g_bytes_get_data (ssid, &l);
-	return nm_utils_is_empty_ssid (p, l);
-}
-
 #define ESSID_MAX_SIZE 32
 
 /**
@@ -428,37 +402,6 @@ nm_utils_escape_ssid (const guint8 *ssid, gsize len)
 	return escaped;
 }
 
-char *
-_nm_utils_ssid_to_string_arr (const guint8 *ssid, gsize len)
-{
-	gs_free char *s_copy = NULL;
-	const char *s_cnst;
-
-	if (len == 0)
-		return g_strdup ("(empty)");
-
-	s_cnst = nm_utils_buf_utf8safe_escape (ssid, len, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL, &s_copy);
-	nm_assert (s_cnst);
-
-	if (nm_utils_is_empty_ssid (ssid, len))
-		return g_strdup_printf ("\"%s\" (hidden)", s_cnst);
-
-	return g_strdup_printf ("\"%s\"", s_cnst);
-}
-
-char *
-_nm_utils_ssid_to_string (GBytes *ssid)
-{
-	gconstpointer p;
-	gsize l;
-
-	if (!ssid)
-		return g_strdup ("(none)");
-
-	p = g_bytes_get_data (ssid, &l);
-	return _nm_utils_ssid_to_string_arr (p, l);
-}
-
 /**
  * nm_utils_same_ssid:
  * @ssid1: (array length=len1): the first SSID to compare
@@ -623,6 +566,39 @@ _nm_utils_copy_strdict (GHashTable *strdict)
 }
 
 GPtrArray *
+_nm_utils_copy_slist_to_array (const GSList *list,
+                               NMUtilsCopyFunc copy_func,
+                               GDestroyNotify unref_func)
+{
+	const GSList *iter;
+	GPtrArray *array;
+
+	array = g_ptr_array_new_with_free_func (unref_func);
+	for (iter = list; iter; iter = iter->next)
+		g_ptr_array_add (array, copy_func ? copy_func (iter->data) : iter->data);
+	return array;
+}
+
+GSList *
+_nm_utils_copy_array_to_slist (const GPtrArray *array,
+                               NMUtilsCopyFunc copy_func)
+{
+	GSList *slist = NULL;
+	gpointer item;
+	int i;
+
+	if (!array)
+		return NULL;
+
+	for (i = 0; i < array->len; i++) {
+		item = array->pdata[i];
+		slist = g_slist_prepend (slist, copy_func (item));
+	}
+
+	return g_slist_reverse (slist);
+}
+
+GPtrArray *
 _nm_utils_copy_array (const GPtrArray *array,
                       NMUtilsCopyFunc copy_func,
                       GDestroyNotify free_func)
@@ -669,6 +645,136 @@ _nm_utils_ptrarray_find_first (gconstpointer *list, gssize len, gconstpointer ne
 	return -1;
 }
 
+gssize
+_nm_utils_ptrarray_find_binary_search (gconstpointer *list,
+                                       gsize len,
+                                       gconstpointer needle,
+                                       GCompareDataFunc cmpfcn,
+                                       gpointer user_data,
+                                       gssize *out_idx_first,
+                                       gssize *out_idx_last)
+{
+	gssize imin, imax, imid, i2min, i2max, i2mid;
+	int cmp;
+
+	g_return_val_if_fail (list || !len, ~((gssize) 0));
+	g_return_val_if_fail (cmpfcn, ~((gssize) 0));
+
+	imin = 0;
+	if (len > 0) {
+		imax = len - 1;
+
+		while (imin <= imax) {
+			imid = imin + (imax - imin) / 2;
+
+			cmp = cmpfcn (list[imid], needle, user_data);
+			if (cmp == 0) {
+				/* we found a matching entry at index imid.
+				 *
+				 * Does the caller request the first/last index as well (in case that
+				 * there are multiple entries which compare equal). */
+
+				if (out_idx_first) {
+					i2min = imin;
+					i2max = imid + 1;
+					while (i2min <= i2max) {
+						i2mid = i2min + (i2max - i2min) / 2;
+
+						cmp = cmpfcn (list[i2mid], needle, user_data);
+						if (cmp == 0)
+							i2max = i2mid -1;
+						else {
+							nm_assert (cmp < 0);
+							i2min = i2mid + 1;
+						}
+					}
+					*out_idx_first = i2min;
+				}
+				if (out_idx_last) {
+					i2min = imid + 1;
+					i2max = imax;
+					while (i2min <= i2max) {
+						i2mid = i2min + (i2max - i2min) / 2;
+
+						cmp = cmpfcn (list[i2mid], needle, user_data);
+						if (cmp == 0)
+							i2min = i2mid + 1;
+						else {
+							nm_assert (cmp > 0);
+							i2max = i2mid - 1;
+						}
+					}
+					*out_idx_last = i2min - 1;
+				}
+				return imid;
+			}
+
+			if (cmp < 0)
+				imin = imid + 1;
+			else
+				imax = imid - 1;
+		}
+	}
+
+	/* return the inverse of @imin. This is a negative number, but
+	 * also is ~imin the position where the value should be inserted. */
+	imin = ~imin;
+	NM_SET_OUT (out_idx_first, imin);
+	NM_SET_OUT (out_idx_last, imin);
+	return imin;
+}
+
+gssize
+_nm_utils_array_find_binary_search (gconstpointer list, gsize elem_size, gsize len, gconstpointer needle, GCompareDataFunc cmpfcn, gpointer user_data)
+{
+	gssize imin, imax, imid;
+	int cmp;
+
+	g_return_val_if_fail (list || !len, ~((gssize) 0));
+	g_return_val_if_fail (cmpfcn, ~((gssize) 0));
+	g_return_val_if_fail (elem_size > 0, ~((gssize) 0));
+
+	imin = 0;
+	if (len == 0)
+		return ~imin;
+
+	imax = len - 1;
+
+	while (imin <= imax) {
+		imid = imin + (imax - imin) / 2;
+
+		cmp = cmpfcn (&((const char *) list)[elem_size * imid], needle, user_data);
+		if (cmp == 0)
+			return imid;
+
+		if (cmp < 0)
+			imin = imid + 1;
+		else
+			imax = imid - 1;
+	}
+
+	/* return the inverse of @imin. This is a negative number, but
+	 * also is ~imin the position where the value should be inserted. */
+	return ~imin;
+}
+
+GVariant *
+_nm_utils_bytes_to_dbus (const GValue *prop_value)
+{
+	GBytes *bytes = g_value_get_boxed (prop_value);
+
+	if (bytes) {
+		return g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
+		                                  g_bytes_get_data (bytes, NULL),
+		                                  g_bytes_get_size (bytes),
+		                                  1);
+	} else {
+		return g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
+		                                  NULL, 0,
+		                                  1);
+	}
+}
+
 void
 _nm_utils_bytes_from_dbus (GVariant *dbus_value,
                            GValue *prop_value)
@@ -2141,10 +2247,10 @@ _tc_read_common_opts (const char *str,
 	gs_unref_hashtable GHashTable *ht = NULL;
 	GVariant *variant;
 
-	ht = nm_utils_parse_variant_attributes (str,
-	                                        ' ', ' ', FALSE,
-	                                        tc_object_attribute_spec,
-	                                        error);
+        ht = nm_utils_parse_variant_attributes (str,
+                                                ' ', ' ', FALSE,
+                                                tc_object_attribute_spec,
+                                                error);
 	if (!ht)
 		return FALSE;
 
@@ -2504,10 +2610,10 @@ nm_utils_tc_tfilter_from_str (const char *str, GError **error)
 		return NULL;
 
 	if (rest) {
-		ht = nm_utils_parse_variant_attributes (rest,
-		                                        ' ', ' ', FALSE,
-		                                        tc_tfilter_attribute_spec,
-		                                        error);
+	        ht = nm_utils_parse_variant_attributes (rest,
+	                                                ' ', ' ', FALSE,
+	                                                tc_tfilter_attribute_spec,
+	                                                error);
 		if (!ht)
 			return NULL;
 
@@ -2542,249 +2648,6 @@ nm_utils_tc_tfilter_from_str (const char *str, GError **error)
 
 /*****************************************************************************/
 
-extern const NMVariantAttributeSpec *const _nm_sriov_vf_attribute_spec[];
-
-/**
- * nm_utils_sriov_vf_to_str:
- * @vf: the %NMSriovVF
- * @omit_index: if %TRUE, the VF index will be omitted from output string
- * @error: (out) (allow-none): location to store the error on failure
- *
- * Converts a SR-IOV virtual function object to its string representation.
- *
- * Returns: a newly allocated string or %NULL on error
- *
- * Since: 1.14
- */
-char *
-nm_utils_sriov_vf_to_str (const NMSriovVF *vf, gboolean omit_index, GError **error)
-{
-	gs_free NMUtilsNamedValue *values = NULL;
-	gs_free const char **names = NULL;
-	const guint *vlan_ids;
-	guint num_vlans, num_attrs;
-	guint i;
-	GString *str;
-
-	str = g_string_new ("");
-	if (!omit_index)
-		g_string_append_printf (str, "%u", nm_sriov_vf_get_index (vf));
-
-	names = nm_sriov_vf_get_attribute_names (vf);
-	num_attrs = names ? g_strv_length ((char **) names) : 0;
-	values = g_new0 (NMUtilsNamedValue, num_attrs);
-
-	for (i = 0; i < num_attrs; i++) {
-		values[i].name = names[i];
-		values[i].value_ptr = nm_sriov_vf_get_attribute (vf, names[i]);
-	}
-
-	if (num_attrs > 0) {
-		if (!omit_index)
-			g_string_append_c (str, ' ');
-		_nm_utils_format_variant_attributes_full (str, values, num_attrs, ' ', '=');
-	}
-
-	vlan_ids = nm_sriov_vf_get_vlan_ids (vf, &num_vlans);
-	if (num_vlans != 0) {
-		g_string_append (str, " vlans");
-		for (i = 0; i < num_vlans; i++) {
-			guint32 qos;
-			NMSriovVFVlanProtocol protocol;
-
-			qos = nm_sriov_vf_get_vlan_qos (vf, vlan_ids[i]);
-			protocol = nm_sriov_vf_get_vlan_protocol (vf, vlan_ids[i]);
-
-			g_string_append_c (str, i == 0 ? '=' : ';');
-
-			g_string_append_printf (str, "%u", vlan_ids[i]);
-
-			if (   qos != 0
-			    || protocol != NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q) {
-				g_string_append_printf (str,
-				                        ".%u%s",
-				                        (unsigned) qos,
-				                        protocol == NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q ? "" : ".ad");
-			}
-		}
-	}
-
-	return g_string_free (str, FALSE);
-}
-
-gboolean
-_nm_sriov_vf_parse_vlans (NMSriovVF *vf, const char *str, GError **error)
-{
-	gs_free const char **vlans = NULL;
-	guint i;
-
-	vlans = nm_utils_strsplit_set (str, ";", FALSE);
-	if (!vlans) {
-		g_set_error_literal (error,
-		                     NM_CONNECTION_ERROR,
-		                     NM_CONNECTION_ERROR_FAILED,
-		                     "empty VF VLAN");
-		return FALSE;
-	}
-
-	for (i = 0; vlans[i]; i++) {
-		gs_strfreev char **params = NULL;
-		guint id = G_MAXUINT;
-		gint64 qos = -1;
-
-		/* we accept leading/trailing whitespace around vlans[1]. Hence
-		 * the nm_str_skip_leading_spaces() and g_strchomp() below.
-		 *
-		 * However, we don't accept any whitespace inside the specifier.
-		 * Hence the NM_STRCHAR_ALL() checks. */
-
-		params = g_strsplit (nm_str_skip_leading_spaces (vlans[i]), ".", 3);
-		if (!params || !params[0] || *params[0] == '\0') {
-			g_set_error_literal (error,
-			                     NM_CONNECTION_ERROR,
-			                     NM_CONNECTION_ERROR_FAILED,
-			                     "empty VF VLAN");
-			return FALSE;
-		}
-
-		if (!params[1])
-			g_strchomp (params[0]);
-		if (NM_STRCHAR_ALL (params[0], ch, ch == 'x' || g_ascii_isdigit (ch)))
-			id = _nm_utils_ascii_str_to_int64 (params[0], 0, 0, 4095, G_MAXUINT);
-		if (id == G_MAXUINT) {
-			g_set_error (error,
-			             NM_CONNECTION_ERROR,
-			             NM_CONNECTION_ERROR_FAILED,
-			             "invalid VF VLAN id '%s'",
-			             params[0]);
-			return FALSE;
-		}
-		if (!nm_sriov_vf_add_vlan (vf, id)) {
-			g_set_error (error,
-			             NM_CONNECTION_ERROR,
-			             NM_CONNECTION_ERROR_FAILED,
-			             "duplicate VLAN id %u",
-			             id);
-			return FALSE;
-		}
-
-		if (!params[1])
-			continue;
-
-		if (!params[2])
-			g_strchomp (params[1]);
-		if (NM_STRCHAR_ALL (params[1], ch, ch == 'x' || g_ascii_isdigit (ch)))
-			qos = _nm_utils_ascii_str_to_int64 (params[1], 0, 0, G_MAXUINT32, -1);
-		if (qos == -1) {
-			g_set_error (error,
-			             NM_CONNECTION_ERROR,
-			             NM_CONNECTION_ERROR_FAILED,
-			             "invalid VF VLAN QoS '%s'",
-			             params[1]);
-			return FALSE;
-		}
-		nm_sriov_vf_set_vlan_qos (vf, id, qos);
-
-		if (!params[2])
-			continue;
-
-		g_strchomp (params[2]);
-
-		if (nm_streq (params[2], "ad"))
-			nm_sriov_vf_set_vlan_protocol (vf, id, NM_SRIOV_VF_VLAN_PROTOCOL_802_1AD);
-		else if (nm_streq (params[2], "q"))
-			nm_sriov_vf_set_vlan_protocol (vf, id, NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q);
-		else {
-			g_set_error (error,
-			             NM_CONNECTION_ERROR,
-			             NM_CONNECTION_ERROR_FAILED,
-			             "invalid VF VLAN protocol '%s'",
-			             params[2]);
-			return FALSE;
-		}
-	}
-
-	return TRUE;
-}
-
-/**
- * nm_utils_sriov_vf_from_str:
- * @str: the input string
- * @error: (out) (allow-none): location to store the error on failure
- *
- * Converts a string to a SR-IOV virtual function object.
- *
- * Returns: (transfer full): the virtual function object
- *
- * Since: 1.14
- */
-NMSriovVF *
-nm_utils_sriov_vf_from_str (const char *str, GError **error)
-{
-	gs_free char *index_free = NULL;
-	const char *detail;
-
-	g_return_val_if_fail (str, NULL);
-	g_return_val_if_fail (!error || !*error, NULL);
-
-	while (*str == ' ')
-		str++;
-
-	detail = strchr (str, ' ');
-	if (detail) {
-		index_free = g_strndup (str, detail - str);
-		str = index_free;
-		detail++;
-	}
-
-	return _nm_utils_sriov_vf_from_strparts (str, detail, error);
-}
-
-NMSriovVF *
-_nm_utils_sriov_vf_from_strparts (const char *index, const char *detail, GError **error)
-{
-	NMSriovVF *vf;
-	guint32 n_index;
-	GHashTableIter iter;
-	char *key;
-	GVariant *variant;
-	gs_unref_hashtable GHashTable *ht = NULL;
-
-	n_index = _nm_utils_ascii_str_to_int64 (index, 10, 0, G_MAXUINT32, 0);
-	if (errno) {
-		g_set_error_literal (error,
-		                     NM_CONNECTION_ERROR,
-		                     NM_CONNECTION_ERROR_FAILED,
-		                     "invalid index");
-		return NULL;
-	}
-
-	vf = nm_sriov_vf_new (n_index);
-	if (detail) {
-		ht = nm_utils_parse_variant_attributes (detail, ' ', '=', TRUE, _nm_sriov_vf_attribute_spec, error);
-		if (!ht) {
-			nm_sriov_vf_unref (vf);
-			return NULL;
-		}
-
-		if ((variant = g_hash_table_lookup (ht, "vlans"))) {
-			if (!_nm_sriov_vf_parse_vlans (vf, g_variant_get_string (variant, NULL), error)) {
-				nm_sriov_vf_unref (vf);
-				return NULL;
-			}
-			g_hash_table_remove (ht, "vlans");
-		}
-
-		g_hash_table_iter_init (&iter, ht);
-		while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &variant))
-			nm_sriov_vf_set_attribute (vf, key, g_variant_ref_sink (variant));
-	}
-
-	return vf;
-}
-
-/*****************************************************************************/
-
 /**
  * nm_utils_uuid_generate_buf_:
  * @buf: input buffer, must contain at least 37 bytes
@@ -2838,17 +2701,9 @@ nm_utils_uuid_generate_from_string (const char *s, gssize slen, int uuid_type, g
 	g_return_val_if_fail (uuid_type == NM_UTILS_UUID_TYPE_LEGACY || uuid_type == NM_UTILS_UUID_TYPE_VARIANT3, NULL);
 	g_return_val_if_fail (!type_args || uuid_type == NM_UTILS_UUID_TYPE_VARIANT3, NULL);
 
-	if (slen < 0)
-		slen = s ? strlen (s) : 0;
-
 	switch (uuid_type) {
 	case NM_UTILS_UUID_TYPE_LEGACY:
-		nm_crypto_md5_hash (NULL,
-		                    0,
-		                    (guint8 *) s,
-		                    slen,
-		                    (guint8 *) uuid,
-		                    sizeof (uuid));
+		crypto_md5_hash (NULL, 0, s, slen, (char *) uuid, sizeof (uuid));
 		break;
 	case NM_UTILS_UUID_TYPE_VARIANT3: {
 		uuid_t ns_uuid = { 0 };
@@ -2859,12 +2714,7 @@ nm_utils_uuid_generate_from_string (const char *s, gssize slen, int uuid_type, g
 				g_return_val_if_reached (NULL);
 		}
 
-		nm_crypto_md5_hash ((guint8 *) s,
-		                    slen,
-		                    (guint8 *) ns_uuid,
-		                    sizeof (ns_uuid),
-		                    (guint8 *) uuid,
-		                    sizeof (uuid));
+		crypto_md5_hash (s, slen, (char *) ns_uuid, sizeof (ns_uuid), (char *) uuid, sizeof (uuid));
 
 		uuid[6] = (uuid[6] & 0x0F) | 0x30;
 		uuid[8] = (uuid[8] & 0x3F) | 0x80;
@@ -2924,6 +2774,110 @@ _nm_utils_uuid_generate_from_strings (const char *string1, ...)
 
 /*****************************************************************************/
 
+/**
+ * nm_utils_rsa_key_encrypt:
+ * @data: (array length=len): RSA private key data to be encrypted
+ * @len: length of @data
+ * @in_password: (allow-none): existing password to use, if any
+ * @out_password: (out) (allow-none): if @in_password was %NULL, a random
+ *  password will be generated and returned in this argument
+ * @error: detailed error information on return, if an error occurred
+ *
+ * Encrypts the given RSA private key data with the given password (or generates
+ * a password if no password was given) and converts the data to PEM format
+ * suitable for writing to a file. It uses Triple DES cipher for the encryption.
+ *
+ * Returns: (transfer full): on success, PEM-formatted data suitable for writing
+ * to a PEM-formatted certificate/private key file.
+ **/
+GByteArray *
+nm_utils_rsa_key_encrypt (const guint8 *data,
+                          gsize len,
+                          const char *in_password,
+                          char **out_password,
+                          GError **error)
+{
+	char salt[16];
+	int salt_len;
+	char *key = NULL, *enc = NULL, *pw_buf[32];
+	gsize key_len = 0, enc_len = 0;
+	GString *pem = NULL;
+	char *tmp, *tmp_password = NULL;
+	int left;
+	const char *p;
+	GByteArray *ret = NULL;
+
+	g_return_val_if_fail (data != NULL, NULL);
+	g_return_val_if_fail (len > 0, NULL);
+	if (out_password)
+		g_return_val_if_fail (*out_password == NULL, NULL);
+
+	/* Make the password if needed */
+	if (!in_password) {
+		if (!crypto_randomize (pw_buf, sizeof (pw_buf), error))
+			return NULL;
+		in_password = tmp_password = nm_utils_bin2hexstr (pw_buf, sizeof (pw_buf), -1);
+	}
+
+	salt_len = 8;
+	if (!crypto_randomize (salt, salt_len, error))
+		goto out;
+
+	key = crypto_make_des_aes_key (CIPHER_DES_EDE3_CBC, &salt[0], salt_len, in_password, &key_len, NULL);
+	if (!key)
+		g_return_val_if_reached (NULL);
+
+	enc = crypto_encrypt (CIPHER_DES_EDE3_CBC, data, len, salt, salt_len, key, key_len, &enc_len, error);
+	if (!enc)
+		goto out;
+
+	pem = g_string_sized_new (enc_len * 2 + 100);
+	g_string_append (pem, "-----BEGIN RSA PRIVATE KEY-----\n");
+	g_string_append (pem, "Proc-Type: 4,ENCRYPTED\n");
+
+	/* Convert the salt to a hex string */
+	tmp = nm_utils_bin2hexstr (salt, salt_len, salt_len * 2);
+	g_string_append_printf (pem, "DEK-Info: %s,%s\n\n", CIPHER_DES_EDE3_CBC, tmp);
+	g_free (tmp);
+
+	/* Convert the encrypted key to a base64 string */
+	p = tmp = g_base64_encode ((const guchar *) enc, enc_len);
+	left = strlen (tmp);
+	while (left > 0) {
+		g_string_append_len (pem, p, (left < 64) ? left : 64);
+		g_string_append_c (pem, '\n');
+		left -= 64;
+		p += 64;
+	}
+	g_free (tmp);
+
+	g_string_append (pem, "-----END RSA PRIVATE KEY-----\n");
+
+	ret = g_byte_array_sized_new (pem->len);
+	g_byte_array_append (ret, (const unsigned char *) pem->str, pem->len);
+	if (tmp_password && out_password)
+		*out_password = g_strdup (tmp_password);
+
+out:
+	if (key) {
+		memset (key, 0, key_len);
+		g_free (key);
+	}
+	if (enc) {
+		memset (enc, 0, enc_len);
+		g_free (enc);
+	}
+	if (pem)
+		g_string_free (pem, TRUE);
+
+	if (tmp_password) {
+		memset (tmp_password, 0, strlen (tmp_password));
+		g_free (tmp_password);
+	}
+
+	return ret;
+}
+
 static gboolean
 file_has_extension (const char *filename, const char *extensions[])
 {
@@ -2956,15 +2910,18 @@ gboolean
 nm_utils_file_is_certificate (const char *filename)
 {
 	const char *extensions[] = { ".der", ".pem", ".crt", ".cer", NULL };
-	NMCryptoFileFormat file_format;
+	NMCryptoFileFormat file_format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
+	GByteArray *cert;
 
 	g_return_val_if_fail (filename != NULL, FALSE);
 
 	if (!file_has_extension (filename, extensions))
 		return FALSE;
 
-	if (!nm_crypto_load_and_verify_certificate (filename, &file_format, NULL, NULL))
-		return FALSE;
+	cert = crypto_load_and_verify_certificate (filename, &file_format, NULL);
+	if (cert)
+		g_byte_array_unref (cert);
+
 	return file_format = NM_CRYPTO_FILE_FORMAT_X509;
 }
 
@@ -2990,7 +2947,7 @@ nm_utils_file_is_private_key (const char *filename, gboolean *out_encrypted)
 	if (!file_has_extension (filename, extensions))
 		return FALSE;
 
-	return nm_crypto_verify_private_key (filename, NULL, out_encrypted, NULL) != NM_CRYPTO_FILE_FORMAT_UNKNOWN;
+	return crypto_verify_private_key (filename, NULL, out_encrypted, NULL) != NM_CRYPTO_FILE_FORMAT_UNKNOWN;
 }
 
 /**
@@ -3006,7 +2963,7 @@ nm_utils_file_is_pkcs12 (const char *filename)
 {
 	g_return_val_if_fail (filename != NULL, FALSE);
 
-	return nm_crypto_is_pkcs12_file (filename, NULL);
+	return crypto_is_pkcs12_file (filename, NULL);
 }
 
 /*****************************************************************************/
@@ -3526,13 +3483,13 @@ nm_utils_hwaddr_len (int type)
 	g_return_val_if_reached (0);
 }
 
-guint8 *
-_nm_utils_str2bin_full (const char *asc,
-                        gboolean delimiter_required,
-                        const char *delimiter_candidates,
-                        guint8 *buffer,
-                        gsize buffer_length,
-                        gsize *out_len)
+static guint8 *
+_str2bin (const char *asc,
+          gboolean delimiter_required,
+          const char *delimiter_candidates,
+          guint8 *buffer,
+          gsize buffer_length,
+          gsize *out_len)
 {
 	const char *in = asc;
 	guint8 *out = buffer;
@@ -3602,7 +3559,7 @@ _nm_utils_str2bin_full (const char *asc,
 	return buffer;
 }
 
-#define hwaddr_aton(asc, buffer, buffer_length, out_len) _nm_utils_str2bin_full ((asc), TRUE, ":-", (buffer), (buffer_length), (out_len))
+#define hwaddr_aton(asc, buffer, buffer_length, out_len) _str2bin ((asc), TRUE, ":-", (buffer), (buffer_length), (out_len))
 
 /**
  * nm_utils_hexstr2bin:
@@ -3628,7 +3585,7 @@ nm_utils_hexstr2bin (const char *hex)
 
 	buffer_length = strlen (hex) / 2 + 3;
 	buffer = g_malloc (buffer_length);
-	if (!_nm_utils_str2bin_full (hex, FALSE, ":", buffer, buffer_length, &len)) {
+	if (!_str2bin (hex, FALSE, ":", buffer, buffer_length, &len)) {
 		g_free (buffer);
 		return NULL;
 	}
@@ -4333,8 +4290,6 @@ nm_utils_is_uuid (const char *str)
 	const char *p = str;
 	int num_dashes = 0;
 
-	g_return_val_if_fail (str, FALSE);
-
 	while (*p) {
 		if (*p == '-')
 			num_dashes++;
@@ -4510,7 +4465,7 @@ _nm_utils_dhcp_duid_valid (const char *duid, GBytes **out_duid_bin)
 		return TRUE;
 	}
 
-	if (_nm_utils_str2bin_full (duid, FALSE, ":", duid_arr, sizeof (duid_arr), &duid_len)) {
+	if (_str2bin (duid, FALSE, ":", duid_arr, sizeof (duid_arr), &duid_len)) {
 		/* MAX DUID length is 128 octects + the type code (2 octects). */
 		if (   duid_len > 2
 		    && duid_len <= (128 + 2)) {
@@ -4931,7 +4886,7 @@ nm_utils_enum_from_str (GType type, const char *str,
  *
  * Since: 1.2
  */
-const char **nm_utils_enum_get_values (GType type, int from, int to)
+const char **nm_utils_enum_get_values (GType type, gint from, gint to)
 {
 	return _nm_utils_enum_get_values (type, from, to);
 }
@@ -5584,7 +5539,7 @@ _nm_utils_team_config_get (const char *conf,
 				g_ptr_array_free (data, TRUE);
 
 		} else if (json_is_array (json_element)) {
-			GPtrArray *data = g_ptr_array_new_with_free_func (g_free);
+			GPtrArray *data = g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
 			json_t *str_element;
 			int index;
 
@@ -6035,9 +5990,7 @@ attribute_unescape (const char *start, const char *end)
  * Parse attributes from a string.
  *
  * Returns: (transfer full) (element-type utf8 GVariant): a #GHashTable mapping
- * attribute names to #GVariant values. Warning: the variant are still floating
- * references, owned by the hash table. If you take a reference, ensure to sink
- * the one of the hash table first.
+ * attribute names to #GVariant values.
  *
  * Since: 1.8
  */
@@ -6194,21 +6147,44 @@ next:
 	return g_steal_pointer (&ht);
 }
 
-void
-_nm_utils_format_variant_attributes_full (GString *str,
-                                          const NMUtilsNamedValue *values,
-                                          guint num_values,
-                                          char attr_separator,
-                                          char key_value_separator)
+/*
+ * nm_utils_format_variant_attributes:
+ * @attributes: (element-type utf8 GVariant): a #GHashTable mapping attribute names to #GVariant values
+ * @attr_separator: the attribute separator character
+ * @key_value_separator: character separating key and values
+ *
+ * Format attributes to a string.
+ *
+ * Returns: (transfer full): the string representing attributes, or %NULL
+ *    in case there are no attributes
+ *
+ * Since: 1.8
+ */
+char *
+nm_utils_format_variant_attributes (GHashTable *attributes,
+                                    char attr_separator,
+                                    char key_value_separator)
 {
-	const char *name, *value;
+	GString *str = NULL;
 	GVariant *variant;
+	char sep = 0;
+	const char *name, *value;
 	char *escaped;
 	char buf[64];
-	char sep = 0;
-	guint i;
+	gs_free NMUtilsNamedValue *values = NULL;
+	guint i, len;
+
+	g_return_val_if_fail (attr_separator, NULL);
+	g_return_val_if_fail (key_value_separator, NULL);
 
-	for (i = 0; i < num_values; i++) {
+	if (!attributes || !g_hash_table_size (attributes))
+		return NULL;
+
+	values = nm_utils_named_values_from_str_dict (attributes, &len);
+
+	str = g_string_new ("");
+
+	for (i = 0; i < len; i++) {
 		name = values[i].name;
 		variant = (GVariant *) values[i].value_ptr;
 		value = NULL;
@@ -6241,44 +6217,7 @@ _nm_utils_format_variant_attributes_full (GString *str,
 
 		sep = attr_separator;
 	}
-}
-
-/*
- * nm_utils_format_variant_attributes:
- * @attributes: (element-type utf8 GVariant): a #GHashTable mapping attribute names to #GVariant values
- * @attr_separator: the attribute separator character
- * @key_value_separator: character separating key and values
- *
- * Format attributes to a string.
- *
- * Returns: (transfer full): the string representing attributes, or %NULL
- *    in case there are no attributes
- *
- * Since: 1.8
- */
-char *
-nm_utils_format_variant_attributes (GHashTable *attributes,
-                                    char attr_separator,
-                                    char key_value_separator)
-{
-	GString *str = NULL;
-	gs_free NMUtilsNamedValue *values = NULL;
-	guint len;
 
-	g_return_val_if_fail (attr_separator, NULL);
-	g_return_val_if_fail (key_value_separator, NULL);
-
-	if (!attributes || !g_hash_table_size (attributes))
-		return NULL;
-
-	values = nm_utils_named_values_from_str_dict (attributes, &len);
-
-	str = g_string_new ("");
-	_nm_utils_format_variant_attributes_full (str,
-	                                          values,
-	                                          len,
-	                                          attr_separator,
-	                                          key_value_separator);
 	return g_string_free (str, FALSE);
 }
 
diff --git a/libnm-core/nm-utils.h b/libnm-core/nm-utils.h
index cf9572b9..70245869 100644
--- a/libnm-core/nm-utils.h
+++ b/libnm-core/nm-utils.h
@@ -34,9 +34,8 @@
 #include <linux/if_infiniband.h>
 
 #include "nm-core-enum-types.h"
-#include "nm-setting-sriov.h"
-#include "nm-setting-tc-config.h"
 #include "nm-setting-wireless-security.h"
+#include "nm-setting-tc-config.h"
 
 G_BEGIN_DECLS
 
@@ -214,7 +213,7 @@ NM_AVAILABLE_IN_1_2
 gboolean nm_utils_enum_from_str (GType type, const char *str, int *out_value, char **err_token);
 
 NM_AVAILABLE_IN_1_2
-const char **nm_utils_enum_get_values (GType type, int from, int to);
+const char **nm_utils_enum_get_values (GType type, gint from, gint to);
 
 NM_AVAILABLE_IN_1_6
 guint nm_utils_version (void);
@@ -251,17 +250,9 @@ char *nm_utils_tc_tfilter_to_str           (NMTCTfilter *tfilter, GError **error
 
 /*****************************************************************************/
 
-NM_AVAILABLE_IN_1_14
-char *nm_utils_sriov_vf_to_str (const NMSriovVF *vf, gboolean omit_index, GError **error);
-NM_AVAILABLE_IN_1_14
-NMSriovVF *nm_utils_sriov_vf_from_str (const char *str, GError **error);
-
-/*****************************************************************************/
-
 NM_AVAILABLE_IN_1_12
 gint64 nm_utils_get_timestamp_msec         (void);
 
-
 G_END_DECLS
 
 #endif /* __NM_UTILS_H__ */
diff --git a/libnm-core/nm-version.h b/libnm-core/nm-version.h
index 59482d4e..c2404895 100644
--- a/libnm-core/nm-version.h
+++ b/libnm-core/nm-version.h
@@ -160,18 +160,10 @@
 # define NM_AVAILABLE_IN_1_12
 #endif
 
-#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_1_14
-# define NM_DEPRECATED_IN_1_14           G_DEPRECATED
-# define NM_DEPRECATED_IN_1_14_FOR(f)    G_DEPRECATED_FOR(f)
+#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_12_2
+# define NM_AVAILABLE_IN_1_12_2          G_UNAVAILABLE(1,12.2)
 #else
-# define NM_DEPRECATED_IN_1_14
-# define NM_DEPRECATED_IN_1_14_FOR(f)
-#endif
-
-#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_14
-# define NM_AVAILABLE_IN_1_14            G_UNAVAILABLE(1,14)
-#else
-# define NM_AVAILABLE_IN_1_14
+# define NM_AVAILABLE_IN_1_12_2
 #endif
 
 #endif  /* NM_VERSION_H */
diff --git a/libnm-core/tests/meson.build b/libnm-core/tests/meson.build
index 627e6b53..2eeadd88 100644
--- a/libnm-core/tests/meson.build
+++ b/libnm-core/tests/meson.build
@@ -37,7 +37,8 @@ foreach test_unit: test_units
     c_args: [
         '-DNETWORKMANAGER_COMPILATION_TEST',
         '-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_LIBNM_CORE',
-      ],
+      ] +
+      nm_build_cflags,
     link_with: libnm_core
   )
   test(
diff --git a/libnm-core/tests/test-crypto.c b/libnm-core/tests/test-crypto.c
index 6b63e6fd..5fb26c1f 100644
--- a/libnm-core/tests/test-crypto.c
+++ b/libnm-core/tests/test-crypto.c
@@ -28,7 +28,7 @@
 #include <stdio.h>
 #include <string.h>
 
-#include "nm-crypto-impl.h"
+#include "crypto.h"
 #include "nm-utils.h"
 #include "nm-errors.h"
 #include "nm-core-internal.h"
@@ -99,20 +99,37 @@ static void
 test_cert (gconstpointer test_data)
 {
 	gs_free char *path = NULL;
-	gs_unref_bytes GBytes *cert = NULL;
+	GByteArray *array;
 	NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
 	GError *error = NULL;
-	gboolean success;
 
 	path = g_build_filename (TEST_CERT_DIR, (const char *) test_data, NULL);
 
-	success = nm_crypto_load_and_verify_certificate (path, &format, &cert, &error);
-	nmtst_assert_success (success, error);
+	array = crypto_load_and_verify_certificate (path, &format, &error);
+	g_assert_no_error (error);
 	g_assert_cmpint (format, ==, NM_CRYPTO_FILE_FORMAT_X509);
 
+	g_byte_array_free (array, TRUE);
+
 	g_assert (nm_utils_file_is_certificate (path));
 }
 
+static GByteArray *
+file_to_byte_array (const char *filename)
+{
+	char *contents;
+	GByteArray *array = NULL;
+	gsize length = 0;
+
+	if (g_file_get_contents (filename, &contents, &length, NULL)) {
+		array = g_byte_array_sized_new (length);
+		g_byte_array_append (array, (guint8 *) contents, length);
+		g_assert (array->len == length);
+		g_free (contents);
+	}
+	return array;
+}
+
 static void
 test_load_private_key (const char *path,
                        const char *password,
@@ -121,13 +138,13 @@ test_load_private_key (const char *path,
 {
 	NMCryptoKeyType key_type = NM_CRYPTO_KEY_TYPE_UNKNOWN;
 	gboolean is_encrypted = FALSE;
-	gs_unref_bytes GBytes *array = NULL;
+	GByteArray *array, *decrypted;
 	GError *error = NULL;
 
 	g_assert (nm_utils_file_is_private_key (path, &is_encrypted));
 	g_assert (is_encrypted);
 
-	array = nmtst_crypto_decrypt_openssl_private_key (path, password, &key_type, &error);
+	array = crypto_decrypt_openssl_private_key (path, password, &key_type, &error);
 	/* Even if the password is wrong, we should determine the key type */
 	g_assert_cmpint (key_type, ==, NM_CRYPTO_KEY_TYPE_RSA);
 
@@ -147,14 +164,16 @@ test_load_private_key (const char *path,
 	g_assert (array != NULL);
 
 	if (decrypted_path) {
-		gs_free char *contents = NULL;
-		gsize length;
-
 		/* Compare the crypto decrypted key against a known-good decryption */
-		if (!g_file_get_contents (decrypted_path, &contents, &length, NULL))
-			g_assert_not_reached ();
-		g_assert (nm_utils_gbytes_equal_mem (array, contents, length));
+		decrypted = file_to_byte_array (decrypted_path);
+		g_assert (decrypted != NULL);
+		g_assert (decrypted->len == array->len);
+		g_assert (memcmp (decrypted->data, array->data, array->len) == 0);
+
+		g_byte_array_free (decrypted, TRUE);
 	}
+
+	g_byte_array_free (array, TRUE);
 }
 
 static void
@@ -168,7 +187,7 @@ test_load_pkcs12 (const char *path,
 
 	g_assert (nm_utils_file_is_private_key (path, NULL));
 
-	format = nm_crypto_verify_private_key (path, password, &is_encrypted, &error);
+	format = crypto_verify_private_key (path, password, &is_encrypted, &error);
 	if (expected_error != -1) {
 		g_assert_error (error, NM_CRYPTO_ERROR, expected_error);
 		g_assert_cmpint (format, ==, NM_CRYPTO_FILE_FORMAT_UNKNOWN);
@@ -190,7 +209,7 @@ test_load_pkcs12_no_password (const char *path)
 	g_assert (nm_utils_file_is_private_key (path, NULL));
 
 	/* We should still get a valid returned crypto file format */
-	format = nm_crypto_verify_private_key (path, NULL, &is_encrypted, &error);
+	format = crypto_verify_private_key (path, NULL, &is_encrypted, &error);
 	g_assert_no_error (error);
 	g_assert_cmpint (format, ==, NM_CRYPTO_FILE_FORMAT_PKCS12);
 	g_assert (is_encrypted);
@@ -202,7 +221,7 @@ test_is_pkcs12 (const char *path, gboolean expect_fail)
 	gboolean is_pkcs12;
 	GError *error = NULL;
 
-	is_pkcs12 = nm_crypto_is_pkcs12_file (path, &error);
+	is_pkcs12 = crypto_is_pkcs12_file (path, &error);
 
 	if (expect_fail) {
 		g_assert_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_INVALID_DATA);
@@ -225,7 +244,7 @@ test_load_pkcs8 (const char *path,
 
 	g_assert (nm_utils_file_is_private_key (path, NULL));
 
-	format = nm_crypto_verify_private_key (path, password, &is_encrypted, &error);
+	format = crypto_verify_private_key (path, password, &is_encrypted, &error);
 	if (expected_error != -1) {
 		g_assert_error (error, NM_CRYPTO_ERROR, expected_error);
 		g_assert_cmpint (format, ==, NM_CRYPTO_FILE_FORMAT_UNKNOWN);
@@ -242,35 +261,34 @@ test_encrypt_private_key (const char *path,
                           const char *password)
 {
 	NMCryptoKeyType key_type = NM_CRYPTO_KEY_TYPE_UNKNOWN;
-	gs_unref_bytes GBytes *array = NULL;
-	gs_unref_bytes GBytes *encrypted = NULL;
-	gs_unref_bytes GBytes *re_decrypted = NULL;
+	GByteArray *array, *encrypted, *re_decrypted;
 	GError *error = NULL;
 
-	array = nmtst_crypto_decrypt_openssl_private_key (path, password, &key_type, &error);
-	nmtst_assert_success (array, error);
+	array = crypto_decrypt_openssl_private_key (path, password, &key_type, &error);
+	g_assert_no_error (error);
+	g_assert (array != NULL);
 	g_assert_cmpint (key_type, ==, NM_CRYPTO_KEY_TYPE_RSA);
 
 	/* Now re-encrypt the private key */
-	encrypted = nmtst_crypto_rsa_key_encrypt (g_bytes_get_data (array, NULL),
-	                                          g_bytes_get_size (array),
-	                                          password,
-	                                          NULL,
-	                                          &error);
-	nmtst_assert_success (encrypted, error);
+	encrypted = nm_utils_rsa_key_encrypt (array->data, array->len, password, NULL, &error);
+	g_assert_no_error (error);
+	g_assert (encrypted != NULL);
 
 	/* Then re-decrypt the private key */
 	key_type = NM_CRYPTO_KEY_TYPE_UNKNOWN;
-	re_decrypted = nmtst_crypto_decrypt_openssl_private_key_data (g_bytes_get_data (encrypted, NULL),
-	                                                              g_bytes_get_size (encrypted),
-	                                                              password,
-	                                                              &key_type,
-	                                                              &error);
-	nmtst_assert_success (re_decrypted, error);
+	re_decrypted = crypto_decrypt_openssl_private_key_data (encrypted->data, encrypted->len,
+	                                                        password, &key_type, &error);
+	g_assert_no_error (error);
+	g_assert (re_decrypted != NULL);
 	g_assert_cmpint (key_type, ==, NM_CRYPTO_KEY_TYPE_RSA);
 
 	/* Compare the original decrypted key with the re-decrypted key */
-	g_assert (g_bytes_equal (array, re_decrypted));
+	g_assert_cmpint (array->len, ==, re_decrypted->len);
+	g_assert (!memcmp (array->data, re_decrypted->data, array->len));
+
+	g_byte_array_free (re_decrypted, TRUE);
+	g_byte_array_free (encrypted, TRUE);
+	g_byte_array_free (array, TRUE);
 }
 
 static void
@@ -399,16 +417,15 @@ test_md5 (void)
 
 	for (i = 0; i < G_N_ELEMENTS (md5_tests); i++) {
 		memset (digest, 0, sizeof (digest));
-		nm_crypto_md5_hash ((const guint8 *) md5_tests[i].salt,
-		                    /* nm_crypto_md5_hash() used to clamp salt_len to 8.  It
-		                     * doesn't any more, so we need to do it here now to
-		                     * get output that matches md5_tests[i].result.
-		                     */
-		                    md5_tests[i].salt ? 8 : 0,
-		                    (const guint8 *) md5_tests[i].password,
-		                    strlen (md5_tests[i].password),
-		                    (guint8 *) digest,
-		                    md5_tests[i].digest_size);
+		crypto_md5_hash (md5_tests[i].salt,
+		                 /* crypto_md5_hash() used to clamp salt_len to 8.  It
+		                  * doesn't any more, so we need to do it here now to
+		                  * get output that matches md5_tests[i].result.
+		                  */
+		                 md5_tests[i].salt ? 8 : 0,
+		                 md5_tests[i].password,
+		                 strlen (md5_tests[i].password),
+		                 digest, md5_tests[i].digest_size);
 
 		hex = nm_utils_bin2hexstr (digest, md5_tests[i].digest_size, -1);
 		g_assert_cmpstr (hex, ==, md5_tests[i].result);
@@ -427,7 +444,7 @@ main (int argc, char **argv)
 
 	nmtst_init (&argc, &argv, TRUE);
 
-	success = _nm_crypto_init (&error);
+	success = crypto_init (&error);
 	g_assert_no_error (error);
 	g_assert (success);
 
diff --git a/libnm-core/tests/test-general.c b/libnm-core/tests/test-general.c
index 38531248..3b9debd9 100644
--- a/libnm-core/tests/test-general.c
+++ b/libnm-core/tests/test-general.c
@@ -15,7 +15,7 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
- * Copyright 2008 - 2018 Red Hat, Inc.
+ * Copyright 2008 - 2011 Red Hat, Inc.
  *
  */
 
@@ -43,7 +43,6 @@
 #include "nm-setting-bridge-port.h"
 #include "nm-setting-cdma.h"
 #include "nm-setting-connection.h"
-#include "nm-setting-ethtool.h"
 #include "nm-setting-generic.h"
 #include "nm-setting-gsm.h"
 #include "nm-setting-infiniband.h"
@@ -62,11 +61,9 @@
 #include "nm-setting-wired.h"
 #include "nm-setting-wireless.h"
 #include "nm-setting-wireless-security.h"
-#include "nm-setting-wpan.h"
 #include "nm-simple-connection.h"
 #include "nm-keyfile-internal.h"
 #include "nm-utils/nm-dedup-multi.h"
-#include "nm-ethtool-utils.h"
 
 #include "test-general-enums.h"
 
@@ -225,8 +222,8 @@ test_nm_g_slice_free_fcn (void)
 	p = g_slice_new (gint32);
 	(nm_g_slice_free_fcn (gint32)) (p);
 
-	p = g_slice_new (int);
-	(nm_g_slice_free_fcn (int)) (p);
+	p = g_slice_new (gint);
+	(nm_g_slice_free_fcn (gint)) (p);
 
 	p = g_slice_new (gint64);
 	nm_g_slice_free_fcn_gint64 (p);
@@ -238,7 +235,7 @@ test_nm_g_slice_free_fcn (void)
 /*****************************************************************************/
 
 static void
-_do_test_nm_utils_strsplit_set (gboolean escape, const char *str, ...)
+_do_test_nm_utils_strsplit_set (const char *str, ...)
 {
 	gs_unref_ptrarray GPtrArray *args_array = g_ptr_array_new ();
 	const char *const*args;
@@ -255,7 +252,7 @@ _do_test_nm_utils_strsplit_set (gboolean escape, const char *str, ...)
 
 	args = (const char *const*) args_array->pdata;
 
-	words = nm_utils_strsplit_set (str, " \t\n", escape);
+	words = nm_utils_strsplit_set (str, " \t\n");
 
 	if (!args[0]) {
 		g_assert (!words);
@@ -268,7 +265,7 @@ _do_test_nm_utils_strsplit_set (gboolean escape, const char *str, ...)
 		g_assert (args[i]);
 		g_assert (words[i]);
 		g_assert (args[i][0]);
-		g_assert (escape || NM_STRCHAR_ALL (args[i], ch, !NM_IN_SET (ch, ' ', '\t', '\n')));
+		g_assert (NM_STRCHAR_ALL (args[i], ch, !NM_IN_SET (ch, ' ', '\t', '\n')));
 		g_assert_cmpstr (args[i], ==, words[i]);
 	}
 }
@@ -279,29 +276,21 @@ _do_test_nm_utils_strsplit_set (gboolean escape, const char *str, ...)
 static void
 test_nm_utils_strsplit_set (void)
 {
-	do_test_nm_utils_strsplit_set (FALSE, NULL);
-	do_test_nm_utils_strsplit_set (FALSE, "");
-	do_test_nm_utils_strsplit_set (FALSE, "\t");
-	do_test_nm_utils_strsplit_set (FALSE, " \t\n");
-	do_test_nm_utils_strsplit_set (FALSE, "a", "a");
-	do_test_nm_utils_strsplit_set (FALSE, "a b", "a", "b");
-	do_test_nm_utils_strsplit_set (FALSE, "a\rb", "a\rb");
-	do_test_nm_utils_strsplit_set (FALSE, "  a\rb  ", "a\rb");
-	do_test_nm_utils_strsplit_set (FALSE, "  a bbbd afds ere", "a", "bbbd", "afds", "ere");
-	do_test_nm_utils_strsplit_set (FALSE,
-	                               "1 2 3 4 5 6 7 8 9 0 "
+	do_test_nm_utils_strsplit_set (NULL);
+	do_test_nm_utils_strsplit_set ("");
+	do_test_nm_utils_strsplit_set ("\t");
+	do_test_nm_utils_strsplit_set (" \t\n");
+	do_test_nm_utils_strsplit_set ("a", "a");
+	do_test_nm_utils_strsplit_set ("a b", "a", "b");
+	do_test_nm_utils_strsplit_set ("a\rb", "a\rb");
+	do_test_nm_utils_strsplit_set ("  a\rb  ", "a\rb");
+	do_test_nm_utils_strsplit_set ("  a bbbd afds ere", "a", "bbbd", "afds", "ere");
+	do_test_nm_utils_strsplit_set ("1 2 3 4 5 6 7 8 9 0 "
 	                               "1 2 3 4 5 6 7 8 9 0 "
 	                               "1 2 3 4 5 6 7 8 9 0",
 	                               "1", "2", "3", "4", "5", "6", "7", "8", "9", "0",
 	                               "1", "2", "3", "4", "5", "6", "7", "8", "9", "0",
 	                               "1", "2", "3", "4", "5", "6", "7", "8", "9", "0");
-	do_test_nm_utils_strsplit_set (TRUE, "\\", "\\");
-	do_test_nm_utils_strsplit_set (TRUE, "\\ ", "\\ ");
-	do_test_nm_utils_strsplit_set (TRUE, "\\\\", "\\\\");
-	do_test_nm_utils_strsplit_set (TRUE, "\\\t", "\\\t");
-	do_test_nm_utils_strsplit_set (TRUE, "foo\\", "foo\\");
-	do_test_nm_utils_strsplit_set (TRUE, "bar foo\\", "bar", "foo\\");
-	do_test_nm_utils_strsplit_set (TRUE, "\\ a b\\ \\  c", "\\ a", "b\\ \\ ", "c");
 }
 
 /*****************************************************************************/
@@ -2605,7 +2594,6 @@ test_connection_diff_a_only (void)
 			{ NM_SETTING_CONNECTION_AUTOCONNECT,          NM_SETTING_DIFF_RESULT_IN_A },
 			{ NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY, NM_SETTING_DIFF_RESULT_IN_A },
 			{ NM_SETTING_CONNECTION_AUTOCONNECT_RETRIES,  NM_SETTING_DIFF_RESULT_IN_A },
-			{ NM_SETTING_CONNECTION_MULTI_CONNECT,        NM_SETTING_DIFF_RESULT_IN_A },
 			{ NM_SETTING_CONNECTION_READ_ONLY,            NM_SETTING_DIFF_RESULT_IN_A },
 			{ NM_SETTING_CONNECTION_PERMISSIONS,          NM_SETTING_DIFF_RESULT_IN_A },
 			{ NM_SETTING_CONNECTION_ZONE,                 NM_SETTING_DIFF_RESULT_IN_A },
@@ -2618,7 +2606,6 @@ test_connection_diff_a_only (void)
 			{ NM_SETTING_CONNECTION_LLDP,                 NM_SETTING_DIFF_RESULT_IN_A },
 			{ NM_SETTING_CONNECTION_AUTH_RETRIES,         NM_SETTING_DIFF_RESULT_IN_A },
 			{ NM_SETTING_CONNECTION_MDNS,                 NM_SETTING_DIFF_RESULT_IN_A },
-			{ NM_SETTING_CONNECTION_LLMNR,                NM_SETTING_DIFF_RESULT_IN_A },
 			{ NULL, NM_SETTING_DIFF_RESULT_UNKNOWN }
 		} },
 		{ NM_SETTING_WIRED_SETTING_NAME, {
@@ -5341,17 +5328,18 @@ test_hexstr2bin (void)
 		{ "aab:ccc:ddd" },
 		{ "aab::ccc:ddd" },
 	};
+	GBytes *b;
 	guint i;
 
 	for (i = 0; i < G_N_ELEMENTS (items); i++) {
-		gs_unref_bytes GBytes *b = NULL;
-
 		b = nm_utils_hexstr2bin (items[i].str);
-		if (items[i].expected_len)
+		if (items[i].expected_len) {
 			g_assert (b);
-		else
-			g_assert (!b);
-		g_assert (nm_utils_gbytes_equal_mem (b, items[i].expected, items[i].expected_len));
+			g_assert_cmpint (g_bytes_get_size (b), ==, items[i].expected_len);
+			g_assert (memcmp (g_bytes_get_data (b, NULL), items[i].expected, g_bytes_get_size (b)) == 0);
+			g_bytes_unref (b);
+		} else
+			g_assert (b == NULL);
 	}
 }
 
@@ -6045,7 +6033,7 @@ static void
 test_nm_utils_is_power_of_two (void)
 {
 	guint64 xyes, xno;
-	int i, j;
+	gint i, j;
 	GRand *rand = nmtst_get_rand ();
 	int numbits;
 
@@ -6136,7 +6124,7 @@ _test_find_binary_search_do (const int *array, gsize len)
 
 	expected_result = _nm_utils_ptrarray_find_first (parray, len, pneedle);
 
-	idx = nm_utils_ptrarray_find_binary_search (parray, len, pneedle, _test_find_binary_search_cmp, NULL, &idx_first, &idx_last);
+	idx = _nm_utils_ptrarray_find_binary_search (parray, len, pneedle, _test_find_binary_search_cmp, NULL, &idx_first, &idx_last);
 	if (expected_result >= 0) {
 		g_assert_cmpint (expected_result, ==, idx);
 	} else {
@@ -6198,12 +6186,12 @@ _test_find_binary_search_do_uint32 (const int *int_array, gsize len)
 			expected_result = idx;
 	}
 
-	idx = nm_utils_array_find_binary_search (array,
-	                                         sizeof (guint32),
-	                                         len,
-	                                         &NEEDLE,
-	                                         nm_cmp_uint32_p_with_data,
-	                                         NULL);
+	idx = _nm_utils_array_find_binary_search (array,
+	                                          sizeof (guint32),
+	                                          len,
+	                                          &NEEDLE,
+	                                          nm_cmp_uint32_p_with_data,
+	                                          NULL);
 	if (expected_result >= 0)
 		g_assert_cmpint (expected_result, ==, idx);
 	else {
@@ -6303,11 +6291,11 @@ test_nm_utils_ptrarray_find_binary_search_with_duplicates (void)
 			for (i = 0; i < i_len + BIN_SEARCH_W_DUPS_JITTER; i++) {
 				gconstpointer p = GINT_TO_POINTER (i);
 
-				idx = nm_utils_ptrarray_find_binary_search (arr, i_len, p, _test_bin_search2_cmp, NULL, &idx_first, &idx_last);
+				idx = _nm_utils_ptrarray_find_binary_search (arr, i_len, p, _test_bin_search2_cmp, NULL, &idx_first, &idx_last);
 
 				idx_first2 = _nm_utils_ptrarray_find_first (arr, i_len, p);
 
-				idx2 = nm_utils_array_find_binary_search (arr, sizeof (gpointer), i_len, &p, _test_bin_search2_cmp_p, NULL);
+				idx2 = _nm_utils_array_find_binary_search (arr, sizeof (gpointer), i_len, &p, _test_bin_search2_cmp_p, NULL);
 				g_assert_cmpint (idx, ==, idx2);
 
 				if (idx_first2 < 0) {
@@ -6559,161 +6547,74 @@ test_nm_utils_enum (void)
 /*****************************************************************************/
 
 static void
-_do_test_utils_str_utf8safe_unescape (const char *str, const char *expected, gsize expected_len)
+do_test_utils_str_utf8safe (const char *str, const char *expected, NMUtilsStrUtf8SafeFlags flags)
 {
-	gsize l;
-	const char *s;
-	gs_free gpointer buf_free_1 = NULL;
-	gs_free char *str_free_1 = NULL;
+	const char *str_safe, *s;
+	gs_free char *str2 = NULL;
+	gs_free char *str3 = NULL;
 
-	s = nm_utils_buf_utf8safe_unescape (str, &l, &buf_free_1);
-	g_assert_cmpint (expected_len, ==, l);
-	g_assert_cmpstr (s, ==, expected);
+	str_safe = nm_utils_str_utf8safe_escape (str, flags, &str2);
 
-	if (str == NULL) {
-		g_assert (!s);
-		g_assert (!buf_free_1);
-		g_assert_cmpint (l, ==, 0);
-	} else {
-		g_assert (s);
-		if (!strchr (str, '\\')) {
-			g_assert (!buf_free_1);
-			g_assert (s == str);
-			g_assert_cmpint (l, ==, strlen (str));
-		} else {
-			g_assert (buf_free_1);
-			g_assert (s == buf_free_1);
-			g_assert (memcmp (s, expected, expected_len) == 0);
-		}
-	}
-
-	if (   expected
-	    && l == strlen (expected)) {
-		/* there are no embeeded NULs. Check that nm_utils_str_utf8safe_unescape() yields the same result. */
-		s = nm_utils_str_utf8safe_unescape (str, &str_free_1);
-		g_assert_cmpstr (s, ==, expected);
-		if (strchr (str, '\\')) {
-			g_assert (str_free_1 != str);
-			g_assert (s == str_free_1);
-		} else
-			g_assert (s == str);
-	}
-}
-
-#define do_test_utils_str_utf8safe_unescape(str, expected) \
-	_do_test_utils_str_utf8safe_unescape (""str"", expected, NM_STRLEN (expected))
-
-static void
-_do_test_utils_str_utf8safe (const char *str, gsize str_len, const char *expected, NMUtilsStrUtf8SafeFlags flags)
-{
-	const char *str_safe;
-	const char *buf_safe;
-	const char *s;
-	gs_free gpointer buf_free_1 = NULL;
-	gs_free char *str_free_1 = NULL;
-	gs_free char *str_free_2 = NULL;
-	gs_free char *str_free_3 = NULL;
-	gs_free char *str_free_4 = NULL;
-	gs_free char *str_free_5 = NULL;
-	gs_free char *str_free_6 = NULL;
-	gs_free char *str_free_7 = NULL;
-	gs_free char *str_free_8 = NULL;
-	gboolean str_has_nul = FALSE;
-
-	buf_safe = nm_utils_buf_utf8safe_escape (str, str_len, flags, &str_free_1);
-
-	str_safe = nm_utils_str_utf8safe_escape (str, flags, &str_free_2);
-
-	if (str_len == 0) {
-		g_assert (buf_safe == NULL);
-		g_assert (str_free_1 == NULL);
-		g_assert (str_safe == str);
-		g_assert (str == NULL || str[0] == '\0');
-		g_assert (str_free_2 == NULL);
-	} else if (str_len == strlen (str)) {
-		g_assert (buf_safe);
-		g_assert_cmpstr (buf_safe, ==, str_safe);
-
-		/* nm_utils_buf_utf8safe_escape() can only return a pointer equal to the input string,
-		 * if and only if str_len is negative. Otherwise, the input str won't be NUL terminated
-		 * and cannot be returned. */
-		g_assert (buf_safe != str);
-		g_assert (buf_safe == str_free_1);
-	} else
-		str_has_nul = TRUE;
-
-	str_free_3 = nm_utils_str_utf8safe_escape_cp (str, flags);
-	g_assert_cmpstr (str_free_3, ==, str_safe);
-	g_assert ((!str && !str_free_3) || (str != str_free_3));
-
-	if (str_len > 0)
-		_do_test_utils_str_utf8safe_unescape (buf_safe, str, str_len);
+	str3 = nm_utils_str_utf8safe_escape_cp (str, flags);
+	g_assert_cmpstr (str3, ==, str_safe);
+	g_assert ((!str && !str3) || (str != str3));
+	g_clear_pointer (&str3, g_free);
 
 	if (expected == NULL) {
-		g_assert (!str_has_nul);
-
 		g_assert (str_safe == str);
-		g_assert (!str_free_2);
+		g_assert (!str2);
 		if (str) {
 			g_assert (!strchr (str, '\\'));
 			g_assert (g_utf8_validate (str, -1, NULL));
 		}
 
-		g_assert (str == nm_utils_str_utf8safe_unescape (str_safe, &str_free_4));
-		g_assert (!str_free_4);
+		g_assert (str == nm_utils_str_utf8safe_unescape (str_safe, &str3));
+		g_assert (!str3);
 
-		str_free_5 = nm_utils_str_utf8safe_unescape_cp (str_safe);
+		str3 = nm_utils_str_utf8safe_unescape_cp (str_safe);
 		if (str) {
-			g_assert (str_free_5 != str);
-			g_assert_cmpstr (str_free_5, ==, str);
+			g_assert (str3 != str);
+			g_assert_cmpstr (str3, ==, str);
 		} else
-			g_assert (!str_free_5);
+			g_assert (!str3);
+		g_clear_pointer (&str3, g_free);
 		return;
 	}
 
-	if (!str_has_nul) {
-		g_assert (str);
-		g_assert (str_safe != str);
-		g_assert (str_safe == str_free_2);
-		g_assert (   strchr (str, '\\')
-		          || !g_utf8_validate (str, -1, NULL)
-		          || (   NM_FLAGS_HAS (flags, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_NON_ASCII)
-		              && NM_STRCHAR_ANY (str, ch, (guchar) ch >= 127))
-		          || (   NM_FLAGS_HAS (flags, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL)
-		              && NM_STRCHAR_ANY (str, ch, (guchar) ch < ' ')));
-		g_assert (g_utf8_validate (str_safe, -1, NULL));
+	g_assert (str);
+	g_assert (str_safe != str);
+	g_assert (str_safe == str2);
+	g_assert (   strchr (str, '\\')
+	          || !g_utf8_validate (str, -1, NULL)
+	          || (   NM_FLAGS_HAS (flags, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_NON_ASCII)
+	              && NM_STRCHAR_ANY (str, ch, (guchar) ch >= 127))
+	          || (   NM_FLAGS_HAS (flags, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL)
+	              && NM_STRCHAR_ANY (str, ch, (guchar) ch < ' ')));
+	g_assert (g_utf8_validate (str_safe, -1, NULL));
 
-		str_free_6 = g_strcompress (str_safe);
-		g_assert_cmpstr (str, ==, str_free_6);
+	str3 = g_strcompress (str_safe);
+	g_assert_cmpstr (str, ==, str3);
+	g_clear_pointer (&str3, g_free);
 
-		str_free_7 = nm_utils_str_utf8safe_unescape_cp (str_safe);
-		g_assert (str_free_7 != str);
-		g_assert_cmpstr (str_free_7, ==, str);
+	str3 = nm_utils_str_utf8safe_unescape_cp (str_safe);
+	g_assert (str3 != str);
+	g_assert_cmpstr (str3, ==, str);
+	g_clear_pointer (&str3, g_free);
 
-		s = nm_utils_str_utf8safe_unescape (str_safe, &str_free_8);
-		g_assert (str_free_8 != str);
-		g_assert (s == str_free_8);
-		g_assert_cmpstr (str_free_8, ==, str);
-
-		g_assert_cmpstr (str_safe, ==, expected);
-
-		return;
-	}
-
-	g_assert_cmpstr (buf_safe, ==, expected);
+	s = nm_utils_str_utf8safe_unescape (str_safe, &str3);
+	g_assert (str3 != str);
+	g_assert (s == str3);
+	g_assert_cmpstr (str3, ==, str);
+	g_clear_pointer (&str3, g_free);
 
+	g_assert_cmpstr (str_safe, ==, expected);
 }
-#define do_test_utils_str_utf8safe(str, expected, flags) \
-	_do_test_utils_str_utf8safe (""str"", NM_STRLEN (str), expected, flags)
 
 static void
 test_utils_str_utf8safe (void)
 {
-	_do_test_utils_str_utf8safe (NULL, 0, NULL,                                   NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
-
+	do_test_utils_str_utf8safe (NULL, NULL,                                       NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
 	do_test_utils_str_utf8safe ("", NULL,                                         NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
-	do_test_utils_str_utf8safe ("\\", "\\\\",                                     NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
-	do_test_utils_str_utf8safe ("\\a", "\\\\a",                                   NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
 	do_test_utils_str_utf8safe ("\314", "\\314",                                  NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
 	do_test_utils_str_utf8safe ("\314\315x\315\315x", "\\314\\315x\\315\\315x",   NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
 	do_test_utils_str_utf8safe ("\314\315xx", "\\314\\315xx",                     NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
@@ -6735,18 +6636,6 @@ test_utils_str_utf8safe (void)
 	do_test_utils_str_utf8safe ("㈞abä㈞b", NULL,                                 NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
 	do_test_utils_str_utf8safe ("abäb", "ab\\303\\244b",                          NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_NON_ASCII);
 	do_test_utils_str_utf8safe ("ab\ab", "ab\\007b",                              NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL);
-
-	do_test_utils_str_utf8safe ("\0", "\\000",                                    NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
-	do_test_utils_str_utf8safe ("\0a\0", "\\000a\\000",                           NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
-	do_test_utils_str_utf8safe ("\\\0", "\\\\\\000",                              NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
-	do_test_utils_str_utf8safe ("\n\0", "\n\\000",                                NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
-	do_test_utils_str_utf8safe ("\n\0", "\\012\\000",                             NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL);
-
-	do_test_utils_str_utf8safe_unescape ("\n\\0", "\n\0");
-	do_test_utils_str_utf8safe_unescape ("\n\\01", "\n\01");
-	do_test_utils_str_utf8safe_unescape ("\n\\012", "\n\012");
-	do_test_utils_str_utf8safe_unescape ("\n\\.", "\n.");
-	do_test_utils_str_utf8safe_unescape ("\\n\\.3\\r", "\n.3\r");
 }
 
 /*****************************************************************************/
@@ -7062,7 +6951,7 @@ test_route_attributes_format (void)
 /*****************************************************************************/
 
 static gboolean
-do_test_nm_set_out_called (int *call_count)
+do_test_nm_set_out_called (gint *call_count)
 {
 	(*call_count)++;
 	return TRUE;
@@ -7116,120 +7005,6 @@ test_get_start_time_for_pid (void)
 
 /*****************************************************************************/
 
-static void
-test_nm_va_args_macros (void)
-{
-#define GET_NARG_1(...) \
-	NM_NARG (__VA_ARGS__)
-
-	g_assert_cmpint ( 0, ==, GET_NARG_1 ());
-	g_assert_cmpint ( 1, ==, GET_NARG_1 (x));
-	g_assert_cmpint ( 2, ==, GET_NARG_1 ( ,  ));
-	g_assert_cmpint ( 2, ==, GET_NARG_1 ( , x));
-	g_assert_cmpint ( 2, ==, GET_NARG_1 (x,  ));
-	g_assert_cmpint ( 2, ==, GET_NARG_1 (x, x));
-	g_assert_cmpint ( 3, ==, GET_NARG_1 ( ,  ,  ));
-	g_assert_cmpint ( 3, ==, GET_NARG_1 ( ,  , x));
-	g_assert_cmpint ( 3, ==, GET_NARG_1 ( , x,  ));
-	g_assert_cmpint ( 3, ==, GET_NARG_1 ( , x, x));
-	g_assert_cmpint ( 3, ==, GET_NARG_1 (x,  ,  ));
-	g_assert_cmpint ( 3, ==, GET_NARG_1 (x,  , x));
-	g_assert_cmpint ( 3, ==, GET_NARG_1 (x, x,  ));
-	g_assert_cmpint ( 3, ==, GET_NARG_1 (x, x, x));
-	g_assert_cmpint ( 4, ==, GET_NARG_1 ( ,  ,  ,  ));
-	g_assert_cmpint ( 4, ==, GET_NARG_1 ( ,  ,  , x));
-	g_assert_cmpint ( 4, ==, GET_NARG_1 ( ,  , x,  ));
-	g_assert_cmpint ( 4, ==, GET_NARG_1 ( ,  , x, x));
-	g_assert_cmpint ( 4, ==, GET_NARG_1 ( , x,  ,  ));
-	g_assert_cmpint ( 4, ==, GET_NARG_1 ( , x,  , x));
-	g_assert_cmpint ( 4, ==, GET_NARG_1 ( , x, x,  ));
-	g_assert_cmpint ( 4, ==, GET_NARG_1 ( , x, x, x));
-	g_assert_cmpint ( 4, ==, GET_NARG_1 (x,  ,  ,  ));
-	g_assert_cmpint ( 4, ==, GET_NARG_1 (x,  ,  , x));
-	g_assert_cmpint ( 4, ==, GET_NARG_1 (x,  , x,  ));
-	g_assert_cmpint ( 4, ==, GET_NARG_1 (x,  , x, x));
-	g_assert_cmpint ( 4, ==, GET_NARG_1 (x, x,  ,  ));
-	g_assert_cmpint ( 4, ==, GET_NARG_1 (x, x,  , x));
-	g_assert_cmpint ( 4, ==, GET_NARG_1 (x, x, x,  ));
-	g_assert_cmpint ( 4, ==, GET_NARG_1 (x, x, x, x));
-
-	g_assert_cmpint ( 5, ==, GET_NARG_1 (x, x, x, x, x));
-	g_assert_cmpint ( 6, ==, GET_NARG_1 (x, x, x, x, x, x));
-	g_assert_cmpint ( 7, ==, GET_NARG_1 (x, x, x, x, x, x, x));
-	g_assert_cmpint ( 8, ==, GET_NARG_1 (x, x, x, x, x, x, x, x));
-	g_assert_cmpint ( 9, ==, GET_NARG_1 (x, x, x, x, x, x, x, x, x));
-	g_assert_cmpint (10, ==, GET_NARG_1 (x, x, x, x, x, x, x, x, x, x));
-
-	G_STATIC_ASSERT_EXPR (0 == GET_NARG_1 ());
-	G_STATIC_ASSERT_EXPR (1 == GET_NARG_1 (x));
-	G_STATIC_ASSERT_EXPR (2 == GET_NARG_1 (x, x));
-}
-
-/*****************************************************************************/
-
-static void
-test_ethtool_offload (void)
-{
-	const NMEthtoolData *d;
-
-	g_assert_cmpint (nm_ethtool_id_get_by_name ("invalid"),    ==, NM_ETHTOOL_ID_UNKNOWN);
-	g_assert_cmpint (nm_ethtool_id_get_by_name ("feature-rx"), ==, NM_ETHTOOL_ID_FEATURE_RX);
-
-	d = nm_ethtool_data_get_by_optname (NM_ETHTOOL_OPTNAME_FEATURE_RXHASH);
-	g_assert (d);
-	g_assert_cmpint (d->id, ==, NM_ETHTOOL_ID_FEATURE_RXHASH);
-	g_assert_cmpstr (d->optname, ==, NM_ETHTOOL_OPTNAME_FEATURE_RXHASH);
-}
-
-static void
-test_nm_utils_escape_spaces (void)
-{
-	char *to_free;
-
-	g_assert_cmpstr (_nm_utils_escape_spaces (NULL, &to_free), ==, NULL);
-	g_free (to_free);
-
-	g_assert_cmpstr (_nm_utils_escape_spaces ("", &to_free), ==, "");
-	g_free (to_free);
-
-	g_assert_cmpstr (_nm_utils_escape_spaces (" ", &to_free), ==, "\\ ");
-	g_free (to_free);
-
-	g_assert_cmpstr (_nm_utils_escape_spaces ("\t ", &to_free), ==, "\\\t\\ ");
-	g_free (to_free);
-
-	g_assert_cmpstr (_nm_utils_escape_spaces ("abc", &to_free), ==, "abc");
-	g_free (to_free);
-
-	g_assert_cmpstr (_nm_utils_escape_spaces ("abc def", &to_free), ==, "abc\\ def");
-	g_free (to_free);
-
-	g_assert_cmpstr (_nm_utils_escape_spaces ("abc\tdef", &to_free), ==, "abc\\\tdef");
-	g_free (to_free);
-}
-
-static void
-test_nm_utils_unescape_spaces (void)
-{
-#define CHECK_STR(in, out) \
-	G_STMT_START { \
-		gs_free char *str = g_strdup (in); \
-		\
-		g_assert_cmpstr (_nm_utils_unescape_spaces (str), ==, out); \
-	} G_STMT_END
-
-	CHECK_STR ("\\a", "\\a");
-	CHECK_STR ("foobar", "foobar");
-	CHECK_STR ("foo bar", "foo bar");
-	CHECK_STR ("foo\\ bar", "foo bar");
-	CHECK_STR ("foo\\", "foo\\");
-	CHECK_STR ("\\\\\t", "\\\t");
-
-#undef CHECK_STR
-}
-
-/*****************************************************************************/
-
 NMTST_DEFINE ();
 
 int main (int argc, char **argv)
@@ -7369,8 +7144,8 @@ int main (int argc, char **argv)
 
 	g_test_add_func ("/core/general/_nm_utils_ascii_str_to_int64", test_nm_utils_ascii_str_to_int64);
 	g_test_add_func ("/core/general/nm_utils_is_power_of_two", test_nm_utils_is_power_of_two);
-	g_test_add_func ("/core/general/nm_utils_ptrarray_find_binary_search", test_nm_utils_ptrarray_find_binary_search);
-	g_test_add_func ("/core/general/nm_utils_ptrarray_find_binary_search_with_duplicates", test_nm_utils_ptrarray_find_binary_search_with_duplicates);
+	g_test_add_func ("/core/general/_nm_utils_ptrarray_find_binary_search", test_nm_utils_ptrarray_find_binary_search);
+	g_test_add_func ("/core/general/_nm_utils_ptrarray_find_binary_search_with_duplicates", test_nm_utils_ptrarray_find_binary_search_with_duplicates);
 	g_test_add_func ("/core/general/_nm_utils_strstrdictkey", test_nm_utils_strstrdictkey);
 	g_test_add_func ("/core/general/nm_ptrarray_len", test_nm_ptrarray_len);
 
@@ -7378,16 +7153,12 @@ int main (int argc, char **argv)
 	g_test_add_func ("/core/general/_nm_utils_dns_option_find_idx", test_nm_utils_dns_option_find_idx);
 	g_test_add_func ("/core/general/_nm_utils_validate_json", test_nm_utils_check_valid_json);
 	g_test_add_func ("/core/general/_nm_utils_team_config_equal", test_nm_utils_team_config_equal);
-	g_test_add_func ("/core/general/_nm_utils_escape_spaces", test_nm_utils_escape_spaces);
-	g_test_add_func ("/core/general/_nm_utils_unescape_spaces", test_nm_utils_unescape_spaces);
 	g_test_add_func ("/core/general/test_nm_utils_enum", test_nm_utils_enum);
 	g_test_add_func ("/core/general/nm-set-out", test_nm_set_out);
 	g_test_add_func ("/core/general/route_attributes/parse", test_route_attributes_parse);
 	g_test_add_func ("/core/general/route_attributes/format", test_route_attributes_format);
 
 	g_test_add_func ("/core/general/get_start_time_for_pid", test_get_start_time_for_pid);
-	g_test_add_func ("/core/general/test_nm_va_args_macros", test_nm_va_args_macros);
-	g_test_add_func ("/core/general/test_ethtool_offload", test_ethtool_offload);
 
 	return g_test_run ();
 }
diff --git a/libnm-core/tests/test-keyfile.c b/libnm-core/tests/test-keyfile.c
index d941fa22..672c72b6 100644
--- a/libnm-core/tests/test-keyfile.c
+++ b/libnm-core/tests/test-keyfile.c
@@ -127,8 +127,10 @@ _assert_gbytes (GBytes *bytes, gconstpointer data, gssize len)
 
 	if (!len)
 		g_assert (!bytes);
-
-	g_assert (nm_utils_gbytes_equal_mem (bytes, data, len));
+	else {
+		g_assert_cmpint (g_bytes_get_size (bytes), ==, len);
+		g_assert (memcmp (g_bytes_get_data (bytes, NULL), data, len) == 0);
+	}
 }
 
 static GKeyFile *
@@ -275,9 +277,8 @@ _keyfile_convert (NMConnection **con,
 
 				b1 = nm_setting_802_1x_get_ca_cert_blob (s1);
 				b2 = nm_setting_802_1x_get_ca_cert_blob (s2);
-				g_assert (b1);
-				g_assert (b2);
-				g_assert (g_bytes_equal (b1, b2));
+				g_assert_cmpint (g_bytes_get_size (b1), ==, g_bytes_get_size (b2));
+				g_assert (memcmp (g_bytes_get_data (b1, NULL), g_bytes_get_data (b2, NULL), g_bytes_get_size (b1)) == 0);
 				break;
 			}
 			default:
@@ -343,7 +344,8 @@ _test_8021x_cert_check (NMConnection *con,
 		}
 
 		g_assert (blob);
-		g_assert (nm_utils_gbytes_equal_mem (blob, value, val_len));
+		g_assert_cmpint (g_bytes_get_size (blob), ==, val_len);
+		g_assert (!memcmp (g_bytes_get_data (blob, NULL), value, val_len));
 
 		kval = g_key_file_get_string (keyfile, "802-1x", "ca-cert", NULL);
 		g_assert (kval);
diff --git a/libnm-core/tests/test-setting.c b/libnm-core/tests/test-setting.c
index c8eda381..e71d6b7c 100644
--- a/libnm-core/tests/test-setting.c
+++ b/libnm-core/tests/test-setting.c
@@ -23,12 +23,9 @@
 #include <string.h>
 
 #include "nm-utils.h"
-#include "nm-utils-private.h"
-#include "nm-core-internal.h"
 #include "nm-setting-8021x.h"
 #include "nm-setting-bond.h"
 #include "nm-setting-dcb.h"
-#include "nm-setting-ethtool.h"
 #include "nm-setting-team.h"
 #include "nm-setting-team-port.h"
 #include "nm-setting-tc-config.h"
@@ -37,7 +34,6 @@
 #include "nm-simple-connection.h"
 #include "nm-setting-connection.h"
 #include "nm-errors.h"
-#include "nm-keyfile-internal.h"
 
 #include "nm-utils/nm-test-utils.h"
 
@@ -50,7 +46,7 @@ compare_blob_data (const char *test,
                    const char *key_path,
                    GBytes *key)
 {
-	gs_free char *contents = NULL;
+	char *contents = NULL;
 	gsize len = 0;
 	GError *error = NULL;
 	gboolean success;
@@ -61,18 +57,18 @@ compare_blob_data (const char *test,
 	nmtst_assert_success (success, error);
 
 	g_assert_cmpmem (contents, len, g_bytes_get_data (key, NULL), g_bytes_get_size (key));
+
+	g_free (contents);
 }
 
 static void
 check_scheme_path (GBytes *value, const char *path)
 {
 	const guint8 *p;
-	gsize l;
 
 	g_assert (value);
 
-	p = g_bytes_get_data (value, &l);
-	g_assert_cmpint (l, ==, strlen (path) + NM_STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH) + 1);
+	p = g_bytes_get_data (value, NULL);
 	g_assert (memcmp (p, NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH, strlen (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH)) == 0);
 	p += strlen (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH);
 	g_assert (memcmp (p, path, strlen (path)) == 0);
@@ -1002,7 +998,7 @@ test_runner_loadbalance_sync_from_config (void)
 {
 	gs_unref_ptrarray GPtrArray *tx_hash = NULL;
 
-	tx_hash = g_ptr_array_new_with_free_func (g_free);
+	tx_hash = g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
 	g_ptr_array_add (tx_hash, g_strdup ("eth"));
 	g_ptr_array_add (tx_hash, g_strdup ("ipv4"));
 	g_ptr_array_add (tx_hash, g_strdup ("ipv6"));
@@ -1039,7 +1035,7 @@ test_runner_lacp_sync_from_config (void)
 {
 	gs_unref_ptrarray GPtrArray *tx_hash = NULL;
 
-	tx_hash = g_ptr_array_new_with_free_func (g_free);
+	tx_hash = g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
 	g_ptr_array_add (tx_hash, g_strdup ("eth"));
 	g_ptr_array_add (tx_hash, g_strdup ("ipv4"));
 	g_ptr_array_add (tx_hash, g_strdup ("ipv6"));
@@ -1267,307 +1263,6 @@ test_team_port_full_config (void)
 /*****************************************************************************/
 
 static void
-test_ethtool_1 (void)
-{
-	gs_unref_object NMConnection *con = NULL;
-	gs_unref_object NMConnection *con2 = NULL;
-	gs_unref_object NMConnection *con3 = NULL;
-	gs_unref_variant GVariant *variant = NULL;
-	gs_free_error GError *error = NULL;
-	gs_unref_keyfile GKeyFile *keyfile = NULL;
-	NMSettingConnection *s_con;
-	NMSettingEthtool *s_ethtool;
-	NMSettingEthtool *s_ethtool2;
-	NMSettingEthtool *s_ethtool3;
-
-	con = nmtst_create_minimal_connection ("ethtool-1",
-	                                        NULL,
-	                                        NM_SETTING_WIRED_SETTING_NAME,
-	                                        &s_con);
-	s_ethtool = NM_SETTING_ETHTOOL (nm_setting_ethtool_new ());
-	nm_connection_add_setting (con, NM_SETTING (s_ethtool));
-
-	nm_setting_ethtool_set_feature (s_ethtool,
-	                                NM_ETHTOOL_OPTNAME_FEATURE_RX,
-	                                NM_TERNARY_TRUE);
-	nm_setting_ethtool_set_feature (s_ethtool,
-	                                NM_ETHTOOL_OPTNAME_FEATURE_LRO,
-	                                NM_TERNARY_FALSE);
-
-	g_assert_cmpint (nm_setting_ethtool_get_feature (s_ethtool, NM_ETHTOOL_OPTNAME_FEATURE_RX), ==, NM_TERNARY_TRUE);
-	g_assert_cmpint (nm_setting_ethtool_get_feature (s_ethtool, NM_ETHTOOL_OPTNAME_FEATURE_LRO), ==, NM_TERNARY_FALSE);
-	g_assert_cmpint (nm_setting_ethtool_get_feature (s_ethtool, NM_ETHTOOL_OPTNAME_FEATURE_SG),  ==, NM_TERNARY_DEFAULT);
-
-	nmtst_connection_normalize (con);
-
-	variant = nm_connection_to_dbus (con, NM_CONNECTION_SERIALIZE_ALL);
-
-	con2 = nm_simple_connection_new_from_dbus (variant, &error);
-	nmtst_assert_success (con2, error);
-
-	s_ethtool2 = NM_SETTING_ETHTOOL (nm_connection_get_setting (con2, NM_TYPE_SETTING_ETHTOOL));
-
-	g_assert_cmpint (nm_setting_ethtool_get_feature (s_ethtool2, NM_ETHTOOL_OPTNAME_FEATURE_RX),  ==, NM_TERNARY_TRUE);
-	g_assert_cmpint (nm_setting_ethtool_get_feature (s_ethtool2, NM_ETHTOOL_OPTNAME_FEATURE_LRO), ==, NM_TERNARY_FALSE);
-	g_assert_cmpint (nm_setting_ethtool_get_feature (s_ethtool2, NM_ETHTOOL_OPTNAME_FEATURE_SG),  ==, NM_TERNARY_DEFAULT);
-
-	nmtst_assert_connection_verifies_without_normalization (con2);
-
-	nmtst_assert_connection_equals (con, FALSE, con2, FALSE);
-
-	keyfile = nm_keyfile_write (con, NULL, NULL, &error);
-	nmtst_assert_success (keyfile, error);
-
-	con3 = nm_keyfile_read (keyfile,
-	                        "ethtool-keyfile-name",
-	                        NULL,
-	                        NULL,
-	                        NULL,
-	                        &error);
-	nmtst_assert_success (con3, error);
-
-	nmtst_connection_normalize (con3);
-
-	nmtst_assert_connection_equals (con, FALSE, con3, FALSE);
-
-	s_ethtool3 = NM_SETTING_ETHTOOL (nm_connection_get_setting (con3, NM_TYPE_SETTING_ETHTOOL));
-
-	g_assert_cmpint (nm_setting_ethtool_get_feature (s_ethtool3, NM_ETHTOOL_OPTNAME_FEATURE_RX),  ==, NM_TERNARY_TRUE);
-	g_assert_cmpint (nm_setting_ethtool_get_feature (s_ethtool3, NM_ETHTOOL_OPTNAME_FEATURE_LRO), ==, NM_TERNARY_FALSE);
-	g_assert_cmpint (nm_setting_ethtool_get_feature (s_ethtool3, NM_ETHTOOL_OPTNAME_FEATURE_SG),  ==, NM_TERNARY_DEFAULT);
-}
-
-/*****************************************************************************/
-
-static void
-test_sriov_vf (void)
-{
-	NMSriovVF *vf1, *vf2;
-	GError *error = NULL;
-	char *str;
-
-	vf1 = nm_sriov_vf_new (1);
-	nm_sriov_vf_set_attribute (vf1, NM_SRIOV_VF_ATTRIBUTE_MAC, g_variant_new_string ("00:11:22:33:44:55"));
-	nm_sriov_vf_set_attribute (vf1, NM_SRIOV_VF_ATTRIBUTE_SPOOF_CHECK, g_variant_new_boolean (TRUE));
-	nm_sriov_vf_set_attribute (vf1, NM_SRIOV_VF_ATTRIBUTE_TRUST, g_variant_new_boolean (FALSE));
-	nm_sriov_vf_set_attribute (vf1, NM_SRIOV_VF_ATTRIBUTE_MIN_TX_RATE, g_variant_new_uint32 (100));
-	nm_sriov_vf_set_attribute (vf1, NM_SRIOV_VF_ATTRIBUTE_MAX_TX_RATE, g_variant_new_uint32 (500));
-
-	str = nm_utils_sriov_vf_to_str (vf1, FALSE, &error);
-	g_assert_no_error (error);
-	g_assert_cmpstr (str, ==, "1 mac=00:11:22:33:44:55 max-tx-rate=500 min-tx-rate=100 spoof-check=true trust=false");
-	g_free (str);
-
-	vf2 = nm_utils_sriov_vf_from_str (" 1  mac=00:11:22:33:44:55  max-tx-rate=500 min-tx-rate=100", &error);
-	nmtst_assert_success (vf2, error);
-	nm_sriov_vf_set_attribute (vf2, NM_SRIOV_VF_ATTRIBUTE_SPOOF_CHECK, g_variant_new_boolean (FALSE));
-	nm_sriov_vf_set_attribute (vf2, NM_SRIOV_VF_ATTRIBUTE_SPOOF_CHECK, g_variant_new_boolean (TRUE));
-	nm_sriov_vf_set_attribute (vf2, NM_SRIOV_VF_ATTRIBUTE_TRUST, g_variant_new_boolean (TRUE));
-	nm_sriov_vf_set_attribute (vf2, NM_SRIOV_VF_ATTRIBUTE_TRUST, NULL);
-	nm_sriov_vf_set_attribute (vf2, NM_SRIOV_VF_ATTRIBUTE_TRUST, g_variant_new_boolean (FALSE));
-
-	g_assert (nm_sriov_vf_equal (vf1, vf2));
-
-	nm_sriov_vf_unref (vf1);
-	nm_sriov_vf_unref (vf2);
-}
-
-static void
-test_sriov_vf_dup (void)
-{
-	NMSriovVF *vf1, *vf2;
-
-	vf1 = nm_sriov_vf_new (1);
-	nm_sriov_vf_set_attribute (vf1, NM_SRIOV_VF_ATTRIBUTE_MAC, g_variant_new_string ("foobar"));
-	nm_sriov_vf_set_attribute (vf1, NM_SRIOV_VF_ATTRIBUTE_TRUST, g_variant_new_boolean (FALSE));
-	nm_sriov_vf_set_attribute (vf1, NM_SRIOV_VF_ATTRIBUTE_MIN_TX_RATE, g_variant_new_uint32 (10));
-	nm_sriov_vf_set_attribute (vf1, NM_SRIOV_VF_ATTRIBUTE_MAX_TX_RATE, g_variant_new_uint32 (1000));
-	nm_sriov_vf_add_vlan (vf1, 80);
-	nm_sriov_vf_set_vlan_qos (vf1, 80, NM_SRIOV_VF_VLAN_PROTOCOL_802_1AD);
-
-	vf2 = nm_sriov_vf_dup (vf1);
-	g_assert (nm_sriov_vf_equal (vf1, vf2));
-
-	nm_sriov_vf_unref (vf1);
-	nm_sriov_vf_unref (vf2);
-}
-
-static void
-test_sriov_vf_vlan (void)
-{
-	NMSriovVF *vf;
-	const guint *vlan_ids;
-	guint num;
-	GError *error = NULL;
-	gs_free char *str = NULL;
-
-	vf = nm_sriov_vf_new (19);
-	nm_sriov_vf_set_attribute (vf, NM_SRIOV_VF_ATTRIBUTE_MAC, g_variant_new_string ("00:11:22"));
-	g_assert (nm_sriov_vf_add_vlan (vf, 80));
-	g_assert (!nm_sriov_vf_add_vlan (vf, 80));
-	g_assert (nm_sriov_vf_add_vlan (vf, 82));
-	g_assert (nm_sriov_vf_add_vlan (vf, 83));
-	g_assert (nm_sriov_vf_add_vlan (vf, 81));
-	g_assert (!nm_sriov_vf_remove_vlan (vf, 100));
-	g_assert (nm_sriov_vf_remove_vlan (vf, 82));
-	nm_sriov_vf_set_vlan_qos (vf, 81, 0xabba);
-	nm_sriov_vf_set_vlan_protocol (vf, 81, NM_SRIOV_VF_VLAN_PROTOCOL_802_1AD);
-
-	vlan_ids = nm_sriov_vf_get_vlan_ids (vf, &num);
-	g_assert (vlan_ids);
-	g_assert_cmpint (num, ==, 3);
-	g_assert_cmpint (vlan_ids[0], ==, 80);
-	g_assert_cmpint (vlan_ids[1], ==, 81);
-	g_assert_cmpint (vlan_ids[2], ==, 83);
-	g_assert_cmpint (nm_sriov_vf_get_vlan_qos (vf, 80), ==, 0x0);
-	g_assert_cmpint (nm_sriov_vf_get_vlan_protocol (vf, 80), ==, NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q);
-	g_assert_cmpint (nm_sriov_vf_get_vlan_qos (vf, 81), ==, 0xabba);
-	g_assert_cmpint (nm_sriov_vf_get_vlan_protocol (vf, 81), ==, NM_SRIOV_VF_VLAN_PROTOCOL_802_1AD);
-
-	nm_sriov_vf_unref (vf);
-
-	vf = nm_utils_sriov_vf_from_str ("20 spoof-check=false vlans=85.0.q;4000.0x20.ad;81.10;83", &error);
-	nmtst_assert_success (vf, error);
-	vlan_ids = nm_sriov_vf_get_vlan_ids (vf, &num);
-	g_assert (vlan_ids);
-	g_assert_cmpint (num, ==, 4);
-	g_assert_cmpint (vlan_ids[0], ==, 81);
-	g_assert_cmpint (nm_sriov_vf_get_vlan_qos (vf, 81), ==, 10);
-	g_assert_cmpint (nm_sriov_vf_get_vlan_protocol (vf, 81), ==, NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q);
-	g_assert_cmpint (vlan_ids[1], ==, 83);
-	g_assert_cmpint (nm_sriov_vf_get_vlan_qos (vf, 83), ==, 0);
-	g_assert_cmpint (nm_sriov_vf_get_vlan_protocol (vf, 83), ==, NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q);
-	g_assert_cmpint (vlan_ids[2], ==, 85);
-	g_assert_cmpint (nm_sriov_vf_get_vlan_qos (vf, 85), ==, 0);
-	g_assert_cmpint (nm_sriov_vf_get_vlan_protocol (vf, 85), ==, NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q);
-	g_assert_cmpint (vlan_ids[3], ==, 4000);
-	g_assert_cmpint (nm_sriov_vf_get_vlan_qos (vf, 4000), ==, 0x20);
-	g_assert_cmpint (nm_sriov_vf_get_vlan_protocol (vf, 4000), ==, NM_SRIOV_VF_VLAN_PROTOCOL_802_1AD);
-
-	str = nm_utils_sriov_vf_to_str (vf, FALSE, &error);
-	nmtst_assert_success (str, error);
-	g_assert_cmpstr (str, ==, "20 spoof-check=false vlans=81.10;83;85;4000.32.ad");
-
-	nm_sriov_vf_unref (vf);
-}
-
-static void
-test_sriov_setting (void)
-{
-	gs_unref_object NMConnection *con = NULL;
-	NMSettingConnection *s_con;
-	NMSettingSriov *s_sriov = NULL;
-	NMSriovVF *vf1, *vf2, *vf3;
-	GError *error = NULL;
-	gboolean success;
-
-	con = nm_simple_connection_new ();
-
-	s_con = (NMSettingConnection *) nm_setting_connection_new ();
-	nm_connection_add_setting (con, NM_SETTING (s_con));
-
-	g_object_set (s_con,
-	              NM_SETTING_CONNECTION_ID, "Test SR-IOV connection",
-	              NM_SETTING_CONNECTION_UUID, nm_utils_uuid_generate_a (),
-	              NM_SETTING_CONNECTION_AUTOCONNECT, TRUE,
-	              NM_SETTING_CONNECTION_INTERFACE_NAME, "eth0",
-	              NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME,
-	              NULL);
-
-	nm_connection_add_setting (con, nm_setting_wired_new ());
-
-	s_sriov = (NMSettingSriov *) nm_setting_sriov_new ();
-	nm_connection_add_setting (con, NM_SETTING (s_sriov));
-
-	g_object_set (s_sriov, NM_SETTING_SRIOV_TOTAL_VFS, 16, NULL);
-	nm_setting_sriov_add_vf (s_sriov, (vf1 = nm_sriov_vf_new (0)));
-	nm_setting_sriov_add_vf (s_sriov, (vf2 = nm_sriov_vf_new (4)));
-	nm_setting_sriov_add_vf (s_sriov, (vf3 = nm_sriov_vf_new (10)));
-	g_assert (nm_setting_sriov_remove_vf_by_index (s_sriov, 4));
-	nm_sriov_vf_unref (vf2);
-	nm_setting_sriov_add_vf (s_sriov, (vf2 = nm_sriov_vf_new (2)));
-
-	nmtst_assert_connection_verifies_and_normalizable (con);
-	nmtst_connection_normalize (con);
-	success = nm_setting_verify ((NMSetting *) s_sriov, con, &error);
-	nmtst_assert_success (success, error);
-
-	g_assert_cmpint (nm_setting_sriov_get_num_vfs (s_sriov), ==, 3);
-	g_assert_cmpint (nm_sriov_vf_get_index (nm_setting_sriov_get_vf (s_sriov, 0)), ==, 0);
-	g_assert_cmpint (nm_sriov_vf_get_index (nm_setting_sriov_get_vf (s_sriov, 1)), ==, 2);
-	g_assert_cmpint (nm_sriov_vf_get_index (nm_setting_sriov_get_vf (s_sriov, 2)), ==, 10);
-
-	nm_sriov_vf_unref (vf1);
-	nm_sriov_vf_unref (vf2);
-	nm_sriov_vf_unref (vf3);
-}
-
-typedef struct {
-	guint id;
-	guint qos;
-	bool  proto_ad;
-} VlanData;
-
-static void
-_test_sriov_parse_vlan_one (const char *string, gboolean exp_res, VlanData *data, guint data_length)
-{
-	NMSriovVF *vf;
-	gboolean res;
-	guint i, num_vlans;
-	const guint *vlan_ids;
-
-	vf = nm_sriov_vf_new (1);
-	g_assert (vf);
-
-	res = _nm_sriov_vf_parse_vlans (vf, string, NULL);
-	g_assert_cmpint (res, ==, exp_res);
-
-	if (exp_res) {
-		vlan_ids = nm_sriov_vf_get_vlan_ids (vf, &num_vlans);
-		g_assert_cmpint (num_vlans, ==, data_length);
-		for (i = 0; i < num_vlans; i++) {
-			g_assert_cmpint (vlan_ids[i], ==, data[i].id);
-			g_assert_cmpint (nm_sriov_vf_get_vlan_qos (vf, vlan_ids[i]), ==, data[i].qos);
-			g_assert_cmpint (nm_sriov_vf_get_vlan_protocol (vf, vlan_ids[i]),
-			                 ==,
-			                 data[i].proto_ad ? NM_SRIOV_VF_VLAN_PROTOCOL_802_1AD: NM_SRIOV_VF_VLAN_PROTOCOL_802_1Q);
-		}
-	}
-
-	nm_sriov_vf_unref (vf);
-}
-
-#define test_sriov_parse_vlan_one(string, result, ...) \
-	{ \
-		VlanData _data[] = { __VA_ARGS__ }; \
-		guint _length = G_N_ELEMENTS (_data); \
-		\
-		_test_sriov_parse_vlan_one (string, result, _data, _length); \
-	}
-
-static void
-test_sriov_parse_vlans (void)
-{
-	test_sriov_parse_vlan_one ("",  FALSE, {});
-	test_sriov_parse_vlan_one ("1", TRUE, {1, 0, 0});
-	test_sriov_parse_vlan_one ("1;2", TRUE, {1, 0, 0}, {2, 0, 0});
-	test_sriov_parse_vlan_one ("4095;;2", TRUE, {2, 0, 0}, {4095, 0, 0});
-	test_sriov_parse_vlan_one ("1 2", FALSE, {});
-	test_sriov_parse_vlan_one ("4096", FALSE, {});
-	test_sriov_parse_vlan_one ("1.10", TRUE, {1, 10, 0});
-	test_sriov_parse_vlan_one ("1.20.ad", TRUE, {1, 20, 1});
-	test_sriov_parse_vlan_one ("1.21.q", TRUE, {1, 21, 0});
-	test_sriov_parse_vlan_one ("9.20.foo", FALSE, {});
-	test_sriov_parse_vlan_one ("1.20.ad.12", FALSE, {});
-	test_sriov_parse_vlan_one ("1;1.10", FALSE, {});
-	test_sriov_parse_vlan_one ("1..1;2", FALSE, {});
-	test_sriov_parse_vlan_one ("1..ad;2", FALSE, {});
-	test_sriov_parse_vlan_one ("1.2.ad;2.0.q;5;3", TRUE, {1, 2, 1}, {2, 0, 0}, {3, 0, 0}, {5, 0, 0});
-}
-
-/*****************************************************************************/
-
-static void
 test_tc_config_qdisc (void)
 {
 	NMTCQdisc *qdisc1, *qdisc2;
@@ -1974,14 +1669,6 @@ main (int argc, char **argv)
 	g_test_add_func ("/libnm/settings/dcb/priorities", test_dcb_priorities_valid);
 	g_test_add_func ("/libnm/settings/dcb/bandwidth-sums", test_dcb_bandwidth_sums);
 
-	g_test_add_func ("/libnm/settings/ethtool/1", test_ethtool_1);
-
-	g_test_add_func ("/libnm/settings/sriov/vf", test_sriov_vf);
-	g_test_add_func ("/libnm/settings/sriov/vf-dup", test_sriov_vf_dup);
-	g_test_add_func ("/libnm/settings/sriov/vf-vlan", test_sriov_vf_vlan);
-	g_test_add_func ("/libnm/settings/sriov/setting", test_sriov_setting);
-	g_test_add_func ("/libnm/settings/sriov/vlans", test_sriov_parse_vlans);
-
 	g_test_add_func ("/libnm/settings/tc_config/qdisc", test_tc_config_qdisc);
 	g_test_add_func ("/libnm/settings/tc_config/action", test_tc_config_action);
 	g_test_add_func ("/libnm/settings/tc_config/tfilter", test_tc_config_tfilter);