about summary refs log tree commit diff
path: root/libnm-util
diff options
context:
space:
mode:
Diffstat (limited to 'libnm-util')
-rw-r--r--libnm-util/Makefile.am44
-rw-r--r--libnm-util/Makefile.in450
-rw-r--r--libnm-util/crypto.c82
-rw-r--r--libnm-util/crypto.h3
-rw-r--r--libnm-util/crypto_gnutls.c26
-rw-r--r--libnm-util/crypto_nss.c24
-rw-r--r--libnm-util/libnm-util.pc.in2
-rw-r--r--libnm-util/libnm-util.ver97
-rw-r--r--libnm-util/nm-connection.c730
-rw-r--r--libnm-util/nm-connection.h36
-rw-r--r--libnm-util/nm-param-spec-specialized.c45
-rw-r--r--libnm-util/nm-setting-8021x.c790
-rw-r--r--libnm-util/nm-setting-8021x.h32
-rw-r--r--libnm-util/nm-setting-adsl.c70
-rw-r--r--libnm-util/nm-setting-bluetooth.c62
-rw-r--r--libnm-util/nm-setting-bond.c315
-rw-r--r--libnm-util/nm-setting-bond.h26
-rw-r--r--libnm-util/nm-setting-bridge-port.c28
-rw-r--r--libnm-util/nm-setting-bridge.c103
-rw-r--r--libnm-util/nm-setting-bridge.h4
-rw-r--r--libnm-util/nm-setting-cdma.c51
-rw-r--r--libnm-util/nm-setting-connection.c458
-rw-r--r--libnm-util/nm-setting-connection.h40
-rw-r--r--libnm-util/nm-setting-dcb.c1268
-rw-r--r--libnm-util/nm-setting-dcb.h189
-rw-r--r--libnm-util/nm-setting-generic.c100
-rw-r--r--libnm-util/nm-setting-generic.h78
-rw-r--r--libnm-util/nm-setting-gsm.c149
-rw-r--r--libnm-util/nm-setting-gsm.h42
-rw-r--r--libnm-util/nm-setting-infiniband.c183
-rw-r--r--libnm-util/nm-setting-infiniband.h4
-rw-r--r--libnm-util/nm-setting-ip4-config.c509
-rw-r--r--libnm-util/nm-setting-ip4-config.h32
-rw-r--r--libnm-util/nm-setting-ip6-config.c385
-rw-r--r--libnm-util/nm-setting-ip6-config.h32
-rw-r--r--libnm-util/nm-setting-olpc-mesh.c48
-rw-r--r--libnm-util/nm-setting-ppp.c91
-rw-r--r--libnm-util/nm-setting-pppoe.c46
-rw-r--r--libnm-util/nm-setting-private.h53
-rw-r--r--libnm-util/nm-setting-serial.c19
-rw-r--r--libnm-util/nm-setting-team-port.c188
-rw-r--r--libnm-util/nm-setting-team-port.h79
-rw-r--r--libnm-util/nm-setting-team.c270
-rw-r--r--libnm-util/nm-setting-team.h81
-rw-r--r--libnm-util/nm-setting-vlan.c203
-rw-r--r--libnm-util/nm-setting-vlan.h15
-rw-r--r--libnm-util/nm-setting-vpn.c141
-rw-r--r--libnm-util/nm-setting-vpn.h6
-rw-r--r--libnm-util/nm-setting-wimax.c43
-rw-r--r--libnm-util/nm-setting-wired.c334
-rw-r--r--libnm-util/nm-setting-wired.h26
-rw-r--r--libnm-util/nm-setting-wireless-security.c441
-rw-r--r--libnm-util/nm-setting-wireless-security.h42
-rw-r--r--libnm-util/nm-setting-wireless.c381
-rw-r--r--libnm-util/nm-setting-wireless.h31
-rw-r--r--libnm-util/nm-setting.c568
-rw-r--r--libnm-util/nm-setting.h13
-rw-r--r--libnm-util/nm-utils-enum-types.c105
-rw-r--r--libnm-util/nm-utils-enum-types.h10
-rw-r--r--libnm-util/nm-utils-private.h35
-rw-r--r--libnm-util/nm-utils.c1404
-rw-r--r--libnm-util/nm-utils.h38
-rw-r--r--libnm-util/nm-value-transforms.c594
-rw-r--r--libnm-util/tests/Makefile.am28
-rw-r--r--libnm-util/tests/Makefile.in233
-rw-r--r--libnm-util/tests/certs/Makefile.am3
-rw-r--r--libnm-util/tests/certs/Makefile.in24
-rw-r--r--libnm-util/tests/certs/test-aes-key.pem30
-rw-r--r--libnm-util/tests/test-crypto.c40
-rw-r--r--libnm-util/tests/test-general.c1159
-rw-r--r--libnm-util/tests/test-secrets.c108
-rw-r--r--libnm-util/tests/test-setting-8021x.c5
-rw-r--r--libnm-util/tests/test-setting-dcb.c328
-rw-r--r--libnm-util/tests/test-settings-defaults.c8
74 files changed, 10303 insertions, 3457 deletions
diff --git a/libnm-util/Makefile.am b/libnm-util/Makefile.am
index 2d41164b..01b2026a 100644
--- a/libnm-util/Makefile.am
+++ b/libnm-util/Makefile.am
@@ -5,15 +5,22 @@ SUBDIRS = . tests
 AM_CPPFLAGS = \
 	-I${top_srcdir} \
 	-I${top_srcdir}/include \
-	-I${top_builddir}/include
-
-lib_LTLIBRARIES=libnm-util.la
-
-libnm_util_la_CPPFLAGS = \
+	-I${top_builddir}/include \
+	-DG_LOG_DOMAIN=\""libnm-util"\" \
+	-DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \
 	$(GLIB_CFLAGS) \
 	$(DBUS_CFLAGS) \
-	$(UUID_CFLAGS) \
-	$(AM_CPPFLAGS)
+	$(UUID_CFLAGS)
+
+if WITH_GNUTLS
+AM_CPPFLAGS += $(LIBGCRYPT_CFLAGS) $(GNUTLS_CFLAGS)
+endif
+
+if WITH_NSS
+AM_CPPFLAGS += $(NSS_CFLAGS)
+endif
+
+lib_LTLIBRARIES=libnm-util.la
 
 libnm_util_include_HEADERS = 		\
 	nm-connection.h			\
@@ -22,9 +29,12 @@ libnm_util_include_HEADERS = 		\
 	nm-setting-adsl.h		\
 	nm-setting-bluetooth.h		\
 	nm-setting-bond.h		\
+	nm-setting-team.h		\
+	nm-setting-team-port.h		\
 	nm-setting-bridge.h		\
 	nm-setting-bridge-port.h	\
 	nm-setting-connection.h		\
+	nm-setting-dcb.h                \
 	nm-setting-infiniband.h		\
 	nm-setting-ip4-config.h		\
 	nm-setting-vlan.h		\
@@ -32,6 +42,7 @@ libnm_util_include_HEADERS = 		\
 	nm-setting-ppp.h		\
 	nm-setting-pppoe.h		\
 	nm-setting-serial.h		\
+	nm-setting-generic.h		\
 	nm-setting-gsm.h		\
 	nm-setting-cdma.h		\
 	nm-setting-olpc-mesh.h		\
@@ -46,7 +57,7 @@ libnm_util_include_HEADERS = 		\
 libnm_util_la_private_headers = \
 	crypto.h			\
 	nm-param-spec-specialized.h	\
-	nm-utils-private.h \
+	nm-utils-private.h		\
 	nm-setting-private.h
 
 libnm_util_la_csources = \
@@ -58,9 +69,12 @@ libnm_util_la_csources = \
 	nm-setting-adsl.c		\
 	nm-setting-bluetooth.c		\
 	nm-setting-bond.c		\
+	nm-setting-team.c		\
+	nm-setting-team-port.c		\
 	nm-setting-bridge.c		\
 	nm-setting-bridge-port.c	\
 	nm-setting-connection.c		\
+	nm-setting-dcb.c                \
 	nm-setting-infiniband.c		\
 	nm-setting-ip4-config.c		\
 	nm-setting-vlan.c		\
@@ -68,6 +82,7 @@ libnm_util_la_csources = \
 	nm-setting-ppp.c		\
 	nm-setting-pppoe.c		\
 	nm-setting-serial.c		\
+	nm-setting-generic.c		\
 	nm-setting-gsm.c		\
 	nm-setting-cdma.c		\
 	nm-setting-olpc-mesh.c		\
@@ -77,7 +92,8 @@ libnm_util_la_csources = \
 	nm-setting-wireless-security.c	\
 	nm-setting-vpn.c		\
 	nm-utils-enum-types.c		\
-	nm-utils.c
+	nm-utils.c			\
+	nm-value-transforms.c
 
 libnm_util_la_SOURCES = \
 	$(libnm_util_la_csources) \
@@ -94,17 +110,15 @@ libnm_util_la_LIBADD = $(GLIB_LIBS) $(DBUS_LIBS) $(UUID_LIBS)
 SYMBOL_VIS_FILE=$(srcdir)/libnm-util.ver
 
 libnm_util_la_LDFLAGS = -Wl,--version-script=$(SYMBOL_VIS_FILE) \
-	-version-info "6:0:4"
+	-version-info "8:0:6"
 
 if WITH_GNUTLS
 libnm_util_la_SOURCES += crypto_gnutls.c
-libnm_util_la_CPPFLAGS += $(LIBGCRYPT_CFLAGS) $(GNUTLS_CFLAGS)
 libnm_util_la_LIBADD += $(LIBGCRYPT_LIBS) $(GNUTLS_LIBS)
 endif
 
 if WITH_NSS
 libnm_util_la_SOURCES += crypto_nss.c
-libnm_util_la_CPPFLAGS += $(NSS_CFLAGS)
 libnm_util_la_LIBADD += $(NSS_LIBS)
 endif
 
@@ -119,22 +133,16 @@ noinst_LTLIBRARIES = libtest-crypto.la
 
 libtest_crypto_la_SOURCES = crypto.c
 
-libtest_crypto_la_CPPFLAGS = \
-	$(GLIB_CFLAGS) \
-	$(AM_CPPFLAGS)
-
 libtest_crypto_la_LIBADD = \
 	$(GLIB_LIBS)
 
 if WITH_GNUTLS
 libtest_crypto_la_SOURCES += crypto_gnutls.c
-libtest_crypto_la_CPPFLAGS += $(LIBGCRYPT_CFLAGS) $(GNUTLS_CFLAGS)
 libtest_crypto_la_LIBADD += $(LIBGCRYPT_LIBS) $(GNUTLS_LIBS)
 endif
 
 if WITH_NSS
 libtest_crypto_la_SOURCES += crypto_nss.c
-libtest_crypto_la_CPPFLAGS += $(NSS_CFLAGS)
 libtest_crypto_la_LIBADD += $(NSS_LIBS)
 endif
 
diff --git a/libnm-util/Makefile.in b/libnm-util/Makefile.in
index bde92403..fa461f1f 100644
--- a/libnm-util/Makefile.in
+++ b/libnm-util/Makefile.in
@@ -80,26 +80,25 @@ PRE_UNINSTALL = :
 POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
-@WITH_GNUTLS_TRUE@am__append_1 = crypto_gnutls.c
-@WITH_GNUTLS_TRUE@am__append_2 = $(LIBGCRYPT_CFLAGS) $(GNUTLS_CFLAGS)
-@WITH_GNUTLS_TRUE@am__append_3 = $(LIBGCRYPT_LIBS) $(GNUTLS_LIBS)
-@WITH_NSS_TRUE@am__append_4 = crypto_nss.c
-@WITH_NSS_TRUE@am__append_5 = $(NSS_CFLAGS)
+@WITH_GNUTLS_TRUE@am__append_1 = $(LIBGCRYPT_CFLAGS) $(GNUTLS_CFLAGS)
+@WITH_NSS_TRUE@am__append_2 = $(NSS_CFLAGS)
+@WITH_GNUTLS_TRUE@am__append_3 = crypto_gnutls.c
+@WITH_GNUTLS_TRUE@am__append_4 = $(LIBGCRYPT_LIBS) $(GNUTLS_LIBS)
+@WITH_NSS_TRUE@am__append_5 = crypto_nss.c
 @WITH_NSS_TRUE@am__append_6 = $(NSS_LIBS)
 @WITH_GNUTLS_TRUE@am__append_7 = crypto_gnutls.c
-@WITH_GNUTLS_TRUE@am__append_8 = $(LIBGCRYPT_CFLAGS) $(GNUTLS_CFLAGS)
-@WITH_GNUTLS_TRUE@am__append_9 = $(LIBGCRYPT_LIBS) $(GNUTLS_LIBS)
-@WITH_NSS_TRUE@am__append_10 = crypto_nss.c
-@WITH_NSS_TRUE@am__append_11 = $(NSS_CFLAGS)
-@WITH_NSS_TRUE@am__append_12 = $(NSS_LIBS)
-@HAVE_INTROSPECTION_TRUE@am__append_13 = NetworkManager-1.0.gir
-@HAVE_INTROSPECTION_TRUE@am__append_14 = $(gir_DATA) $(typelib_DATA)
+@WITH_GNUTLS_TRUE@am__append_8 = $(LIBGCRYPT_LIBS) $(GNUTLS_LIBS)
+@WITH_NSS_TRUE@am__append_9 = crypto_nss.c
+@WITH_NSS_TRUE@am__append_10 = $(NSS_LIBS)
+@HAVE_INTROSPECTION_TRUE@am__append_11 = NetworkManager-1.0.gir
+@HAVE_INTROSPECTION_TRUE@am__append_12 = $(gir_DATA) $(typelib_DATA)
 subdir = libnm-util
 DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
 	$(srcdir)/libnm-util.pc.in $(top_srcdir)/build-aux/depcomp \
 	$(libnm_util_include_HEADERS) COPYING
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_lib_readline.m4 \
+	$(top_srcdir)/m4/compiler_warnings.m4 \
 	$(top_srcdir)/m4/gettext.m4 \
 	$(top_srcdir)/m4/gnome-code-coverage.m4 \
 	$(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \
@@ -158,44 +157,34 @@ libnm_util_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
 am__libnm_util_la_SOURCES_DIST = crypto.c nm-connection.c \
 	nm-param-spec-specialized.c nm-setting.c nm-setting-8021x.c \
 	nm-setting-adsl.c nm-setting-bluetooth.c nm-setting-bond.c \
-	nm-setting-bridge.c nm-setting-bridge-port.c \
-	nm-setting-connection.c nm-setting-infiniband.c \
+	nm-setting-team.c nm-setting-team-port.c nm-setting-bridge.c \
+	nm-setting-bridge-port.c nm-setting-connection.c \
+	nm-setting-dcb.c nm-setting-infiniband.c \
 	nm-setting-ip4-config.c nm-setting-vlan.c \
 	nm-setting-ip6-config.c nm-setting-ppp.c nm-setting-pppoe.c \
-	nm-setting-serial.c nm-setting-gsm.c nm-setting-cdma.c \
-	nm-setting-olpc-mesh.c nm-setting-wimax.c nm-setting-wired.c \
-	nm-setting-wireless.c nm-setting-wireless-security.c \
-	nm-setting-vpn.c nm-utils-enum-types.c nm-utils.c crypto.h \
-	nm-param-spec-specialized.h nm-utils-private.h \
+	nm-setting-serial.c nm-setting-generic.c nm-setting-gsm.c \
+	nm-setting-cdma.c nm-setting-olpc-mesh.c nm-setting-wimax.c \
+	nm-setting-wired.c nm-setting-wireless.c \
+	nm-setting-wireless-security.c nm-setting-vpn.c \
+	nm-utils-enum-types.c nm-utils.c nm-value-transforms.c \
+	crypto.h nm-param-spec-specialized.h nm-utils-private.h \
 	nm-setting-private.h crypto_gnutls.c crypto_nss.c
-am__objects_1 = libnm_util_la-crypto.lo libnm_util_la-nm-connection.lo \
-	libnm_util_la-nm-param-spec-specialized.lo \
-	libnm_util_la-nm-setting.lo libnm_util_la-nm-setting-8021x.lo \
-	libnm_util_la-nm-setting-adsl.lo \
-	libnm_util_la-nm-setting-bluetooth.lo \
-	libnm_util_la-nm-setting-bond.lo \
-	libnm_util_la-nm-setting-bridge.lo \
-	libnm_util_la-nm-setting-bridge-port.lo \
-	libnm_util_la-nm-setting-connection.lo \
-	libnm_util_la-nm-setting-infiniband.lo \
-	libnm_util_la-nm-setting-ip4-config.lo \
-	libnm_util_la-nm-setting-vlan.lo \
-	libnm_util_la-nm-setting-ip6-config.lo \
-	libnm_util_la-nm-setting-ppp.lo \
-	libnm_util_la-nm-setting-pppoe.lo \
-	libnm_util_la-nm-setting-serial.lo \
-	libnm_util_la-nm-setting-gsm.lo \
-	libnm_util_la-nm-setting-cdma.lo \
-	libnm_util_la-nm-setting-olpc-mesh.lo \
-	libnm_util_la-nm-setting-wimax.lo \
-	libnm_util_la-nm-setting-wired.lo \
-	libnm_util_la-nm-setting-wireless.lo \
-	libnm_util_la-nm-setting-wireless-security.lo \
-	libnm_util_la-nm-setting-vpn.lo \
-	libnm_util_la-nm-utils-enum-types.lo libnm_util_la-nm-utils.lo
+am__objects_1 = crypto.lo nm-connection.lo \
+	nm-param-spec-specialized.lo nm-setting.lo nm-setting-8021x.lo \
+	nm-setting-adsl.lo nm-setting-bluetooth.lo nm-setting-bond.lo \
+	nm-setting-team.lo nm-setting-team-port.lo \
+	nm-setting-bridge.lo nm-setting-bridge-port.lo \
+	nm-setting-connection.lo nm-setting-dcb.lo \
+	nm-setting-infiniband.lo nm-setting-ip4-config.lo \
+	nm-setting-vlan.lo nm-setting-ip6-config.lo nm-setting-ppp.lo \
+	nm-setting-pppoe.lo nm-setting-serial.lo nm-setting-generic.lo \
+	nm-setting-gsm.lo nm-setting-cdma.lo nm-setting-olpc-mesh.lo \
+	nm-setting-wimax.lo nm-setting-wired.lo nm-setting-wireless.lo \
+	nm-setting-wireless-security.lo nm-setting-vpn.lo \
+	nm-utils-enum-types.lo nm-utils.lo nm-value-transforms.lo
 am__objects_2 =
-@WITH_GNUTLS_TRUE@am__objects_3 = libnm_util_la-crypto_gnutls.lo
-@WITH_NSS_TRUE@am__objects_4 = libnm_util_la-crypto_nss.lo
+@WITH_GNUTLS_TRUE@am__objects_3 = crypto_gnutls.lo
+@WITH_NSS_TRUE@am__objects_4 = crypto_nss.lo
 am_libnm_util_la_OBJECTS = $(am__objects_1) $(am__objects_2) \
 	$(am__objects_3) $(am__objects_4)
 libnm_util_la_OBJECTS = $(am_libnm_util_la_OBJECTS)
@@ -210,10 +199,8 @@ libtest_crypto_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
 	$(am__DEPENDENCIES_2) $(am__DEPENDENCIES_3)
 am__libtest_crypto_la_SOURCES_DIST = crypto.c crypto_gnutls.c \
 	crypto_nss.c
-@WITH_GNUTLS_TRUE@am__objects_5 = libtest_crypto_la-crypto_gnutls.lo
-@WITH_NSS_TRUE@am__objects_6 = libtest_crypto_la-crypto_nss.lo
-am_libtest_crypto_la_OBJECTS = libtest_crypto_la-crypto.lo \
-	$(am__objects_5) $(am__objects_6)
+am_libtest_crypto_la_OBJECTS = crypto.lo $(am__objects_3) \
+	$(am__objects_4)
 libtest_crypto_la_OBJECTS = $(am_libtest_crypto_la_OBJECTS)
 AM_V_P = $(am__v_P_@AM_V@)
 am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
@@ -346,12 +333,15 @@ CXXFLAGS = @CXXFLAGS@
 CYGPATH_W = @CYGPATH_W@
 DATADIRNAME = @DATADIRNAME@
 DBUS_CFLAGS = @DBUS_CFLAGS@
+DBUS_GLIB_100_CFLAGS = @DBUS_GLIB_100_CFLAGS@
+DBUS_GLIB_100_LIBS = @DBUS_GLIB_100_LIBS@
 DBUS_LIBS = @DBUS_LIBS@
 DBUS_SYS_DIR = @DBUS_SYS_DIR@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
 DHCLIENT_PATH = @DHCLIENT_PATH@
 DHCPCD_PATH = @DHCPCD_PATH@
+DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@
 DLLTOOL = @DLLTOOL@
 DNSMASQ_PATH = @DNSMASQ_PATH@
 DSYMUTIL = @DSYMUTIL@
@@ -376,7 +366,6 @@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
 GNUTLS_LIBS = @GNUTLS_LIBS@
 GREP = @GREP@
 GTKDOC_CHECK = @GTKDOC_CHECK@
-GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@
 GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@
 GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@
 GTKDOC_MKPDF = @GTKDOC_MKPDF@
@@ -421,12 +410,16 @@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
 LIBICONV = @LIBICONV@
 LIBINTL = @LIBINTL@
 LIBM = @LIBM@
+LIBNDP_CFLAGS = @LIBNDP_CFLAGS@
+LIBNDP_LIBS = @LIBNDP_LIBS@
 LIBNL_CFLAGS = @LIBNL_CFLAGS@
 LIBNL_LIBS = @LIBNL_LIBS@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
 LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@
 LIBSOUP_LIBS = @LIBSOUP_LIBS@
+LIBTEAMDCTL_CFLAGS = @LIBTEAMDCTL_CFLAGS@
+LIBTEAMDCTL_LIBS = @LIBTEAMDCTL_LIBS@
 LIBTOOL = @LIBTOOL@
 LIPO = @LIPO@
 LN_S = @LN_S@
@@ -443,6 +436,8 @@ MOC = @MOC@
 MSGFMT = @MSGFMT@
 MSGFMT_015 = @MSGFMT_015@
 MSGMERGE = @MSGMERGE@
+NEWT_CFLAGS = @NEWT_CFLAGS@
+NEWT_LIBS = @NEWT_LIBS@
 NM = @NM@
 NMEDIT = @NMEDIT@
 NM_MAJOR_VERSION = @NM_MAJOR_VERSION@
@@ -470,11 +465,16 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
 POLKIT_CFLAGS = @POLKIT_CFLAGS@
 POLKIT_LIBS = @POLKIT_LIBS@
 POSUB = @POSUB@
+PPPD_PATH = @PPPD_PATH@
 PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@
+PPPOE_PATH = @PPPOE_PATH@
 QT_CFLAGS = @QT_CFLAGS@
 QT_LIBS = @QT_LIBS@
 RANLIB = @RANLIB@
+READLINE_LIBS = @READLINE_LIBS@
 SED = @SED@
+SELINUX_CFLAGS = @SELINUX_CFLAGS@
+SELINUX_LIBS = @SELINUX_LIBS@
 SET_MAKE = @SET_MAKE@
 SHELL = @SHELL@
 STRIP = @STRIP@
@@ -489,6 +489,7 @@ UDEV_BASE_DIR = @UDEV_BASE_DIR@
 USE_NLS = @USE_NLS@
 UUID_CFLAGS = @UUID_CFLAGS@
 UUID_LIBS = @UUID_LIBS@
+VALGRIND_RULES = @VALGRIND_RULES@
 VAPIGEN = @VAPIGEN@
 VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@
 VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@
@@ -551,6 +552,7 @@ psdir = @psdir@
 sbindir = @sbindir@
 sharedstatedir = @sharedstatedir@
 srcdir = @srcdir@
+subdirs = @subdirs@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 target_alias = @target_alias@
@@ -561,15 +563,13 @@ with_dhclient = @with_dhclient@
 with_dhcpcd = @with_dhcpcd@
 with_netconfig = @with_netconfig@
 with_resolvconf = @with_resolvconf@
+with_valgrind = @with_valgrind@
 SUBDIRS = . tests
-AM_CPPFLAGS = \
-	-I${top_srcdir} \
-	-I${top_srcdir}/include \
-	-I${top_builddir}/include
-
+AM_CPPFLAGS = -I${top_srcdir} -I${top_srcdir}/include \
+	-I${top_builddir}/include -DG_LOG_DOMAIN=\""libnm-util"\" \
+	-DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE $(GLIB_CFLAGS) \
+	$(DBUS_CFLAGS) $(UUID_CFLAGS) $(am__append_1) $(am__append_2)
 lib_LTLIBRARIES = libnm-util.la
-libnm_util_la_CPPFLAGS = $(GLIB_CFLAGS) $(DBUS_CFLAGS) $(UUID_CFLAGS) \
-	$(AM_CPPFLAGS) $(am__append_2) $(am__append_5)
 libnm_util_include_HEADERS = \
 	nm-connection.h			\
 	nm-setting.h			\
@@ -577,9 +577,12 @@ libnm_util_include_HEADERS = \
 	nm-setting-adsl.h		\
 	nm-setting-bluetooth.h		\
 	nm-setting-bond.h		\
+	nm-setting-team.h		\
+	nm-setting-team-port.h		\
 	nm-setting-bridge.h		\
 	nm-setting-bridge-port.h	\
 	nm-setting-connection.h		\
+	nm-setting-dcb.h                \
 	nm-setting-infiniband.h		\
 	nm-setting-ip4-config.h		\
 	nm-setting-vlan.h		\
@@ -587,6 +590,7 @@ libnm_util_include_HEADERS = \
 	nm-setting-ppp.h		\
 	nm-setting-pppoe.h		\
 	nm-setting-serial.h		\
+	nm-setting-generic.h		\
 	nm-setting-gsm.h		\
 	nm-setting-cdma.h		\
 	nm-setting-olpc-mesh.h		\
@@ -601,7 +605,7 @@ libnm_util_include_HEADERS = \
 libnm_util_la_private_headers = \
 	crypto.h			\
 	nm-param-spec-specialized.h	\
-	nm-utils-private.h \
+	nm-utils-private.h		\
 	nm-setting-private.h
 
 libnm_util_la_csources = \
@@ -613,9 +617,12 @@ libnm_util_la_csources = \
 	nm-setting-adsl.c		\
 	nm-setting-bluetooth.c		\
 	nm-setting-bond.c		\
+	nm-setting-team.c		\
+	nm-setting-team-port.c		\
 	nm-setting-bridge.c		\
 	nm-setting-bridge-port.c	\
 	nm-setting-connection.c		\
+	nm-setting-dcb.c                \
 	nm-setting-infiniband.c		\
 	nm-setting-ip4-config.c		\
 	nm-setting-vlan.c		\
@@ -623,6 +630,7 @@ libnm_util_la_csources = \
 	nm-setting-ppp.c		\
 	nm-setting-pppoe.c		\
 	nm-setting-serial.c		\
+	nm-setting-generic.c		\
 	nm-setting-gsm.c		\
 	nm-setting-cdma.c		\
 	nm-setting-olpc-mesh.c		\
@@ -632,21 +640,22 @@ libnm_util_la_csources = \
 	nm-setting-wireless-security.c	\
 	nm-setting-vpn.c		\
 	nm-utils-enum-types.c		\
-	nm-utils.c
+	nm-utils.c			\
+	nm-value-transforms.c
 
 libnm_util_la_SOURCES = $(libnm_util_la_csources) \
-	$(libnm_util_la_private_headers) $(am__append_1) \
-	$(am__append_4)
+	$(libnm_util_la_private_headers) $(am__append_3) \
+	$(am__append_5)
 GLIB_GENERATED = nm-utils-enum-types.h nm-utils-enum-types.c
 BUILT_SOURCES = $(GLIB_GENERATED)
 nm_utils_enum_types_sources = $(libnm_util_include_HEADERS)
 GLIB_MKENUMS_H_FLAGS = --identifier-prefix NM
 GLIB_MKENUMS_C_FLAGS = --identifier-prefix NM
 libnm_util_la_LIBADD = $(GLIB_LIBS) $(DBUS_LIBS) $(UUID_LIBS) \
-	$(am__append_3) $(am__append_6)
+	$(am__append_4) $(am__append_6)
 SYMBOL_VIS_FILE = $(srcdir)/libnm-util.ver
 libnm_util_la_LDFLAGS = -Wl,--version-script=$(SYMBOL_VIS_FILE) \
-	-version-info "6:0:4"
+	-version-info "8:0:6"
 
 libnm_util_includedir = $(includedir)/NetworkManager
 
@@ -654,17 +663,15 @@ libnm_util_includedir = $(includedir)/NetworkManager
 # Crypto test library
 ###########################################
 noinst_LTLIBRARIES = libtest-crypto.la
-libtest_crypto_la_SOURCES = crypto.c $(am__append_7) $(am__append_10)
-libtest_crypto_la_CPPFLAGS = $(GLIB_CFLAGS) $(AM_CPPFLAGS) \
-	$(am__append_8) $(am__append_11)
-libtest_crypto_la_LIBADD = $(GLIB_LIBS) $(am__append_9) \
-	$(am__append_12)
+libtest_crypto_la_SOURCES = crypto.c $(am__append_7) $(am__append_9)
+libtest_crypto_la_LIBADD = $(GLIB_LIBS) $(am__append_8) \
+	$(am__append_10)
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = libnm-util.pc
 DISTCLEANFILES = libnm-util.pc
-CLEANFILES = $(am__append_14)
+CLEANFILES = $(am__append_12)
 EXTRA_DIST = libnm-util.pc.in libnm-util.ver
-INTROSPECTION_GIRS = $(am__append_13)
+INTROSPECTION_GIRS = $(am__append_11)
 INTROSPECTION_SCANNER_ARGS = --add-include-path=$(srcdir)
 INTROSPECTION_COMPILER_ARGS = --includedir=$(srcdir)
 @HAVE_INTROSPECTION_TRUE@introspection_sources = $(libnm_util_include_HEADERS) $(libnm_util_la_csources) $(top_srcdir)/include/NetworkManager.h $(top_srcdir)/include/NetworkManagerVPN.h
@@ -775,39 +782,41 @@ mostlyclean-compile:
 distclean-compile:
 	-rm -f *.tab.c
 
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-crypto.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-crypto_gnutls.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-crypto_nss.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-nm-connection.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-nm-param-spec-specialized.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-nm-setting-8021x.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-nm-setting-adsl.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-nm-setting-bluetooth.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-nm-setting-bond.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-nm-setting-bridge-port.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-nm-setting-bridge.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-nm-setting-cdma.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-nm-setting-connection.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-nm-setting-gsm.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-nm-setting-infiniband.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-nm-setting-ip4-config.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-nm-setting-ip6-config.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-nm-setting-olpc-mesh.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-nm-setting-ppp.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-nm-setting-pppoe.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-nm-setting-serial.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-nm-setting-vlan.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-nm-setting-vpn.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-nm-setting-wimax.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-nm-setting-wired.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-nm-setting-wireless-security.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-nm-setting-wireless.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-nm-setting.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-nm-utils-enum-types.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_util_la-nm-utils.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtest_crypto_la-crypto.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtest_crypto_la-crypto_gnutls.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtest_crypto_la-crypto_nss.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crypto.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crypto_gnutls.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crypto_nss.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-connection.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-param-spec-specialized.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-8021x.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-adsl.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-bluetooth.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-bond.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-bridge-port.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-bridge.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-cdma.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-connection.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-dcb.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-generic.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-gsm.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-infiniband.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-ip4-config.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-ip6-config.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-olpc-mesh.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-ppp.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-pppoe.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-serial.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-team-port.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-team.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-vlan.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-vpn.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-wimax.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-wired.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-wireless-security.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-wireless.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-utils-enum-types.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-utils.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-value-transforms.Plo@am__quote@
 
 .c.o:
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@@ -830,237 +839,6 @@ distclean-compile:
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
 
-libnm_util_la-crypto.lo: crypto.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-crypto.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-crypto.Tpo -c -o libnm_util_la-crypto.lo `test -f 'crypto.c' || echo '$(srcdir)/'`crypto.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_util_la-crypto.Tpo $(DEPDIR)/libnm_util_la-crypto.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='crypto.c' object='libnm_util_la-crypto.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-crypto.lo `test -f 'crypto.c' || echo '$(srcdir)/'`crypto.c
-
-libnm_util_la-nm-connection.lo: nm-connection.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-nm-connection.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-nm-connection.Tpo -c -o libnm_util_la-nm-connection.lo `test -f 'nm-connection.c' || echo '$(srcdir)/'`nm-connection.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_util_la-nm-connection.Tpo $(DEPDIR)/libnm_util_la-nm-connection.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='nm-connection.c' object='libnm_util_la-nm-connection.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-nm-connection.lo `test -f 'nm-connection.c' || echo '$(srcdir)/'`nm-connection.c
-
-libnm_util_la-nm-param-spec-specialized.lo: nm-param-spec-specialized.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-nm-param-spec-specialized.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-nm-param-spec-specialized.Tpo -c -o libnm_util_la-nm-param-spec-specialized.lo `test -f 'nm-param-spec-specialized.c' || echo '$(srcdir)/'`nm-param-spec-specialized.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_util_la-nm-param-spec-specialized.Tpo $(DEPDIR)/libnm_util_la-nm-param-spec-specialized.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='nm-param-spec-specialized.c' object='libnm_util_la-nm-param-spec-specialized.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-nm-param-spec-specialized.lo `test -f 'nm-param-spec-specialized.c' || echo '$(srcdir)/'`nm-param-spec-specialized.c
-
-libnm_util_la-nm-setting.lo: nm-setting.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-nm-setting.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-nm-setting.Tpo -c -o libnm_util_la-nm-setting.lo `test -f 'nm-setting.c' || echo '$(srcdir)/'`nm-setting.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_util_la-nm-setting.Tpo $(DEPDIR)/libnm_util_la-nm-setting.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='nm-setting.c' object='libnm_util_la-nm-setting.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-nm-setting.lo `test -f 'nm-setting.c' || echo '$(srcdir)/'`nm-setting.c
-
-libnm_util_la-nm-setting-8021x.lo: nm-setting-8021x.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-nm-setting-8021x.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-nm-setting-8021x.Tpo -c -o libnm_util_la-nm-setting-8021x.lo `test -f 'nm-setting-8021x.c' || echo '$(srcdir)/'`nm-setting-8021x.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_util_la-nm-setting-8021x.Tpo $(DEPDIR)/libnm_util_la-nm-setting-8021x.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='nm-setting-8021x.c' object='libnm_util_la-nm-setting-8021x.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-nm-setting-8021x.lo `test -f 'nm-setting-8021x.c' || echo '$(srcdir)/'`nm-setting-8021x.c
-
-libnm_util_la-nm-setting-adsl.lo: nm-setting-adsl.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-nm-setting-adsl.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-nm-setting-adsl.Tpo -c -o libnm_util_la-nm-setting-adsl.lo `test -f 'nm-setting-adsl.c' || echo '$(srcdir)/'`nm-setting-adsl.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_util_la-nm-setting-adsl.Tpo $(DEPDIR)/libnm_util_la-nm-setting-adsl.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='nm-setting-adsl.c' object='libnm_util_la-nm-setting-adsl.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-nm-setting-adsl.lo `test -f 'nm-setting-adsl.c' || echo '$(srcdir)/'`nm-setting-adsl.c
-
-libnm_util_la-nm-setting-bluetooth.lo: nm-setting-bluetooth.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-nm-setting-bluetooth.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-nm-setting-bluetooth.Tpo -c -o libnm_util_la-nm-setting-bluetooth.lo `test -f 'nm-setting-bluetooth.c' || echo '$(srcdir)/'`nm-setting-bluetooth.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_util_la-nm-setting-bluetooth.Tpo $(DEPDIR)/libnm_util_la-nm-setting-bluetooth.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='nm-setting-bluetooth.c' object='libnm_util_la-nm-setting-bluetooth.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-nm-setting-bluetooth.lo `test -f 'nm-setting-bluetooth.c' || echo '$(srcdir)/'`nm-setting-bluetooth.c
-
-libnm_util_la-nm-setting-bond.lo: nm-setting-bond.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-nm-setting-bond.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-nm-setting-bond.Tpo -c -o libnm_util_la-nm-setting-bond.lo `test -f 'nm-setting-bond.c' || echo '$(srcdir)/'`nm-setting-bond.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_util_la-nm-setting-bond.Tpo $(DEPDIR)/libnm_util_la-nm-setting-bond.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='nm-setting-bond.c' object='libnm_util_la-nm-setting-bond.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-nm-setting-bond.lo `test -f 'nm-setting-bond.c' || echo '$(srcdir)/'`nm-setting-bond.c
-
-libnm_util_la-nm-setting-bridge.lo: nm-setting-bridge.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-nm-setting-bridge.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-nm-setting-bridge.Tpo -c -o libnm_util_la-nm-setting-bridge.lo `test -f 'nm-setting-bridge.c' || echo '$(srcdir)/'`nm-setting-bridge.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_util_la-nm-setting-bridge.Tpo $(DEPDIR)/libnm_util_la-nm-setting-bridge.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='nm-setting-bridge.c' object='libnm_util_la-nm-setting-bridge.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-nm-setting-bridge.lo `test -f 'nm-setting-bridge.c' || echo '$(srcdir)/'`nm-setting-bridge.c
-
-libnm_util_la-nm-setting-bridge-port.lo: nm-setting-bridge-port.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-nm-setting-bridge-port.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-nm-setting-bridge-port.Tpo -c -o libnm_util_la-nm-setting-bridge-port.lo `test -f 'nm-setting-bridge-port.c' || echo '$(srcdir)/'`nm-setting-bridge-port.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_util_la-nm-setting-bridge-port.Tpo $(DEPDIR)/libnm_util_la-nm-setting-bridge-port.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='nm-setting-bridge-port.c' object='libnm_util_la-nm-setting-bridge-port.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-nm-setting-bridge-port.lo `test -f 'nm-setting-bridge-port.c' || echo '$(srcdir)/'`nm-setting-bridge-port.c
-
-libnm_util_la-nm-setting-connection.lo: nm-setting-connection.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-nm-setting-connection.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-nm-setting-connection.Tpo -c -o libnm_util_la-nm-setting-connection.lo `test -f 'nm-setting-connection.c' || echo '$(srcdir)/'`nm-setting-connection.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_util_la-nm-setting-connection.Tpo $(DEPDIR)/libnm_util_la-nm-setting-connection.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='nm-setting-connection.c' object='libnm_util_la-nm-setting-connection.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-nm-setting-connection.lo `test -f 'nm-setting-connection.c' || echo '$(srcdir)/'`nm-setting-connection.c
-
-libnm_util_la-nm-setting-infiniband.lo: nm-setting-infiniband.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-nm-setting-infiniband.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-nm-setting-infiniband.Tpo -c -o libnm_util_la-nm-setting-infiniband.lo `test -f 'nm-setting-infiniband.c' || echo '$(srcdir)/'`nm-setting-infiniband.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_util_la-nm-setting-infiniband.Tpo $(DEPDIR)/libnm_util_la-nm-setting-infiniband.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='nm-setting-infiniband.c' object='libnm_util_la-nm-setting-infiniband.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-nm-setting-infiniband.lo `test -f 'nm-setting-infiniband.c' || echo '$(srcdir)/'`nm-setting-infiniband.c
-
-libnm_util_la-nm-setting-ip4-config.lo: nm-setting-ip4-config.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-nm-setting-ip4-config.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-nm-setting-ip4-config.Tpo -c -o libnm_util_la-nm-setting-ip4-config.lo `test -f 'nm-setting-ip4-config.c' || echo '$(srcdir)/'`nm-setting-ip4-config.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_util_la-nm-setting-ip4-config.Tpo $(DEPDIR)/libnm_util_la-nm-setting-ip4-config.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='nm-setting-ip4-config.c' object='libnm_util_la-nm-setting-ip4-config.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-nm-setting-ip4-config.lo `test -f 'nm-setting-ip4-config.c' || echo '$(srcdir)/'`nm-setting-ip4-config.c
-
-libnm_util_la-nm-setting-vlan.lo: nm-setting-vlan.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-nm-setting-vlan.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-nm-setting-vlan.Tpo -c -o libnm_util_la-nm-setting-vlan.lo `test -f 'nm-setting-vlan.c' || echo '$(srcdir)/'`nm-setting-vlan.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_util_la-nm-setting-vlan.Tpo $(DEPDIR)/libnm_util_la-nm-setting-vlan.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='nm-setting-vlan.c' object='libnm_util_la-nm-setting-vlan.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-nm-setting-vlan.lo `test -f 'nm-setting-vlan.c' || echo '$(srcdir)/'`nm-setting-vlan.c
-
-libnm_util_la-nm-setting-ip6-config.lo: nm-setting-ip6-config.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-nm-setting-ip6-config.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-nm-setting-ip6-config.Tpo -c -o libnm_util_la-nm-setting-ip6-config.lo `test -f 'nm-setting-ip6-config.c' || echo '$(srcdir)/'`nm-setting-ip6-config.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_util_la-nm-setting-ip6-config.Tpo $(DEPDIR)/libnm_util_la-nm-setting-ip6-config.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='nm-setting-ip6-config.c' object='libnm_util_la-nm-setting-ip6-config.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-nm-setting-ip6-config.lo `test -f 'nm-setting-ip6-config.c' || echo '$(srcdir)/'`nm-setting-ip6-config.c
-
-libnm_util_la-nm-setting-ppp.lo: nm-setting-ppp.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-nm-setting-ppp.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-nm-setting-ppp.Tpo -c -o libnm_util_la-nm-setting-ppp.lo `test -f 'nm-setting-ppp.c' || echo '$(srcdir)/'`nm-setting-ppp.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_util_la-nm-setting-ppp.Tpo $(DEPDIR)/libnm_util_la-nm-setting-ppp.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='nm-setting-ppp.c' object='libnm_util_la-nm-setting-ppp.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-nm-setting-ppp.lo `test -f 'nm-setting-ppp.c' || echo '$(srcdir)/'`nm-setting-ppp.c
-
-libnm_util_la-nm-setting-pppoe.lo: nm-setting-pppoe.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-nm-setting-pppoe.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-nm-setting-pppoe.Tpo -c -o libnm_util_la-nm-setting-pppoe.lo `test -f 'nm-setting-pppoe.c' || echo '$(srcdir)/'`nm-setting-pppoe.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_util_la-nm-setting-pppoe.Tpo $(DEPDIR)/libnm_util_la-nm-setting-pppoe.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='nm-setting-pppoe.c' object='libnm_util_la-nm-setting-pppoe.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-nm-setting-pppoe.lo `test -f 'nm-setting-pppoe.c' || echo '$(srcdir)/'`nm-setting-pppoe.c
-
-libnm_util_la-nm-setting-serial.lo: nm-setting-serial.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-nm-setting-serial.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-nm-setting-serial.Tpo -c -o libnm_util_la-nm-setting-serial.lo `test -f 'nm-setting-serial.c' || echo '$(srcdir)/'`nm-setting-serial.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_util_la-nm-setting-serial.Tpo $(DEPDIR)/libnm_util_la-nm-setting-serial.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='nm-setting-serial.c' object='libnm_util_la-nm-setting-serial.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-nm-setting-serial.lo `test -f 'nm-setting-serial.c' || echo '$(srcdir)/'`nm-setting-serial.c
-
-libnm_util_la-nm-setting-gsm.lo: nm-setting-gsm.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-nm-setting-gsm.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-nm-setting-gsm.Tpo -c -o libnm_util_la-nm-setting-gsm.lo `test -f 'nm-setting-gsm.c' || echo '$(srcdir)/'`nm-setting-gsm.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_util_la-nm-setting-gsm.Tpo $(DEPDIR)/libnm_util_la-nm-setting-gsm.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='nm-setting-gsm.c' object='libnm_util_la-nm-setting-gsm.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-nm-setting-gsm.lo `test -f 'nm-setting-gsm.c' || echo '$(srcdir)/'`nm-setting-gsm.c
-
-libnm_util_la-nm-setting-cdma.lo: nm-setting-cdma.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-nm-setting-cdma.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-nm-setting-cdma.Tpo -c -o libnm_util_la-nm-setting-cdma.lo `test -f 'nm-setting-cdma.c' || echo '$(srcdir)/'`nm-setting-cdma.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_util_la-nm-setting-cdma.Tpo $(DEPDIR)/libnm_util_la-nm-setting-cdma.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='nm-setting-cdma.c' object='libnm_util_la-nm-setting-cdma.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-nm-setting-cdma.lo `test -f 'nm-setting-cdma.c' || echo '$(srcdir)/'`nm-setting-cdma.c
-
-libnm_util_la-nm-setting-olpc-mesh.lo: nm-setting-olpc-mesh.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-nm-setting-olpc-mesh.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-nm-setting-olpc-mesh.Tpo -c -o libnm_util_la-nm-setting-olpc-mesh.lo `test -f 'nm-setting-olpc-mesh.c' || echo '$(srcdir)/'`nm-setting-olpc-mesh.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_util_la-nm-setting-olpc-mesh.Tpo $(DEPDIR)/libnm_util_la-nm-setting-olpc-mesh.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='nm-setting-olpc-mesh.c' object='libnm_util_la-nm-setting-olpc-mesh.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-nm-setting-olpc-mesh.lo `test -f 'nm-setting-olpc-mesh.c' || echo '$(srcdir)/'`nm-setting-olpc-mesh.c
-
-libnm_util_la-nm-setting-wimax.lo: nm-setting-wimax.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-nm-setting-wimax.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-nm-setting-wimax.Tpo -c -o libnm_util_la-nm-setting-wimax.lo `test -f 'nm-setting-wimax.c' || echo '$(srcdir)/'`nm-setting-wimax.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_util_la-nm-setting-wimax.Tpo $(DEPDIR)/libnm_util_la-nm-setting-wimax.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='nm-setting-wimax.c' object='libnm_util_la-nm-setting-wimax.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-nm-setting-wimax.lo `test -f 'nm-setting-wimax.c' || echo '$(srcdir)/'`nm-setting-wimax.c
-
-libnm_util_la-nm-setting-wired.lo: nm-setting-wired.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-nm-setting-wired.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-nm-setting-wired.Tpo -c -o libnm_util_la-nm-setting-wired.lo `test -f 'nm-setting-wired.c' || echo '$(srcdir)/'`nm-setting-wired.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_util_la-nm-setting-wired.Tpo $(DEPDIR)/libnm_util_la-nm-setting-wired.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='nm-setting-wired.c' object='libnm_util_la-nm-setting-wired.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-nm-setting-wired.lo `test -f 'nm-setting-wired.c' || echo '$(srcdir)/'`nm-setting-wired.c
-
-libnm_util_la-nm-setting-wireless.lo: nm-setting-wireless.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-nm-setting-wireless.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-nm-setting-wireless.Tpo -c -o libnm_util_la-nm-setting-wireless.lo `test -f 'nm-setting-wireless.c' || echo '$(srcdir)/'`nm-setting-wireless.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_util_la-nm-setting-wireless.Tpo $(DEPDIR)/libnm_util_la-nm-setting-wireless.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='nm-setting-wireless.c' object='libnm_util_la-nm-setting-wireless.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-nm-setting-wireless.lo `test -f 'nm-setting-wireless.c' || echo '$(srcdir)/'`nm-setting-wireless.c
-
-libnm_util_la-nm-setting-wireless-security.lo: nm-setting-wireless-security.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-nm-setting-wireless-security.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-nm-setting-wireless-security.Tpo -c -o libnm_util_la-nm-setting-wireless-security.lo `test -f 'nm-setting-wireless-security.c' || echo '$(srcdir)/'`nm-setting-wireless-security.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_util_la-nm-setting-wireless-security.Tpo $(DEPDIR)/libnm_util_la-nm-setting-wireless-security.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='nm-setting-wireless-security.c' object='libnm_util_la-nm-setting-wireless-security.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-nm-setting-wireless-security.lo `test -f 'nm-setting-wireless-security.c' || echo '$(srcdir)/'`nm-setting-wireless-security.c
-
-libnm_util_la-nm-setting-vpn.lo: nm-setting-vpn.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-nm-setting-vpn.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-nm-setting-vpn.Tpo -c -o libnm_util_la-nm-setting-vpn.lo `test -f 'nm-setting-vpn.c' || echo '$(srcdir)/'`nm-setting-vpn.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_util_la-nm-setting-vpn.Tpo $(DEPDIR)/libnm_util_la-nm-setting-vpn.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='nm-setting-vpn.c' object='libnm_util_la-nm-setting-vpn.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-nm-setting-vpn.lo `test -f 'nm-setting-vpn.c' || echo '$(srcdir)/'`nm-setting-vpn.c
-
-libnm_util_la-nm-utils-enum-types.lo: nm-utils-enum-types.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-nm-utils-enum-types.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-nm-utils-enum-types.Tpo -c -o libnm_util_la-nm-utils-enum-types.lo `test -f 'nm-utils-enum-types.c' || echo '$(srcdir)/'`nm-utils-enum-types.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_util_la-nm-utils-enum-types.Tpo $(DEPDIR)/libnm_util_la-nm-utils-enum-types.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='nm-utils-enum-types.c' object='libnm_util_la-nm-utils-enum-types.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-nm-utils-enum-types.lo `test -f 'nm-utils-enum-types.c' || echo '$(srcdir)/'`nm-utils-enum-types.c
-
-libnm_util_la-nm-utils.lo: nm-utils.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-nm-utils.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-nm-utils.Tpo -c -o libnm_util_la-nm-utils.lo `test -f 'nm-utils.c' || echo '$(srcdir)/'`nm-utils.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_util_la-nm-utils.Tpo $(DEPDIR)/libnm_util_la-nm-utils.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='nm-utils.c' object='libnm_util_la-nm-utils.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-nm-utils.lo `test -f 'nm-utils.c' || echo '$(srcdir)/'`nm-utils.c
-
-libnm_util_la-crypto_gnutls.lo: crypto_gnutls.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-crypto_gnutls.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-crypto_gnutls.Tpo -c -o libnm_util_la-crypto_gnutls.lo `test -f 'crypto_gnutls.c' || echo '$(srcdir)/'`crypto_gnutls.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_util_la-crypto_gnutls.Tpo $(DEPDIR)/libnm_util_la-crypto_gnutls.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='crypto_gnutls.c' object='libnm_util_la-crypto_gnutls.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-crypto_gnutls.lo `test -f 'crypto_gnutls.c' || echo '$(srcdir)/'`crypto_gnutls.c
-
-libnm_util_la-crypto_nss.lo: crypto_nss.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_util_la-crypto_nss.lo -MD -MP -MF $(DEPDIR)/libnm_util_la-crypto_nss.Tpo -c -o libnm_util_la-crypto_nss.lo `test -f 'crypto_nss.c' || echo '$(srcdir)/'`crypto_nss.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_util_la-crypto_nss.Tpo $(DEPDIR)/libnm_util_la-crypto_nss.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='crypto_nss.c' object='libnm_util_la-crypto_nss.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_util_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_util_la-crypto_nss.lo `test -f 'crypto_nss.c' || echo '$(srcdir)/'`crypto_nss.c
-
-libtest_crypto_la-crypto.lo: crypto.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtest_crypto_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libtest_crypto_la-crypto.lo -MD -MP -MF $(DEPDIR)/libtest_crypto_la-crypto.Tpo -c -o libtest_crypto_la-crypto.lo `test -f 'crypto.c' || echo '$(srcdir)/'`crypto.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libtest_crypto_la-crypto.Tpo $(DEPDIR)/libtest_crypto_la-crypto.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='crypto.c' object='libtest_crypto_la-crypto.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtest_crypto_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libtest_crypto_la-crypto.lo `test -f 'crypto.c' || echo '$(srcdir)/'`crypto.c
-
-libtest_crypto_la-crypto_gnutls.lo: crypto_gnutls.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtest_crypto_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libtest_crypto_la-crypto_gnutls.lo -MD -MP -MF $(DEPDIR)/libtest_crypto_la-crypto_gnutls.Tpo -c -o libtest_crypto_la-crypto_gnutls.lo `test -f 'crypto_gnutls.c' || echo '$(srcdir)/'`crypto_gnutls.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libtest_crypto_la-crypto_gnutls.Tpo $(DEPDIR)/libtest_crypto_la-crypto_gnutls.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='crypto_gnutls.c' object='libtest_crypto_la-crypto_gnutls.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtest_crypto_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libtest_crypto_la-crypto_gnutls.lo `test -f 'crypto_gnutls.c' || echo '$(srcdir)/'`crypto_gnutls.c
-
-libtest_crypto_la-crypto_nss.lo: crypto_nss.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtest_crypto_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libtest_crypto_la-crypto_nss.lo -MD -MP -MF $(DEPDIR)/libtest_crypto_la-crypto_nss.Tpo -c -o libtest_crypto_la-crypto_nss.lo `test -f 'crypto_nss.c' || echo '$(srcdir)/'`crypto_nss.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libtest_crypto_la-crypto_nss.Tpo $(DEPDIR)/libtest_crypto_la-crypto_nss.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='crypto_nss.c' object='libtest_crypto_la-crypto_nss.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtest_crypto_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libtest_crypto_la-crypto_nss.lo `test -f 'crypto_nss.c' || echo '$(srcdir)/'`crypto_nss.c
-
 mostlyclean-libtool:
 	-rm -f *.lo
 
diff --git a/libnm-util/crypto.c b/libnm-util/crypto.c
index 0cad7f60..0ac4fbac 100644
--- a/libnm-util/crypto.c
+++ b/libnm-util/crypto.c
@@ -148,13 +148,6 @@ parse_old_openssl_key_file (const GByteArray *contents,
 	}
 
 	str = g_string_new_len (NULL, end - start);
-	if (!str) {
-		g_set_error (error, NM_CRYPTO_ERROR,
-		             NM_CRYPTO_ERR_OUT_OF_MEMORY,
-		             _("Not enough memory to store PEM file data."));
-		goto parse_error;
-	}
-
 	for (ln = lines; *ln; ln++) {
 		char *p = *ln;
 
@@ -213,6 +206,8 @@ parse_old_openssl_key_file (const GByteArray *contents,
 				cipher = g_strdup (p);
 			} else if (!strcasecmp (p, "DES-CBC")) {
 				cipher = g_strdup (p);
+			} else if (!strcasecmp (p, "AES-128-CBC")) {
+				cipher = g_strdup (p);
 			} else {
 				g_set_error (error, NM_CRYPTO_ERROR,
 				             NM_CRYPTO_ERR_UNKNOWN_KEY_TYPE,
@@ -308,15 +303,9 @@ parse_pkcs8_key_file (const GByteArray *contents,
 
 	if (der && length) {
 		key = g_byte_array_sized_new (length);
-		if (key) {
-			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_ERR_OUT_OF_MEMORY,
-			                     _("Not enough memory to store private key data."));
-		}
+		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_ERR_DECODE_FAILED,
@@ -336,14 +325,8 @@ file_to_g_byte_array (const char *filename, GError **error)
 
 	if (g_file_get_contents (filename, &contents, &length, error)) {
 		array = g_byte_array_sized_new (length);
-		if (array) {
-			g_byte_array_append (array, (guint8 *) contents, length);
-			g_assert (array->len == length);
-		} else {
-			g_set_error (error, NM_CRYPTO_ERROR,
-				         NM_CRYPTO_ERR_OUT_OF_MEMORY,
-				         _("Not enough memory to store certificate data."));
-		}
+		g_byte_array_append (array, (guint8 *) contents, length);
+		g_assert (array->len == length);
 		g_free (contents);
 	}
 	return array;
@@ -374,12 +357,6 @@ convert_iv (const char *src,
 
 	num /= 2;
 	c = g_malloc0 (num + 1);
-	if (c == NULL) {
-		g_set_error (error, NM_CRYPTO_ERROR,
-		             NM_CRYPTO_ERR_OUT_OF_MEMORY,
-		             _("Not enough memory to store the IV."));
-        return NULL;
-	}
 
 	conv[2] = '\0';
 	for (i = 0; i < num; i++) {
@@ -403,12 +380,12 @@ error:
 }
 
 static char *
-make_des_key (const char *cipher,
-              const char *salt,
-              const gsize salt_len,
-              const char *password,
-              gsize *out_len,
-              GError **error)
+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;
@@ -423,6 +400,8 @@ make_des_key (const char *cipher,
 		digest_len = 24;
 	else if (!strcmp (cipher, "DES-CBC"))
 		digest_len = 8;
+	else if (!strcmp (cipher, "AES-128-CBC"))
+		digest_len = 16;
 	else {
 		g_set_error (error, NM_CRYPTO_ERROR,
 		             NM_CRYPTO_ERR_UNKNOWN_CIPHER,
@@ -431,13 +410,10 @@ make_des_key (const char *cipher,
 		return NULL;
 	}
 
-	key = g_malloc0 (digest_len + 1);
-	if (!key) {
-		g_set_error (error, NM_CRYPTO_ERROR,
-		             NM_CRYPTO_ERR_OUT_OF_MEMORY,
-		             _("Not enough memory to decrypt private key."));
+	if (password[0] == '\0')
 		return NULL;
-	}
+
+	key = g_malloc0 (digest_len + 1);
 
 	if (!crypto_md5_hash (salt,
 	                      salt_len,
@@ -482,8 +458,8 @@ decrypt_key (const char *cipher,
 	if (!bin_iv)
 		return NULL;
 
-	/* Convert the PIN and IV into a DES key */
-	key = make_des_key (cipher, bin_iv, bin_iv_len, password, &key_len, error);
+	/* Convert the password and IV into a DES or AES key */
+	key = make_des_aes_key (cipher, bin_iv, bin_iv_len, password, &key_len, error);
 	if (!key || !key_len)
 		goto out;
 
@@ -495,13 +471,7 @@ decrypt_key (const char *cipher,
 	                         error);
 	if (output && decrypted_len) {
 		decrypted = g_byte_array_sized_new (decrypted_len);
-		if (decrypted)
-			g_byte_array_append (decrypted, (guint8 *) output, decrypted_len);
-		else {
-			g_set_error (error, NM_CRYPTO_ERROR,
-					     NM_CRYPTO_ERR_OUT_OF_MEMORY,
-					     _("Not enough memory to store decrypted private key."));
-		}
+		g_byte_array_append (decrypted, (guint8 *) output, decrypted_len);
 	}
 
 out:
@@ -622,14 +592,8 @@ extract_pem_cert_data (GByteArray *contents, GError **error)
 
 	if (der && length) {
 		cert = g_byte_array_sized_new (length);
-		if (cert) {
-			g_byte_array_append (cert, der, length);
-			g_assert (cert->len == length);
-		} else {
-			g_set_error (error, NM_CRYPTO_ERROR,
-						 NM_CRYPTO_ERR_OUT_OF_MEMORY,
-						 _("Not enough memory to store certificate data."));
-		}
+		g_byte_array_append (cert, der, length);
+		g_assert (cert->len == length);
 	} else {
 		g_set_error (error, NM_CRYPTO_ERROR,
 			         NM_CRYPTO_ERR_DECODE_FAILED,
diff --git a/libnm-util/crypto.h b/libnm-util/crypto.h
index 482ed087..1cbf61c1 100644
--- a/libnm-util/crypto.h
+++ b/libnm-util/crypto.h
@@ -18,7 +18,7 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2007 - 2011 Red Hat, Inc.
+ * (C) Copyright 2007 - 2014 Red Hat, Inc.
  */
 
 #ifndef __CRYPTO_H__
@@ -29,6 +29,7 @@
 #define MD5_HASH_LEN 20
 #define CIPHER_DES_EDE3_CBC "DES-EDE3-CBC"
 #define CIPHER_DES_CBC "DES-CBC"
+#define CIPHER_AES_CBC "AES-128-CBC"
 
 enum {
 	NM_CRYPTO_ERR_NONE = 0,
diff --git a/libnm-util/crypto_gnutls.c b/libnm-util/crypto_gnutls.c
index d82230b0..e829c23c 100644
--- a/libnm-util/crypto_gnutls.c
+++ b/libnm-util/crypto_gnutls.c
@@ -141,6 +141,9 @@ crypto_decrypt (const char *cipher,
 	} else if (!strcmp (cipher, CIPHER_DES_CBC)) {
 		cipher_mech = GCRY_CIPHER_DES;
 		real_iv_len = SALT_LEN;
+	} else if (!strcmp (cipher, CIPHER_AES_CBC)) {
+		cipher_mech = GCRY_CIPHER_AES;
+		real_iv_len = 16;
 	} else {
 		g_set_error (error, NM_CRYPTO_ERROR,
 		             NM_CRYPTO_ERR_UNKNOWN_CIPHER,
@@ -158,12 +161,6 @@ crypto_decrypt (const char *cipher,
 	}
 
 	output = g_malloc0 (data->len);
-	if (!output) {
-		g_set_error (error, NM_CRYPTO_ERROR,
-		             NM_CRYPTO_ERR_OUT_OF_MEMORY,
-		             _("Not enough memory for decrypted key buffer."));
-		return NULL;
-	}
 
 	err = gcry_cipher_open (&ctx, cipher_mech, GCRY_CIPHER_MODE_CBC, 0);
 	if (err) {
@@ -256,10 +253,15 @@ crypto_encrypt (const char *cipher,
 	gsize padded_buf_len, pad_len, output_len;
 	char *padded_buf = NULL;
 	guint32 i;
+	gsize salt_len;
 
-	if (!strcmp (cipher, CIPHER_DES_EDE3_CBC))
+	if (!strcmp (cipher, CIPHER_DES_EDE3_CBC)) {
 		cipher_mech = GCRY_CIPHER_3DES;
-	else {
+		salt_len = SALT_LEN;
+	} else if (!strcmp (cipher, CIPHER_AES_CBC)) {
+		cipher_mech = GCRY_CIPHER_AES;
+		salt_len = iv_len;
+	} else {
 		g_set_error (error, NM_CRYPTO_ERROR,
 		             NM_CRYPTO_ERR_UNKNOWN_CIPHER,
 		             _("Private key cipher '%s' was unknown."),
@@ -279,12 +281,6 @@ crypto_encrypt (const char *cipher,
 		padded_buf[data->len + i] = (guint8) (pad_len & 0xFF);
 
 	output = g_malloc0 (output_len);
-	if (!output) {
-		g_set_error (error, NM_CRYPTO_ERROR,
-		             NM_CRYPTO_ERR_OUT_OF_MEMORY,
-		             _("Could not allocate memory for encrypting."));
-		return NULL;
-	}
 
 	err = gcry_cipher_open (&ctx, cipher_mech, GCRY_CIPHER_MODE_CBC, 0);
 	if (err) {
@@ -305,7 +301,7 @@ crypto_encrypt (const char *cipher,
 	}
 
 	/* gcrypt only wants 8 bytes of the IV (same as the DES block length) */
-	err = gcry_cipher_setiv (ctx, iv, SALT_LEN);
+	err = gcry_cipher_setiv (ctx, iv, salt_len);
 	if (err) {
 		g_set_error (error, NM_CRYPTO_ERROR,
 		             NM_CRYPTO_ERR_CIPHER_SET_IV_FAILED,
diff --git a/libnm-util/crypto_nss.c b/libnm-util/crypto_nss.c
index 5a7aa30b..af3de666 100644
--- a/libnm-util/crypto_nss.c
+++ b/libnm-util/crypto_nss.c
@@ -161,6 +161,9 @@ crypto_decrypt (const char *cipher,
 	} else if (!strcmp (cipher, CIPHER_DES_CBC)) {
 		cipher_mech = CKM_DES_CBC_PAD;
 		real_iv_len = 8;
+	} else if (!strcmp (cipher, CIPHER_AES_CBC)) {
+		cipher_mech = CKM_AES_CBC_PAD;
+		real_iv_len = 16;
 	} else {
 		g_set_error (error, NM_CRYPTO_ERROR,
 		             NM_CRYPTO_ERR_UNKNOWN_CIPHER,
@@ -178,12 +181,6 @@ crypto_decrypt (const char *cipher,
 	}
 
 	output = g_malloc0 (data->len);
-	if (!output) {
-		g_set_error (error, NM_CRYPTO_ERROR,
-		             NM_CRYPTO_ERR_OUT_OF_MEMORY,
-		             _("Not enough memory for decrypted key buffer."));
-		return NULL;
-	}
 
 	slot = PK11_GetBestSlot (cipher_mech, NULL);
 	if (!slot) {
@@ -326,6 +323,8 @@ crypto_encrypt (const char *cipher,
 
 	if (!strcmp (cipher, CIPHER_DES_EDE3_CBC))
 		cipher_mech = CKM_DES3_CBC_PAD;
+	else if (!strcmp (cipher, CIPHER_AES_CBC))
+		cipher_mech = CKM_AES_CBC_PAD;
 	else {
 		g_set_error (error, NM_CRYPTO_ERROR,
 		             NM_CRYPTO_ERR_UNKNOWN_CIPHER,
@@ -346,12 +345,6 @@ crypto_encrypt (const char *cipher,
 		padded_buf[data->len + i] = (guint8) (pad_len & 0xFF);
 
 	output = g_malloc0 (output_len);
-	if (!output) {
-		g_set_error (error, NM_CRYPTO_ERROR,
-		             NM_CRYPTO_ERR_OUT_OF_MEMORY,
-		             _("Could not allocate memory for encrypting."));
-		return NULL;
-	}
 
 	slot = PK11_GetBestSlot (cipher_mech, NULL);
 	if (!slot) {
@@ -414,11 +407,8 @@ out:
 	if (slot)
 		PK11_FreeSlot (slot);
 
-	if (padded_buf) {
-		memset (padded_buf, 0, padded_buf_len);
-		g_free (padded_buf);
-		padded_buf = NULL;
-	}
+	memset (padded_buf, 0, padded_buf_len);
+	g_free (padded_buf);
 
 	if (!success) {
 		memset (output, 0, output_len);
diff --git a/libnm-util/libnm-util.pc.in b/libnm-util/libnm-util.pc.in
index a6e8ee59..4f1ff3ef 100644
--- a/libnm-util/libnm-util.pc.in
+++ b/libnm-util/libnm-util.pc.in
@@ -6,7 +6,7 @@ includedir=@includedir@
 Name: libnm-util
 Description: Convenience library for clients of NetworkManager
 Version: @VERSION@
-Requires: glib-2.0 dbus-glib-1
+Requires: NetworkManager >= @VERSION@ glib-2.0 dbus-glib-1
 Cflags: -I${includedir}/NetworkManager
 Libs: -L${libdir} -lnm-util
 
diff --git a/libnm-util/libnm-util.ver b/libnm-util/libnm-util.ver
index 04f2a911..e14f08d9 100644
--- a/libnm-util/libnm-util.ver
+++ b/libnm-util/libnm-util.ver
@@ -11,6 +11,7 @@ global:
 	nm_connection_error_get_type;
 	nm_connection_error_quark;
 	nm_connection_for_each_setting_value;
+	nm_connection_get_connection_type;
 	nm_connection_get_id;
 	nm_connection_get_path;
 	nm_connection_get_setting;
@@ -23,6 +24,8 @@ global:
 	nm_connection_get_setting_by_name;
 	nm_connection_get_setting_cdma;
 	nm_connection_get_setting_connection;
+	nm_connection_get_setting_dcb;
+	nm_connection_get_setting_generic;
 	nm_connection_get_setting_gsm;
 	nm_connection_get_setting_infiniband;
 	nm_connection_get_setting_ip4_config;
@@ -31,6 +34,8 @@ global:
 	nm_connection_get_setting_ppp;
 	nm_connection_get_setting_pppoe;
 	nm_connection_get_setting_serial;
+	nm_connection_get_setting_team;
+	nm_connection_get_setting_team_port;
 	nm_connection_get_setting_vlan;
 	nm_connection_get_setting_vpn;
 	nm_connection_get_setting_wimax;
@@ -39,6 +44,7 @@ global:
 	nm_connection_get_setting_wireless_security;
 	nm_connection_get_type;
 	nm_connection_get_uuid;
+	nm_connection_get_virtual_device_description;
 	nm_connection_get_virtual_iface_name;
 	nm_connection_is_type;
 	nm_connection_lookup_setting_type;
@@ -48,6 +54,7 @@ global:
 	nm_connection_new_from_hash;
 	nm_connection_remove_setting;
 	nm_connection_replace_settings;
+	nm_connection_replace_settings_from_connection;
 	nm_connection_set_path;
 	nm_connection_to_hash;
 	nm_connection_update_secrets;
@@ -166,8 +173,11 @@ global:
 	nm_setting_802_1x_get_type;
 	nm_setting_802_1x_new;
 	nm_setting_802_1x_remove_altsubject_match;
+	nm_setting_802_1x_remove_altsubject_match_by_value;
 	nm_setting_802_1x_remove_eap_method;
+	nm_setting_802_1x_remove_eap_method_by_value;
 	nm_setting_802_1x_remove_phase2_altsubject_match;
+	nm_setting_802_1x_remove_phase2_altsubject_match_by_value;
 	nm_setting_802_1x_set_ca_cert;
 	nm_setting_802_1x_set_client_cert;
 	nm_setting_802_1x_set_phase2_ca_cert;
@@ -203,12 +213,14 @@ global:
 	nm_setting_bond_get_valid_options;
 	nm_setting_bond_new;
 	nm_setting_bond_remove_option;
+	nm_setting_bond_validate_option;
 	nm_setting_bridge_error_get_type;
 	nm_setting_bridge_error_quark;
 	nm_setting_bridge_get_ageing_time;
 	nm_setting_bridge_get_forward_delay;
 	nm_setting_bridge_get_hello_time;
 	nm_setting_bridge_get_interface_name;
+	nm_setting_bridge_get_mac_address;
 	nm_setting_bridge_get_max_age;
 	nm_setting_bridge_get_priority;
 	nm_setting_bridge_get_stp;
@@ -239,7 +251,9 @@ global:
 	nm_setting_connection_error_quark;
 	nm_setting_connection_get_autoconnect;
 	nm_setting_connection_get_connection_type;
+	nm_setting_connection_get_gateway_ping_timeout;
 	nm_setting_connection_get_id;
+	nm_setting_connection_get_interface_name;
 	nm_setting_connection_get_master;
 	nm_setting_connection_get_num_permissions;
 	nm_setting_connection_get_num_secondaries;
@@ -255,13 +269,45 @@ global:
 	nm_setting_connection_new;
 	nm_setting_connection_permissions_user_allowed;
 	nm_setting_connection_remove_permission;
+	nm_setting_connection_remove_permission_by_value;
 	nm_setting_connection_remove_secondary;
+	nm_setting_connection_remove_secondary_by_value;
+	nm_setting_dcb_error_get_type;
+	nm_setting_dcb_error_quark;
+	nm_setting_dcb_flags_get_type;
+	nm_setting_dcb_get_app_fcoe_flags;
+	nm_setting_dcb_get_app_fcoe_mode;
+	nm_setting_dcb_get_app_fcoe_priority;
+	nm_setting_dcb_get_app_fip_flags;
+	nm_setting_dcb_get_app_fip_priority;
+	nm_setting_dcb_get_app_iscsi_flags;
+	nm_setting_dcb_get_app_iscsi_priority;
+	nm_setting_dcb_get_priority_bandwidth;
+	nm_setting_dcb_get_priority_flow_control;
+	nm_setting_dcb_get_priority_flow_control_flags;
+	nm_setting_dcb_get_priority_group_bandwidth;
+	nm_setting_dcb_get_priority_group_flags;
+	nm_setting_dcb_get_priority_group_id;
+	nm_setting_dcb_get_priority_strict_bandwidth;
+	nm_setting_dcb_get_priority_traffic_class;
+	nm_setting_dcb_get_type;
+	nm_setting_dcb_new;
+	nm_setting_dcb_set_priority_bandwidth;
+	nm_setting_dcb_set_priority_flow_control;
+	nm_setting_dcb_set_priority_group_bandwidth;
+	nm_setting_dcb_set_priority_group_id;
+	nm_setting_dcb_set_priority_strict_bandwidth;
+	nm_setting_dcb_set_priority_traffic_class;
 	nm_setting_diff;
 	nm_setting_diff_result_get_type;
 	nm_setting_duplicate;
 	nm_setting_enumerate_values;
 	nm_setting_error_get_type;
 	nm_setting_error_quark;
+	nm_setting_generic_error_get_type;
+	nm_setting_generic_error_quark;
+	nm_setting_generic_get_type;
+	nm_setting_generic_new;
 	nm_setting_get_name;
 	nm_setting_get_secret_flags;
 	nm_setting_get_type;
@@ -288,6 +334,8 @@ global:
 	nm_setting_infiniband_error_quark;
 	nm_setting_infiniband_get_mac_address;
 	nm_setting_infiniband_get_mtu;
+	nm_setting_infiniband_get_p_key;
+	nm_setting_infiniband_get_parent;
 	nm_setting_infiniband_get_transport_mode;
 	nm_setting_infiniband_get_type;
 	nm_setting_infiniband_new;
@@ -320,9 +368,13 @@ global:
 	nm_setting_ip4_config_get_type;
 	nm_setting_ip4_config_new;
 	nm_setting_ip4_config_remove_address;
+	nm_setting_ip4_config_remove_address_by_value;
 	nm_setting_ip4_config_remove_dns;
+	nm_setting_ip4_config_remove_dns_by_value;
 	nm_setting_ip4_config_remove_dns_search;
+	nm_setting_ip4_config_remove_dns_search_by_value;
 	nm_setting_ip4_config_remove_route;
+	nm_setting_ip4_config_remove_route_by_value;
 	nm_setting_ip6_config_add_address;
 	nm_setting_ip6_config_add_dns;
 	nm_setting_ip6_config_add_dns_search;
@@ -352,9 +404,13 @@ global:
 	nm_setting_ip6_config_new;
 	nm_setting_ip6_config_privacy_get_type;
 	nm_setting_ip6_config_remove_address;
+	nm_setting_ip6_config_remove_address_by_value;
 	nm_setting_ip6_config_remove_dns;
+	nm_setting_ip6_config_remove_dns_by_value;
 	nm_setting_ip6_config_remove_dns_search;
+	nm_setting_ip6_config_remove_dns_search_by_value;
 	nm_setting_ip6_config_remove_route;
+	nm_setting_ip6_config_remove_route_by_value;
 	nm_setting_need_secrets;
 	nm_setting_new_from_hash;
 	nm_setting_olpc_mesh_error_get_type;
@@ -405,6 +461,17 @@ global:
 	nm_setting_serial_get_type;
 	nm_setting_serial_new;
 	nm_setting_set_secret_flags;
+	nm_setting_team_error_get_type;
+	nm_setting_team_error_quark;
+	nm_setting_team_get_config;
+	nm_setting_team_get_interface_name;
+	nm_setting_team_get_type;
+	nm_setting_team_new;
+	nm_setting_team_port_error_get_type;
+	nm_setting_team_port_error_quark;
+	nm_setting_team_port_get_config;
+	nm_setting_team_port_get_type;
+	nm_setting_team_port_new;
 	nm_setting_to_hash;
 	nm_setting_to_string;
 	nm_setting_update_secrets;
@@ -423,6 +490,8 @@ global:
 	nm_setting_vlan_get_type;
 	nm_setting_vlan_new;
 	nm_setting_vlan_remove_priority;
+	nm_setting_vlan_remove_priority_by_value;
+	nm_setting_vlan_remove_priority_str_by_value;
 	nm_setting_vpn_add_data_item;
 	nm_setting_vpn_add_secret;
 	nm_setting_vpn_error_get_type;
@@ -445,7 +514,9 @@ global:
 	nm_setting_wimax_get_network_name;
 	nm_setting_wimax_get_type;
 	nm_setting_wimax_new;
+	nm_setting_wired_add_mac_blacklist_item;
 	nm_setting_wired_add_s390_option;
+	nm_setting_wired_clear_mac_blacklist_items;
 	nm_setting_wired_error_get_type;
 	nm_setting_wired_error_quark;
 	nm_setting_wired_get_auto_negotiate;
@@ -453,7 +524,9 @@ global:
 	nm_setting_wired_get_duplex;
 	nm_setting_wired_get_mac_address;
 	nm_setting_wired_get_mac_address_blacklist;
+	nm_setting_wired_get_mac_blacklist_item;
 	nm_setting_wired_get_mtu;
+	nm_setting_wired_get_num_mac_blacklist_items;
 	nm_setting_wired_get_num_s390_options;
 	nm_setting_wired_get_port;
 	nm_setting_wired_get_s390_nettype;
@@ -462,10 +535,15 @@ global:
 	nm_setting_wired_get_s390_subchannels;
 	nm_setting_wired_get_speed;
 	nm_setting_wired_get_type;
+	nm_setting_wired_get_valid_s390_options;
 	nm_setting_wired_new;
+	nm_setting_wired_remove_mac_blacklist_item;
+	nm_setting_wired_remove_mac_blacklist_item_by_value;
 	nm_setting_wired_remove_s390_option;
+	nm_setting_wireless_add_mac_blacklist_item;
 	nm_setting_wireless_add_seen_bssid;
 	nm_setting_wireless_ap_security_compatible;
+	nm_setting_wireless_clear_mac_blacklist_items;
 	nm_setting_wireless_error_get_type;
 	nm_setting_wireless_error_quark;
 	nm_setting_wireless_get_band;
@@ -475,8 +553,10 @@ global:
 	nm_setting_wireless_get_hidden;
 	nm_setting_wireless_get_mac_address;
 	nm_setting_wireless_get_mac_address_blacklist;
+	nm_setting_wireless_get_mac_blacklist_item;
 	nm_setting_wireless_get_mode;
 	nm_setting_wireless_get_mtu;
+	nm_setting_wireless_get_num_mac_blacklist_items;
 	nm_setting_wireless_get_num_seen_bssids;
 	nm_setting_wireless_get_rate;
 	nm_setting_wireless_get_security;
@@ -485,6 +565,8 @@ global:
 	nm_setting_wireless_get_tx_power;
 	nm_setting_wireless_get_type;
 	nm_setting_wireless_new;
+	nm_setting_wireless_remove_mac_blacklist_item;
+	nm_setting_wireless_remove_mac_blacklist_item_by_value;
 	nm_setting_wireless_security_add_group;
 	nm_setting_wireless_security_add_pairwise;
 	nm_setting_wireless_security_add_proto;
@@ -513,20 +595,34 @@ global:
 	nm_setting_wireless_security_get_wep_tx_keyidx;
 	nm_setting_wireless_security_new;
 	nm_setting_wireless_security_remove_group;
+	nm_setting_wireless_security_remove_group_by_value;
 	nm_setting_wireless_security_remove_pairwise;
+	nm_setting_wireless_security_remove_pairwise_by_value;
 	nm_setting_wireless_security_remove_proto;
+	nm_setting_wireless_security_remove_proto_by_value;
 	nm_setting_wireless_security_set_wep_key;
+	nm_util_get_private;
 	nm_utils_ap_mode_security_valid;
+	nm_utils_bin2hexstr;
+	nm_utils_check_virtual_device_compatibility;
 	nm_utils_deinit;
 	nm_utils_escape_ssid;
 	nm_utils_file_is_pkcs12;
+	nm_utils_get_private;
 	nm_utils_gvalue_hash_dup;
+	nm_utils_hex2byte;
+	nm_utils_hexstr2bin;
 	nm_utils_hwaddr_atoba;
 	nm_utils_hwaddr_aton;
+	nm_utils_hwaddr_aton_len;
 	nm_utils_hwaddr_len;
 	nm_utils_hwaddr_ntoa;
+	nm_utils_hwaddr_ntoa_len;
 	nm_utils_hwaddr_type;
+	nm_utils_hwaddr_valid;
 	nm_utils_iface_valid_name;
+	nm_utils_inet4_ntop;
+	nm_utils_inet6_ntop;
 	nm_utils_init;
 	nm_utils_ip4_addresses_from_gvalue;
 	nm_utils_ip4_addresses_to_gvalue;
@@ -544,6 +640,7 @@ global:
 	nm_utils_is_empty_ssid;
 	nm_utils_is_uuid;
 	nm_utils_rsa_key_encrypt;
+	nm_utils_rsa_key_encrypt_aes;
 	nm_utils_same_ssid;
 	nm_utils_security_type_get_type;
 	nm_utils_security_valid;
diff --git a/libnm-util/nm-connection.c b/libnm-util/nm-connection.c
index 390b2a3b..b0b683bd 100644
--- a/libnm-util/nm-connection.c
+++ b/libnm-util/nm-connection.c
@@ -19,16 +19,16 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2007 - 2011 Red Hat, Inc.
+ * (C) Copyright 2007 - 2013 Red Hat, Inc.
  * (C) Copyright 2007 - 2008 Novell, Inc.
  */
 
 #include <glib-object.h>
+#include <glib/gi18n.h>
 #include <dbus/dbus-glib.h>
 #include <string.h>
 #include "nm-connection.h"
 #include "nm-utils.h"
-#include "nm-utils-private.h"
 #include "nm-dbus-glib-types.h"
 #include "nm-setting-private.h"
 
@@ -49,6 +49,8 @@
 #include "nm-setting-vpn.h"
 #include "nm-setting-olpc-mesh.h"
 #include "nm-setting-bond.h"
+#include "nm-setting-team.h"
+#include "nm-setting-team-port.h"
 #include "nm-setting-bridge.h"
 #include "nm-setting-bridge-port.h"
 #include "nm-setting-vlan.h"
@@ -114,6 +116,7 @@ enum {
 enum {
 	SECRETS_UPDATED,
 	SECRETS_CLEARED,
+	CHANGED,
 	LAST_SIGNAL
 };
 
@@ -121,114 +124,6 @@ static guint signals[LAST_SIGNAL] = { 0 };
 
 /*************************************************************/
 
-static GHashTable *registered_settings = NULL;
-
-static void __attribute__((constructor))
-_ensure_registered (void)
-{
-	g_type_init ();
-	_nm_utils_register_value_transformations ();
-	if (G_UNLIKELY (registered_settings == NULL))
-		registered_settings = g_hash_table_new (g_str_hash, g_str_equal);
-}
-
-typedef struct {
-	GType type;
-	guint32 priority;
-	GQuark error_quark;
-} SettingInfo;
-
-/*
- * _nm_register_setting:
- * @name: the name of the #NMSetting object to register
- * @type: the #GType of the #NMSetting
- * @priority: the sort priority of the setting, see below
- * @error_quark: the setting's error quark
- *
- * INTERNAL ONLY: registers a setting's internal properties, like its priority
- * and its error quark type, with libnm-util.
- *
- * 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 the Connection setting
- *
- * 1: hardware-related settings like Ethernet, WiFi, 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.
- *
- * 2: hardware-related auxiliary settings that require a base setting to be
- * successful first, like WiFi security, 802.1x, etc.
- *
- * 3: hardware-independent settings that are required before IP connectivity
- * can be established, like PPP, PPPoE, etc.
- *
- * 4: IP-level stuff
- */
-void
-_nm_register_setting (const char *name,
-                      const GType type,
-                      const guint32 priority,
-                      const GQuark error_quark)
-{
-	SettingInfo *info;
-
-	g_return_if_fail (name != NULL);
-	g_return_if_fail (type != G_TYPE_INVALID);
-	g_return_if_fail (type != G_TYPE_NONE);
-	g_return_if_fail (error_quark != 0);
-	g_return_if_fail (priority <= 4);
-
-	_ensure_registered ();
-
-	if (G_LIKELY (g_hash_table_lookup (registered_settings, name)))
-		return;
-
-	if (priority == 0)
-		g_assert_cmpstr (name, ==, NM_SETTING_CONNECTION_SETTING_NAME);
-
-	info = g_slice_new0 (SettingInfo);
-	info->type = type;
-	info->priority = priority;
-	info->error_quark = error_quark;
-	g_hash_table_insert (registered_settings, (gpointer) name, info);
-}
-
-static guint32
-_get_setting_priority (NMSetting *setting)
-{
-	GHashTableIter iter;
-	SettingInfo *info;
-
-	_ensure_registered ();
-
-	g_hash_table_iter_init (&iter, registered_settings);
-	while (g_hash_table_iter_next (&iter, NULL, (gpointer) &info)) {
-		if (G_OBJECT_TYPE (setting) == info->type)
-			return info->priority;
-	}
-	return G_MAXUINT32;
-}
-
-static gboolean
-_is_setting_base_type (NMSetting *setting)
-{
-	/* Historical oddity: PPPoE is a base-type even though it's not
-	 * priority 1.  It needs to be sorted *after* lower-level stuff like
-	 * WiFi security or 802.1x for secrets, but it's still allowed as a
-	 * base type.
-	 */
-	return _get_setting_priority (setting) == 1 || NM_IS_SETTING_PPPOE (setting);
-}
-
-/*************************************************************/
-
 /**
  * nm_connection_lookup_setting_type:
  * @name: a setting name
@@ -240,18 +135,7 @@ _is_setting_base_type (NMSetting *setting)
 GType
 nm_connection_lookup_setting_type (const char *name)
 {
-	SettingInfo *info;
-
-	g_return_val_if_fail (name != NULL, G_TYPE_NONE);
-
-	_ensure_registered ();
-
-	info = g_hash_table_lookup (registered_settings, name);
-	if (info)
-		return info->type;
-
-	g_warning ("Unknown setting '%s'", name);
-	return G_TYPE_INVALID;
+	return _nm_setting_lookup_setting_type (name);
 }
 
 /**
@@ -266,17 +150,7 @@ nm_connection_lookup_setting_type (const char *name)
 GType
 nm_connection_lookup_setting_type_by_quark (GQuark error_quark)
 {
-	SettingInfo *info;
-	GHashTableIter iter;
-
-	_ensure_registered ();
-
-	g_hash_table_iter_init (&iter, registered_settings);
-	while (g_hash_table_iter_next (&iter, NULL, (gpointer) &info)) {
-		if (info->error_quark == error_quark)
-			return info->type;
-	}
-	return G_TYPE_INVALID;
+	return _nm_setting_lookup_setting_type_by_quark (error_quark);
 }
 
 /**
@@ -303,17 +177,21 @@ nm_connection_create_setting (const char *name)
 }
 
 static void
-parse_one_setting (gpointer key, gpointer value, gpointer user_data)
+setting_changed_cb (NMSetting *setting,
+                    GParamSpec *pspec,
+                    NMConnection *self)
 {
-	NMConnection *connection = (NMConnection *) user_data;
-	GType type;
-	NMSetting *setting = NULL;
+	g_signal_emit (self, signals[CHANGED], 0);
+}
 
-	type = nm_connection_lookup_setting_type ((char *) key);
-	if (type)
-		setting = nm_setting_new_from_hash (type, (GHashTable *) value);
-	if (setting)
-		nm_connection_add_setting (connection, setting);
+static void
+_nm_connection_add_setting (NMConnection *connection, NMSetting *setting)
+{
+	g_hash_table_insert (NM_CONNECTION_GET_PRIVATE (connection)->settings,
+	                     (gpointer) G_OBJECT_TYPE_NAME (setting),
+	                     setting);
+	/* Listen for property changes so we can emit the 'changed' signal */
+	g_signal_connect (setting, "notify", (GCallback) setting_changed_cb, connection);
 }
 
 /**
@@ -332,8 +210,8 @@ nm_connection_add_setting (NMConnection *connection, NMSetting *setting)
 	g_return_if_fail (NM_IS_CONNECTION (connection));
 	g_return_if_fail (NM_IS_SETTING (setting));
 
-	g_hash_table_insert (NM_CONNECTION_GET_PRIVATE (connection)->settings,
-					 g_strdup (G_OBJECT_TYPE_NAME (setting)), setting);
+	_nm_connection_add_setting (connection, setting);
+	g_signal_emit (connection, signals[CHANGED], 0);
 }
 
 /**
@@ -347,10 +225,21 @@ nm_connection_add_setting (NMConnection *connection, NMSetting *setting)
 void
 nm_connection_remove_setting (NMConnection *connection, GType setting_type)
 {
+	NMConnectionPrivate *priv;
+	NMSetting *setting;
+	const char *setting_name;
+
 	g_return_if_fail (NM_IS_CONNECTION (connection));
 	g_return_if_fail (g_type_is_a (setting_type, NM_TYPE_SETTING));
 
-	g_hash_table_remove (NM_CONNECTION_GET_PRIVATE (connection)->settings, g_type_name (setting_type));
+	priv = NM_CONNECTION_GET_PRIVATE (connection);
+	setting_name = g_type_name (setting_type);
+	setting = g_hash_table_lookup (priv->settings, setting_name);
+	if (setting) {
+		g_signal_handlers_disconnect_by_func (setting, setting_changed_cb, connection);
+		g_hash_table_remove (priv->settings, setting_name);
+		g_signal_emit (connection, signals[CHANGED], 0);
+	}
 }
 
 /**
@@ -371,7 +260,7 @@ nm_connection_get_setting (NMConnection *connection, GType setting_type)
 	g_return_val_if_fail (g_type_is_a (setting_type, NM_TYPE_SETTING), NULL);
 
 	return (NMSetting *) g_hash_table_lookup (NM_CONNECTION_GET_PRIVATE (connection)->settings,
-									  g_type_name (setting_type));
+	                                          g_type_name (setting_type));
 }
 
 /**
@@ -380,7 +269,7 @@ nm_connection_get_setting (NMConnection *connection, GType setting_type)
  * @name: a setting name
  *
  * Gets the #NMSetting with the given name, if one has been previously added
- * the the #NMConnection.
+ * the #NMConnection.
  *
  * Returns: (transfer none): the #NMSetting, or %NULL if no setting with that name was previously
  * added to the #NMConnection
@@ -447,6 +336,38 @@ validate_permissions_type (GHashTable *hash, GError **error)
 	return TRUE;
 }
 
+static gboolean
+hash_to_connection (NMConnection *connection, GHashTable *new, GError **error)
+{
+	GHashTableIter iter;
+	const char *setting_name;
+	GHashTable *setting_hash;
+	gboolean changed, valid;
+	NMConnectionPrivate *priv = NM_CONNECTION_GET_PRIVATE (connection);
+
+	if ((changed = g_hash_table_size (priv->settings) > 0))
+		g_hash_table_remove_all (priv->settings);
+
+	g_hash_table_iter_init (&iter, new);
+	while (g_hash_table_iter_next (&iter, (gpointer) &setting_name, (gpointer) &setting_hash)) {
+		GType type = nm_connection_lookup_setting_type (setting_name);
+
+		if (type) {
+			NMSetting *setting = nm_setting_new_from_hash (type, setting_hash);
+
+			if (setting) {
+				_nm_connection_add_setting (connection, setting);
+				changed = TRUE;
+			}
+		}
+	}
+
+	valid = nm_connection_verify (connection, error);
+	if (changed)
+		g_signal_emit (connection, signals[CHANGED], 0);
+	return valid;
+}
+
 /**
  * nm_connection_replace_settings:
  * @connection: a #NMConnection
@@ -461,42 +382,71 @@ nm_connection_replace_settings (NMConnection *connection,
                                 GHashTable *new_settings,
                                 GError **error)
 {
-	g_return_val_if_fail (connection != NULL, FALSE);
+	gboolean valid = FALSE;
+
 	g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
 	g_return_val_if_fail (new_settings != NULL, FALSE);
 	if (error)
 		g_return_val_if_fail (*error == NULL, FALSE);
 
-	if (!validate_permissions_type (new_settings, error))
-		return FALSE;
+	if (validate_permissions_type (new_settings, error))
+		valid = hash_to_connection (connection, new_settings, error);
+	return valid;
+}
 
-	g_hash_table_remove_all (NM_CONNECTION_GET_PRIVATE (connection)->settings);
-	g_hash_table_foreach (new_settings, parse_one_setting, connection);
+/**
+ * nm_connection_replace_settings_from_connection:
+ * @connection: a #NMConnection
+ * @new_connection: a #NMConnection to replace the settings of @connection with
+ * @error: location to store error, or %NULL
+ *
+ * Deep-copies the settings of @new_conenction and replaces the settings of @connection
+ * with the copied settings.
+ *
+ * Returns: %TRUE if the settings were valid and added to the connection, %FALSE
+ * if they were not
+ *
+ * Since: 0.9.10
+ **/
+gboolean
+nm_connection_replace_settings_from_connection (NMConnection *connection,
+                                                NMConnection *new_connection,
+                                                GError **error)
+{
+	NMConnectionPrivate *priv;
+	GHashTableIter iter;
+	NMSetting *setting;
+	gboolean changed, valid;
 
-	return nm_connection_verify (connection, error);
-}
+	g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
+	g_return_val_if_fail (NM_IS_CONNECTION (new_connection), FALSE);
+	if (error)
+		g_return_val_if_fail (*error == NULL, FALSE);
 
-typedef struct {
-	NMConnection *other;
-	gboolean failed;
-	NMSettingCompareFlags flags;
-} CompareConnectionInfo;
+	/* When 'connection' and 'new_connection' are the same object simply return
+	 * in order not to destroy 'connection' */
+	if (connection == new_connection)
+		return TRUE;
 
-static void
-compare_one_setting (gpointer key, gpointer value, gpointer user_data)
-{
-	NMSetting *setting = (NMSetting *) value;
-	CompareConnectionInfo *info = (CompareConnectionInfo *) user_data;
-	NMSetting *other_setting;
+	/* No need to validate permissions like nm_connection_replace_settings()
+	 * since we're dealing with an NMConnection which has already done that.
+	 */
 
-	if (info->failed)
-		return;
+	priv = NM_CONNECTION_GET_PRIVATE (connection);
+	if ((changed = g_hash_table_size (priv->settings) > 0))
+		g_hash_table_remove_all (priv->settings);
+
+	if (g_hash_table_size (NM_CONNECTION_GET_PRIVATE (new_connection)->settings)) {
+		g_hash_table_iter_init (&iter, NM_CONNECTION_GET_PRIVATE (new_connection)->settings);
+		while (g_hash_table_iter_next (&iter, NULL, (gpointer) &setting))
+			_nm_connection_add_setting (connection, nm_setting_duplicate (setting));
+		changed = TRUE;
+	}
 
-	other_setting = nm_connection_get_setting (info->other, G_OBJECT_TYPE (setting));
-	if (other_setting)
-		info->failed = nm_setting_compare (setting, other_setting, info->flags) ? FALSE : TRUE;
-	else
-		info->failed = TRUE;
+	valid =  nm_connection_verify (connection, error);
+	if (changed)
+		g_signal_emit (connection, signals[CHANGED], 0);
+	return valid;
 }
 
 /**
@@ -516,28 +466,29 @@ nm_connection_compare (NMConnection *a,
                        NMConnection *b,
                        NMSettingCompareFlags flags)
 {
-	NMConnectionPrivate *priv;
-	CompareConnectionInfo info = { b, FALSE, flags };
+	GHashTableIter iter;
+	NMSetting *src;
 
-	if (!a && !b)
+	if (a == b)
 		return TRUE;
-
 	if (!a || !b)
 		return FALSE;
 
-	priv = NM_CONNECTION_GET_PRIVATE (a);
-	g_hash_table_foreach (priv->settings, compare_one_setting, &info);
-	if (info.failed == FALSE) {
-		/* compare A to B, then if that is the same compare B to A to ensure
-		 * that keys that are in B but not A will make the comparison fail.
-		 */
-		info.failed = FALSE;
-		info.other = a;
-		priv = NM_CONNECTION_GET_PRIVATE (b);
-		g_hash_table_foreach (priv->settings, compare_one_setting, &info);
+	/* B / A: ensure settings in B that are not in A make the comparison fail */
+	if (g_hash_table_size (NM_CONNECTION_GET_PRIVATE (a)->settings) !=
+		g_hash_table_size (NM_CONNECTION_GET_PRIVATE (b)->settings))
+		return FALSE;
+
+	/* A / B: ensure all settings in A match corresponding ones in B */
+	g_hash_table_iter_init (&iter, NM_CONNECTION_GET_PRIVATE (a)->settings);
+	while (g_hash_table_iter_next (&iter, NULL, (gpointer) &src)) {
+		NMSetting *cmp = nm_connection_get_setting (b, G_OBJECT_TYPE (src));
+
+		if (!cmp || !nm_setting_compare (src, cmp, flags))
+			return FALSE;
 	}
 
-	return info.failed ? FALSE : TRUE;
+	return TRUE;
 }
 
 
@@ -600,7 +551,6 @@ nm_connection_diff (NMConnection *a,
 {
 	GHashTable *diffs;
 
-	g_return_val_if_fail (a != NULL, FALSE);
 	g_return_val_if_fail (NM_IS_CONNECTION (a), FALSE);
 	g_return_val_if_fail (out_settings != NULL, FALSE);
 	g_return_val_if_fail (*out_settings == NULL, FALSE);
@@ -632,7 +582,7 @@ nm_connection_diff (NMConnection *a,
  *
  * Validates the connection and all its settings.  Each setting's properties
  * have allowed values, and some values are dependent on other values.  For
- * example, if a WiFi connection is security enabled, the #NMSettingWireless
+ * example, if a Wi-Fi connection is security enabled, the #NMSettingWireless
  * setting object's 'security' property must contain the setting name of the
  * #NMSettingWirelessSecurity object, which must also be present in the 
  * connection for the connection to be valid.  As another example, the
@@ -712,7 +662,7 @@ nm_connection_verify (NMConnection *connection, GError **error)
 		return FALSE;
 	}
 
-	if (!_is_setting_base_type (base)) {
+	if (!_nm_setting_is_base_type (base)) {
 		g_set_error (error,
 			         NM_CONNECTION_ERROR,
 			         NM_CONNECTION_ERROR_CONNECTION_TYPE_INVALID,
@@ -749,73 +699,113 @@ nm_connection_update_secrets (NMConnection *connection,
                               GError **error)
 {
 	NMSetting *setting;
-	gboolean success;
-	GHashTable *tmp;
+	gboolean success = TRUE, updated = FALSE;
+	GHashTable *setting_hash = NULL;
+	GHashTableIter iter;
+	const char *key;
+	gboolean hashed_connection = FALSE;
+	int success_detail;
 
-	g_return_val_if_fail (connection != NULL, FALSE);
 	g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
 	g_return_val_if_fail (secrets != NULL, FALSE);
 	if (error)
 		g_return_val_if_fail (*error == NULL, FALSE);
 
+	/* Empty @secrets means success */
+	if (g_hash_table_size (secrets) == 0)
+		return TRUE;
+
+	/* For backwards compatibility, this function accepts either a hashed
+	 * connection (GHashTable of GHashTables of GValues) or a single hashed
+	 * setting (GHashTable of GValues).
+	 */
+	g_hash_table_iter_init (&iter, secrets);
+	while (g_hash_table_iter_next (&iter, (gpointer) &key, NULL)) {
+		if (_nm_setting_lookup_setting_type (key) != G_TYPE_INVALID) {
+			/* @secrets looks like a hashed connection */
+			hashed_connection = TRUE;
+			break;
+		}
+	}
+
 	if (setting_name) {
-		/* Update just one setting */
+		/* Update just one setting's secrets */
 		setting = nm_connection_get_setting_by_name (connection, setting_name);
 		if (!setting) {
 			g_set_error_literal (error,
-				                 NM_CONNECTION_ERROR,
-				                 NM_CONNECTION_ERROR_SETTING_NOT_FOUND,
-				                 setting_name);
+			                     NM_CONNECTION_ERROR,
+			                     NM_CONNECTION_ERROR_SETTING_NOT_FOUND,
+			                     setting_name);
 			return FALSE;
 		}
 
-		/* Check if this is a hash of hashes, ie a full deserialized connection,
-		 * not just a single hashed setting.
-		 */
-		tmp = g_hash_table_lookup (secrets, setting_name);
-		success = nm_setting_update_secrets (setting, tmp ? tmp : secrets, error);
-	} else {
-		GHashTableIter iter;
-		const char *name;
+		if (hashed_connection) {
+			setting_hash = g_hash_table_lookup (secrets, setting_name);
+			if (!setting_hash) {
+				/* The hashed connection that didn't contain any secrets for
+				 * @setting_name; just return success.
+				 */
+				return TRUE;
+			}
+		}
 
-		success = TRUE; /* Just in case 'secrets' has no elements */
+		g_signal_handlers_block_by_func (setting, (GCallback) setting_changed_cb, connection);
+		success_detail = _nm_setting_update_secrets (setting,
+		                                      setting_hash ? setting_hash : secrets,
+		                                      error);
+		g_signal_handlers_unblock_by_func (setting, (GCallback) setting_changed_cb, connection);
+
+		if (success_detail == NM_SETTING_UPDATE_SECRET_ERROR)
+			return FALSE;
+		if (success_detail == NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED)
+			updated = TRUE;
+	} else {
+		if (!hashed_connection) {
+			g_set_error_literal (error,
+			                     NM_CONNECTION_ERROR,
+			                     NM_CONNECTION_ERROR_SETTING_NOT_FOUND,
+			                     key);
+			return FALSE;
+		}
 
-		/* Try as a serialized connection (GHashTable of GHashTables) */
+		/* check first, whether all the settings exist... */
 		g_hash_table_iter_init (&iter, secrets);
-		while (g_hash_table_iter_next (&iter, (gpointer) &name, (gpointer) &tmp)) {
-			setting = nm_connection_get_setting_by_name (connection, name);
+		while (g_hash_table_iter_next (&iter, (gpointer) &key, NULL)) {
+			setting = nm_connection_get_setting_by_name (connection, key);
 			if (!setting) {
 				g_set_error_literal (error,
-						             NM_CONNECTION_ERROR,
-						             NM_CONNECTION_ERROR_SETTING_NOT_FOUND,
-						             name);
+				                     NM_CONNECTION_ERROR,
+				                     NM_CONNECTION_ERROR_SETTING_NOT_FOUND,
+				                     key);
 				return FALSE;
 			}
+		}
 
+		/* Update each setting with any secrets from the hashed connection */
+		g_hash_table_iter_init (&iter, secrets);
+		while (g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &setting_hash)) {
 			/* Update the secrets for this setting */
-			success = nm_setting_update_secrets (setting, tmp, error);
-			if (success == FALSE)
+			setting = nm_connection_get_setting_by_name (connection, key);
+
+			g_signal_handlers_block_by_func (setting, (GCallback) setting_changed_cb, connection);
+			success_detail = _nm_setting_update_secrets (setting, setting_hash, error);
+			g_signal_handlers_unblock_by_func (setting, (GCallback) setting_changed_cb, connection);
+
+			if (success_detail == NM_SETTING_UPDATE_SECRET_ERROR) {
+				success = FALSE;
 				break;
+			}
+			if (success_detail == NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED)
+				updated = TRUE;
 		}
 	}
-	if (success)
-		g_signal_emit (connection, signals[SECRETS_UPDATED], 0, setting_name);
-	return success;
-}
 
-static gint
-setting_priority_compare (gconstpointer a, gconstpointer b)
-{
-	guint32 prio_a, prio_b;
-
-	prio_a = _get_setting_priority (NM_SETTING (a));
-	prio_b = _get_setting_priority (NM_SETTING (b));
+	if (updated) {
+		g_signal_emit (connection, signals[SECRETS_UPDATED], 0, setting_name);
+		g_signal_emit (connection, signals[CHANGED], 0);
+	}
 
-	if (prio_a < prio_b)
-		return -1;
-	else if (prio_a == prio_b)
-		return 0;
-	return 1;
+	return success;
 }
 
 /**
@@ -848,7 +838,6 @@ nm_connection_need_secrets (NMConnection *connection,
 	const char *name = NULL;
 	NMSetting *setting;
 
-	g_return_val_if_fail (connection != NULL, NULL);
 	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
 	if (hints)
 		g_return_val_if_fail (*hints == NULL, NULL);
@@ -858,7 +847,7 @@ nm_connection_need_secrets (NMConnection *connection,
 	/* Get list of settings in priority order */
 	g_hash_table_iter_init (&hiter, priv->settings);
 	while (g_hash_table_iter_next (&hiter, NULL, (gpointer) &setting))
-		settings = g_slist_insert_sorted (settings, setting, setting_priority_compare);
+		settings = g_slist_insert_sorted (settings, setting, _nm_setting_compare_priority);
 
 	for (iter = settings; iter; iter = g_slist_next (iter)) {
 		GPtrArray *secrets;
@@ -892,14 +881,20 @@ nm_connection_clear_secrets (NMConnection *connection)
 {
 	GHashTableIter iter;
 	NMSetting *setting;
+	gboolean changed = FALSE;
 
 	g_return_if_fail (NM_IS_CONNECTION (connection));
 
 	g_hash_table_iter_init (&iter, NM_CONNECTION_GET_PRIVATE (connection)->settings);
-	while (g_hash_table_iter_next (&iter, NULL, (gpointer) &setting))
-		nm_setting_clear_secrets (setting);
+	while (g_hash_table_iter_next (&iter, NULL, (gpointer) &setting)) {
+		g_signal_handlers_block_by_func (setting, (GCallback) setting_changed_cb, connection);
+		changed |= _nm_setting_clear_secrets (setting);
+		g_signal_handlers_unblock_by_func (setting, (GCallback) setting_changed_cb, connection);
+	}
 
 	g_signal_emit (connection, signals[SECRETS_CLEARED], 0);
+	if (changed)
+		g_signal_emit (connection, signals[CHANGED], 0);
 }
 
 /**
@@ -918,14 +913,20 @@ nm_connection_clear_secrets_with_flags (NMConnection *connection,
 {
 	GHashTableIter iter;
 	NMSetting *setting;
+	gboolean changed = FALSE;
 
 	g_return_if_fail (NM_IS_CONNECTION (connection));
 
 	g_hash_table_iter_init (&iter, NM_CONNECTION_GET_PRIVATE (connection)->settings);
-	while (g_hash_table_iter_next (&iter, NULL, (gpointer) &setting))
-		nm_setting_clear_secrets_with_flags (setting, func, user_data);
+	while (g_hash_table_iter_next (&iter, NULL, (gpointer) &setting)) {
+		g_signal_handlers_block_by_func (setting, (GCallback) setting_changed_cb, connection);
+		changed |= _nm_setting_clear_secrets_with_flags (setting, func, user_data);
+		g_signal_handlers_unblock_by_func (setting, (GCallback) setting_changed_cb, connection);
+	}
 
 	g_signal_emit (connection, signals[SECRETS_CLEARED], 0);
+	if (changed)
+		g_signal_emit (connection, signals[CHANGED], 0);
 }
 
 /**
@@ -953,7 +954,6 @@ nm_connection_to_hash (NMConnection *connection, NMSettingHashFlags flags)
 	gpointer key, data;
 	GHashTable *ret, *setting_hash;
 
-	g_return_val_if_fail (connection != NULL, NULL);
 	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
 
 	ret = g_hash_table_new_full (g_str_hash, g_str_equal,
@@ -987,7 +987,7 @@ nm_connection_to_hash (NMConnection *connection, NMSettingHashFlags flags)
  * %NM_SETTING_WIRELESS_SETTING_NAME or %NM_SETTING_WIRED_SETTING_NAME)
  *
  * A convenience function to check if the given @connection is a particular
- * type (ie wired, wifi, ppp, etc). Checks the #NMSettingConnection:type
+ * type (ie wired, Wi-Fi, ppp, etc). Checks the #NMSettingConnection:type
  * property of the connection and matches that against @type.
  *
  * Returns: %TRUE if the connection is of the given @type, %FALSE if not
@@ -998,12 +998,12 @@ nm_connection_is_type (NMConnection *connection, const char *type)
 	NMSettingConnection *s_con;
 	const char *type2;
 
-	g_return_val_if_fail (connection != NULL, FALSE);
 	g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
 	g_return_val_if_fail (type != NULL, FALSE);
 
 	s_con = nm_connection_get_setting_connection (connection);
-	g_assert (s_con);
+	if (!s_con)
+		return FALSE;
 
 	type2 = nm_setting_connection_get_connection_type (s_con);
 
@@ -1035,16 +1035,6 @@ nm_connection_for_each_setting_value (NMConnection *connection,
 		nm_setting_enumerate_values (NM_SETTING (value), func, user_data);
 }
 
-static void
-dump_setting (gpointer key, gpointer value, gpointer user_data)
-{
-	char *str;
-
-	str = nm_setting_to_string (NM_SETTING (value));
-	g_print ("%s\n", str);
-	g_free (str);
-}
-
 /**
  * nm_connection_dump:
  * @connection: the #NMConnection
@@ -1056,9 +1046,20 @@ dump_setting (gpointer key, gpointer value, gpointer user_data)
 void
 nm_connection_dump (NMConnection *connection)
 {
-	g_return_if_fail (NM_IS_CONNECTION (connection));
+	GHashTableIter iter;
+	NMSetting *setting;
+	const char *setting_name;
+	char *str;
+
+	if (!connection)
+		return;
 
-	g_hash_table_foreach (NM_CONNECTION_GET_PRIVATE (connection)->settings, dump_setting, NULL);
+	g_hash_table_iter_init (&iter, NM_CONNECTION_GET_PRIVATE (connection)->settings);
+	while (g_hash_table_iter_next (&iter, (gpointer) &setting_name, (gpointer) &setting)) {
+		str = nm_setting_to_string (setting);
+		g_print ("%s\n", str);
+		g_free (str);
+	}
 }
 
 /**
@@ -1165,22 +1166,13 @@ nm_connection_new_from_hash (GHashTable *hash, GError **error)
 		return NULL;
 
 	connection = nm_connection_new ();
-	g_hash_table_foreach (hash, parse_one_setting, connection);
-
-	if (!nm_connection_verify (connection, error)) {
+	if (!hash_to_connection (connection, hash, error)) {
 		g_object_unref (connection);
 		return NULL;
 	}
-
 	return connection;
 }
 
-static void
-duplicate_cb (gpointer key, gpointer value, gpointer user_data)
-{
-	nm_connection_add_setting (NM_CONNECTION (user_data), nm_setting_duplicate (NM_SETTING (value)));
-}
-
 /**
  * nm_connection_duplicate:
  * @connection: the #NMConnection to duplicate
@@ -1194,12 +1186,17 @@ NMConnection *
 nm_connection_duplicate (NMConnection *connection)
 {
 	NMConnection *dup;
+	GHashTableIter iter;
+	NMSetting *setting;
 
 	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
 
 	dup = nm_connection_new ();
 	nm_connection_set_path (dup, nm_connection_get_path (connection));
-	g_hash_table_foreach (NM_CONNECTION_GET_PRIVATE (connection)->settings, duplicate_cb, dup);
+
+	g_hash_table_iter_init (&iter, NM_CONNECTION_GET_PRIVATE (connection)->settings);
+	while (g_hash_table_iter_next (&iter, NULL, (gpointer) &setting))
+		nm_connection_add_setting (dup, nm_setting_duplicate (setting));
 
 	return dup;
 }
@@ -1217,7 +1214,6 @@ nm_connection_get_uuid (NMConnection *connection)
 {
 	NMSettingConnection *s_con;
 
-	g_return_val_if_fail (connection != NULL, NULL);
 	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
 
 	s_con = nm_connection_get_setting_connection (connection);
@@ -1239,7 +1235,6 @@ nm_connection_get_id (NMConnection *connection)
 {
 	NMSettingConnection *s_con;
 
-	g_return_val_if_fail (connection != NULL, NULL);
 	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
 
 	s_con = nm_connection_get_setting_connection (connection);
@@ -1248,6 +1243,72 @@ nm_connection_get_id (NMConnection *connection)
 	return nm_setting_connection_get_id (s_con);
 }
 
+/**
+ * nm_connection_get_connection_type:
+ * @connection: the #NMConnection
+ *
+ * A shortcut to return the type from the connection's #NMSettingConnection.
+ *
+ * Returns: the type from the connection's 'connection' setting
+ *
+ * Since: 0.9.10
+ **/
+const char *
+nm_connection_get_connection_type (NMConnection *connection)
+{
+	NMSettingConnection *s_con;
+
+	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+	s_con = nm_connection_get_setting_connection (connection);
+	g_return_val_if_fail (s_con != NULL, NULL);
+
+	return nm_setting_connection_get_connection_type (s_con);
+}
+
+/**
+ * nm_connection_get_virtual_device_description:
+ * @connection: an #NMConnection for a virtual device type
+ *
+ * Returns the name that nm_device_disambiguate_names() would
+ * return for the virtual device that would be created for @connection.
+ * Eg, "VLAN (eth1.1)".
+ *
+ * Returns: (transfer full): the name of @connection's device,
+ *   or %NULL if @connection is not a virtual connection type
+ *
+ * Since: 0.9.10
+ */
+char *
+nm_connection_get_virtual_device_description (NMConnection *connection)
+{
+	const char *iface, *type, *display_type;
+	NMSettingConnection *s_con;
+
+	iface = nm_connection_get_virtual_iface_name (connection);
+	if (!iface)
+		return NULL;
+
+	s_con = nm_connection_get_setting_connection (connection);
+	g_return_val_if_fail (s_con != NULL, NULL);
+	type = nm_setting_connection_get_connection_type (s_con);
+
+	if (!strcmp (type, NM_SETTING_BOND_SETTING_NAME))
+		display_type = _("Bond");
+	else if (!strcmp (type, NM_SETTING_TEAM_SETTING_NAME))
+		display_type = _("Team");
+	else if (!strcmp (type, NM_SETTING_BRIDGE_SETTING_NAME))
+		display_type = _("Bridge");
+	else if (!strcmp (type, NM_SETTING_VLAN_SETTING_NAME))
+		display_type = _("VLAN");
+	else {
+		g_warning ("Unrecognized virtual device type '%s'", type);
+		display_type = type;
+	}
+
+	return g_strdup_printf ("%s (%s)", display_type, iface);
+}
+
 /*************************************************************/
 
 /**
@@ -1261,7 +1322,6 @@ nm_connection_get_id (NMConnection *connection)
 NMSetting8021x *
 nm_connection_get_setting_802_1x (NMConnection *connection)
 {
-	g_return_val_if_fail (connection != NULL, NULL);
 	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
 
 	return (NMSetting8021x *) nm_connection_get_setting (connection, NM_TYPE_SETTING_802_1X);
@@ -1278,7 +1338,6 @@ nm_connection_get_setting_802_1x (NMConnection *connection)
 NMSettingBluetooth *
 nm_connection_get_setting_bluetooth (NMConnection *connection)
 {
-	g_return_val_if_fail (connection != NULL, NULL);
 	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
 
 	return (NMSettingBluetooth *) nm_connection_get_setting (connection, NM_TYPE_SETTING_BLUETOOTH);
@@ -1295,13 +1354,48 @@ nm_connection_get_setting_bluetooth (NMConnection *connection)
 NMSettingBond *
 nm_connection_get_setting_bond (NMConnection *connection)
 {
-	g_return_val_if_fail (connection != NULL, NULL);
 	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
 
 	return (NMSettingBond *) nm_connection_get_setting (connection, NM_TYPE_SETTING_BOND);
 }
 
 /**
+ * nm_connection_get_setting_team:
+ * @connection: the #NMConnection
+ *
+ * A shortcut to return any #NMSettingTeam the connection might contain.
+ *
+ * Returns: (transfer none): an #NMSettingTeam if the connection contains one, otherwise %NULL
+ *
+ * Since: 0.9.10
+ **/
+NMSettingTeam *
+nm_connection_get_setting_team (NMConnection *connection)
+{
+	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+	return (NMSettingTeam *) nm_connection_get_setting (connection, NM_TYPE_SETTING_TEAM);
+}
+
+/**
+ * nm_connection_get_setting_team_port:
+ * @connection: the #NMConnection
+ *
+ * A shortcut to return any #NMSettingTeamPort the connection might contain.
+ *
+ * Returns: (transfer none): an #NMSettingTeamPort if the connection contains one, otherwise %NULL
+ *
+ * Since: 0.9.10
+ **/
+NMSettingTeamPort *
+nm_connection_get_setting_team_port (NMConnection *connection)
+{
+	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+	return (NMSettingTeamPort *) nm_connection_get_setting (connection, NM_TYPE_SETTING_TEAM_PORT);
+}
+
+/**
  * nm_connection_get_setting_bridge:
  * @connection: the #NMConnection
  *
@@ -1312,7 +1406,6 @@ nm_connection_get_setting_bond (NMConnection *connection)
 NMSettingBridge *
 nm_connection_get_setting_bridge (NMConnection *connection)
 {
-	g_return_val_if_fail (connection != NULL, NULL);
 	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
 
 	return (NMSettingBridge *) nm_connection_get_setting (connection, NM_TYPE_SETTING_BRIDGE);
@@ -1329,7 +1422,6 @@ nm_connection_get_setting_bridge (NMConnection *connection)
 NMSettingCdma *
 nm_connection_get_setting_cdma (NMConnection *connection)
 {
-	g_return_val_if_fail (connection != NULL, NULL);
 	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
 
 	return (NMSettingCdma *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CDMA);
@@ -1346,13 +1438,48 @@ nm_connection_get_setting_cdma (NMConnection *connection)
 NMSettingConnection *
 nm_connection_get_setting_connection (NMConnection *connection)
 {
-	g_return_val_if_fail (connection != NULL, NULL);
 	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
 
 	return (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
 }
 
 /**
+ * nm_connection_get_setting_dcb:
+ * @connection: the #NMConnection
+ *
+ * A shortcut to return any #NMSettingDcb the connection might contain.
+ *
+ * Returns: (transfer none): an #NMSettingDcb if the connection contains one, otherwise NULL
+ *
+ * Since: 0.9.10
+ **/
+NMSettingDcb *
+nm_connection_get_setting_dcb (NMConnection *connection)
+{
+	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+	return (NMSettingDcb *) nm_connection_get_setting (connection, NM_TYPE_SETTING_DCB);
+}
+
+/**
+ * nm_connection_get_setting_generic:
+ * @connection: the #NMConnection
+ *
+ * A shortcut to return any #NMSettingGeneric the connection might contain.
+ *
+ * Returns: (transfer none): an #NMSettingGeneric if the connection contains one, otherwise NULL
+ *
+ * Since: 0.9.10
+ **/
+NMSettingGeneric *
+nm_connection_get_setting_generic (NMConnection *connection)
+{
+	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+	return (NMSettingGeneric *) nm_connection_get_setting (connection, NM_TYPE_SETTING_GENERIC);
+}
+
+/**
  * nm_connection_get_setting_gsm:
  * @connection: the #NMConnection
  *
@@ -1363,7 +1490,6 @@ nm_connection_get_setting_connection (NMConnection *connection)
 NMSettingGsm *
 nm_connection_get_setting_gsm (NMConnection *connection)
 {
-	g_return_val_if_fail (connection != NULL, NULL);
 	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
 
 	return (NMSettingGsm *) nm_connection_get_setting (connection, NM_TYPE_SETTING_GSM);
@@ -1380,7 +1506,6 @@ nm_connection_get_setting_gsm (NMConnection *connection)
 NMSettingInfiniband *
 nm_connection_get_setting_infiniband (NMConnection *connection)
 {
-	g_return_val_if_fail (connection != NULL, NULL);
 	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
 
 	return (NMSettingInfiniband *) nm_connection_get_setting (connection, NM_TYPE_SETTING_INFINIBAND);
@@ -1397,7 +1522,6 @@ nm_connection_get_setting_infiniband (NMConnection *connection)
 NMSettingIP4Config *
 nm_connection_get_setting_ip4_config (NMConnection *connection)
 {
-	g_return_val_if_fail (connection != NULL, NULL);
 	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
 
 	return (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG);
@@ -1414,7 +1538,6 @@ nm_connection_get_setting_ip4_config (NMConnection *connection)
 NMSettingIP6Config *
 nm_connection_get_setting_ip6_config (NMConnection *connection)
 {
-	g_return_val_if_fail (connection != NULL, NULL);
 	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
 
 	return (NMSettingIP6Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP6_CONFIG);
@@ -1431,7 +1554,6 @@ nm_connection_get_setting_ip6_config (NMConnection *connection)
 NMSettingOlpcMesh *
 nm_connection_get_setting_olpc_mesh (NMConnection *connection)
 {
-	g_return_val_if_fail (connection != NULL, NULL);
 	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
 
 	return (NMSettingOlpcMesh *) nm_connection_get_setting (connection, NM_TYPE_SETTING_OLPC_MESH);
@@ -1448,7 +1570,6 @@ nm_connection_get_setting_olpc_mesh (NMConnection *connection)
 NMSettingPPP *
 nm_connection_get_setting_ppp (NMConnection *connection)
 {
-	g_return_val_if_fail (connection != NULL, NULL);
 	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
 
 	return (NMSettingPPP *) nm_connection_get_setting (connection, NM_TYPE_SETTING_PPP);
@@ -1465,7 +1586,6 @@ nm_connection_get_setting_ppp (NMConnection *connection)
 NMSettingPPPOE *
 nm_connection_get_setting_pppoe (NMConnection *connection)
 {
-	g_return_val_if_fail (connection != NULL, NULL);
 	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
 
 	return (NMSettingPPPOE *) nm_connection_get_setting (connection, NM_TYPE_SETTING_PPPOE);
@@ -1482,7 +1602,6 @@ nm_connection_get_setting_pppoe (NMConnection *connection)
 NMSettingSerial *
 nm_connection_get_setting_serial (NMConnection *connection)
 {
-	g_return_val_if_fail (connection != NULL, NULL);
 	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
 
 	return (NMSettingSerial *) nm_connection_get_setting (connection, NM_TYPE_SETTING_SERIAL);
@@ -1499,7 +1618,6 @@ nm_connection_get_setting_serial (NMConnection *connection)
 NMSettingVPN *
 nm_connection_get_setting_vpn (NMConnection *connection)
 {
-	g_return_val_if_fail (connection != NULL, NULL);
 	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
 
 	return (NMSettingVPN *) nm_connection_get_setting (connection, NM_TYPE_SETTING_VPN);
@@ -1516,7 +1634,6 @@ nm_connection_get_setting_vpn (NMConnection *connection)
 NMSettingWimax *
 nm_connection_get_setting_wimax (NMConnection *connection)
 {
-	g_return_val_if_fail (connection != NULL, NULL);
 	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
 
 	return (NMSettingWimax *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIMAX);
@@ -1533,7 +1650,6 @@ nm_connection_get_setting_wimax (NMConnection *connection)
 NMSettingWired *
 nm_connection_get_setting_wired (NMConnection *connection)
 {
-	g_return_val_if_fail (connection != NULL, NULL);
 	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
 
 	return (NMSettingWired *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRED);
@@ -1550,7 +1666,6 @@ nm_connection_get_setting_wired (NMConnection *connection)
 NMSettingAdsl *
 nm_connection_get_setting_adsl (NMConnection *connection)
 {
-	g_return_val_if_fail (connection != NULL, NULL);
 	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
 
 	return (NMSettingAdsl *) nm_connection_get_setting (connection, NM_TYPE_SETTING_ADSL);
@@ -1567,7 +1682,6 @@ nm_connection_get_setting_adsl (NMConnection *connection)
 NMSettingWireless *
 nm_connection_get_setting_wireless (NMConnection *connection)
 {
-	g_return_val_if_fail (connection != NULL, NULL);
 	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
 
 	return (NMSettingWireless *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS);
@@ -1584,7 +1698,6 @@ nm_connection_get_setting_wireless (NMConnection *connection)
 NMSettingWirelessSecurity *
 nm_connection_get_setting_wireless_security (NMConnection *connection)
 {
-	g_return_val_if_fail (connection != NULL, NULL);
 	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
 
 	return (NMSettingWirelessSecurity *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS_SECURITY);
@@ -1601,7 +1714,6 @@ nm_connection_get_setting_wireless_security (NMConnection *connection)
 NMSettingBridgePort *
 nm_connection_get_setting_bridge_port (NMConnection *connection)
 {
-	g_return_val_if_fail (connection != NULL, NULL);
 	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
 
 	return (NMSettingBridgePort *) nm_connection_get_setting (connection, NM_TYPE_SETTING_BRIDGE_PORT);
@@ -1618,7 +1730,6 @@ nm_connection_get_setting_bridge_port (NMConnection *connection)
 NMSettingVlan *
 nm_connection_get_setting_vlan (NMConnection *connection)
 {
-	g_return_val_if_fail (connection != NULL, NULL);
 	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
 
 	return (NMSettingVlan *) nm_connection_get_setting (connection, NM_TYPE_SETTING_VLAN);
@@ -1631,7 +1742,24 @@ nm_connection_init (NMConnection *connection)
 {
 	NMConnectionPrivate *priv = NM_CONNECTION_GET_PRIVATE (connection);
 
-	priv->settings = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
+	priv->settings = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
+}
+
+static void
+dispose (GObject *object)
+{
+	NMConnection *self = NM_CONNECTION (object);
+	NMConnectionPrivate *priv = NM_CONNECTION_GET_PRIVATE (self);
+	GHashTableIter iter;
+	NMSetting *setting;
+
+	g_hash_table_iter_init (&iter, priv->settings);
+	while (g_hash_table_iter_next (&iter, NULL, (gpointer) &setting)) {
+		g_signal_handlers_disconnect_by_func (setting, setting_changed_cb, self);
+		g_hash_table_iter_remove (&iter);
+	}
+
+	G_OBJECT_CLASS (nm_connection_parent_class)->dispose (object);
 }
 
 static void
@@ -1641,10 +1769,7 @@ finalize (GObject *object)
 	NMConnectionPrivate *priv = NM_CONNECTION_GET_PRIVATE (connection);
 
 	g_hash_table_destroy (priv->settings);
-	priv->settings = NULL;
-
 	g_free (priv->path);
-	priv->path = NULL;
 
 	G_OBJECT_CLASS (nm_connection_parent_class)->finalize (object);
 }
@@ -1691,6 +1816,7 @@ nm_connection_class_init (NMConnectionClass *klass)
 	/* virtual methods */
 	object_class->set_property = set_property;
 	object_class->get_property = get_property;
+	object_class->dispose = dispose;
 	object_class->finalize = finalize;
 
 	/* Properties */
@@ -1721,7 +1847,7 @@ nm_connection_class_init (NMConnectionClass *klass)
 	* have been changed.
 	*/
 	signals[SECRETS_UPDATED] =
-		g_signal_new ("secrets-updated",
+		g_signal_new (NM_CONNECTION_SECRETS_UPDATED,
 					  G_OBJECT_CLASS_TYPE (object_class),
 					  G_SIGNAL_RUN_FIRST,
 					  G_STRUCT_OFFSET (NMConnectionClass, secrets_updated),
@@ -1738,7 +1864,25 @@ nm_connection_class_init (NMConnectionClass *klass)
 	* are cleared.
 	*/
 	signals[SECRETS_CLEARED] =
-		g_signal_new ("secrets-cleared",
+		g_signal_new (NM_CONNECTION_SECRETS_CLEARED,
+		              G_OBJECT_CLASS_TYPE (object_class),
+		              G_SIGNAL_RUN_FIRST,
+		              0, NULL, NULL,
+		              g_cclosure_marshal_VOID__VOID,
+		              G_TYPE_NONE, 0);
+
+	/**
+	* NMConnection::changed:
+	* @connection: the object on which the signal is emitted
+	*
+	* The ::changed signal is emitted when any property of any property
+	* (including secrets) of any setting of the connection is modified,
+	* or when settings are added or removed.
+	*
+	* Since: 0.9.10
+	*/
+	signals[CHANGED] =
+		g_signal_new (NM_CONNECTION_CHANGED,
 		              G_OBJECT_CLASS_TYPE (object_class),
 		              G_SIGNAL_RUN_FIRST,
 		              0, NULL, NULL,
diff --git a/libnm-util/nm-connection.h b/libnm-util/nm-connection.h
index 4d060cc9..4524c8f6 100644
--- a/libnm-util/nm-connection.h
+++ b/libnm-util/nm-connection.h
@@ -19,7 +19,7 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2007 - 2008 Red Hat, Inc.
+ * (C) Copyright 2007 - 2013 Red Hat, Inc.
  * (C) Copyright 2007 - 2008 Novell, Inc.
  */
 
@@ -33,10 +33,14 @@
 #include <nm-setting-8021x.h>
 #include <nm-setting-bluetooth.h>
 #include <nm-setting-bond.h>
+#include <nm-setting-team.h>
+#include <nm-setting-team-port.h>
 #include <nm-setting-bridge.h>
 #include <nm-setting-bridge-port.h>
 #include <nm-setting-cdma.h>
 #include <nm-setting-connection.h>
+#include <nm-setting-dcb.h>
+#include <nm-setting-generic.h>
 #include <nm-setting-gsm.h>
 #include <nm-setting-infiniband.h>
 #include <nm-setting-ip4-config.h>
@@ -62,6 +66,13 @@ G_BEGIN_DECLS
 #define NM_IS_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_CONNECTION))
 #define NM_CONNECTION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_CONNECTION, NMConnectionClass))
 
+/* Signals */
+#define NM_CONNECTION_SECRETS_UPDATED "secrets-updated"
+#define NM_CONNECTION_SECRETS_CLEARED "secrets-cleared"
+#define NM_CONNECTION_CHANGED         "changed"
+
+/* Properties */
+#define NM_CONNECTION_PATH "path"
 
 /**
  * NMConnectionError:
@@ -90,8 +101,6 @@ typedef enum
 #define NM_CONNECTION_ERROR nm_connection_error_quark ()
 GQuark nm_connection_error_quark (void);
 
-#define NM_CONNECTION_PATH "path"
-
 /**
  * NMConnection:
  *
@@ -135,6 +144,11 @@ gboolean      nm_connection_replace_settings (NMConnection *connection,
                                               GHashTable *new_settings,
                                               GError **error);
 
+NM_AVAILABLE_IN_0_9_10
+gboolean      nm_connection_replace_settings_from_connection (NMConnection *connection,
+                                                              NMConnection *new_connection,
+                                                              GError **error);
+
 gboolean      nm_connection_compare       (NMConnection *a,
                                            NMConnection *b,
                                            NMSettingCompareFlags flags);
@@ -183,17 +197,29 @@ GType         nm_connection_lookup_setting_type (const char *name);
 GType         nm_connection_lookup_setting_type_by_quark (GQuark error_quark);
 
 /* Helpers */
-const char *  nm_connection_get_uuid      (NMConnection *connection);
+const char *  nm_connection_get_uuid            (NMConnection *connection);
+const char *  nm_connection_get_id              (NMConnection *connection);
+NM_AVAILABLE_IN_0_9_10
+const char *  nm_connection_get_connection_type (NMConnection *connection);
 
-const char *  nm_connection_get_id        (NMConnection *connection);
+NM_AVAILABLE_IN_0_9_10
+char *        nm_connection_get_virtual_device_description (NMConnection *connection);
 
 NMSetting8021x *           nm_connection_get_setting_802_1x            (NMConnection *connection);
 NMSettingBluetooth *       nm_connection_get_setting_bluetooth         (NMConnection *connection);
 NMSettingBond *            nm_connection_get_setting_bond              (NMConnection *connection);
+NM_AVAILABLE_IN_0_9_10
+NMSettingTeam *            nm_connection_get_setting_team              (NMConnection *connection);
+NM_AVAILABLE_IN_0_9_10
+NMSettingTeamPort *        nm_connection_get_setting_team_port         (NMConnection *connection);
 NMSettingBridge *          nm_connection_get_setting_bridge            (NMConnection *connection);
 NMSettingBridgePort *      nm_connection_get_setting_bridge_port       (NMConnection *connection);
 NMSettingCdma *            nm_connection_get_setting_cdma              (NMConnection *connection);
 NMSettingConnection *      nm_connection_get_setting_connection        (NMConnection *connection);
+NM_AVAILABLE_IN_0_9_10
+NMSettingDcb *             nm_connection_get_setting_dcb               (NMConnection *connection);
+NM_AVAILABLE_IN_0_9_10
+NMSettingGeneric *         nm_connection_get_setting_generic           (NMConnection *connection);
 NMSettingGsm *             nm_connection_get_setting_gsm               (NMConnection *connection);
 NMSettingInfiniband *      nm_connection_get_setting_infiniband        (NMConnection *connection);
 NMSettingIP4Config *       nm_connection_get_setting_ip4_config        (NMConnection *connection);
diff --git a/libnm-util/nm-param-spec-specialized.c b/libnm-util/nm-param-spec-specialized.c
index 06d56f04..27e498b5 100644
--- a/libnm-util/nm-param-spec-specialized.c
+++ b/libnm-util/nm-param-spec-specialized.c
@@ -291,10 +291,8 @@ _gvalues_compare_collection (const GValue *value1, const GValue *value2)
 				ret = _gvalues_compare ((GValue *) iter1->data, (GValue *) iter2->data);
 		}
 
-		g_slist_foreach (list1, (GFunc) _gvalue_destroy, NULL);
-		g_slist_free (list1);
-		g_slist_foreach (list2, (GFunc) _gvalue_destroy, NULL);
-		g_slist_free (list2);
+		g_slist_free_full (list1, _gvalue_destroy);
+		g_slist_free_full (list2, _gvalue_destroy);
 	}
 
 	return ret;
@@ -347,7 +345,7 @@ _gvalues_compare_map (const GValue *value1, const GValue *value2)
 	}
 
 	hash1 = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, _gvalue_destroy);
-	dbus_g_type_map_value_iterate (value1, iterate_map, &hash1); 
+	dbus_g_type_map_value_iterate (value1, iterate_map, &hash1);
 	len1 = g_hash_table_size (hash1);
 
 	hash2 = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, _gvalue_destroy);
@@ -649,8 +647,8 @@ _nm_param_spec_specialized (const char *name,
 static void
 compare_ints (void)
 {
-	GValue value1 = { 0 };
-	GValue value2 = { 0 };
+	GValue value1 = G_VALUE_INIT;
+	GValue value2 = G_VALUE_INIT;
 
 	g_value_init (&value1, G_TYPE_INT);
 	g_value_init (&value2, G_TYPE_INT);
@@ -669,8 +667,8 @@ compare_ints (void)
 static void
 compare_strings (void)
 {
-	GValue value1 = { 0 };
-	GValue value2 = { 0 };
+	GValue value1 = G_VALUE_INIT;
+	GValue value2 = G_VALUE_INIT;
 	const char *str1 = "hello";
 	const char *str2 = "world";
 
@@ -688,8 +686,8 @@ compare_strings (void)
 static void
 compare_strv (void)
 {
-	GValue value1 = { 0 };
-	GValue value2 = { 0 };
+	GValue value1 = G_VALUE_INIT;
+	GValue value2 = G_VALUE_INIT;
 	char *strv1[] = { "foo", "bar", "baz", NULL };
 	char *strv2[] = { "foo", "bar", "bar", NULL };
 	char *strv3[] = { "foo", "bar", NULL };
@@ -717,8 +715,8 @@ compare_garrays (void)
 {
 	GArray *array1;
 	GArray *array2;
-	GValue value1 = { 0 };
-	GValue value2 = { 0 };
+	GValue value1 = G_VALUE_INIT;
+	GValue value2 = G_VALUE_INIT;
 	int i;
 
 	g_value_init (&value1, DBUS_TYPE_G_UINT_ARRAY);
@@ -752,8 +750,8 @@ compare_ptrarrays (void)
 {
 	GPtrArray *array1;
 	GPtrArray *array2;
-	GValue value1 = { 0 };
-	GValue value2 = { 0 };
+	GValue value1 = G_VALUE_INIT;
+	GValue value2 = G_VALUE_INIT;
 
 	g_value_init (&value1, dbus_g_type_get_collection ("GPtrArray", G_TYPE_STRING));
 	array1 = g_ptr_array_new ();
@@ -785,8 +783,8 @@ compare_str_hash (void)
 {
 	GHashTable *hash1;
 	GHashTable *hash2;
-	GValue value1 = { 0 };
-	GValue value2 = { 0 };
+	GValue value1 = G_VALUE_INIT;
+	GValue value2 = G_VALUE_INIT;
 
 	g_value_init (&value1, dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING));
 	g_value_init (&value2, dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING));
@@ -842,8 +840,8 @@ compare_gvalue_hash (void)
 {
 	GHashTable *hash1;
 	GHashTable *hash2;
-	GValue value1 = { 0 };
-	GValue value2 = { 0 };
+	GValue value1 = G_VALUE_INIT;
+	GValue value2 = G_VALUE_INIT;
 
 	g_value_init (&value1, dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE));
 	g_value_init (&value2, dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE));
@@ -879,9 +877,9 @@ compare_ip6_addresses (void)
 	GByteArray *ba1;
 	GByteArray *ba2;
 	GByteArray *ba3;
-	GValue element = { 0 };
-	GValue value1 = { 0 };
-	GValue value2 = { 0 };
+	GValue element = G_VALUE_INIT;
+	GValue value1 = G_VALUE_INIT;
+	GValue value2 = G_VALUE_INIT;
 	struct in6_addr addr1;
 	struct in6_addr addr2;
 	struct in6_addr addr3;
@@ -956,7 +954,10 @@ main (int argc, char *argv[])
 {
 	DBusGConnection *bus;
 
+#if !GLIB_CHECK_VERSION (2, 35, 0)
 	g_type_init ();
+#endif
+
 	bus = dbus_g_bus_get (DBUS_BUS_SESSION, NULL);
 
 	compare_ints ();
diff --git a/libnm-util/nm-setting-8021x.c b/libnm-util/nm-setting-8021x.c
index 914c7ea3..d85b87b8 100644
--- a/libnm-util/nm-setting-8021x.c
+++ b/libnm-util/nm-setting-8021x.c
@@ -19,12 +19,14 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2007 - 2012 Red Hat, Inc.
+ * (C) Copyright 2007 - 2013 Red Hat, Inc.
  * (C) Copyright 2007 - 2008 Novell, Inc.
  */
 
 #include <string.h>
 #include <dbus/dbus-glib.h>
+#include <glib/gi18n.h>
+
 #include "nm-setting-8021x.h"
 #include "nm-param-spec-specialized.h"
 #include "nm-utils.h"
@@ -40,7 +42,7 @@
  *
  * The #NMSetting8021x object is a #NMSetting subclass that describes
  * properties necessary for connection to 802.1x-authenticated networks, such as
- * WPA and WPA2 Enterprise WiFi networks and wired 802.1x networks.  802.1x
+ * WPA and WPA2 Enterprise Wi-Fi networks and wired 802.1x networks.  802.1x
  * connections typically use certificates and/or EAP authentication methods to
  * securely verify, identify, and authenticate the client to the network itself,
  * instead of simply relying on a widely shared static key.
@@ -50,7 +52,7 @@
  * the relevant wpa_supplicant configuration options.
  *
  * Furthermore, to get a good idea of 802.1x, EAP, TLS, TTLS, etc and their
- * applications to WiFi and wired networks, you'll want to get copies of the
+ * applications to Wi-Fi and wired networks, you'll want to get copies of the
  * following books.
  *
  *  802.11 Wireless Networks: The Definitive Guide, Second Edition
@@ -246,6 +248,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));
+	g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_EAP);
 	return TRUE;
 }
 
@@ -270,6 +273,39 @@ nm_setting_802_1x_remove_eap_method (NMSetting8021x *setting, guint32 i)
 
 	g_free (elt->data);
 	priv->eap = g_slist_delete_link (priv->eap, elt);
+	g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_EAP);
+}
+
+/**
+ * nm_setting_802_1x_remove_eap_method_by_value:
+ * @setting: the #NMSetting8021x
+ * @eap: the name of the EAP method to remove
+ *
+ * Removes the allowed EAP method @method.
+ *
+ * Returns: %TRUE if the EAP method was founs and removed, %FALSE if it was not.
+ *
+ * Since: 0.9.10
+ **/
+gboolean
+nm_setting_802_1x_remove_eap_method_by_value (NMSetting8021x *setting,
+                                              const char *eap)
+{
+	NMSetting8021xPrivate *priv;
+	GSList *iter;
+
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE);
+	g_return_val_if_fail (eap != NULL, FALSE);
+
+	priv = NM_SETTING_802_1X_GET_PRIVATE (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);
+			g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_EAP);
+			return TRUE;
+		}
+	}
+	return FALSE;
 }
 
 /**
@@ -286,8 +322,9 @@ nm_setting_802_1x_clear_eap_methods (NMSetting8021x *setting)
 	g_return_if_fail (NM_IS_SETTING_802_1X (setting));
 
 	priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
-	nm_utils_slist_free (priv->eap, g_free);
+	g_slist_free_full (priv->eap, g_free);
 	priv->eap = NULL;
+	g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_EAP);
 }
 
 /**
@@ -502,7 +539,7 @@ path_to_scheme_value (const char *path)
  * Returns: %TRUE if the operation succeeded, %FALSE if it was unsuccessful
  **/
 gboolean
-nm_setting_802_1x_set_ca_cert (NMSetting8021x *self,
+nm_setting_802_1x_set_ca_cert (NMSetting8021x *setting,
                                const char *cert_path,
                                NMSetting8021xCKScheme scheme,
                                NMSetting8021xCKFormat *out_format,
@@ -512,7 +549,7 @@ nm_setting_802_1x_set_ca_cert (NMSetting8021x *self,
 	NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
 	GByteArray *data;
 
-	g_return_val_if_fail (NM_IS_SETTING_802_1X (self), FALSE);
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE);
 
 	if (cert_path) {
 		g_return_val_if_fail (g_utf8_validate (cert_path, -1, NULL), FALSE);
@@ -524,7 +561,7 @@ nm_setting_802_1x_set_ca_cert (NMSetting8021x *self,
 	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 (self);
+	priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
 
 	/* Clear out any previous ca_cert blob */
 	if (priv->ca_cert) {
@@ -532,8 +569,10 @@ nm_setting_802_1x_set_ca_cert (NMSetting8021x *self,
 		priv->ca_cert = NULL;
 	}
 
-	if (!cert_path)
+	if (!cert_path) {
+		g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_CA_CERT);
 		return TRUE;
+	}
 
 	data = crypto_load_and_verify_certificate (cert_path, &format, error);
 	if (data) {
@@ -549,14 +588,16 @@ nm_setting_802_1x_set_ca_cert (NMSetting8021x *self,
 			else
 				g_assert_not_reached ();
 		} else {
-			g_set_error (error,
+			g_set_error_literal (error,
 			             NM_SETTING_802_1X_ERROR,
 			             NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
-			             NM_SETTING_802_1X_CA_CERT);
+			             _("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);
 		}
 		g_byte_array_unref (data);
 	}
 
+	g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_CA_CERT);
 	return priv->ca_cert != NULL;
 }
 
@@ -646,6 +687,7 @@ nm_setting_802_1x_add_altsubject_match (NMSetting8021x *setting,
 
 	priv->altsubject_matches = g_slist_append (priv->altsubject_matches,
 	                                           g_strdup (altsubject_match));
+	g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_ALTSUBJECT_MATCHES);
 	return TRUE;
 }
 
@@ -670,6 +712,40 @@ 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);
+	g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_ALTSUBJECT_MATCHES);
+}
+
+/**
+ * nm_setting_802_1x_remove_altsubject_match_by_value:
+ * @setting: the #NMSetting8021x
+ * @altsubject_match: the altSubjectName to remove
+ *
+ * Removes the allowed altSubjectName @altsubject_match.
+ *
+ * Returns: %TRUE if the alternative subject name match was found and removed,
+ *          %FALSE if it was not.
+ *
+ * Since: 0.9.10
+ **/
+gboolean
+nm_setting_802_1x_remove_altsubject_match_by_value (NMSetting8021x *setting,
+                                                    const char *altsubject_match)
+{
+	NMSetting8021xPrivate *priv;
+	GSList *iter;
+
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE);
+	g_return_val_if_fail (altsubject_match != NULL, FALSE);
+
+	priv = NM_SETTING_802_1X_GET_PRIVATE (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);
+			g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_ALTSUBJECT_MATCHES);
+			return TRUE;
+		}
+	}
+	return FALSE;
 }
 
 /**
@@ -686,8 +762,9 @@ nm_setting_802_1x_clear_altsubject_matches (NMSetting8021x *setting)
 	g_return_if_fail (NM_IS_SETTING_802_1X (setting));
 
 	priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
-	nm_utils_slist_free (priv->altsubject_matches, g_free);
+	g_slist_free_full (priv->altsubject_matches, g_free);
 	priv->altsubject_matches = NULL;
+	g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_ALTSUBJECT_MATCHES);
 }
 
 /**
@@ -778,7 +855,7 @@ nm_setting_802_1x_get_client_cert_path (NMSetting8021x *setting)
  * Returns: %TRUE if the operation succeeded, %FALSE if it was unsuccessful
  **/
 gboolean
-nm_setting_802_1x_set_client_cert (NMSetting8021x *self,
+nm_setting_802_1x_set_client_cert (NMSetting8021x *setting,
                                    const char *cert_path,
                                    NMSetting8021xCKScheme scheme,
                                    NMSetting8021xCKFormat *out_format,
@@ -788,7 +865,7 @@ nm_setting_802_1x_set_client_cert (NMSetting8021x *self,
 	NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
 	GByteArray *data;
 
-	g_return_val_if_fail (NM_IS_SETTING_802_1X (self), FALSE);
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE);
 
 	if (cert_path) {
 		g_return_val_if_fail (g_utf8_validate (cert_path, -1, NULL), FALSE);
@@ -800,7 +877,7 @@ nm_setting_802_1x_set_client_cert (NMSetting8021x *self,
 	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 (self);
+	priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
 
 	/* Clear out any previous ca_cert blob */
 	if (priv->client_cert) {
@@ -808,8 +885,10 @@ nm_setting_802_1x_set_client_cert (NMSetting8021x *self,
 		priv->client_cert = NULL;
 	}
 
-	if (!cert_path)
+	if (!cert_path) {
+		g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_CLIENT_CERT);
 		return TRUE;
+	}
 
 	data = crypto_load_and_verify_certificate (cert_path, &format, error);
 	if (data) {
@@ -827,10 +906,11 @@ nm_setting_802_1x_set_client_cert (NMSetting8021x *self,
 			valid = TRUE;
 			break;
 		default:
-			g_set_error (error,
-			             NM_SETTING_802_1X_ERROR,
-			             NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
-			             NM_SETTING_802_1X_CLIENT_CERT);
+			g_set_error_literal (error,
+			                     NM_SETTING_802_1X_ERROR,
+			                     NM_SETTING_802_1X_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;
 		}
 
@@ -845,6 +925,7 @@ nm_setting_802_1x_set_client_cert (NMSetting8021x *self,
 		g_byte_array_unref (data);
 	}
 
+	g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_CLIENT_CERT);
 	return priv->client_cert != NULL;
 }
 
@@ -1039,7 +1120,7 @@ nm_setting_802_1x_get_phase2_ca_cert_path (NMSetting8021x *setting)
  * Returns: %TRUE if the operation succeeded, %FALSE if it was unsuccessful
  **/
 gboolean
-nm_setting_802_1x_set_phase2_ca_cert (NMSetting8021x *self,
+nm_setting_802_1x_set_phase2_ca_cert (NMSetting8021x *setting,
                                       const char *cert_path,
                                       NMSetting8021xCKScheme scheme,
                                       NMSetting8021xCKFormat *out_format,
@@ -1049,7 +1130,7 @@ nm_setting_802_1x_set_phase2_ca_cert (NMSetting8021x *self,
 	NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
 	GByteArray *data;
 
-	g_return_val_if_fail (NM_IS_SETTING_802_1X (self), FALSE);
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE);
 
 	if (cert_path) {
 		g_return_val_if_fail (g_utf8_validate (cert_path, -1, NULL), FALSE);
@@ -1061,7 +1142,7 @@ nm_setting_802_1x_set_phase2_ca_cert (NMSetting8021x *self,
 	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 (self);
+	priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
 
 	/* Clear out any previous ca_cert blob */
 	if (priv->phase2_ca_cert) {
@@ -1069,8 +1150,10 @@ nm_setting_802_1x_set_phase2_ca_cert (NMSetting8021x *self,
 		priv->phase2_ca_cert = NULL;
 	}
 
-	if (!cert_path)
+	if (!cert_path) {
+		g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_CA_CERT);
 		return TRUE;
+	}
 
 	data = crypto_load_and_verify_certificate (cert_path, &format, error);
 	if (data) {
@@ -1086,14 +1169,16 @@ nm_setting_802_1x_set_phase2_ca_cert (NMSetting8021x *self,
 			else
 				g_assert_not_reached ();
 		} else {
-			g_set_error (error,
-			             NM_SETTING_802_1X_ERROR,
-			             NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
-			             NM_SETTING_802_1X_PHASE2_CA_CERT);
+			g_set_error_literal (error,
+			                     NM_SETTING_802_1X_ERROR,
+			                     NM_SETTING_802_1X_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);
 		}
 		g_byte_array_unref (data);
 	}
 
+	g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_CA_CERT);
 	return priv->phase2_ca_cert != NULL;
 }
 
@@ -1184,6 +1269,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));
+	g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_ALTSUBJECT_MATCHES);
 	return TRUE;
 }
 
@@ -1208,6 +1294,41 @@ 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);
+	g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_ALTSUBJECT_MATCHES);
+}
+
+
+/**
+ * nm_setting_802_1x_remove_phase2_altsubject_match_by_value:
+ * @setting: the #NMSetting8021x
+ * @phase2_altsubject_match: the "phase 2" altSubjectName to remove
+ *
+ * Removes the allowed "phase 2" altSubjectName @phase2_altsubject_match.
+ *
+ * Returns: %TRUE if the alternative subject name match for "phase 2" was found and removed,
+ *          %FALSE if it was not.
+ *
+ * Since: 0.9.10
+ **/
+gboolean
+nm_setting_802_1x_remove_phase2_altsubject_match_by_value (NMSetting8021x *setting,
+                                                           const char *phase2_altsubject_match)
+{
+	NMSetting8021xPrivate *priv;
+	GSList *iter;
+
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE);
+	g_return_val_if_fail (phase2_altsubject_match != NULL, FALSE);
+
+	priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
+	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);
+			g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_ALTSUBJECT_MATCHES);
+			return TRUE;
+		}
+	}
+	return FALSE;
 }
 
 /**
@@ -1224,8 +1345,9 @@ nm_setting_802_1x_clear_phase2_altsubject_matches (NMSetting8021x *setting)
 	g_return_if_fail (NM_IS_SETTING_802_1X (setting));
 
 	priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
-	nm_utils_slist_free (priv->phase2_altsubject_matches, g_free);
+	g_slist_free_full (priv->phase2_altsubject_matches, g_free);
 	priv->phase2_altsubject_matches = NULL;
+	g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_ALTSUBJECT_MATCHES);
 }
 
 /**
@@ -1318,7 +1440,7 @@ nm_setting_802_1x_get_phase2_client_cert_path (NMSetting8021x *setting)
  * Returns: %TRUE if the operation succeeded, %FALSE if it was unsuccessful
  **/
 gboolean
-nm_setting_802_1x_set_phase2_client_cert (NMSetting8021x *self,
+nm_setting_802_1x_set_phase2_client_cert (NMSetting8021x *setting,
                                           const char *cert_path,
                                           NMSetting8021xCKScheme scheme,
                                           NMSetting8021xCKFormat *out_format,
@@ -1328,7 +1450,7 @@ nm_setting_802_1x_set_phase2_client_cert (NMSetting8021x *self,
 	NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
 	GByteArray *data;
 
-	g_return_val_if_fail (NM_IS_SETTING_802_1X (self), FALSE);
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE);
 
 	if (cert_path) {
 		g_return_val_if_fail (g_utf8_validate (cert_path, -1, NULL), FALSE);
@@ -1340,7 +1462,7 @@ nm_setting_802_1x_set_phase2_client_cert (NMSetting8021x *self,
 	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 (self);
+	priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
 
 	/* Clear out any previous ca_cert blob */
 	if (priv->phase2_client_cert) {
@@ -1348,8 +1470,10 @@ nm_setting_802_1x_set_phase2_client_cert (NMSetting8021x *self,
 		priv->phase2_client_cert = NULL;
 	}
 
-	if (!cert_path)
+	if (!cert_path) {
+		g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_CLIENT_CERT);
 		return TRUE;
+	}
 
 	data = crypto_load_and_verify_certificate (cert_path, &format, error);
 	if (data) {
@@ -1368,10 +1492,11 @@ nm_setting_802_1x_set_phase2_client_cert (NMSetting8021x *self,
 			valid = TRUE;
 			break;
 		default:
-			g_set_error (error,
-			             NM_SETTING_802_1X_ERROR,
-			             NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
-			             NM_SETTING_802_1X_PHASE2_CLIENT_CERT);
+			g_set_error_literal (error,
+			                     NM_SETTING_802_1X_ERROR,
+			                     NM_SETTING_802_1X_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;
 		}
 
@@ -1386,6 +1511,7 @@ nm_setting_802_1x_set_phase2_client_cert (NMSetting8021x *self,
 		g_byte_array_unref (data);
 	}
 
+	g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_CLIENT_CERT);
 	return priv->phase2_client_cert != NULL;
 }
 
@@ -1558,10 +1684,8 @@ file_to_byte_array (const char *filename)
 
 	if (g_file_get_contents (filename, &contents, &length, NULL)) {
 		array = g_byte_array_sized_new (length);
-		if (array) {
-			g_byte_array_append (array, (guint8 *) contents, length);
-			g_assert (array->len == length);
-		}
+		g_byte_array_append (array, (guint8 *) contents, length);
+		g_assert (array->len == length);
 		g_free (contents);
 	}
 	return array;
@@ -1607,7 +1731,7 @@ file_to_byte_array (const char *filename)
  * Returns: %TRUE if the operation succeeded, %FALSE if it was unsuccessful
  **/
 gboolean
-nm_setting_802_1x_set_private_key (NMSetting8021x *self,
+nm_setting_802_1x_set_private_key (NMSetting8021x *setting,
                                    const char *key_path,
                                    const char *password,
                                    NMSetting8021xCKScheme scheme,
@@ -1616,8 +1740,10 @@ nm_setting_802_1x_set_private_key (NMSetting8021x *self,
 {
 	NMSetting8021xPrivate *priv;
 	NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
+	gboolean key_cleared = FALSE, password_cleared = FALSE;
+	GError *local_err = NULL;
 
-	g_return_val_if_fail (NM_IS_SETTING_802_1X (self), FALSE);
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE);
 
 	if (key_path) {
 		g_return_val_if_fail (g_utf8_validate (key_path, -1, NULL), FALSE);
@@ -1633,17 +1759,19 @@ nm_setting_802_1x_set_private_key (NMSetting8021x *self,
 	 * given, that it decrypts the private key.
 	 */
 	if (key_path) {
-		format = crypto_verify_private_key (key_path, password, NULL);
+		format = crypto_verify_private_key (key_path, password, &local_err);
 		if (format == NM_CRYPTO_FILE_FORMAT_UNKNOWN) {
-			g_set_error (error,
-				         NM_SETTING_802_1X_ERROR,
-				         NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
-				         NM_SETTING_802_1X_PRIVATE_KEY);
+			g_set_error_literal (error,
+			                     NM_SETTING_802_1X_ERROR,
+			                     NM_SETTING_802_1X_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 (self);
+	priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
 
 	/* Clear out any previous private key data */
 	if (priv->private_key) {
@@ -1651,13 +1779,22 @@ nm_setting_802_1x_set_private_key (NMSetting8021x *self,
 		memset (priv->private_key->data, 0, priv->private_key->len);
 		g_byte_array_free (priv->private_key, TRUE);
 		priv->private_key = NULL;
+		key_cleared = TRUE;
 	}
 
-	g_free (priv->private_key_password);
-	priv->private_key_password = NULL;
+	if (priv->private_key_password) {
+		g_free (priv->private_key_password);
+		priv->private_key_password = NULL;
+		password_cleared = TRUE;
+	}
 
-	if (key_path == NULL)
+	if (key_path == NULL) {
+		if (key_cleared)
+			g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PRIVATE_KEY);
+		if (password_cleared)
+			g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD);
 		return TRUE;
+	}
 
 	priv->private_key_password = g_strdup (password);
 	if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) {
@@ -1679,8 +1816,13 @@ nm_setting_802_1x_set_private_key (NMSetting8021x *self,
 
 		priv->client_cert = g_byte_array_sized_new (priv->private_key->len);
 		g_byte_array_append (priv->client_cert, priv->private_key->data, priv->private_key->len);
+		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_cleared || password)
+		g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD);
+
 	if (out_format)
 		*out_format = format;
 	return priv->private_key != NULL;
@@ -1900,7 +2042,7 @@ nm_setting_802_1x_get_phase2_private_key_path (NMSetting8021x *setting)
  * Returns: %TRUE if the operation succeeded, %FALSE if it was unsuccessful
  **/
 gboolean
-nm_setting_802_1x_set_phase2_private_key (NMSetting8021x *self,
+nm_setting_802_1x_set_phase2_private_key (NMSetting8021x *setting,
                                           const char *key_path,
                                           const char *password,
                                           NMSetting8021xCKScheme scheme,
@@ -1909,8 +2051,10 @@ nm_setting_802_1x_set_phase2_private_key (NMSetting8021x *self,
 {
 	NMSetting8021xPrivate *priv;
 	NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
+	gboolean key_cleared = FALSE, password_cleared = FALSE;
+	GError *local_err = NULL;
 
-	g_return_val_if_fail (NM_IS_SETTING_802_1X (self), FALSE);
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE);
 
 	if (key_path) {
 		g_return_val_if_fail (g_utf8_validate (key_path, -1, NULL), FALSE);
@@ -1926,17 +2070,19 @@ nm_setting_802_1x_set_phase2_private_key (NMSetting8021x *self,
 	 * given, that it decrypts the private key.
 	 */
 	if (key_path) {
-		format = crypto_verify_private_key (key_path, password, NULL);
+		format = crypto_verify_private_key (key_path, password, &local_err);
 		if (format == NM_CRYPTO_FILE_FORMAT_UNKNOWN) {
-			g_set_error (error,
-				         NM_SETTING_802_1X_ERROR,
-				         NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
-				         NM_SETTING_802_1X_PHASE2_PRIVATE_KEY);
+			g_set_error_literal (error,
+			                     NM_SETTING_802_1X_ERROR,
+			                     NM_SETTING_802_1X_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 (self);
+	priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
 
 	/* Clear out any previous private key data */
 	if (priv->phase2_private_key) {
@@ -1944,13 +2090,22 @@ nm_setting_802_1x_set_phase2_private_key (NMSetting8021x *self,
 		memset (priv->phase2_private_key->data, 0, priv->phase2_private_key->len);
 		g_byte_array_free (priv->phase2_private_key, TRUE);
 		priv->phase2_private_key = NULL;
+		key_cleared = TRUE;
 	}
 
-	g_free (priv->phase2_private_key_password);
-	priv->phase2_private_key_password = NULL;
+	if (priv->phase2_private_key_password) {
+		g_free (priv->phase2_private_key_password);
+		priv->phase2_private_key_password = NULL;
+		password_cleared = TRUE;
+	}
 
-	if (key_path == NULL)
+	if (key_path == NULL) {
+		if (key_cleared)
+			g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_PRIVATE_KEY);
+		if (password_cleared)
+			g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD);
 		return TRUE;
+	}
 
 	priv->phase2_private_key_password = g_strdup (password);
 	if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) {
@@ -1972,8 +2127,13 @@ nm_setting_802_1x_set_phase2_private_key (NMSetting8021x *self,
 
 		priv->phase2_client_cert = g_byte_array_sized_new (priv->phase2_private_key->len);
 		g_byte_array_append (priv->phase2_client_cert, priv->phase2_private_key->data, priv->phase2_private_key->len);
+		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_cleared || password)
+		g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD);
+
 	if (out_format)
 		*out_format = format;
 	return priv->phase2_private_key != NULL;
@@ -2114,31 +2274,35 @@ verify_tls (NMSetting8021x *self, gboolean phase2, GError **error)
 
 	if (phase2) {
 		if (!priv->phase2_client_cert) {
-			g_set_error (error,
-			             NM_SETTING_802_1X_ERROR,
-			             NM_SETTING_802_1X_ERROR_MISSING_PROPERTY,
-			             NM_SETTING_802_1X_PHASE2_CLIENT_CERT);
+			g_set_error_literal (error,
+			                     NM_SETTING_802_1X_ERROR,
+			                     NM_SETTING_802_1X_ERROR_MISSING_PROPERTY,
+			                     _("property is missing"));
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_PHASE2_CLIENT_CERT);
 			return FALSE;
 		} else if (!priv->phase2_client_cert->len) {
-			g_set_error (error,
-			             NM_SETTING_802_1X_ERROR,
-			             NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
-			             NM_SETTING_802_1X_PHASE2_CLIENT_CERT);
+			g_set_error_literal (error,
+			                     NM_SETTING_802_1X_ERROR,
+			                     NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
+			                     _("property is empty"));
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_PHASE2_CLIENT_CERT);
 			return FALSE;
 		}
 
 		/* Private key is required for TLS */
 		if (!priv->phase2_private_key) {
-			g_set_error (error,
-			             NM_SETTING_802_1X_ERROR,
-			             NM_SETTING_802_1X_ERROR_MISSING_PROPERTY,
-			             NM_SETTING_802_1X_PHASE2_PRIVATE_KEY);
+			g_set_error_literal (error,
+			                     NM_SETTING_802_1X_ERROR,
+			                     NM_SETTING_802_1X_ERROR_MISSING_PROPERTY,
+			                     _("property is missing"));
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY);
 			return FALSE;
 		} else if (!priv->phase2_private_key->len) {
-			g_set_error (error,
-			             NM_SETTING_802_1X_ERROR,
-			             NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
-			             NM_SETTING_802_1X_PHASE2_PRIVATE_KEY);
+			g_set_error_literal (error,
+			                     NM_SETTING_802_1X_ERROR,
+			                     NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
+			                     _("property is empty"));
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY);
 			return FALSE;
 		}
 
@@ -2148,7 +2312,9 @@ verify_tls (NMSetting8021x *self, gboolean phase2, GError **error)
 				g_set_error (error,
 				             NM_SETTING_802_1X_ERROR,
 				             NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
-				             NM_SETTING_802_1X_PHASE2_CLIENT_CERT);
+				             _("has to match '%s' property for PKCS#12"),
+				             NM_SETTING_802_1X_PHASE2_PRIVATE_KEY);
+				g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_PHASE2_CLIENT_CERT);
 				return FALSE;
 			}
 
@@ -2158,37 +2324,43 @@ verify_tls (NMSetting8021x *self, gboolean phase2, GError **error)
 				g_set_error (error,
 				             NM_SETTING_802_1X_ERROR,
 				             NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
-				             NM_SETTING_802_1X_PHASE2_CLIENT_CERT);
+				             _("has to match '%s' property for PKCS#12"),
+				             NM_SETTING_802_1X_PHASE2_PRIVATE_KEY);
+				g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_PHASE2_CLIENT_CERT);
 				return FALSE;
 			}
 		}
 	} else {
 		if (!priv->client_cert) {
-			g_set_error (error,
-			             NM_SETTING_802_1X_ERROR,
-			             NM_SETTING_802_1X_ERROR_MISSING_PROPERTY,
-			             NM_SETTING_802_1X_CLIENT_CERT);
+			g_set_error_literal (error,
+			                     NM_SETTING_802_1X_ERROR,
+			                     NM_SETTING_802_1X_ERROR_MISSING_PROPERTY,
+			                     _("property is missing"));
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_CLIENT_CERT);
 			return FALSE;
 		} else if (!priv->client_cert->len) {
-			g_set_error (error,
-			             NM_SETTING_802_1X_ERROR,
-			             NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
-			             NM_SETTING_802_1X_CLIENT_CERT);
+			g_set_error_literal (error,
+			                     NM_SETTING_802_1X_ERROR,
+			                     NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
+			                     _("property is empty"));
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_CLIENT_CERT);
 			return FALSE;
 		}
 
 		/* Private key is required for TLS */
 		if (!priv->private_key) {
-			g_set_error (error,
-			             NM_SETTING_802_1X_ERROR,
-			             NM_SETTING_802_1X_ERROR_MISSING_PROPERTY,
-			             NM_SETTING_802_1X_PRIVATE_KEY);
+			g_set_error_literal (error,
+			                     NM_SETTING_802_1X_ERROR,
+			                     NM_SETTING_802_1X_ERROR_MISSING_PROPERTY,
+			                     _("property is missing"));
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_PRIVATE_KEY);
 			return FALSE;
 		} else if (!priv->private_key->len) {
-			g_set_error (error,
-			             NM_SETTING_802_1X_ERROR,
-			             NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
-			             NM_SETTING_802_1X_PRIVATE_KEY);
+			g_set_error_literal (error,
+			                     NM_SETTING_802_1X_ERROR,
+			                     NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
+			                     _("property is empty"));
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_PRIVATE_KEY);
 			return FALSE;
 		}
 
@@ -2198,7 +2370,9 @@ verify_tls (NMSetting8021x *self, gboolean phase2, GError **error)
 				g_set_error (error,
 				             NM_SETTING_802_1X_ERROR,
 				             NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
-				             NM_SETTING_802_1X_CLIENT_CERT);
+				             _("has to match '%s' property for PKCS#12"),
+				             NM_SETTING_802_1X_PRIVATE_KEY);
+				g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_CLIENT_CERT);
 				return FALSE;
 			}
 
@@ -2208,7 +2382,9 @@ verify_tls (NMSetting8021x *self, gboolean phase2, GError **error)
 				g_set_error (error,
 				             NM_SETTING_802_1X_ERROR,
 				             NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
-				             NM_SETTING_802_1X_CLIENT_CERT);
+				             _("has to match '%s' property for PKCS#12"),
+				             NM_SETTING_802_1X_PRIVATE_KEY);
+				g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_CLIENT_CERT);
 				return FALSE;
 			}
 		}
@@ -2225,25 +2401,29 @@ verify_ttls (NMSetting8021x *self, gboolean phase2, GError **error)
 	if (   (!priv->identity || !strlen (priv->identity))
 	    && (!priv->anonymous_identity || !strlen (priv->anonymous_identity))) {
 		if (!priv->identity) {
-			g_set_error (error,
-			             NM_SETTING_802_1X_ERROR,
-			             NM_SETTING_802_1X_ERROR_MISSING_PROPERTY,
-			             NM_SETTING_802_1X_IDENTITY);
+			g_set_error_literal (error,
+			                     NM_SETTING_802_1X_ERROR,
+			                     NM_SETTING_802_1X_ERROR_MISSING_PROPERTY,
+			                     _("property is missing"));
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_IDENTITY);
 		} else if (!strlen (priv->identity)) {
-			g_set_error (error,
-			             NM_SETTING_802_1X_ERROR,
-			             NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
-			             NM_SETTING_802_1X_IDENTITY);
+			g_set_error_literal (error,
+			                     NM_SETTING_802_1X_ERROR,
+			                     NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
+			                     _("property is empty"));
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_IDENTITY);
 		} else if (!priv->anonymous_identity) {
-			g_set_error (error,
-			             NM_SETTING_802_1X_ERROR,
-			             NM_SETTING_802_1X_ERROR_MISSING_PROPERTY,
-			             NM_SETTING_802_1X_ANONYMOUS_IDENTITY);
+			g_set_error_literal (error,
+			                     NM_SETTING_802_1X_ERROR,
+			                     NM_SETTING_802_1X_ERROR_MISSING_PROPERTY,
+			                     _("property is missing"));
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_ANONYMOUS_IDENTITY);
 		} else {
-			g_set_error (error,
-			             NM_SETTING_802_1X_ERROR,
-			             NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
-			             NM_SETTING_802_1X_ANONYMOUS_IDENTITY);
+			g_set_error_literal (error,
+			                     NM_SETTING_802_1X_ERROR,
+			                     NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
+			                     _("property is empty"));
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_ANONYMOUS_IDENTITY);
 		}
 		return FALSE;
 	}
@@ -2251,25 +2431,29 @@ verify_ttls (NMSetting8021x *self, gboolean phase2, GError **error)
 	if (   (!priv->phase2_auth || !strlen (priv->phase2_auth))
 	    && (!priv->phase2_autheap || !strlen (priv->phase2_autheap))) {
 		if (!priv->phase2_auth) {
-			g_set_error (error,
-			             NM_SETTING_802_1X_ERROR,
-			             NM_SETTING_802_1X_ERROR_MISSING_PROPERTY,
-			             NM_SETTING_802_1X_PHASE2_AUTH);
+			g_set_error_literal (error,
+			                     NM_SETTING_802_1X_ERROR,
+			                     NM_SETTING_802_1X_ERROR_MISSING_PROPERTY,
+			                     _("property is missing"));
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_PHASE2_AUTH);
 		} else if (!strlen (priv->phase2_auth)) {
-			g_set_error (error,
-			             NM_SETTING_802_1X_ERROR,
-			             NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
-			             NM_SETTING_802_1X_PHASE2_AUTH);
+			g_set_error_literal (error,
+			                     NM_SETTING_802_1X_ERROR,
+			                     NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
+			                     _("property is empty"));
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_PHASE2_AUTH);
 		} else if (!priv->phase2_autheap) {
-			g_set_error (error,
-			             NM_SETTING_802_1X_ERROR,
-			             NM_SETTING_802_1X_ERROR_MISSING_PROPERTY,
-			             NM_SETTING_802_1X_PHASE2_AUTHEAP);
+			g_set_error_literal (error,
+			                     NM_SETTING_802_1X_ERROR,
+			                     NM_SETTING_802_1X_ERROR_MISSING_PROPERTY,
+			                     _("property is missing"));
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_PHASE2_AUTHEAP);
 		} else {
-			g_set_error (error,
-			             NM_SETTING_802_1X_ERROR,
-			             NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
-			             NM_SETTING_802_1X_PHASE2_AUTHEAP);
+			g_set_error_literal (error,
+			                     NM_SETTING_802_1X_ERROR,
+			                     NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
+			                     _("property is empty"));
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_PHASE2_AUTHEAP);
 		}
 		return FALSE;
 	}
@@ -2283,16 +2467,18 @@ verify_identity (NMSetting8021x *self, gboolean phase2, GError **error)
 	NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self);
 
 	if (!priv->identity) {
-		g_set_error (error,
-		             NM_SETTING_802_1X_ERROR,
-		             NM_SETTING_802_1X_ERROR_MISSING_PROPERTY,
-		             NM_SETTING_802_1X_IDENTITY);
+		g_set_error_literal (error,
+		                     NM_SETTING_802_1X_ERROR,
+		                     NM_SETTING_802_1X_ERROR_MISSING_PROPERTY,
+		                     _("property is missing"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_IDENTITY);
 		return FALSE;
 	} else if (!strlen (priv->identity)) {
-		g_set_error (error,
-		             NM_SETTING_802_1X_ERROR,
-		             NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_802_1X_IDENTITY);
+		g_set_error_literal (error,
+		                     NM_SETTING_802_1X_ERROR,
+		                     NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
+		                     _("property is empty"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_IDENTITY);
 		return FALSE;
 	}
 
@@ -2321,6 +2507,7 @@ typedef struct {
 
 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 },
@@ -2433,10 +2620,11 @@ verify_cert (GByteArray *array, const char *prop_name, GError **error)
 		break;
 	}
 
-	g_set_error (error,
-	             NM_SETTING_802_1X_ERROR,
-	             NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
-	             "%s", prop_name);
+	g_set_error_literal (error,
+	                     NM_SETTING_802_1X_ERROR,
+	                     NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
+	                     _("property is invalid"));
+	g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, prop_name);
 	return FALSE;
 }
 
@@ -2445,7 +2633,7 @@ verify (NMSetting *setting, GSList *all_settings, 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", 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 };
@@ -2457,18 +2645,20 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 		g_return_val_if_fail (*error == NULL, FALSE);
 
 	if (!priv->eap) {
-		g_set_error (error,
-		             NM_SETTING_802_1X_ERROR,
-		             NM_SETTING_802_1X_ERROR_MISSING_PROPERTY,
-		             NM_SETTING_802_1X_EAP);
+		g_set_error_literal (error,
+		                     NM_SETTING_802_1X_ERROR,
+		                     NM_SETTING_802_1X_ERROR_MISSING_PROPERTY,
+		                     _("property is missing"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_EAP);
 		return FALSE;
 	}
 
 	if (!_nm_utils_string_slist_validate (priv->eap, valid_eap)) {
-		g_set_error (error,
-		             NM_SETTING_802_1X_ERROR,
-		             NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_802_1X_EAP);
+		g_set_error_literal (error,
+		                     NM_SETTING_802_1X_ERROR,
+		                     NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
+		                     _("property is invalid"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_EAP);
 		return FALSE;
 	}
 
@@ -2492,7 +2682,9 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 		g_set_error (error,
 		             NM_SETTING_802_1X_ERROR,
 		             NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_802_1X_PHASE1_PEAPVER);
+		             _("'%s' is not a valid value for the property"),
+		             priv->phase1_peapver);
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_PHASE1_PEAPVER);
 		return FALSE;
 	}
 
@@ -2500,7 +2692,9 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 		g_set_error (error,
 		             NM_SETTING_802_1X_ERROR,
 		             NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_802_1X_PHASE1_PEAPLABEL);
+		             _("'%s' is not a valid value for the property"),
+		             priv->phase1_peaplabel);
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_PHASE1_PEAPLABEL);
 		return FALSE;
 	}
 
@@ -2508,7 +2702,9 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 		g_set_error (error,
 		             NM_SETTING_802_1X_ERROR,
 		             NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING);
+		             _("'%s' is not a valid value for the property"),
+		             priv->phase1_fast_provisioning);
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING);
 		return FALSE;
 	}
 
@@ -2516,7 +2712,9 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 		g_set_error (error,
 		             NM_SETTING_802_1X_ERROR,
 		             NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_802_1X_PHASE2_AUTH);
+		             _("'%s' is not a valid value for the property"),
+		             priv->phase2_auth);
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_PHASE2_AUTH);
 		return FALSE;
 	}
 
@@ -2524,7 +2722,9 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 		g_set_error (error,
 		             NM_SETTING_802_1X_ERROR,
 		             NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_802_1X_PHASE2_AUTHEAP);
+		             _("'%s' is not a valid value for the property"),
+		             priv->phase2_autheap);
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_PHASE2_AUTHEAP);
 		return FALSE;
 	}
 
@@ -2551,7 +2751,6 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 static void
 nm_setting_802_1x_init (NMSetting8021x *setting)
 {
-	g_object_set (setting, NM_SETTING_NAME, NM_SETTING_802_1X_SETTING_NAME, NULL);
 }
 
 static void
@@ -2578,9 +2777,9 @@ finalize (GObject *object)
 		g_byte_array_free (priv->password_raw, TRUE);
 	g_free (priv->pin);
 
-	nm_utils_slist_free (priv->eap, g_free);
-	nm_utils_slist_free (priv->altsubject_matches, g_free);
-	nm_utils_slist_free (priv->phase2_altsubject_matches, g_free);
+	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 (priv->ca_cert)
 		g_byte_array_free (priv->ca_cert, TRUE);
@@ -2628,7 +2827,7 @@ set_property (GObject *object, guint prop_id,
 
 	switch (prop_id) {
 	case PROP_EAP:
-		nm_utils_slist_free (priv->eap, g_free);
+		g_slist_free_full (priv->eap, g_free);
 		priv->eap = g_value_dup_boxed (value);
 		break;
 	case PROP_IDENTITY:
@@ -2664,7 +2863,7 @@ set_property (GObject *object, guint prop_id,
 		priv->subject_match = g_value_dup_string (value);
 		break;
 	case PROP_ALTSUBJECT_MATCHES:
-		nm_utils_slist_free (priv->altsubject_matches, g_free);
+		g_slist_free_full (priv->altsubject_matches, g_free);
 		priv->altsubject_matches = g_value_dup_boxed (value);
 		break;
 	case PROP_CLIENT_CERT:
@@ -2720,7 +2919,7 @@ set_property (GObject *object, guint prop_id,
 		priv->phase2_subject_match = g_value_dup_string (value);
 		break;
 	case PROP_PHASE2_ALTSUBJECT_MATCHES:
-		nm_utils_slist_free (priv->phase2_altsubject_matches, g_free);
+		g_slist_free_full (priv->phase2_altsubject_matches, g_free);
 		priv->phase2_altsubject_matches = g_value_dup_boxed (value);
 		break;
 	case PROP_PHASE2_CLIENT_CERT:
@@ -2937,9 +3136,9 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
 	 * NMSetting8021x:eap:
 	 *
 	 * The allowed EAP method to be used when authenticating to the network with
-	 * 802.1x.  Valid methods are: "leap", "md5", "tls", "peap", "ttls", and
-	 * "fast".  Each method requires different configuration using the
-	 * properties of this object; refer to wpa_supplicant documentation for the
+	 * 802.1x.  Valid methods are: "leap", "md5", "tls", "peap", "ttls", "pwd",
+	 * and "fast".  Each method requires different configuration using the
+	 * properties of this setting; refer to wpa_supplicant documentation for the
 	 * allowed combinations.
 	 **/
 	g_object_class_install_property
@@ -2949,18 +3148,18 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
 							   "The allowed EAP method to be used when "
 							   "authenticating to the network with 802.1x. "
 							   "Valid methods are: 'leap', 'md5', 'tls', 'peap', "
-							   "'ttls', and 'fast'. Each method requires "
+							   "'ttls', 'pwd', and 'fast'. Each method requires "
 							   "different configuration using the properties of "
 							   "this setting; refer to wpa_supplicant "
 							   "documentation for the allowed combinations.",
 							   DBUS_TYPE_G_LIST_OF_STRING,
-							   G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+							   G_PARAM_READWRITE));
 
 	/**
 	 * NMSetting8021x:identity:
 	 *
-	 * Identity string for EAP authentication methods.  Often the user's
-	 * user or login name.
+	 * Identity string for EAP authentication methods.  Often the user's user or
+	 * login name.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_IDENTITY,
@@ -2969,7 +3168,7 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
 						  "Identity string for EAP authentication methods.  "
 						  "Often the user's user or login name.",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+						  G_PARAM_READWRITE));
 
 	/**
 	 * NMSetting8021x:anonymous-identity:
@@ -2987,7 +3186,7 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
 						  "types that support different tunneled identity like "
 						  "EAP-TTLS.",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+						  G_PARAM_READWRITE));
 
 	/**
 	 * NMSetting8021x:pac-file:
@@ -3000,14 +3199,25 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
 						  "PAC file",
 						  "UTF-8 encoded file path containing PAC for EAP-FAST.",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+						  G_PARAM_READWRITE));
 
 	/**
 	 * NMSetting8021x:ca-cert:
 	 *
 	 * Contains the CA certificate if used by the EAP method specified in the
-	 * #NMSetting8021x:eap property.  Setting this property directly is
-	 * discouraged; use the nm_setting_802_1x_set_ca_cert() function instead.
+	 * #NMSetting8021x:eap property.
+	 *
+	 * Certificate data is specified using a "scheme"; two are currently
+	 * supported: blob and path. When using the blob scheme (which is backwards
+	 * compatible with NM 0.7.x) this property should be set to the
+	 * certificate's DER encoded data. When using the path scheme, this property
+	 * should be set to the full UTF-8 encoded path of the certificate, prefixed
+	 * with the string "file://" and ending with a terminating NUL byte. This
+	 * property can be unset even if the EAP method supports CA certificates,
+	 * but this allows man-in-the-middle attacks and is NOT recommended.
+	 *
+	 * Setting this property directly is discouraged; use the
+	 * nm_setting_802_1x_set_ca_cert() function instead.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_CA_CERT,
@@ -3028,7 +3238,7 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
 							   "supports CA certificates, but this allows "
 							   "man-in-the-middle attacks and is NOT recommended.",
 							   DBUS_TYPE_G_UCHAR_ARRAY,
-							   G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+							   G_PARAM_READWRITE));
 
 	/**
 	 * NMSetting8021x:ca-path:
@@ -3046,15 +3256,14 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
 						  "verification chain in addition to the certificate "
 						  "specified in the 'ca-cert' property.",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+						  G_PARAM_READWRITE));
 
 	/**
 	 * NMSetting8021x:subject-match:
 	 *
-	 * Substring to be matched against the subject of the certificate
-	 * presented by the authentication server. When unset, no
-	 * verification of the authentication server certificate's subject
-	 * is performed.
+	 * Substring to be matched against the subject of the certificate presented
+	 * by the authentication server. When unset, no verification of the
+	 * authentication server certificate's subject is performed.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_SUBJECT_MATCH,
@@ -3066,15 +3275,14 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
 							  "authentication server certificate's subject is "
 							  "performed.",
 							  NULL,
-							  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+							  G_PARAM_READWRITE));
 
 	/**
 	 * NMSetting8021x:altsubject-matches:
 	 *
 	 * List of strings to be matched against the altSubjectName of the
-	 * certificate presented by the authentication server. If the list
-	 * is empty, no verification of the server certificate's
-	 * altSubjectName is performed.
+	 * certificate presented by the authentication server. If the list is empty,
+	 * no verification of the server certificate's altSubjectName is performed.
 	 **/
 	 g_object_class_install_property
 		 (object_class, PROP_ALTSUBJECT_MATCHES,
@@ -3087,14 +3295,23 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
 									  "of the server certificate's "
 									  "altSubjectName is performed.",
 									  DBUS_TYPE_G_LIST_OF_STRING,
-									  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+									  G_PARAM_READWRITE));
 
 	/**
 	 * NMSetting8021x:client-cert:
 	 *
 	 * Contains the client certificate if used by the EAP method specified in
-	 * the #NMSetting8021x:eap property.  Setting this property directly is
-	 * discouraged; use the nm_setting_802_1x_set_client_cert() function instead.
+	 * the #NMSetting8021x:eap property.
+	 *
+	 * Certificate data is specified using a "scheme"; two are currently
+	 * supported: blob and path. When using the blob scheme (which is backwards
+	 * compatible with NM 0.7.x) this property should be set to the
+	 * certificate's DER encoded data. When using the path scheme, this property
+	 * should be set to the full UTF-8 encoded path of the certificate, prefixed
+	 * with the string "file://" and ending with a terminating NUL byte.
+	 *
+	 * Setting this property directly is discouraged; use the
+	 * nm_setting_802_1x_set_client_cert() function instead.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_CLIENT_CERT,
@@ -3112,7 +3329,7 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
 							   "certificate, prefixed with the string 'file://' "
 							   "and ending with a terminating NULL byte.",
 							   DBUS_TYPE_G_UCHAR_ARRAY,
-							   G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+							   G_PARAM_READWRITE));
 
 	/**
 	 * NMSetting8021x:phase1-peapver:
@@ -3136,7 +3353,7 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
 						  "PEAP version.  To do so, this property may be set to "
 						  "'0' or '1' to force that specific PEAP version.",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+						  G_PARAM_READWRITE));
 
 	/**
 	 * NMSetting8021x:phase1-peaplabel:
@@ -3156,7 +3373,7 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
 						  "Set to '1' to force use of the new PEAP label.  See "
 						  "the wpa_supplicant documentation for more details.",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+						  G_PARAM_READWRITE));
 
 	/**
 	 * NMSetting8021x:phase1-fast-provisioning:
@@ -3181,16 +3398,16 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
 						  "provisioning).  See the wpa_supplicant documentation "
 						  "for more details.",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+						  G_PARAM_READWRITE));
 
 	/**
 	 * NMSetting8021x:phase2-auth:
 	 *
 	 * Specifies the allowed "phase 2" inner non-EAP authentication methods when
 	 * an EAP method that uses an inner TLS tunnel is specified in the
-	 * #NMSetting8021x:eap property.  Recognized non-EAP phase2 methods are
+	 * #NMSetting8021x:eap property.  Recognized non-EAP "phase 2" methods are
 	 * "pap", "chap", "mschap", "mschapv2", "gtc", "otp", "md5", and "tls".
-	 * Each 'phase 2' inner method requires specific parameters for successful
+	 * Each "phase 2" inner method requires specific parameters for successful
 	 * authentication; see the wpa_supplicant documentation for more details.
 	 **/
 	g_object_class_install_property
@@ -3206,15 +3423,15 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
 						  "specific parameters for successful authentication; "
 						  "see the wpa_supplicant documentation for more details.",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+						  G_PARAM_READWRITE));
 
 	/**
 	 * NMSetting8021x:phase2-autheap:
 	 *
 	 * Specifies the allowed "phase 2" inner EAP-based authentication methods
 	 * when an EAP method that uses an inner TLS tunnel is specified in the
-	 * #NMSetting8021x:eap property.  Recognized EAP-based phase2 methods are
-	 * "md5", "mschapv2", "otp", "gtc", and "tls". Each 'phase 2' inner method
+	 * #NMSetting8021x:eap property.  Recognized EAP-based "phase 2" methods are
+	 * "md5", "mschapv2", "otp", "gtc", and "tls". Each "phase 2" inner method
 	 * requires specific parameters for successful authentication; see the
 	 * wpa_supplicant documentation for more details.
 	 **/
@@ -3231,13 +3448,24 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
 						  "for successful authentication; see the wpa_supplicant "
 						  "documentation for more details.",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+						  G_PARAM_READWRITE));
 
 	/**
 	 * NMSetting8021x:phase2-ca-cert:
 	 *
-	 * Contains the CA certificate if used by the EAP method specified in the
-	 * #NMSetting8021x:phase2-auth or #NMSetting8021x:phase2-autheap properties.
+	 * Contains the "phase 2" CA certificate if used by the EAP method specified
+	 * in the #NMSetting8021x:phase2-auth or #NMSetting8021x:phase2-autheap
+	 * properties.
+	 *
+	 * Certificate data is specified using a "scheme"; two are currently
+	 * supported: blob and path. When using the blob scheme (which is backwards
+	 * compatible with NM 0.7.x) this property should be set to the
+	 * certificate's DER encoded data. When using the path scheme, this property
+	 * should be set to the full UTF-8 encoded path of the certificate, prefixed
+	 * with the string "file://" and ending with a terminating NUL byte. This
+	 * property can be unset even if the EAP method supports CA certificates,
+	 * but this allows man-in-the-middle attacks and is NOT recommended.
+	 *
 	 * Setting this property directly is discouraged; use the
 	 * nm_setting_802_1x_set_phase2_ca_cert() function instead.
 	 **/
@@ -3261,7 +3489,7 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
 							   "certificates, but this allows man-in-the-middle "
 							   "attacks and is NOT recommended.",
 							   DBUS_TYPE_G_UCHAR_ARRAY,
-							   G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+							   G_PARAM_READWRITE));
 
 	/**
 	 * NMSetting8021x:phase2-ca-path:
@@ -3279,15 +3507,15 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
 						  "verification chain in addition to the certificate "
 						  "specified in the 'phase2-ca-cert' property.",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+						  G_PARAM_READWRITE));
 
 	/**
 	 * NMSetting8021x:phase2-subject-match:
 	 *
-	 * Substring to be matched against the subject of the certificate
-	 * presented by the authentication server during the inner "phase
-	 * 2" authentication. When unset, no verification of the
-	 * authentication server certificate's subject is performed.
+	 * Substring to be matched against the subject of the certificate presented
+	 * by the authentication server during the inner "phase 2"
+	 * authentication. When unset, no verification of the authentication server
+	 * certificate's subject is performed.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_PHASE2_SUBJECT_MATCH,
@@ -3300,16 +3528,15 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
 							  "the authentication server certificate's subject "
 							  "is performed.",
 							  NULL,
-							  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+							  G_PARAM_READWRITE));
 
 	/**
 	 * NMSetting8021x:phase2-altsubject-matches:
 	 *
 	 * List of strings to be matched against the altSubjectName of the
-	 * certificate presented by the authentication server during the
-	 * inner "phase 2" authentication. If the list is empty, no
-	 * verification of the server certificate's altSubjectName is
-	 * performed.
+	 * certificate presented by the authentication server during the inner
+	 * "phase 2" authentication. If the list is empty, no verification of the
+	 * server certificate's altSubjectName is performed.
 	 **/
 	 g_object_class_install_property
 		 (object_class, PROP_PHASE2_ALTSUBJECT_MATCHES,
@@ -3324,14 +3551,25 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
 									  "verification of the server certificate's "
 									  "altSubjectName is performed.",
 									  DBUS_TYPE_G_LIST_OF_STRING,
-									  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+									  G_PARAM_READWRITE));
 
 	/**
 	 * NMSetting8021x:phase2-client-cert:
 	 *
-	 * Contains the client certificate if used by the EAP method specified in
-	 * the #NMSetting8021x:phase2-auth or #NMSetting8021x:phase2-autheap
-	 * properties.  Setting this property directly is discouraged; use the
+	 * Contains the "phase 2" client certificate if used by the EAP method
+	 * specified in the #NMSetting8021x:phase2-auth or
+	 * #NMSetting8021x:phase2-autheap properties.
+	 *
+	 * Certificate data is specified using a "scheme"; two are currently
+	 * supported: blob and path. When using the blob scheme (which is backwards
+	 * compatible with NM 0.7.x) this property should be set to the
+	 * certificate's DER encoded data. When using the path scheme, this property
+	 * should be set to the full UTF-8 encoded path of the certificate, prefixed
+	 * with the string "file://" and ending with a terminating NUL byte. This
+	 * property can be unset even if the EAP method supports CA certificates,
+	 * but this allows man-in-the-middle attacks and is NOT recommended.
+	 *
+	 * Setting this property directly is discouraged; use the
 	 * nm_setting_802_1x_set_phase2_client_cert() function instead.
 	 **/
 	g_object_class_install_property
@@ -3351,14 +3589,14 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
 							   "certificate, prefixed with the string 'file://' "
 							   "and ending with a terminating NULL byte.",
 							   DBUS_TYPE_G_UCHAR_ARRAY,
-							   G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+							   G_PARAM_READWRITE));
 
 	/**
 	 * NMSetting8021x:password:
 	 *
-	 * Password used for EAP authentication methods. If both
-	 * #NMSetting8021x:password and #NMSetting8021x:password-raw are
-	 * specified, #NMSetting8021x:password is preferred.
+	 * UTF-8 encoded password used for EAP authentication methods. If both the
+	 * #NMSetting8021x:password property and the #NMSetting8021x:password-raw
+	 * property are specified, #NMSetting8021x:password is preferred.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_PASSWORD,
@@ -3366,12 +3604,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
 						  "Password",
 						  "UTF-8 encoded password used for EAP authentication methods.",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET));
+						  G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET));
 
 	/**
 	 * NMSetting8021x:password-flags:
 	 *
-	 * Flags indicating how to handle #NMSetting8021x:password:.
+	 * Flags indicating how to handle the #NMSetting8021x:password property.
 	 **/
 	g_object_class_install_property (object_class, PROP_PASSWORD_FLAGS,
 		 g_param_spec_uint (NM_SETTING_802_1X_PASSWORD_FLAGS,
@@ -3380,15 +3618,15 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
 		                    NM_SETTING_SECRET_FLAG_NONE,
 		                    NM_SETTING_SECRET_FLAGS_ALL,
 		                    NM_SETTING_SECRET_FLAG_NONE,
-		                    G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+		                    G_PARAM_READWRITE));
 
 	/**
 	 * NMSetting8021x:password-raw:
 	 *
-	 * Password used for EAP authentication methods delivered as a
-	 * UTF-8-encoded array of bytes. If both #NMSetting8021x:password
-	 * and #NMSetting8021x:password-raw are specified,
-	 * #NMSetting8021x:password is preferred.
+	 * Password used for EAP authentication methods, given as a byte array to
+	 * allow passwords in other encodings than UTF-8 to be used. If both the
+	 * #NMSetting8021x:password property and the #NMSetting8021x:password-raw
+	 * property are specified, #NMSetting8021x:password is preferred.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_PASSWORD_RAW,
@@ -3401,12 +3639,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
 		                             "'password-raw' are given, 'password' is "
 		                             "preferred.",
 		                             DBUS_TYPE_G_UCHAR_ARRAY,
-		                             G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET));
+		                             G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET));
 
 	/**
 	 * NMSetting8021x:password-raw-flags:
 	 *
-	 * Flags indicating how to handle #NMSetting8021x:password-raw:.
+	 * Flags indicating how to handle the #NMSetting8021x:password-raw property.
 	 **/
 	g_object_class_install_property (object_class, PROP_PASSWORD_RAW_FLAGS,
 		 g_param_spec_uint (NM_SETTING_802_1X_PASSWORD_RAW_FLAGS,
@@ -3415,13 +3653,30 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
 		                    NM_SETTING_SECRET_FLAG_NONE,
 		                    NM_SETTING_SECRET_FLAGS_ALL,
 		                    NM_SETTING_SECRET_FLAG_NONE,
-		                    G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+		                    G_PARAM_READWRITE));
 
 	/**
 	 * NMSetting8021x:private-key:
 	 *
-	 * Contains the private key if the #NMSetting8021x:eap property is set to
-	 * 'tls'.  Setting this property directly is discouraged; use the
+	 * Contains the private key when the #NMSetting8021x:eap property is set to
+	 * "tls".
+	 *
+	 * Key data is specified using a "scheme"; two are currently supported: blob
+	 * and path. When using the blob scheme and private keys, this property
+	 * should be set to the key's encrypted PEM encoded data. When using private
+	 * keys with the path scheme, this property should be set to the full UTF-8
+	 * encoded path of the key, prefixed with the string "file://" and ending
+	 * with a terminating NUL byte. When using PKCS#12 format private keys and
+	 * the blob scheme, this property should be set to the PKCS#12 data and the
+	 * #NMSetting8021x:private-key-password property must be set to password
+	 * used to decrypt the PKCS#12 certificate and key. When using PKCS#12 files
+	 * and the path scheme, this property should be set to the full UTF-8
+	 * encoded path of the key, prefixed with the string "file://" and and
+	 * ending with a terminating NUL byte, and as with the blob scheme the
+	 * "private-key-password" property must be set to the password used to
+	 * decode the PKCS#12 private key and certificate.
+	 *
+	 * Setting this property directly is discouraged; use the
 	 * nm_setting_802_1x_set_private_key() function instead.
 	 *
 	 * WARNING: #NMSetting8021x:private-key is not a "secret" property, and thus
@@ -3458,14 +3713,14 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
 							   "the password used to decode the PKCS#12 private "
 							   "key and certificate.",
 							   DBUS_TYPE_G_UCHAR_ARRAY,
-							   G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+							   G_PARAM_READWRITE));
 
 	/**
 	 * NMSetting8021x:private-key-password:
 	 *
-	 * The password used to decrypt the private key specified in
-	 * #NMSetting8021x:private-key when the private key either uses the path
-	 * scheme, or if the private key is a PKCS#12 format key.  Setting this
+	 * The password used to decrypt the private key specified in the
+	 * #NMSetting8021x:private-key property when the private key either uses the
+	 * path scheme, or if the private key is a PKCS#12 format key.  Setting this
 	 * property directly is not generally necessary except when returning
 	 * secrets to NetworkManager; it is generally set automatically when setting
 	 * the private key by the nm_setting_802_1x_set_private_key() function.
@@ -3479,12 +3734,13 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
 						  "private key either uses the path scheme, or if the "
 						  "private key is a PKCS#12 format key.",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET));
+						  G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET));
 
 	/**
 	 * NMSetting8021x:private-key-password-flags:
 	 *
-	 * Flags indicating how to handle #NMSetting8021x:private-key-password:.
+	 * Flags indicating how to handle the #NMSetting8021x:private-key-password
+	 * property.
 	 **/
 	g_object_class_install_property (object_class, PROP_PRIVATE_KEY_PASSWORD_FLAGS,
 		 g_param_spec_uint (NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD_FLAGS,
@@ -3494,16 +3750,31 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
 		                    NM_SETTING_SECRET_FLAG_NONE,
 		                    NM_SETTING_SECRET_FLAGS_ALL,
 		                    NM_SETTING_SECRET_FLAG_NONE,
-		                    G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+		                    G_PARAM_READWRITE));
 
 	/**
 	 * NMSetting8021x:phase2-private-key:
 	 *
-	 * Private key data used by "phase 2" inner authentication methods.
+	 * Contains the "phase 2" inner private key when the
+	 * #NMSetting8021x:phase2-auth or #NMSetting8021x:phase2-autheap property is
+	 * set to "tls".
+	 *
+	 * Key data is specified using a "scheme"; two are currently supported: blob
+	 * and path. When using the blob scheme and private keys, this property
+	 * should be set to the key's encrypted PEM encoded data. When using private
+	 * keys with the path scheme, this property should be set to the full UTF-8
+	 * encoded path of the key, prefixed with the string "file://" and ending
+	 * with a terminating NUL byte. When using PKCS#12 format private keys and
+	 * the blob scheme, this property should be set to the PKCS#12 data and the
+	 * #NMSetting8021x:phase2-private-key-password property must be set to
+	 * password used to decrypt the PKCS#12 certificate and key. When using
+	 * PKCS#12 files and the path scheme, this property should be set to the
+	 * full UTF-8 encoded path of the key, prefixed with the string "file://"
+	 * and and ending with a terminating NUL byte, and as with the blob scheme
+	 * the #NMSetting8021x:phase2-private-key-password property must be set to
+	 * the password used to decode the PKCS#12 private key and certificate.
 	 *
-	 * Contains the "phase 2" inner private key if the #NMSetting8021x:phase2-auth
-	 * or #NMSetting8021x:phase2-autheap property is set to 'tls'.  Setting this
-	 * property directly is discouraged; use the
+	 * Setting this property directly is discouraged; use the
 	 * nm_setting_802_1x_set_phase2_private_key() function instead.
 	 **/
 	g_object_class_install_property
@@ -3535,17 +3806,17 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
 							   "set to the password used to decode the PKCS#12 "
 							   "private key and certificate.",
 							   DBUS_TYPE_G_UCHAR_ARRAY,
-							   G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+							   G_PARAM_READWRITE));
 
 	/**
 	 * NMSetting8021x:phase2-private-key-password:
 	 *
-	 * The password used to decrypt the private key specified in
-	 * #NMSetting8021x:phase2-private-key when the private key either uses the
-	 * path scheme, or if the private key is a PKCS#12 format key.  Setting this
-	 * property directly is not generally necessary except when returning
-	 * secrets to NetworkManager; it is generally set automatically when setting
-	 * the private key by the nm_setting_802_1x_set_phase2_private_key() function.
+	 * The password used to decrypt the "phase 2" private key specified in the
+	 * #NMSetting8021x:phase2-private-key property when the private key either
+	 * uses the path scheme, or is a PKCS#12 format key.  Setting this property
+	 * directly is not generally necessary except when returning secrets to
+	 * NetworkManager; it is generally set automatically when setting the
+	 * private key by the nm_setting_802_1x_set_phase2_private_key() function.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_PHASE2_PRIVATE_KEY_PASSWORD,
@@ -3556,12 +3827,13 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
 						  "phase2 private key either uses the path scheme, or "
 						  "if the phase2 private key is a PKCS#12 format key.",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET));
+						  G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET));
 
 	/**
 	 * NMSetting8021x:phase2-private-key-password-flags:
 	 *
-	 * Flags indicating how to handle #NMSetting8021x:phase2-private-key-password:.
+	 * Flags indicating how to handle the
+	 * #NMSetting8021x:phase2-private-key-password property.
 	 **/
 	g_object_class_install_property (object_class, PROP_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS,
 		 g_param_spec_uint (NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS,
@@ -3571,7 +3843,7 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
 		                    NM_SETTING_SECRET_FLAG_NONE,
 		                    NM_SETTING_SECRET_FLAGS_ALL,
 		                    NM_SETTING_SECRET_FLAG_NONE,
-		                    G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+		                    G_PARAM_READWRITE));
 
 	/**
 	 * NMSetting8021x:pin:
@@ -3584,12 +3856,12 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
 		                      "PIN",
 		                      "PIN used for EAP authentication methods.",
 		                      NULL,
-		                      G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET));
+		                      G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET));
 
 	/**
 	 * NMSetting8021x:pin-flags:
 	 *
-	 * Flags indicating how to handle #NMSetting8021x:pin:.
+	 * Flags indicating how to handle the #NMSetting8021x:pin property.
 	 **/
 	g_object_class_install_property (object_class, PROP_PIN_FLAGS,
 		 g_param_spec_uint (NM_SETTING_802_1X_PIN_FLAGS,
@@ -3598,17 +3870,17 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
 		                    NM_SETTING_SECRET_FLAG_NONE,
 		                    NM_SETTING_SECRET_FLAGS_ALL,
 		                    NM_SETTING_SECRET_FLAG_NONE,
-		                    G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+		                    G_PARAM_READWRITE));
 
 	/**
 	 * NMSetting8021x:system-ca-certs:
 	 *
-	 * When TRUE, overrides #NMSetting8021x:ca-path and
+	 * When %TRUE, overrides the #NMSetting8021x:ca-path and
 	 * #NMSetting8021x:phase2-ca-path properties using the system CA directory
 	 * specified at configure time with the --system-ca-path switch.  The
 	 * certificates in this directory are added to the verification chain in
-	 * addition to any certificates specified by the #NMSetting8021x:ca-cert
-	 * and #NMSetting8021x:phase2-ca-cert properties.
+	 * addition to any certificates specified by the #NMSetting8021x:ca-cert and
+	 * #NMSetting8021x:phase2-ca-cert properties.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_SYSTEM_CA_CERTS,
@@ -3622,7 +3894,7 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
 							   "chain in addition to any certificates specified "
 							   "by the 'ca-cert' and 'phase2-ca-cert' properties.",
 							   FALSE,
-							   G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+							   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
 	/* Initialize crypto lbrary. */
 	if (!nm_utils_init (&error)) {
diff --git a/libnm-util/nm-setting-8021x.h b/libnm-util/nm-setting-8021x.h
index 8381fed7..263630ec 100644
--- a/libnm-util/nm-setting-8021x.h
+++ b/libnm-util/nm-setting-8021x.h
@@ -19,7 +19,7 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2007 - 2012 Red Hat, Inc.
+ * (C) Copyright 2007 - 2014 Red Hat, Inc.
  * (C) Copyright 2007 - 2008 Novell, Inc.
  */
 
@@ -170,6 +170,8 @@ guint32           nm_setting_802_1x_get_num_eap_methods              (NMSetting8
 const char *      nm_setting_802_1x_get_eap_method                   (NMSetting8021x *setting, guint32 i);
 gboolean          nm_setting_802_1x_add_eap_method                   (NMSetting8021x *setting, const char *eap);
 void              nm_setting_802_1x_remove_eap_method                (NMSetting8021x *setting, guint32 i);
+NM_AVAILABLE_IN_0_9_10
+gboolean          nm_setting_802_1x_remove_eap_method_by_value       (NMSetting8021x *setting, const char *eap);
 void              nm_setting_802_1x_clear_eap_methods                (NMSetting8021x *setting);
 
 const char *      nm_setting_802_1x_get_identity                     (NMSetting8021x *setting);
@@ -195,11 +197,14 @@ const char *      nm_setting_802_1x_get_subject_match                (NMSetting8
 
 guint32           nm_setting_802_1x_get_num_altsubject_matches       (NMSetting8021x *setting);
 const char *      nm_setting_802_1x_get_altsubject_match             (NMSetting8021x *setting,
-																	  guint32 i);
+                                                                      guint32 i);
 gboolean          nm_setting_802_1x_add_altsubject_match             (NMSetting8021x *setting,
-																	  const char *altsubject_match);
+                                                                      const char *altsubject_match);
 void              nm_setting_802_1x_remove_altsubject_match          (NMSetting8021x *setting,
-																	  guint32 i);
+                                                                      guint32 i);
+NM_AVAILABLE_IN_0_9_10
+gboolean          nm_setting_802_1x_remove_altsubject_match_by_value (NMSetting8021x *setting,
+                                                                      const char *altsubject_match);
 void              nm_setting_802_1x_clear_altsubject_matches         (NMSetting8021x *setting);
 
 NMSetting8021xCKScheme nm_setting_802_1x_get_client_cert_scheme      (NMSetting8021x *setting);
@@ -232,14 +237,17 @@ gboolean               nm_setting_802_1x_set_phase2_ca_cert          (NMSetting8
 
 const char *      nm_setting_802_1x_get_phase2_subject_match         (NMSetting8021x *setting);
 
-guint32           nm_setting_802_1x_get_num_phase2_altsubject_matches   (NMSetting8021x *setting);
-const char *      nm_setting_802_1x_get_phase2_altsubject_match         (NMSetting8021x *setting,
-																		 guint32 i);
-gboolean          nm_setting_802_1x_add_phase2_altsubject_match         (NMSetting8021x *setting,
-																		 const char *phase2_altsubject_match);
-void              nm_setting_802_1x_remove_phase2_altsubject_match      (NMSetting8021x *setting,
-																		 guint32 i);
-void              nm_setting_802_1x_clear_phase2_altsubject_matches     (NMSetting8021x *setting);
+guint32           nm_setting_802_1x_get_num_phase2_altsubject_matches       (NMSetting8021x *setting);
+const char *      nm_setting_802_1x_get_phase2_altsubject_match             (NMSetting8021x *setting,
+                                                                             guint32 i);
+gboolean          nm_setting_802_1x_add_phase2_altsubject_match             (NMSetting8021x *setting,
+                                                                             const char *phase2_altsubject_match);
+void              nm_setting_802_1x_remove_phase2_altsubject_match          (NMSetting8021x *setting,
+                                                                             guint32 i);
+NM_AVAILABLE_IN_0_9_10
+gboolean          nm_setting_802_1x_remove_phase2_altsubject_match_by_value (NMSetting8021x *setting,
+                                                                             const char *phase2_altsubject_match);
+void              nm_setting_802_1x_clear_phase2_altsubject_matches         (NMSetting8021x *setting);
 
 NMSetting8021xCKScheme nm_setting_802_1x_get_phase2_client_cert_scheme   (NMSetting8021x *setting);
 const GByteArray *     nm_setting_802_1x_get_phase2_client_cert_blob     (NMSetting8021x *setting);
diff --git a/libnm-util/nm-setting-adsl.c b/libnm-util/nm-setting-adsl.c
index de0850e6..00cbb4af 100644
--- a/libnm-util/nm-setting-adsl.c
+++ b/libnm-util/nm-setting-adsl.c
@@ -20,14 +20,16 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2007 - 2008 Red Hat, Inc.
+ * (C) Copyright 2011 - 2013 Red Hat, Inc.
  */
 
+#include <string.h>
+#include <glib/gi18n.h>
+
 #include "nm-setting-adsl.h"
 #include "nm-setting-ppp.h"
 #include "nm-setting-private.h"
 #include "nm-utils.h"
-#include <string.h>
 
 /**
  * SECTION:nm-setting-adsl
@@ -204,34 +206,39 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 	NMSettingAdslPrivate *priv = NM_SETTING_ADSL_GET_PRIVATE (setting);
 
 	if (!priv->username) {
-		g_set_error (error,
-		             NM_SETTING_ADSL_ERROR,
-		             NM_SETTING_ADSL_ERROR_MISSING_PROPERTY,
-		             NM_SETTING_ADSL_USERNAME);
+		g_set_error_literal (error,
+		                     NM_SETTING_ADSL_ERROR,
+		                     NM_SETTING_ADSL_ERROR_MISSING_PROPERTY,
+		                     _("property is missing"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_ADSL_SETTING_NAME, NM_SETTING_ADSL_USERNAME);
 		return FALSE;
 	} else if (!strlen (priv->username)) {
-		g_set_error (error,
-		             NM_SETTING_ADSL_ERROR,
-		             NM_SETTING_ADSL_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_ADSL_USERNAME);
+		g_set_error_literal (error,
+		                     NM_SETTING_ADSL_ERROR,
+		                     NM_SETTING_ADSL_ERROR_INVALID_PROPERTY,
+		                     _("property is empty"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_ADSL_SETTING_NAME, NM_SETTING_ADSL_USERNAME);
 		return FALSE;
 	}
 
 	if (priv->password && !strlen (priv->password)) {
-		g_set_error (error,
-		             NM_SETTING_ADSL_ERROR,
-		             NM_SETTING_ADSL_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_ADSL_PASSWORD);
+		g_set_error_literal (error,
+		                     NM_SETTING_ADSL_ERROR,
+		                     NM_SETTING_ADSL_ERROR_INVALID_PROPERTY,
+		                     _("property is empty"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_ADSL_SETTING_NAME, NM_SETTING_ADSL_PASSWORD);
 		return FALSE;
 	}
 
 	if (strcmp (priv->protocol, NM_SETTING_ADSL_PROTOCOL_PPPOA) &&
-		strcmp (priv->protocol, NM_SETTING_ADSL_PROTOCOL_PPPOE) &&
-		strcmp (priv->protocol, NM_SETTING_ADSL_PROTOCOL_IPOATM)) {
+	    strcmp (priv->protocol, NM_SETTING_ADSL_PROTOCOL_PPPOE) &&
+	    strcmp (priv->protocol, NM_SETTING_ADSL_PROTOCOL_IPOATM)) {
 		g_set_error (error,
 		             NM_SETTING_ADSL_ERROR,
 		             NM_SETTING_ADSL_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_ADSL_PROTOCOL);
+		             _("'%s' is not a valid value for the property"),
+		             priv->protocol);
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_ADSL_SETTING_NAME, NM_SETTING_ADSL_PROTOCOL);
 		return FALSE;
 	}
 
@@ -240,7 +247,9 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 		g_set_error (error,
 		             NM_SETTING_ADSL_ERROR,
 		             NM_SETTING_ADSL_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_ADSL_ENCAPSULATION);
+		             _("'%s' is not a valid value for the property"),
+		             priv->encapsulation);
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_ADSL_SETTING_NAME, NM_SETTING_ADSL_ENCAPSULATION);
 		return FALSE;
 	}
 
@@ -267,7 +276,6 @@ need_secrets (NMSetting *setting)
 static void
 nm_setting_adsl_init (NMSettingAdsl *setting)
 {
-	g_object_set (setting, NM_SETTING_NAME, NM_SETTING_ADSL_SETTING_NAME, NULL);
 }
 
 static void
@@ -383,7 +391,7 @@ nm_setting_adsl_class_init (NMSettingAdslClass *setting_class)
 						  "Username",
 						  "Username used to authenticate with the pppoa service.",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+						  G_PARAM_READWRITE));
 
 	/**
 	 * NMSettingAdsl:password:
@@ -396,12 +404,12 @@ nm_setting_adsl_class_init (NMSettingAdslClass *setting_class)
 						  "Password",
 						  "Password used to authenticate with the pppoa service.",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET));
+						  G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET));
 
 	/**
 	 * NMSettingAdsl:password-flags:
 	 *
-	 * Flags indicating how to handle #NMSettingAdsl:password:.
+	 * Flags indicating how to handle the #NMSettingAdsl:password property.
 	 **/
 	g_object_class_install_property (object_class, PROP_PASSWORD_FLAGS,
 		 g_param_spec_uint (NM_SETTING_ADSL_PASSWORD_FLAGS,
@@ -410,12 +418,12 @@ nm_setting_adsl_class_init (NMSettingAdslClass *setting_class)
 		                    NM_SETTING_SECRET_FLAG_NONE,
 		                    NM_SETTING_SECRET_FLAGS_ALL,
 		                    NM_SETTING_SECRET_FLAG_NONE,
-		                    G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+		                    G_PARAM_READWRITE));
 
 	/**
 	 * NMSettingAdsl:protocol:
 	 *
-	 * ADSL connection protocol, can be pppoa, pppoe or ipoatm.
+	 * ADSL connection protocol.  Can be "pppoa", "pppoe" or "ipoatm".
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_PROTOCOL,
@@ -423,12 +431,12 @@ nm_setting_adsl_class_init (NMSettingAdslClass *setting_class)
 						  "Protocol",
 						  "ADSL connection protocol.",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+						  G_PARAM_READWRITE));
 
 	/**
 	 * NMSettingAdsl:encapsulation:
 	 *
-	 * ADSL connection encapsulation, can be vcmux or llc.
+	 * Encapsulation of ADSL connection.  Can be "vcmux" or "llc".
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_ENCAPSULATION,
@@ -436,12 +444,12 @@ nm_setting_adsl_class_init (NMSettingAdslClass *setting_class)
 						  "Encapsulation",
 						  "Encapsulation of ADSL connection",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+						  G_PARAM_READWRITE));
 
 	/**
 	 * NMSettingAdsl:vpi:
 	 *
-	 * ADSL connection vpi.
+	 * VPI of ADSL connection
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_VPI,
@@ -449,12 +457,12 @@ nm_setting_adsl_class_init (NMSettingAdslClass *setting_class)
 						  "VPI",
 						  "VPI of ADSL connection",
 						  0, 65536, 0,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+						  G_PARAM_READWRITE));
 
 	/**
 	 * NMSettingAdsl:vci:
 	 *
-	 * ADSL connection vci.
+	 * VCI of ADSL connection
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_VCI,
@@ -462,5 +470,5 @@ nm_setting_adsl_class_init (NMSettingAdslClass *setting_class)
 						  "VCI",
 						  "VCI of ADSL connection",
 						  0, 65536, 0,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+						  G_PARAM_READWRITE));
 }
diff --git a/libnm-util/nm-setting-bluetooth.c b/libnm-util/nm-setting-bluetooth.c
index e81e5333..5c13257c 100644
--- a/libnm-util/nm-setting-bluetooth.c
+++ b/libnm-util/nm-setting-bluetooth.c
@@ -20,12 +20,13 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2007 - 2009 Red Hat, Inc.
+ * (C) Copyright 2007 - 2013 Red Hat, Inc.
  * (C) Copyright 2007 - 2008 Novell, Inc.
  */
 
 #include <string.h>
 #include <net/ethernet.h>
+#include <glib/gi18n.h>
 
 #include "nm-param-spec-specialized.h"
 #include "nm-dbus-glib-types.h"
@@ -131,48 +132,44 @@ nm_setting_bluetooth_get_bdaddr (NMSettingBluetooth *setting)
 	return NM_SETTING_BLUETOOTH_GET_PRIVATE (setting)->bdaddr;
 }
 
-static gint
-find_setting_by_name (gconstpointer a, gconstpointer b)
-{
-	NMSetting *setting = NM_SETTING (a);
-	const char *str = (const char *) b;
-
-	return strcmp (nm_setting_get_name (setting), str);
-}
-
 static gboolean
 verify (NMSetting *setting, GSList *all_settings, GError **error)
 {
 	NMSettingBluetoothPrivate *priv = NM_SETTING_BLUETOOTH_GET_PRIVATE (setting);
 
 	if (!priv->bdaddr) {
-		g_set_error (error,
-		             NM_SETTING_BLUETOOTH_ERROR,
-		             NM_SETTING_BLUETOOTH_ERROR_MISSING_PROPERTY,
-		             NM_SETTING_BLUETOOTH_BDADDR);
+		g_set_error_literal (error,
+		                     NM_SETTING_BLUETOOTH_ERROR,
+		                     NM_SETTING_BLUETOOTH_ERROR_MISSING_PROPERTY,
+		                     _("property is missing"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_BLUETOOTH_SETTING_NAME, NM_SETTING_BLUETOOTH_BDADDR);
 		return FALSE;
 	}
 
 	if (priv->bdaddr && priv->bdaddr->len != ETH_ALEN) {
-		g_set_error (error,
-		             NM_SETTING_BLUETOOTH_ERROR,
-		             NM_SETTING_BLUETOOTH_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_BLUETOOTH_BDADDR);
+		g_set_error_literal (error,
+		                     NM_SETTING_BLUETOOTH_ERROR,
+		                     NM_SETTING_BLUETOOTH_ERROR_INVALID_PROPERTY,
+		                     _("property is invalid"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_BLUETOOTH_SETTING_NAME, NM_SETTING_BLUETOOTH_BDADDR);
 		return FALSE;
 	}
 
 	if (!priv->type) {
-		g_set_error (error,
-		             NM_SETTING_BLUETOOTH_ERROR,
-		             NM_SETTING_BLUETOOTH_ERROR_MISSING_PROPERTY,
-		             NM_SETTING_BLUETOOTH_TYPE);
+		g_set_error_literal (error,
+		                     NM_SETTING_BLUETOOTH_ERROR,
+		                     NM_SETTING_BLUETOOTH_ERROR_MISSING_PROPERTY,
+		                     _("property is missing"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_BLUETOOTH_SETTING_NAME, NM_SETTING_BLUETOOTH_TYPE);
 		return FALSE;
 	} else if (!g_str_equal (priv->type, NM_SETTING_BLUETOOTH_TYPE_DUN) &&
 		   !g_str_equal (priv->type, NM_SETTING_BLUETOOTH_TYPE_PANU)) {
 		g_set_error (error,
 		             NM_SETTING_BLUETOOTH_ERROR,
 		             NM_SETTING_BLUETOOTH_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_BLUETOOTH_TYPE);
+		             _("'%s' is not a valid value for the property"),
+		             priv->type);
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_BLUETOOTH_SETTING_NAME, NM_SETTING_BLUETOOTH_TYPE);
 		return FALSE;
 	}
 
@@ -181,18 +178,16 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 	    && !strcmp (priv->type, NM_SETTING_BLUETOOTH_TYPE_DUN)) {
 		gboolean gsm = FALSE, cdma = FALSE;
 
-		gsm = !!g_slist_find_custom (all_settings,
-		                             (gpointer) NM_SETTING_GSM_SETTING_NAME,
-		                             find_setting_by_name);
-		cdma = !!g_slist_find_custom (all_settings,
-		                              (gpointer) NM_SETTING_CDMA_SETTING_NAME,
-		                              find_setting_by_name);
+		gsm = !!nm_setting_find_in_list (all_settings, NM_SETTING_GSM_SETTING_NAME);
+		cdma = !!nm_setting_find_in_list (all_settings, NM_SETTING_CDMA_SETTING_NAME);
 
 		if (!gsm && !cdma) {
 			g_set_error (error,
 			             NM_SETTING_BLUETOOTH_ERROR,
 			             NM_SETTING_BLUETOOTH_ERROR_TYPE_SETTING_NOT_FOUND,
-			             NM_SETTING_BLUETOOTH_TYPE);
+			             _("requires '%s' or '%s' setting"),
+			             NM_SETTING_GSM_SETTING_NAME, NM_SETTING_CDMA_SETTING_NAME);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_BLUETOOTH_SETTING_NAME, NM_SETTING_BLUETOOTH_TYPE);
 			return FALSE;
 		}
 	}
@@ -206,7 +201,6 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 static void
 nm_setting_bluetooth_init (NMSettingBluetooth *setting)
 {
-	g_object_set (setting, NM_SETTING_NAME, NM_SETTING_BLUETOOTH_SETTING_NAME, NULL);
 }
 
 static void
@@ -289,12 +283,12 @@ nm_setting_bluetooth_class_init (NMSettingBluetoothClass *setting_class)
 		                             "Bluetooth address",
 		                             "The Bluetooth address of the device",
 		                             DBUS_TYPE_G_UCHAR_ARRAY,
-		                             G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+		                             G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE));
 
 	/**
 	 * NMSettingBluetooth:type:
 	 *
-	 * Either 'dun' for Dial-Up Networking connections or 'panu' for Personal
+	 * Either "dun" for Dial-Up Networking connections or "panu" for Personal
 	 * Area Networking connections to devices supporting the NAP profile.
 	 **/
 	g_object_class_install_property
@@ -306,5 +300,5 @@ nm_setting_bluetooth_class_init (NMSettingBluetoothClass *setting_class)
 						  "'" NM_SETTING_BLUETOOTH_TYPE_PANU "' for "
 						  "Personal Area Networking connections.",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+						  G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE));
 }
diff --git a/libnm-util/nm-setting-bond.c b/libnm-util/nm-setting-bond.c
index e8e7b639..5f919027 100644
--- a/libnm-util/nm-setting-bond.c
+++ b/libnm-util/nm-setting-bond.c
@@ -18,12 +18,16 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2011 - 2012 Red Hat, Inc.
+ * (C) Copyright 2011 - 2013 Red Hat, Inc.
  */
 
 #include <string.h>
 #include <stdlib.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
 #include <dbus/dbus-glib.h>
+#include <glib/gi18n.h>
 
 #include "nm-setting-bond.h"
 #include "nm-param-spec-specialized.h"
@@ -80,18 +84,44 @@ enum {
 	LAST_PROP
 };
 
+enum {
+	TYPE_INT,
+	TYPE_STR,
+	TYPE_BOTH,
+	TYPE_IP,
+	TYPE_IFNAME,
+};
+
 typedef struct {
 	const char *opt;
 	const char *val;
+	guint opt_type;
+	guint min;
+	guint max;
+	char *list[10];
 } BondDefault;
 
 static const BondDefault defaults[] = {
-	{ NM_SETTING_BOND_OPTION_MODE,          "balance-rr" },
-	{ NM_SETTING_BOND_OPTION_MIIMON,        "100"        },
-	{ NM_SETTING_BOND_OPTION_DOWNDELAY,     "0"          },
-	{ NM_SETTING_BOND_OPTION_UPDELAY,       "0"          },
-	{ NM_SETTING_BOND_OPTION_ARP_INTERVAL,  "0"          },
-	{ NM_SETTING_BOND_OPTION_ARP_IP_TARGET, ""           },
+	{ NM_SETTING_BOND_OPTION_MODE,             "balance-rr", TYPE_BOTH, 0, 6,
+	  { "balance-rr", "active-backup", "balance-xor", "broadcast", "802.3ad", "balance-tlb", "balance-alb", NULL } },
+	{ NM_SETTING_BOND_OPTION_MIIMON,           "100",        TYPE_INT, 0, G_MAXINT },
+	{ NM_SETTING_BOND_OPTION_DOWNDELAY,        "0",          TYPE_INT, 0, G_MAXINT },
+	{ NM_SETTING_BOND_OPTION_UPDELAY,          "0",          TYPE_INT, 0, G_MAXINT },
+	{ NM_SETTING_BOND_OPTION_ARP_INTERVAL,     "0",          TYPE_INT, 0, G_MAXINT },
+	{ NM_SETTING_BOND_OPTION_ARP_IP_TARGET,    "",           TYPE_IP },
+	{ NM_SETTING_BOND_OPTION_ARP_VALIDATE,     "0",          TYPE_BOTH, 0, 3,
+	  { "none", "active", "backup", "all", NULL } },
+	{ NM_SETTING_BOND_OPTION_PRIMARY,          "",           TYPE_IFNAME },
+	{ NM_SETTING_BOND_OPTION_PRIMARY_RESELECT, "0",          TYPE_BOTH, 0, 2,
+	  { "always", "better", "failure", NULL } },
+	{ NM_SETTING_BOND_OPTION_FAIL_OVER_MAC,    "0",          TYPE_BOTH, 0, 2,
+	  { "none", "active", "follow", NULL } },
+	{ NM_SETTING_BOND_OPTION_USE_CARRIER,      "1",          TYPE_INT, 0, 1 },
+	{ NM_SETTING_BOND_OPTION_AD_SELECT,        "0",          TYPE_BOTH, 0, 2,
+	  { "stable", "bandwidth", "count", NULL } },
+	{ NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY, "0",          TYPE_BOTH, 0, 2,
+	  { "layer2", "layer3+4", "layer2+3", NULL } },
+	{ NM_SETTING_BOND_OPTION_RESEND_IGMP,      "1",          TYPE_INT, 0, 255 },
 };
 
 /**
@@ -190,17 +220,109 @@ nm_setting_bond_get_option (NMSettingBond *setting,
 }
 
 static gboolean
-validate_option (const char *name)
+validate_int (const char *name, const char *value, const BondDefault *def)
 {
+	glong num;
 	guint i;
 
-	g_return_val_if_fail (name != NULL, FALSE);
-	g_return_val_if_fail (name[0] != '\0', FALSE);
+	for (i = 0; i < strlen (value); i++) {
+		if (!g_ascii_isdigit (value[i]) && value[i] != '-')
+			return FALSE;
+	}
 
-	for (i = 0; i < G_N_ELEMENTS (defaults); i++) {
-		if (g_strcmp0 (defaults[i].opt, name) == 0)
+	errno = 0;
+	num = strtol (value, NULL, 10);
+	if (errno)
+		return FALSE;
+	if (num < def->min || num > def->max)
+		return FALSE;
+
+	return TRUE;
+}
+
+static gboolean
+validate_list (const char *name, const char *value, const BondDefault *def)
+{
+	guint i;
+
+	for (i = 0; i < G_N_ELEMENTS (def->list) && def->list[i]; i++) {
+		if (g_strcmp0 (def->list[i], value) == 0)
 			return TRUE;
 	}
+
+	/* empty validation list means all values pass */
+	return def->list[0] == NULL ? TRUE : FALSE;
+}
+
+static gboolean
+validate_ip (const char *name, const char *value)
+{
+	char **ips, **iter;
+	gboolean success = TRUE;
+	struct in_addr addr;
+
+	if (!value || !value[0])
+		return FALSE;
+
+	ips = g_strsplit_set (value, ",", 0);
+	for (iter = ips; iter && *iter && success; iter++)
+		success = !!inet_aton (*iter, &addr);
+	g_strfreev (ips);
+
+	return success;
+}
+
+static gboolean
+validate_ifname (const char *name, const char *value)
+{
+	if (!value || !value[0])
+		return FALSE;
+
+	return nm_utils_iface_valid_name (value);
+}
+
+/**
+ * nm_setting_bond_validate_option:
+ * @name: the name of the option to validate
+ * @value: the value of the option to validate
+ *
+ * Checks whether @name is a valid bond option and @value is a valid value for
+ * the @name. If @value is %NULL, the function only validates the option name.
+ *
+ * Returns: %TRUE, if the @value is valid for the given name.
+ * If the @name is not a valid option, %FALSE will be returned.
+ *
+ * Since: 0.9.10
+ **/
+gboolean
+nm_setting_bond_validate_option (const char *name,
+                                 const char *value)
+{
+	guint i;
+
+	if (!name || !name[0])
+		return FALSE;
+
+	for (i = 0; i < G_N_ELEMENTS (defaults); i++) {
+		if (g_strcmp0 (defaults[i].opt, name) == 0) {
+			if (value == NULL)
+				return TRUE;
+			switch (defaults[i].opt_type) {
+			case TYPE_INT:
+				return validate_int (name, value, &defaults[i]);
+			case TYPE_STR:
+				return validate_list (name, value, &defaults[i]);
+			case TYPE_BOTH:
+				return    validate_int (name, value, &defaults[i])
+				       || validate_list (name, value, &defaults[i]);
+			case TYPE_IP:
+				return validate_ip (name, value);
+			case TYPE_IFNAME:
+				return validate_ifname (name, value);
+			}
+			return FALSE;
+		}
+	}
 	return FALSE;
 }
 
@@ -220,7 +342,9 @@ nm_setting_bond_get_option_by_name (NMSettingBond *setting,
                                     const char *name)
 {
 	g_return_val_if_fail (NM_IS_SETTING_BOND (setting), NULL);
-	g_return_val_if_fail (validate_option (name), NULL);
+
+	if (!nm_setting_bond_validate_option (name, NULL))
+		return NULL;
 
 	return g_hash_table_lookup (NM_SETTING_BOND_GET_PRIVATE (setting)->options, name);
 }
@@ -236,24 +360,25 @@ nm_setting_bond_get_option_by_name (NMSettingBond *setting,
  * (ie [a-zA-Z0-9]).  Adding a new name replaces any existing name/value pair
  * that may already exist.
  *
+ * The order of how to set several options is relevant because there are options
+ * that conflict with each other.
+ *
  * Returns: %TRUE if the option was valid and was added to the internal option
  * list, %FALSE if it was not.
  **/
-gboolean nm_setting_bond_add_option (NMSettingBond *setting,
-                                     const char *name,
-                                     const char *value)
+gboolean
+nm_setting_bond_add_option (NMSettingBond *setting,
+                            const char *name,
+                            const char *value)
 {
 	NMSettingBondPrivate *priv;
-	size_t value_len;
 
 	g_return_val_if_fail (NM_IS_SETTING_BOND (setting), FALSE);
-	g_return_val_if_fail (validate_option (name), FALSE);
-	g_return_val_if_fail (value != NULL, FALSE);
 
-	priv = NM_SETTING_BOND_GET_PRIVATE (setting);
+	if (!value || !nm_setting_bond_validate_option (name, value))
+		return FALSE;
 
-	value_len = strlen (value);
-	g_return_val_if_fail (value_len > 0 && value_len < 200, FALSE);
+	priv = NM_SETTING_BOND_GET_PRIVATE (setting);
 
 	g_hash_table_insert (priv->options, g_strdup (name), g_strdup (value));
 
@@ -268,6 +393,8 @@ gboolean nm_setting_bond_add_option (NMSettingBond *setting,
 		g_hash_table_remove (priv->options, NM_SETTING_BOND_OPTION_UPDELAY);
 	}
 
+	g_object_notify (G_OBJECT (setting), NM_SETTING_BOND_OPTIONS);
+
 	return TRUE;
 }
 
@@ -286,10 +413,17 @@ gboolean
 nm_setting_bond_remove_option (NMSettingBond *setting,
                                const char *name)
 {
+	gboolean found;
+
 	g_return_val_if_fail (NM_IS_SETTING_BOND (setting), FALSE);
-	g_return_val_if_fail (validate_option (name), FALSE);
 
-	return g_hash_table_remove (NM_SETTING_BOND_GET_PRIVATE (setting)->options, name);
+	if (!nm_setting_bond_validate_option (name, NULL))
+		return FALSE;
+
+	found = g_hash_table_remove (NM_SETTING_BOND_GET_PRIVATE (setting)->options, name);
+	if (found)
+		g_object_notify (G_OBJECT (setting), NM_SETTING_BOND_OPTIONS);
+	return found;
 }
 
 /**
@@ -329,25 +463,16 @@ nm_setting_bond_get_option_default (NMSettingBond *setting, const char *name)
 	guint i;
 
 	g_return_val_if_fail (NM_IS_SETTING_BOND (setting), NULL);
-	g_return_val_if_fail (validate_option (name), NULL);
+	g_return_val_if_fail (nm_setting_bond_validate_option (name, NULL), NULL);
 
 	for (i = 0; i < G_N_ELEMENTS (defaults); i++) {
 		if (g_strcmp0 (defaults[i].opt, name) == 0)
 			return defaults[i].val;
 	}
-	/* Any option that passes validate_option() should also be found in defaults */
+	/* Any option that passes nm_setting_bond_validate_option() should also be found in defaults */
 	g_assert_not_reached ();
 }
 
-static gint
-find_setting_by_name (gconstpointer a, gconstpointer b)
-{
-	NMSetting *setting = NM_SETTING (a);
-	const char *str = (const char *) b;
-
-	return strcmp (nm_setting_get_name (setting), str);
-}
-
 static gboolean
 verify (NMSetting *setting, GSList *all_settings, GError **error)
 {
@@ -364,33 +489,35 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 	                              NULL };
 	int miimon = 0, arp_interval = 0;
 	const char *arp_ip_target = NULL;
+	const char *primary;
 
 	if (!priv->interface_name || !strlen(priv->interface_name)) {
-		g_set_error (error,
-		             NM_SETTING_BOND_ERROR,
-		             NM_SETTING_BOND_ERROR_MISSING_PROPERTY,
-		             NM_SETTING_BOND_INTERFACE_NAME);
+		g_set_error_literal (error,
+		                     NM_SETTING_BOND_ERROR,
+		                     NM_SETTING_BOND_ERROR_MISSING_PROPERTY,
+		                     _("property is missing"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_INTERFACE_NAME);
 		return FALSE;
 	}
 
 	if (!nm_utils_iface_valid_name (priv->interface_name)) {
-		g_set_error (error,
-		             NM_SETTING_BOND_ERROR,
-		             NM_SETTING_BOND_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_BOND_INTERFACE_NAME);
+		g_set_error_literal (error,
+		                     NM_SETTING_BOND_ERROR,
+		                     NM_SETTING_BOND_ERROR_INVALID_PROPERTY,
+		                     _("property is invalid"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_INTERFACE_NAME);
 		return FALSE;
 	}
 
 	g_hash_table_iter_init (&iter, priv->options);
 	while (g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &value)) {
-		if (   !validate_option (key)
-		    || !value[0]
-		    || (strlen (value) > 200)
-		    || strchr (value, ' ')) {
-			g_set_error_literal (error,
-			                     NM_SETTING_BOND_ERROR,
-			                     NM_SETTING_BOND_ERROR_INVALID_OPTION,
-			                     key);
+		if (!value[0] || !nm_setting_bond_validate_option (key, value)) {
+			g_set_error (error,
+			             NM_SETTING_BOND_ERROR,
+			             NM_SETTING_BOND_ERROR_INVALID_OPTION,
+			             _("invalid option '%s' or its value '%s'"),
+			             key, value);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
 			return FALSE;
 		}
 	}
@@ -407,7 +534,10 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 		g_set_error (error,
 		             NM_SETTING_BOND_ERROR,
 		             NM_SETTING_BOND_ERROR_INVALID_OPTION,
+		             _("only one of '%s' and '%s' can be set"),
+		             NM_SETTING_BOND_OPTION_MIIMON,
 		             NM_SETTING_BOND_OPTION_ARP_INTERVAL);
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
 	}
 
 	value = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_MODE);
@@ -415,14 +545,18 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 		g_set_error (error,
 		             NM_SETTING_BOND_ERROR,
 		             NM_SETTING_BOND_ERROR_MISSING_OPTION,
+		             _("mandatory option '%s' is missing"),
 		             NM_SETTING_BOND_OPTION_MODE);
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
 		return FALSE;
 	}
 	if (!_nm_utils_string_in_list (value, valid_modes)) {
 		g_set_error (error,
 		             NM_SETTING_BOND_ERROR,
 		             NM_SETTING_BOND_ERROR_INVALID_OPTION,
-		             NM_SETTING_BOND_OPTION_MODE);
+		             _("'%s' is not a valid value for '%s'"),
+		             value, NM_SETTING_BOND_OPTION_MODE);
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
 		return FALSE;
 	}
 
@@ -433,15 +567,45 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 			g_set_error (error,
 			             NM_SETTING_BOND_ERROR,
 			             NM_SETTING_BOND_ERROR_INVALID_OPTION,
-			             NM_SETTING_BOND_OPTION_ARP_INTERVAL);
+			             _("'%s=%s' is incompatible with '%s > 0'"),
+			             NM_SETTING_BOND_OPTION_MODE, value, NM_SETTING_BOND_OPTION_ARP_INTERVAL);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
+			return FALSE;
 		}
 	}
-	if (g_slist_find_custom (all_settings, NM_SETTING_INFINIBAND_SETTING_NAME, find_setting_by_name)) {
+
+	primary = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_PRIMARY);
+	if (strcmp (value, "active-backup") == 0) {
+		if (primary && !nm_utils_iface_valid_name (primary)) {
+			g_set_error (error,
+			             NM_SETTING_BOND_ERROR,
+			             NM_SETTING_BOND_ERROR_INVALID_OPTION,
+			             _("'%s' is not a valid interface name for '%s' option"),
+			             primary, NM_SETTING_BOND_OPTION_PRIMARY);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
+			return FALSE;
+		}
+	} else {
+		if (primary) {
+			g_set_error (error,
+			             NM_SETTING_BOND_ERROR,
+			             NM_SETTING_BOND_ERROR_INVALID_OPTION,
+			             _("'%s' option is only valid for '%s=%s'"),
+			             NM_SETTING_BOND_OPTION_PRIMARY,
+			             NM_SETTING_BOND_OPTION_MODE, "active-backup");
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
+			return FALSE;
+		}
+	}
+
+	if (nm_setting_find_in_list (all_settings, NM_SETTING_INFINIBAND_SETTING_NAME)) {
 		if (strcmp (value, "active-backup") != 0) {
 			g_set_error (error,
 			             NM_SETTING_BOND_ERROR,
 			             NM_SETTING_BOND_ERROR_INVALID_OPTION,
-			             NM_SETTING_BOND_OPTION_MODE);
+			             _("'%s=%s' is not a valid configuration for '%s'"),
+			             NM_SETTING_BOND_OPTION_MODE, value, NM_SETTING_INFINIBAND_SETTING_NAME);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
 			return FALSE;
 		}
 	}
@@ -452,14 +616,18 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 			g_set_error (error,
 			             NM_SETTING_BOND_ERROR,
 			             NM_SETTING_BOND_ERROR_INVALID_OPTION,
-			             NM_SETTING_BOND_OPTION_UPDELAY);
+			             _("'%s' option requires '%s' option to be set"),
+			             NM_SETTING_BOND_OPTION_UPDELAY, NM_SETTING_BOND_OPTION_MIIMON);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
 			return FALSE;
 		}
 		if (g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_DOWNDELAY)) {
 			g_set_error (error,
 			             NM_SETTING_BOND_ERROR,
 			             NM_SETTING_BOND_ERROR_INVALID_OPTION,
-			             NM_SETTING_BOND_OPTION_DOWNDELAY);
+			             _("'%s' option requires '%s' option to be set"),
+			             NM_SETTING_BOND_OPTION_DOWNDELAY, NM_SETTING_BOND_OPTION_MIIMON);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
 			return FALSE;
 		}
 	}
@@ -477,27 +645,33 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 			g_set_error (error,
 			             NM_SETTING_BOND_ERROR,
 			             NM_SETTING_BOND_ERROR_MISSING_OPTION,
-			             NM_SETTING_BOND_OPTION_ARP_IP_TARGET);
+			             _("'%s' option requires '%s' option to be set"),
+			             NM_SETTING_BOND_OPTION_ARP_INTERVAL, NM_SETTING_BOND_OPTION_ARP_IP_TARGET);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
 			return FALSE;
 		}
 
 		addrs = g_strsplit (arp_ip_target, ",", -1);
 		if (!addrs[0]) {
-			g_strfreev (addrs);
 			g_set_error (error,
 			             NM_SETTING_BOND_ERROR,
 			             NM_SETTING_BOND_ERROR_INVALID_OPTION,
+			             _("'%s' option is empty"),
 			             NM_SETTING_BOND_OPTION_ARP_IP_TARGET);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
+			g_strfreev (addrs);
 			return FALSE;
 		}
 
 		for (i = 0; addrs[i]; i++) {
 			if (!inet_pton (AF_INET, addrs[i], &addr)) {
-				g_strfreev (addrs);
 				g_set_error (error,
 				             NM_SETTING_BOND_ERROR,
 				             NM_SETTING_BOND_ERROR_INVALID_OPTION,
-				             NM_SETTING_BOND_OPTION_ARP_IP_TARGET);
+				             _("'%s' is not a valid IPv4 address for '%s' option"),
+				             NM_SETTING_BOND_OPTION_ARP_IP_TARGET, addrs[i]);
+				g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
+				g_strfreev (addrs);
 				return FALSE;
 			}
 		}
@@ -507,7 +681,9 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 			g_set_error (error,
 			             NM_SETTING_BOND_ERROR,
 			             NM_SETTING_BOND_ERROR_INVALID_OPTION,
-			             NM_SETTING_BOND_OPTION_ARP_IP_TARGET);
+			             _("'%s' option requires '%s' option to be set"),
+			             NM_SETTING_BOND_OPTION_ARP_IP_TARGET, NM_SETTING_BOND_OPTION_ARP_INTERVAL);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
 			return FALSE;
 		}
 	}
@@ -528,14 +704,10 @@ nm_setting_bond_init (NMSettingBond *setting)
 {
 	NMSettingBondPrivate *priv = NM_SETTING_BOND_GET_PRIVATE (setting);
 
-	g_object_set (setting, NM_SETTING_NAME, NM_SETTING_BOND_SETTING_NAME,
-	              NULL);
-
 	priv->options = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
 
 	/* Default values: */
 	nm_setting_bond_add_option (setting, NM_SETTING_BOND_OPTION_MODE, "balance-rr");
-	nm_setting_bond_add_option (setting, NM_SETTING_BOND_OPTION_MIIMON, "100");
 }
 
 static void
@@ -564,6 +736,7 @@ set_property (GObject *object, guint prop_id,
 
 	switch (prop_id) {
 	case PROP_INTERFACE_NAME:
+		g_free (priv->interface_name);
 		priv->interface_name = g_value_dup_string (value);
 		break;
 	case PROP_OPTIONS:
@@ -626,14 +799,14 @@ nm_setting_bond_class_init (NMSettingBondClass *setting_class)
 		                      "InterfaceName",
 		                      "The name of the virtual in-kernel bonding network interface",
 		                      NULL,
-		                      G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+		                      G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE));
 
 	/**
 	 * NMSettingBond:options:
 	 *
-	 * Dictionary of key/value pairs of bonding options.  Both keys
-	 * and values must be strings. Option names must contain only
-	 * alphanumeric characters (ie, [a-zA-Z0-9]).
+	 * Dictionary of key/value pairs of bonding options.  Both keys and values
+	 * must be strings. Option names must contain only alphanumeric characters
+	 * (ie, [a-zA-Z0-9]).
 	 **/
 	 g_object_class_install_property
 		 (object_class, PROP_OPTIONS,
@@ -644,5 +817,5 @@ nm_setting_bond_class_init (NMSettingBondClass *setting_class)
 		                             "strings.  Option names must contain only "
 		                             "alphanumeric characters (ie, [a-zA-Z0-9]).",
 		                             DBUS_TYPE_G_MAP_OF_STRING,
-		                             G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+		                             G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE));
 }
diff --git a/libnm-util/nm-setting-bond.h b/libnm-util/nm-setting-bond.h
index f326a95b..f3358c7f 100644
--- a/libnm-util/nm-setting-bond.h
+++ b/libnm-util/nm-setting-bond.h
@@ -18,7 +18,7 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2011 - 2012 Red Hat, Inc.
+ * (C) Copyright 2011 - 2013 Red Hat, Inc.
  */
 
 #ifndef NM_SETTING_BOND_H
@@ -59,12 +59,20 @@ GQuark nm_setting_bond_error_quark (void);
 #define NM_SETTING_BOND_OPTIONS "options"
 
 /* Valid options for the 'options' property */
-#define NM_SETTING_BOND_OPTION_MODE          "mode"
-#define NM_SETTING_BOND_OPTION_MIIMON        "miimon"
-#define NM_SETTING_BOND_OPTION_DOWNDELAY     "downdelay"
-#define NM_SETTING_BOND_OPTION_UPDELAY       "updelay"
-#define NM_SETTING_BOND_OPTION_ARP_INTERVAL  "arp_interval"
-#define NM_SETTING_BOND_OPTION_ARP_IP_TARGET "arp_ip_target"
+#define NM_SETTING_BOND_OPTION_MODE             "mode"
+#define NM_SETTING_BOND_OPTION_MIIMON           "miimon"
+#define NM_SETTING_BOND_OPTION_DOWNDELAY        "downdelay"
+#define NM_SETTING_BOND_OPTION_UPDELAY          "updelay"
+#define NM_SETTING_BOND_OPTION_ARP_INTERVAL     "arp_interval"
+#define NM_SETTING_BOND_OPTION_ARP_IP_TARGET    "arp_ip_target"
+#define NM_SETTING_BOND_OPTION_ARP_VALIDATE     "arp_validate"
+#define NM_SETTING_BOND_OPTION_PRIMARY          "primary"
+#define NM_SETTING_BOND_OPTION_PRIMARY_RESELECT "primary_reselect"
+#define NM_SETTING_BOND_OPTION_FAIL_OVER_MAC    "fail_over_mac"
+#define NM_SETTING_BOND_OPTION_USE_CARRIER      "use_carrier"
+#define NM_SETTING_BOND_OPTION_AD_SELECT        "ad_select"
+#define NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY "xmit_hash_policy"
+#define NM_SETTING_BOND_OPTION_RESEND_IGMP      "resend_igmp"
 
 typedef struct {
 	NMSetting parent;
@@ -97,6 +105,10 @@ gboolean     nm_setting_bond_add_option         (NMSettingBond *setting,
 gboolean     nm_setting_bond_remove_option      (NMSettingBond *setting,
                                                  const char *name);
 
+NM_AVAILABLE_IN_0_9_10
+gboolean     nm_setting_bond_validate_option    (const char *name,
+                                                 const char *value);
+
 const char **nm_setting_bond_get_valid_options  (NMSettingBond *setting);
 
 const char * nm_setting_bond_get_option_default (NMSettingBond *setting,
diff --git a/libnm-util/nm-setting-bridge-port.c b/libnm-util/nm-setting-bridge-port.c
index c1abf9c8..64be5662 100644
--- a/libnm-util/nm-setting-bridge-port.c
+++ b/libnm-util/nm-setting-bridge-port.c
@@ -18,13 +18,14 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2012 Red Hat, Inc.
+ * (C) Copyright 2012 - 2013 Red Hat, Inc.
  */
 
 #include <string.h>
 #include <ctype.h>
 #include <stdlib.h>
 #include <dbus/dbus-glib.h>
+#include <glib/gi18n.h>
 
 #include "nm-setting-bridge-port.h"
 #include "nm-utils.h"
@@ -151,7 +152,11 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 		g_set_error (error,
 		             NM_SETTING_BRIDGE_PORT_ERROR,
 		             NM_SETTING_BRIDGE_PORT_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_BRIDGE_PORT_PRIORITY);
+		             _("'%d' is not a valid value for the property (should be <= %d)"),
+		             priv->priority, BR_MAX_PORT_PRIORITY);
+		g_prefix_error (error, "%s.%s: ",
+		                NM_SETTING_BRIDGE_PORT_SETTING_NAME,
+		                NM_SETTING_BRIDGE_PORT_PRIORITY);
 		return FALSE;
 	}
 
@@ -159,7 +164,11 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 		g_set_error (error,
 		             NM_SETTING_BRIDGE_PORT_ERROR,
 		             NM_SETTING_BRIDGE_PORT_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_BRIDGE_PORT_PATH_COST);
+		             _("'%d' is not a valid value for the property (should be <= %d)"),
+		             priv->path_cost, BR_MAX_PATH_COST);
+		g_prefix_error (error, "%s.%s: ",
+		                NM_SETTING_BRIDGE_PORT_SETTING_NAME,
+		                NM_SETTING_BRIDGE_PORT_PATH_COST);
 		return FALSE;
 	}
 
@@ -186,7 +195,6 @@ nm_setting_bridge_port_new (void)
 static void
 nm_setting_bridge_port_init (NMSettingBridgePort *setting)
 {
-	g_object_set (setting, NM_SETTING_NAME, NM_SETTING_BRIDGE_PORT_SETTING_NAME, NULL);
 }
 
 static void
@@ -260,12 +268,13 @@ nm_setting_bridge_port_class_init (NMSettingBridgePortClass *setting_class)
 		                    "Priority",
 		                    "The Spanning Tree Protocol (STP) priority of this bridge port",
 		                    0, BR_MAX_PORT_PRIORITY, BR_DEF_PRIORITY,
-		                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+		                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE));
 
 	/**
 	 * NMSettingBridgePort:path-cost:
 	 *
-	 * The Spanning Tree Protocol (STP) port cost for destinations via this port.
+	 * The Spanning Tree Protocol (STP) port cost for destinations via this
+	 * port.
 	 *
 	 * Since: 0.9.8
 	 **/
@@ -276,12 +285,12 @@ nm_setting_bridge_port_class_init (NMSettingBridgePortClass *setting_class)
 		                    "The Spanning Tree Protocol (STP) port cost for "
 		                    "destinations via this port.",
 		                    0, BR_MAX_PATH_COST, 100,
-		                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+		                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE));
 
 	/**
 	 * NMSettingBridgePort:hairpin-mode:
 	 *
-	 * Enables or disabled 'hairpin mode' for the port, which allows frames to
+	 * Enables or disabled "hairpin mode" for the port, which allows frames to
 	 * be sent back out through the port the frame was received on.
 	 *
 	 * Since: 0.9.8
@@ -294,6 +303,5 @@ nm_setting_bridge_port_class_init (NMSettingBridgePortClass *setting_class)
 		                       "port, which allows frames to be sent back out "
 		                       "through the port the frame was received on.",
 		                       FALSE,
-		                       G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
-
+		                       G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE));
 }
diff --git a/libnm-util/nm-setting-bridge.c b/libnm-util/nm-setting-bridge.c
index a763206b..0908573d 100644
--- a/libnm-util/nm-setting-bridge.c
+++ b/libnm-util/nm-setting-bridge.c
@@ -18,13 +18,15 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2011 - 2012 Red Hat, Inc.
+ * (C) Copyright 2011 - 2013 Red Hat, Inc.
  */
 
 #include <string.h>
 #include <ctype.h>
 #include <stdlib.h>
 #include <dbus/dbus-glib.h>
+#include <glib/gi18n.h>
+#include <linux/if_ether.h>
 
 #include "nm-setting-bridge.h"
 #include "nm-param-spec-specialized.h"
@@ -75,6 +77,7 @@ NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_BRIDGE)
 
 typedef struct {
 	char *   interface_name;
+	GByteArray *mac_address;
 	gboolean stp;
 	guint16  priority;
 	guint16  forward_delay;
@@ -86,6 +89,7 @@ typedef struct {
 enum {
 	PROP_0,
 	PROP_INTERFACE_NAME,
+	PROP_MAC_ADDRESS,
 	PROP_STP,
 	PROP_PRIORITY,
 	PROP_FORWARD_DELAY,
@@ -127,6 +131,22 @@ nm_setting_bridge_get_interface_name (NMSettingBridge *setting)
 }
 
 /**
+ * nm_setting_bridge_get_mac_address:
+ * @setting: the #NMSettingBridge
+ *
+ * Returns: the #NMSettingBridge:mac-address property of the setting
+ *
+ * Since: 0.9.10
+ **/
+const GByteArray *
+nm_setting_bridge_get_mac_address (NMSettingBridge *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_BRIDGE (setting), NULL);
+
+	return NM_SETTING_BRIDGE_GET_PRIVATE (setting)->mac_address;
+}
+
+/**
  * nm_setting_bridge_get_stp:
  * @setting: the #NMSettingBridge
  *
@@ -244,10 +264,12 @@ check_range (guint32 val,
              GError **error)
 {
 	if ((val != 0) && (val < min || val > max)) {
-		g_set_error_literal (error,
-		                     NM_SETTING_BRIDGE_ERROR,
-		                     NM_SETTING_BRIDGE_ERROR_INVALID_PROPERTY,
-		                     prop);
+		g_set_error (error,
+		             NM_SETTING_BRIDGE_ERROR,
+		             NM_SETTING_BRIDGE_ERROR_INVALID_PROPERTY,
+		             _("value '%d' is out of range <%d-%d>"),
+		             val, min, max);
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_BRIDGE_SETTING_NAME, prop);
 		return FALSE;
 	}
 	return TRUE;
@@ -259,10 +281,11 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 	NMSettingBridgePrivate *priv = NM_SETTING_BRIDGE_GET_PRIVATE (setting);
 
 	if (!priv->interface_name || !strlen(priv->interface_name)) {
-		g_set_error (error,
-		             NM_SETTING_BRIDGE_ERROR,
-		             NM_SETTING_BRIDGE_ERROR_MISSING_PROPERTY,
-		             NM_SETTING_BRIDGE_INTERFACE_NAME);
+		g_set_error_literal (error,
+		                     NM_SETTING_BRIDGE_ERROR,
+		                     NM_SETTING_BRIDGE_ERROR_MISSING_PROPERTY,
+		                     _("property is missing"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_BRIDGE_SETTING_NAME, NM_SETTING_BRIDGE_INTERFACE_NAME);
 		return FALSE;
 	}
 
@@ -270,7 +293,18 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 		g_set_error (error,
 		             NM_SETTING_BRIDGE_ERROR,
 		             NM_SETTING_BRIDGE_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_BRIDGE_INTERFACE_NAME);
+		             _("'%s' is not a valid interface name"),
+		             priv->interface_name);
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_BRIDGE_SETTING_NAME, NM_SETTING_BRIDGE_INTERFACE_NAME);
+		return FALSE;
+	}
+
+	if (priv->mac_address && priv->mac_address->len != ETH_ALEN) {
+		g_set_error_literal (error,
+		                     NM_SETTING_BRIDGE_ERROR,
+		                     NM_SETTING_BRIDGE_ERROR_INVALID_PROPERTY,
+		                     _("is not a valid MAC address"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_BRIDGE_SETTING_NAME, NM_SETTING_BRIDGE_MAC_ADDRESS);
 		return FALSE;
 	}
 
@@ -316,7 +350,6 @@ get_virtual_iface_name (NMSetting *setting)
 static void
 nm_setting_bridge_init (NMSettingBridge *setting)
 {
-	g_object_set (setting, NM_SETTING_NAME, NM_SETTING_BRIDGE_SETTING_NAME, NULL);
 }
 
 static void
@@ -326,6 +359,9 @@ finalize (GObject *object)
 
 	g_free (priv->interface_name);
 
+	if (priv->mac_address)
+		g_byte_array_free (priv->mac_address, TRUE);
+
 	G_OBJECT_CLASS (nm_setting_bridge_parent_class)->finalize (object);
 }
 
@@ -340,6 +376,11 @@ set_property (GObject *object, guint prop_id,
 		g_free (priv->interface_name);
 		priv->interface_name = g_value_dup_string (value);
 		break;
+	case PROP_MAC_ADDRESS:
+		if (priv->mac_address)
+			g_byte_array_free (priv->mac_address, TRUE);
+		priv->mac_address = g_value_dup_boxed (value);
+		break;
 	case PROP_STP:
 		priv->stp = g_value_get_boolean (value);
 		break;
@@ -375,6 +416,9 @@ get_property (GObject *object, guint prop_id,
 	case PROP_INTERFACE_NAME:
 		g_value_set_string (value, nm_setting_bridge_get_interface_name (setting));
 		break;
+	case PROP_MAC_ADDRESS:
+		g_value_set_boxed (value, nm_setting_bridge_get_mac_address (setting));
+		break;
 	case PROP_STP:
 		g_value_set_boolean (value, priv->stp);
 		break;
@@ -418,7 +462,7 @@ nm_setting_bridge_class_init (NMSettingBridgeClass *setting_class)
 	/**
 	 * NMSettingBridge:interface-name:
 	 *
-	 * The name of the virtual in-kernel briding network interface
+	 * The name of the virtual in-kernel bridging network interface
 	 *
 	 * Since: 0.9.8
 	 **/
@@ -428,7 +472,24 @@ nm_setting_bridge_class_init (NMSettingBridgeClass *setting_class)
 		                      "InterfaceName",
 		                      "The name of the virtual in-kernel bridging network interface",
 		                      NULL,
-		                      G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+		                      G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE));
+
+	/**
+	 * NMSettingBridge:mac-address:
+	 *
+	 * If specified, the MAC address of bridge. When creating a new bridge, this
+	 * MAC address will be set. When matching an existing (outside
+	 * NetworkManager created) bridge, this MAC address must match.
+	 *
+	 * Since: 0.9.10
+	 **/
+	g_object_class_install_property
+	    (object_class, PROP_MAC_ADDRESS,
+	     _nm_param_spec_specialized (NM_SETTING_BRIDGE_MAC_ADDRESS,
+	                          "MAC Address",
+	                          "The MAC address of the bridge",
+	                          DBUS_TYPE_G_UCHAR_ARRAY,
+	                          G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE));
 
 	/**
 	 * NMSettingBridge:stp:
@@ -444,7 +505,7 @@ nm_setting_bridge_class_init (NMSettingBridgeClass *setting_class)
 		                        "Controls whether Spanning Tree Protocol (STP) "
 		                        "is enabled for this bridge.",
 		                        TRUE,
-		                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+		                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE));
 
 	/**
 	 * NMSettingBridge:priority:
@@ -464,7 +525,7 @@ nm_setting_bridge_class_init (NMSettingBridgeClass *setting_class)
 		                     "lowest priority bridge will be elected the root "
 		                     "bridge.",
 		                     0, G_MAXUINT16, 0x8000,
-		                     G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+		                     G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE));
 
 	/**
 	 * NMSettingBridge:forward-delay:
@@ -480,7 +541,7 @@ nm_setting_bridge_class_init (NMSettingBridgeClass *setting_class)
 		                     "The Spanning Tree Protocol (STP) forwarding "
 		                     "delay, in seconds.",
 		                     0, BR_MAX_FORWARD_DELAY, 15,
-		                     G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+		                     G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE));
 
 	/**
 	 * NMSettingBridge:hello-time:
@@ -496,7 +557,7 @@ nm_setting_bridge_class_init (NMSettingBridgeClass *setting_class)
 		                     "The Spanning Tree Protocol (STP) hello time, in "
 		                     "seconds.",
 		                     0, BR_MAX_HELLO_TIME, 2,
-		                     G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+		                     G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE));
 
 	/**
 	 * NMSettingBridge:max-age:
@@ -512,12 +573,12 @@ nm_setting_bridge_class_init (NMSettingBridgeClass *setting_class)
 		                     "The Spanning Tree Protocol (STP) maximum message "
 		                     "age, in seconds.",
 		                     0, BR_MAX_MAX_AGE, 20,
-		                     G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+		                     G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE));
 
 	/**
 	 * NMSettingBridge:ageing-time:
 	 *
-	 * The ethernet MAC address aging time, in seconds.
+	 * The Ethernet MAC address aging time, in seconds.
 	 *
 	 * Since: 0.9.8
 	 **/
@@ -525,8 +586,8 @@ nm_setting_bridge_class_init (NMSettingBridgeClass *setting_class)
 		 (object_class, PROP_AGEING_TIME,
 		  g_param_spec_uint (NM_SETTING_BRIDGE_AGEING_TIME,
 		                     "AgeingTime",
-		                     "The ethernet MAC address aging time, in seconds.",
+		                     "The Ethernet MAC address aging time, in seconds.",
 		                     0, BR_MAX_AGEING_TIME, 300,
-		                     G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+		                     G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE));
 }
 
diff --git a/libnm-util/nm-setting-bridge.h b/libnm-util/nm-setting-bridge.h
index b0b53fd5..1e895704 100644
--- a/libnm-util/nm-setting-bridge.h
+++ b/libnm-util/nm-setting-bridge.h
@@ -56,6 +56,7 @@ typedef enum {
 GQuark nm_setting_bridge_error_quark (void);
 
 #define NM_SETTING_BRIDGE_INTERFACE_NAME "interface-name"
+#define NM_SETTING_BRIDGE_MAC_ADDRESS    "mac-address"
 #define NM_SETTING_BRIDGE_STP            "stp"
 #define NM_SETTING_BRIDGE_PRIORITY       "priority"
 #define NM_SETTING_BRIDGE_FORWARD_DELAY  "forward-delay"
@@ -83,6 +84,9 @@ NMSetting *  nm_setting_bridge_new                (void);
 
 const char * nm_setting_bridge_get_interface_name (NMSettingBridge *setting);
 
+NM_AVAILABLE_IN_0_9_10
+const GByteArray *nm_setting_bridge_get_mac_address (NMSettingBridge *setting);
+
 gboolean     nm_setting_bridge_get_stp            (NMSettingBridge *setting);
 
 guint16      nm_setting_bridge_get_priority       (NMSettingBridge *setting);
diff --git a/libnm-util/nm-setting-cdma.c b/libnm-util/nm-setting-cdma.c
index d68531a6..7acfe852 100644
--- a/libnm-util/nm-setting-cdma.c
+++ b/libnm-util/nm-setting-cdma.c
@@ -18,10 +18,12 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2007 - 2011 Red Hat, Inc.
+ * (C) Copyright 2007 - 2013 Red Hat, Inc.
  */
 
 #include <string.h>
+#include <glib/gi18n.h>
+
 #include "nm-setting-cdma.h"
 #include "nm-utils.h"
 #include "nm-setting-private.h"
@@ -155,32 +157,36 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 	NMSettingCdmaPrivate *priv = NM_SETTING_CDMA_GET_PRIVATE (setting);
 
 	if (!priv->number) {
-		g_set_error (error,
-		             NM_SETTING_CDMA_ERROR,
-		             NM_SETTING_CDMA_ERROR_MISSING_PROPERTY,
-		             NM_SETTING_CDMA_NUMBER);
+		g_set_error_literal (error,
+		                     NM_SETTING_CDMA_ERROR,
+		                     NM_SETTING_CDMA_ERROR_MISSING_PROPERTY,
+		                     _("property is missing"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_CDMA_SETTING_NAME, NM_SETTING_CDMA_NUMBER);
 		return FALSE;
 	} else if (!strlen (priv->number)) {
-		g_set_error (error,
-		             NM_SETTING_CDMA_ERROR,
-		             NM_SETTING_CDMA_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_CDMA_NUMBER);
+		g_set_error_literal (error,
+		                     NM_SETTING_CDMA_ERROR,
+		                     NM_SETTING_CDMA_ERROR_INVALID_PROPERTY,
+		                     _("property is empty'"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_CDMA_SETTING_NAME, NM_SETTING_CDMA_NUMBER);
 		return FALSE;
 	}
 
 	if (priv->username && !strlen (priv->username)) {
-		g_set_error (error,
-		             NM_SETTING_CDMA_ERROR,
-		             NM_SETTING_CDMA_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_CDMA_USERNAME);
+		g_set_error_literal (error,
+		                     NM_SETTING_CDMA_ERROR,
+		                     NM_SETTING_CDMA_ERROR_INVALID_PROPERTY,
+		                     _("property is empty"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_CDMA_SETTING_NAME, NM_SETTING_CDMA_USERNAME);
 		return FALSE;
 	}
 
 	if (priv->password && !strlen (priv->password)) {
-		g_set_error (error,
-		             NM_SETTING_CDMA_ERROR,
-		             NM_SETTING_CDMA_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_CDMA_PASSWORD);
+		g_set_error_literal (error,
+		                     NM_SETTING_CDMA_ERROR,
+		                     NM_SETTING_CDMA_ERROR_INVALID_PROPERTY,
+		                     _("property is empty"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_CDMA_SETTING_NAME, NM_SETTING_CDMA_PASSWORD);
 		return FALSE;
 	}
 
@@ -209,7 +215,6 @@ need_secrets (NMSetting *setting)
 static void
 nm_setting_cdma_init (NMSettingCdma *setting)
 {
-	g_object_set (setting, NM_SETTING_NAME, NM_SETTING_CDMA_SETTING_NAME, NULL);
 }
 
 static void
@@ -310,7 +315,7 @@ nm_setting_cdma_class_init (NMSettingCdmaClass *setting_class)
 						  "specified, the default number (#777) is used when "
 						  "required.",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+						  G_PARAM_READWRITE));
 
 	/**
 	 * NMSettingCdma:username:
@@ -327,7 +332,7 @@ nm_setting_cdma_class_init (NMSettingCdmaClass *setting_class)
 						  "required.  Note that many providers do not require "
 						  "a username or accept any username.",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+						  G_PARAM_READWRITE));
 
 	/**
 	 * NMSettingCdma:password:
@@ -344,12 +349,12 @@ nm_setting_cdma_class_init (NMSettingCdmaClass *setting_class)
 						  "required.  Note that many providers do not require "
 						  "a password or accept any password.",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET));
+						  G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET));
 
 	/**
 	 * NMSettingCdma:password-flags:
 	 *
-	 * Flags indicating how to handle #NMSettingCdma:password:.
+	 * Flags indicating how to handle the #NMSettingCdma:password property.
 	 **/
 	g_object_class_install_property (object_class, PROP_PASSWORD_FLAGS,
 		 g_param_spec_uint (NM_SETTING_CDMA_PASSWORD_FLAGS,
@@ -358,5 +363,5 @@ nm_setting_cdma_class_init (NMSettingCdmaClass *setting_class)
 		                    NM_SETTING_SECRET_FLAG_NONE,
 		                    NM_SETTING_SECRET_FLAGS_ALL,
 		                    NM_SETTING_SECRET_FLAG_NONE,
-		                    G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+		                    G_PARAM_READWRITE));
 }
diff --git a/libnm-util/nm-setting-connection.c b/libnm-util/nm-setting-connection.c
index 9c3f2ce2..56e87a4d 100644
--- a/libnm-util/nm-setting-connection.c
+++ b/libnm-util/nm-setting-connection.c
@@ -19,11 +19,13 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2007 - 2012 Red Hat, Inc.
+ * (C) Copyright 2007 - 2013 Red Hat, Inc.
  * (C) Copyright 2007 - 2008 Novell, Inc.
  */
 
 #include <string.h>
+#include <glib/gi18n.h>
+
 #include "nm-utils.h"
 #include "nm-dbus-glib-types.h"
 #include "nm-param-spec-specialized.h"
@@ -80,6 +82,7 @@ typedef struct {
 typedef struct {
 	char *id;
 	char *uuid;
+	char *interface_name;
 	char *type;
 	char *master;
 	char *slave_type;
@@ -89,12 +92,14 @@ typedef struct {
 	gboolean read_only;
 	char *zone;
 	GSList *secondaries; /* secondary connections to activate with the base connection */
+	guint gateway_ping_timeout;
 } NMSettingConnectionPrivate;
 
 enum {
 	PROP_0,
 	PROP_ID,
 	PROP_UUID,
+	PROP_INTERFACE_NAME,
 	PROP_TYPE,
 	PROP_PERMISSIONS,
 	PROP_AUTOCONNECT,
@@ -104,6 +109,7 @@ enum {
 	PROP_MASTER,
 	PROP_SLAVE_TYPE,
 	PROP_SECONDARIES,
+	PROP_GATEWAY_PING_TIMEOUT,
 
 	LAST_PROP
 };
@@ -236,6 +242,24 @@ nm_setting_connection_get_uuid (NMSettingConnection *setting)
 }
 
 /**
+ * nm_setting_connection_get_interface_name:
+ * @setting: the #NMSettingConnection
+ *
+ * Returns the #NMSettingConnection:interface-name property of the connection.
+ *
+ * Returns: the connection's interface name
+ *
+ * Since: 0.9.10
+ **/
+const char *
+nm_setting_connection_get_interface_name (NMSettingConnection *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), NULL);
+
+	return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->interface_name;
+}
+
+/**
  * nm_setting_connection_get_connection_type:
  * @setting: the #NMSettingConnection
  *
@@ -393,6 +417,7 @@ nm_setting_connection_add_permission (NMSettingConnection *setting,
 	p = permission_new (pitem);
 	g_return_val_if_fail (p != NULL, FALSE);
 	priv->permissions = g_slist_append (priv->permissions, p);
+	g_object_notify (G_OBJECT (setting), NM_SETTING_CONNECTION_PERMISSIONS);
 
 	return TRUE;
 }
@@ -419,8 +444,54 @@ nm_setting_connection_remove_permission (NMSettingConnection *setting,
 
 	permission_free ((Permission *) iter->data);
 	priv->permissions = g_slist_delete_link (priv->permissions, iter);
+	g_object_notify (G_OBJECT (setting), NM_SETTING_CONNECTION_PERMISSIONS);
 }
 
+/**
+ * nm_setting_connection_remove_permission_by_value:
+ * @setting: the #NMSettingConnection
+ * @ptype: the permission type; at this time only "user" is supported
+ * @pitem: the permission item formatted as required for @ptype
+ * @detail: (allow-none): unused at this time; must be %NULL
+ *
+ * Removes the permission from the connection.
+ * At this time, only the "user" permission type is supported, and @pitem must
+ * be a username. See #NMSettingConnection:permissions: for more details.
+ *
+ * Returns: %TRUE if the permission was found and removed; %FALSE if it was not.
+ * 
+ * Since: 0.9.10
+ */
+gboolean
+nm_setting_connection_remove_permission_by_value (NMSettingConnection *setting,
+                                                  const char *ptype,
+                                                  const char *pitem,
+                                                  const char *detail)
+{
+	NMSettingConnectionPrivate *priv;
+	Permission *p;
+	GSList *iter;
+
+	g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), FALSE);
+	g_return_val_if_fail (ptype, FALSE);
+	g_return_val_if_fail (strlen (ptype) > 0, FALSE);
+	g_return_val_if_fail (detail == NULL, FALSE);
+
+	/* Only "user" for now... */
+	g_return_val_if_fail (strcmp (ptype, "user") == 0, FALSE);
+
+	priv = NM_SETTING_CONNECTION_GET_PRIVATE (setting);
+	for (iter = priv->permissions; iter; iter = g_slist_next (iter)) {
+		p = iter->data;
+		if (strcmp (pitem, p->item) == 0) {
+			permission_free ((Permission *) iter->data);
+			priv->permissions = g_slist_delete_link (priv->permissions, iter);
+			g_object_notify (G_OBJECT (setting), NM_SETTING_CONNECTION_PERMISSIONS);
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
 
 /**
  * nm_setting_connection_get_autoconnect:
@@ -604,6 +675,7 @@ nm_setting_connection_add_secondary (NMSettingConnection *setting,
 	}
 
 	priv->secondaries = g_slist_append (priv->secondaries, g_strdup (sec_uuid));
+	g_object_notify (G_OBJECT (setting), NM_SETTING_CONNECTION_SECONDARIES);
 	return TRUE;
 }
 
@@ -630,108 +702,196 @@ nm_setting_connection_remove_secondary (NMSettingConnection *setting, guint32 id
 
 	g_free (elt->data);
 	priv->secondaries = g_slist_delete_link (priv->secondaries, elt);
+	g_object_notify (G_OBJECT (setting), NM_SETTING_CONNECTION_SECONDARIES);
 }
 
-static gint
-find_setting_by_name (gconstpointer a, gconstpointer b)
+/**
+ * nm_setting_connection_remove_secondary_by_value:
+ * @setting: the #NMSettingConnection
+ * @sec_uuid: the secondary connection UUID to remove
+ *
+ * Removes the secondary coonnection UUID @sec_uuid.
+ *
+ * Returns: %TRUE if the secondary connection UUID was found and removed; %FALSE if it was not.
+ *
+ * Since: 0.9.10
+ **/
+gboolean
+nm_setting_connection_remove_secondary_by_value (NMSettingConnection *setting,
+                                                 const char *sec_uuid)
 {
-	NMSetting *setting = NM_SETTING (a);
-	const char *str = (const char *) b;
+	NMSettingConnectionPrivate *priv;
+	GSList *iter;
 
-	return strcmp (nm_setting_get_name (setting), str);
+	g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), FALSE);
+	g_return_val_if_fail (sec_uuid != NULL, FALSE);
+	g_return_val_if_fail (sec_uuid[0] != '\0', FALSE);
+
+	priv = NM_SETTING_CONNECTION_GET_PRIVATE (setting);
+	for (iter = priv->secondaries; iter; iter = g_slist_next (iter)) {
+		if (!strcmp (sec_uuid, (char *) iter->data)) {
+			priv->secondaries = g_slist_delete_link (priv->secondaries, iter);
+			g_object_notify (G_OBJECT (setting), NM_SETTING_CONNECTION_SECONDARIES);
+			return TRUE;
+		}
+	}
+	return FALSE;
 }
 
+/**
+ * nm_setting_connection_get_gateway_ping_timeout:
+ * @setting: the #NMSettingConnection
+ *
+ * Returns: the value contained in the #NMSettingConnection:gateway-ping-timeout
+ * property.
+ *
+ * Since: 0.9.10
+ **/
+guint32
+nm_setting_connection_get_gateway_ping_timeout (NMSettingConnection *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), 0);
+
+	return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->gateway_ping_timeout;
+}
+
+
 static gboolean
 verify (NMSetting *setting, GSList *all_settings, GError **error)
 {
 	NMSettingConnectionPrivate *priv = NM_SETTING_CONNECTION_GET_PRIVATE (setting);
+	gboolean is_slave;
+	GSList *iter;
 
 	if (!priv->id) {
-		g_set_error (error,
-		             NM_SETTING_CONNECTION_ERROR,
-		             NM_SETTING_CONNECTION_ERROR_MISSING_PROPERTY,
-		             NM_SETTING_CONNECTION_ID);
+		g_set_error_literal (error,
+		                     NM_SETTING_CONNECTION_ERROR,
+		                     NM_SETTING_CONNECTION_ERROR_MISSING_PROPERTY,
+		                     _("property is missing"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_ID);
 		return FALSE;
 	} else if (!strlen (priv->id)) {
-		g_set_error (error,
-		             NM_SETTING_CONNECTION_ERROR,
-		             NM_SETTING_CONNECTION_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_CONNECTION_ID);
+		g_set_error_literal (error,
+		                     NM_SETTING_CONNECTION_ERROR,
+		                     NM_SETTING_CONNECTION_ERROR_INVALID_PROPERTY,
+		                     _("property is empty"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_ID);
 		return FALSE;
 	}
 
 	if (!priv->uuid) {
-		g_set_error (error,
-		             NM_SETTING_CONNECTION_ERROR,
-		             NM_SETTING_CONNECTION_ERROR_MISSING_PROPERTY,
-		             NM_SETTING_CONNECTION_UUID);
+		g_set_error_literal (error,
+		                     NM_SETTING_CONNECTION_ERROR,
+		                     NM_SETTING_CONNECTION_ERROR_MISSING_PROPERTY,
+		                     _("property is missing"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_UUID);
 		return FALSE;
 	} else if (!nm_utils_is_uuid (priv->uuid)) {
 		g_set_error (error,
 		             NM_SETTING_CONNECTION_ERROR,
 		             NM_SETTING_CONNECTION_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_CONNECTION_UUID);
+		             _("'%s' is not a valid UUID"),
+		             priv->uuid);
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_UUID);
 		return FALSE;
 	}
 
+	/* If the connection has a virtual interface name, it must match
+	 * the connection setting's interface name.
+	 */
+	for (iter = all_settings; iter; iter = iter->next) {
+		const char *virtual_iface;
+
+		virtual_iface = nm_setting_get_virtual_iface_name (iter->data);
+		if (virtual_iface) {
+			if (priv->interface_name) {
+				if (strcmp (priv->interface_name, virtual_iface) != 0) {
+					g_set_error (error,
+					             NM_SETTING_CONNECTION_ERROR,
+					             NM_SETTING_CONNECTION_ERROR_INVALID_PROPERTY,
+					             _("'%s' doesn't match the virtual interface name '%s'"),
+					             priv->interface_name, virtual_iface);
+					g_prefix_error (error, "%s.%s: ",
+					                NM_SETTING_CONNECTION_SETTING_NAME,
+					                NM_SETTING_CONNECTION_INTERFACE_NAME);
+					return FALSE;
+				}
+			} else
+				priv->interface_name = g_strdup (virtual_iface);
+			break;
+		}
+	}
+
+	if (priv->interface_name) {
+		if (!nm_utils_iface_valid_name (priv->interface_name)) {
+			g_set_error (error,
+			             NM_SETTING_CONNECTION_ERROR,
+			             NM_SETTING_CONNECTION_ERROR_INVALID_PROPERTY,
+			             _("'%s' is not a valid interface name"),
+			             priv->interface_name);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_INTERFACE_NAME);
+			return FALSE;
+		}
+	}
+
 	if (!priv->type) {
-		g_set_error (error,
-		             NM_SETTING_CONNECTION_ERROR,
-		             NM_SETTING_CONNECTION_ERROR_MISSING_PROPERTY,
-		             NM_SETTING_CONNECTION_TYPE);
+		g_set_error_literal (error,
+		                     NM_SETTING_CONNECTION_ERROR,
+		                     NM_SETTING_CONNECTION_ERROR_MISSING_PROPERTY,
+		                     _("property is missing"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_TYPE);
 		return FALSE;
 	} else if (!strlen (priv->type)) {
-		g_set_error (error,
-		             NM_SETTING_CONNECTION_ERROR,
-		             NM_SETTING_CONNECTION_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_CONNECTION_TYPE);
+		g_set_error_literal (error,
+		                     NM_SETTING_CONNECTION_ERROR,
+		                     NM_SETTING_CONNECTION_ERROR_INVALID_PROPERTY,
+		                     _("property is empty"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_TYPE);
 		return FALSE;
 	}
 
 	/* Make sure the corresponding 'type' item is present */
-	if (all_settings && !g_slist_find_custom (all_settings, priv->type, find_setting_by_name)) {
+	if (all_settings && !nm_setting_find_in_list (all_settings, priv->type)) {
 		g_set_error (error,
 		             NM_SETTING_CONNECTION_ERROR,
 		             NM_SETTING_CONNECTION_ERROR_TYPE_SETTING_NOT_FOUND,
-		             NM_SETTING_CONNECTION_TYPE);
+		             _("requires presence of '%s' setting in the connection"),
+		             priv->type);
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_TYPE);
 		return FALSE;
 	}
 
-	/*
-	 * Bonding: Slaves are not allowed to have any IP configuration.
-	 */
-	if (priv->slave_type && all_settings &&
-	    !strcmp(priv->slave_type, NM_SETTING_BOND_SETTING_NAME)) {
-		GSList *list;
+	is_slave = (   !g_strcmp0 (priv->slave_type, NM_SETTING_BOND_SETTING_NAME)
+	            || !g_strcmp0 (priv->slave_type, NM_SETTING_BRIDGE_SETTING_NAME)
+	            || !g_strcmp0 (priv->slave_type, NM_SETTING_TEAM_SETTING_NAME));
 
-		list = g_slist_find_custom (all_settings, NM_SETTING_IP4_CONFIG_SETTING_NAME,
-		                            find_setting_by_name);
-		if (list) {
-			NMSettingIP4Config *s_ip4 = g_slist_nth_data (list, 0);
-			g_assert (s_ip4);
+	/* Bond/bridge/team slaves are not allowed to have any IP configuration. */
+	if (is_slave) {
+		NMSettingIP4Config *s_ip4;
+		NMSettingIP6Config *s_ip6;
 
+		s_ip4 = NM_SETTING_IP4_CONFIG (nm_setting_find_in_list (all_settings, NM_SETTING_IP4_CONFIG_SETTING_NAME));
+		if (s_ip4) {
 			if (strcmp (nm_setting_ip4_config_get_method (s_ip4),
 			            NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) {
-				g_set_error (error,
-				             NM_SETTING_CONNECTION_ERROR,
-				             NM_SETTING_CONNECTION_ERROR_IP_CONFIG_NOT_ALLOWED,
-				             "No IP configuration allowed for bonding slave");
+				g_set_error_literal (error,
+				                     NM_SETTING_CONNECTION_ERROR,
+				                     NM_SETTING_CONNECTION_ERROR_IP_CONFIG_NOT_ALLOWED,
+				                     _("IPv4 configuration is not allowed for slave"));
+				g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_SLAVE_TYPE);
 				return FALSE;
 			}
 		}
 
-		list = g_slist_find_custom (all_settings, NM_SETTING_IP6_CONFIG_SETTING_NAME,
-		                            find_setting_by_name);
-		if (list) {
-			NMSettingIP6Config *s_ip6 = g_slist_nth_data (list, 0);
-			g_assert (s_ip6);
-
+		s_ip6 = NM_SETTING_IP6_CONFIG (nm_setting_find_in_list (all_settings, NM_SETTING_IP6_CONFIG_SETTING_NAME));
+		if (s_ip6) {
 			if (strcmp (nm_setting_ip6_config_get_method (s_ip6),
 			            NM_SETTING_IP6_CONFIG_METHOD_IGNORE)) {
-				g_set_error (error,
-				             NM_SETTING_CONNECTION_ERROR,
-				             NM_SETTING_CONNECTION_ERROR_IP_CONFIG_NOT_ALLOWED,
-				             "No IPv6 configuration allowed for bonding slave");
+				g_set_error_literal (error,
+				                     NM_SETTING_CONNECTION_ERROR,
+				                     NM_SETTING_CONNECTION_ERROR_IP_CONFIG_NOT_ALLOWED,
+				                     _("IPv6 configuration is not allowed for slave"));
+				g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_SLAVE_TYPE);
 				return FALSE;
 			}
 		}
@@ -758,7 +918,6 @@ compare_property (NMSetting *setting,
 static void
 nm_setting_connection_init (NMSettingConnection *setting)
 {
-	g_object_set (setting, NM_SETTING_NAME, NM_SETTING_CONNECTION_SETTING_NAME, NULL);
 }
 
 static void
@@ -768,12 +927,13 @@ finalize (GObject *object)
 
 	g_free (priv->id);
 	g_free (priv->uuid);
+	g_free (priv->interface_name);
 	g_free (priv->type);
 	g_free (priv->zone);
 	g_free (priv->master);
 	g_free (priv->slave_type);
-	nm_utils_slist_free (priv->permissions, (GDestroyNotify) permission_free);
-	nm_utils_slist_free (priv->secondaries, g_free);
+	g_slist_free_full (priv->permissions, (GDestroyNotify) permission_free);
+	g_slist_free_full (priv->secondaries, g_free);
 
 	G_OBJECT_CLASS (nm_setting_connection_parent_class)->finalize (object);
 }
@@ -809,12 +969,16 @@ set_property (GObject *object, guint prop_id,
 		g_free (priv->uuid);
 		priv->uuid = g_value_dup_string (value);
 		break;
+	case PROP_INTERFACE_NAME:
+		g_free (priv->interface_name);
+		priv->interface_name = g_value_dup_string (value);
+		break;
 	case PROP_TYPE:
 		g_free (priv->type);
 		priv->type = g_value_dup_string (value);
 		break;
 	case PROP_PERMISSIONS:
-		nm_utils_slist_free (priv->permissions, (GDestroyNotify) permission_free);
+		g_slist_free_full (priv->permissions, (GDestroyNotify) permission_free);
 		priv->permissions = perm_stringlist_to_permlist (g_value_get_boxed (value));
 		break;
 	case PROP_AUTOCONNECT:
@@ -839,9 +1003,12 @@ set_property (GObject *object, guint prop_id,
 		priv->slave_type = g_value_dup_string (value);
 		break;
 	case PROP_SECONDARIES:
-		nm_utils_slist_free (priv->secondaries, g_free);
+		g_slist_free_full (priv->secondaries, g_free);
 		priv->secondaries = g_value_dup_boxed (value);
 		break;
+	case PROP_GATEWAY_PING_TIMEOUT:
+		priv->gateway_ping_timeout = g_value_get_uint (value);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -872,6 +1039,9 @@ get_property (GObject *object, guint prop_id,
 	case PROP_UUID:
 		g_value_set_string (value, nm_setting_connection_get_uuid (setting));
 		break;
+	case PROP_INTERFACE_NAME:
+		g_value_set_string (value, nm_setting_connection_get_interface_name (setting));
+		break;
 	case PROP_TYPE:
 		g_value_set_string (value, nm_setting_connection_get_connection_type (setting));
 		break;
@@ -899,6 +1069,9 @@ get_property (GObject *object, guint prop_id,
 	case PROP_SECONDARIES:
 		g_value_set_boxed (value, priv->secondaries);
 		break;
+	case PROP_GATEWAY_PING_TIMEOUT:
+		g_value_set_uint (value, priv->gateway_ping_timeout);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -925,8 +1098,8 @@ nm_setting_connection_class_init (NMSettingConnectionClass *setting_class)
 	/**
 	 * NMSettingConnection:id:
 	 *
-	 * A human readable unique idenfier for the connection, like "Work WiFi" or
-	 * "T-Mobile 3G".
+	 * A human readable unique identifier for the connection, like "Work Wi-Fi"
+	 * or "T-Mobile 3G".
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_ID,
@@ -936,21 +1109,21 @@ nm_setting_connection_class_init (NMSettingConnectionClass *setting_class)
 						  "one or more characters and may change over the lifetime "
 						  "of the connection if the user decides to rename it.",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_FUZZY_IGNORE));
+						  G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE));
 
 	/**
 	 * NMSettingConnection:uuid:
 	 *
-	 * A universally unique idenfier for the connection, for example generated
-	 * with libuuid.  Should be assigned when the connection is created, and
+	 * A universally unique identifier for the connection, for example generated
+	 * with libuuid.  It should be assigned when the connection is created, and
 	 * never changed as long as the connection still applies to the same
-	 * network.  For example, should not be changed when the
-	 * #NMSettingConnection:id or #NMSettingIP4Config changes, but might need
-	 * to be re-created when the WiFi SSID, mobile broadband network provider,
-	 * or #NMSettingConnection:type changes.
+	 * network.  For example, it should not be changed when the
+	 * #NMSettingConnection:id property or #NMSettingIP4Config changes, but
+	 * might need to be re-created when the Wi-Fi SSID, mobile broadband network
+	 * provider, or #NMSettingConnection:type property changes.
 	 *
-	 * The UUID must be in the format '2815492f-7e56-435e-b2e9-246bd7cdc664'
-	 * (ie, contains only hexadecimal characters and '-').  A suitable UUID may
+	 * The UUID must be in the format "2815492f-7e56-435e-b2e9-246bd7cdc664"
+	 * (ie, contains only hexadecimal characters and "-").  A suitable UUID may
 	 * be generated by nm_utils_uuid_generate() or
 	 * nm_utils_uuid_generate_from_string().
 	 **/
@@ -966,18 +1139,52 @@ nm_setting_connection_class_init (NMSettingConnectionClass *setting_class)
 						  "still applies to the same network.  For example, "
 						  "it should not be changed when the user changes the "
 						  "connection's 'id', but should be recreated when the "
-						  "WiFi SSID, mobile broadband network provider, or the "
+						  "Wi-Fi SSID, mobile broadband network provider, or the "
 						  "connection type changes.",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_FUZZY_IGNORE));
+						  G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE));
+
+	/**
+	 * NMSettingConnection:interface-name:
+	 *
+	 * The name of the network interface this connection is bound to. If not
+	 * set, then the connection can be attached to any interface of the
+	 * appropriate type (subject to restrictions imposed by other settings).
+	 *
+	 * For connection types where interface names cannot easily be made
+	 * persistent (e.g. mobile broadband or USB Ethernet), this property should
+	 * not be used. Setting this property restricts the interfaces a connection
+	 * can be used with, and if interface names change or are reordered the
+	 * connection may be applied to the wrong interface.
+	 *
+	 * Since: 0.9.10
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_INTERFACE_NAME,
+		 g_param_spec_string (NM_SETTING_CONNECTION_INTERFACE_NAME,
+		                      "Interface name",
+		                      "Interface name this connection is bound to. "
+		                      "If not set, then the connection can be attached "
+		                      "to any interface of the appropriate type (subject "
+		                      "to restrictions imposed by other settings). For "
+		                      "connection types where interface names cannot easily "
+		                      "be made persistent (e.g. mobile broadband or USB "
+		                      "Ethernet), this property should not be used. Setting "
+		                      "this property restricts the interfaces a connection can "
+		                      "be used with, and if interface names change or are "
+		                      "reordered the connection may be applied to the wrong "
+		                      "interface.",
+		                      NULL,
+		                      G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE));
 
 	/**
 	 * NMSettingConnection:type:
 	 *
-	 * The general hardware type of the device used for the network connection,
-	 * contains the name of the #NMSetting object that describes that hardware
-	 * type's parameters.  For example, for WiFi devices, the name of the
-	 * #NMSettingWireless setting.
+	 * Base type of the connection. For hardware-dependent connections, should
+	 * contain the setting name of the hardware-type specific setting (ie,
+	 * "802-3-ethernet" or "802-11-wireless" or "bluetooth", etc), and for
+	 * non-hardware dependent connections like VPN or otherwise, should contain
+	 * the setting name of that setting type (ie, "vpn" or "bridge", etc).
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_TYPE,
@@ -991,24 +1198,22 @@ nm_setting_connection_class_init (NMSettingConnectionClass *setting_class)
 						  "otherwise, should contain the setting name of that "
 						  "setting type (ie, 'vpn' or 'bridge', etc).",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+						  G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE));
 
 	/**
 	 * NMSettingConnection:permissions:
 	 * 
 	 * An array of strings defining what access a given user has to this
-	 * connection.  If this is NULL or empty, all users are allowed to access
+	 * connection.  If this is %NULL or empty, all users are allowed to access
 	 * this connection.  Otherwise a user is allowed to access this connection
 	 * if and only if they are in this list. Each entry is of the form
-	 * "[type]:[id]:[reserved]", for example:
-	 *
-	 *    user:dcbw:blah
+	 * "[type]:[id]:[reserved]"; for example, "user:dcbw:blah".
 	 *
-	 * At this time only the 'user' [type] is allowed.  Any other values are
+	 * At this time only the "user" [type] is allowed.  Any other values are
 	 * ignored and reserved for future use.  [id] is the username that this
-	 * permission refers to, which may not contain the ':' character. Any
-	 * [reserved] information present must be ignored and is reserved for
-	 * future use.  All of [type], [id], and [reserved] must be valid UTF-8.
+	 * permission refers to, which may not contain the ":" character. Any
+	 * [reserved] information present must be ignored and is reserved for future
+	 * use.  All of [type], [id], and [reserved] must be valid UTF-8.
 	 */
 	g_object_class_install_property
 		(object_class, PROP_PERMISSIONS,
@@ -1030,7 +1235,7 @@ nm_setting_connection_class_init (NMSettingConnectionClass *setting_class)
 		                  "use.  All of [type], [id], and [reserved] must be "
 		                  "valid UTF-8.",
 		                  DBUS_TYPE_G_LIST_OF_STRING,
-		                  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+		                  G_PARAM_READWRITE));
 
 	/**
 	 * NMSettingConnection:autoconnect:
@@ -1038,7 +1243,7 @@ nm_setting_connection_class_init (NMSettingConnectionClass *setting_class)
 	 * Whether or not the connection should be automatically connected by
 	 * NetworkManager when the resources for the connection are available.
 	 * %TRUE to automatically activate the connection, %FALSE to require manual
-	 * intervention to activate the connection.  Defaults to %TRUE.
+	 * intervention to activate the connection.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_AUTOCONNECT,
@@ -1049,32 +1254,38 @@ nm_setting_connection_class_init (NMSettingConnectionClass *setting_class)
 						   "the connection must be manually activated by the user "
 						   "or some other mechanism.",
 						   TRUE,
-						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_FUZZY_IGNORE));
+						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE));
 
 	/**
 	 * NMSettingConnection:timestamp:
 	 *
 	 * The time, in seconds since the Unix Epoch, that the connection was last
 	 * _successfully_ fully activated.
+	 *
+	 * NetworkManager updates the connection timestamp periodically when the
+	 * connection is active to ensure that an active connection has the latest
+	 * timestamp. The property is only meant for reading (changes to this
+	 * property will not be preserved).
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_TIMESTAMP,
 		 g_param_spec_uint64 (NM_SETTING_CONNECTION_TIMESTAMP,
-						  "Timestamp",
-						  "Timestamp (in seconds since the Unix Epoch) that the "
-						  "connection was last successfully activated.  Settings "
-						  "services should update the connection timestamp "
-						  "periodically when the connection is active to ensure "
-						  "that an active connection has the latest timestamp.",
-						  0, G_MAXUINT64, 0,
-						  G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_FUZZY_IGNORE));
+		                      "Timestamp",
+		                      "Timestamp (in seconds since the Unix Epoch) that the "
+		                      "connection was last successfully activated.  NetworkManager "
+		                      "updates the connection timestamp periodically when the "
+		                      "connection is active to ensure that an active connection "
+		                      "has the latest timestamp. The property is only meant for "
+		                      "reading (changes to this property will not be preserved).",
+		                      0, G_MAXUINT64, 0,
+		                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE));
 
 	/**
 	 * NMSettingConnection:read-only:
 	 *
-	 * %TRUE if the connection can be modified using the providing settings
-	 * service's D-Bus interface with the right privileges, or %FALSE
-	 * if the connection is read-only and cannot be modified.
+	 * %FALSE if the connection can be modified using the provided settings
+	 * service's D-Bus interface with the right privileges, or %TRUE if the
+	 * connection is read-only and cannot be modified.
 	 **/
 	g_object_class_install_property
 	    (object_class, PROP_READ_ONLY,
@@ -1085,15 +1296,15 @@ nm_setting_connection_class_init (NMSettingConnectionClass *setting_class)
 	                      "normally set for system connections whose plugin "
 	                      "cannot yet write updated connections back out.",
 	                      FALSE,
-	                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_FUZZY_IGNORE));
+	                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE));
 
 	/**
 	 * NMSettingConnection:zone:
 	 *
-	 * The trust level of a the connection.
-	 * Free form case-insensitive string (for example "Home", "Work", "Public").
-	 * NULL or unspecified zone means the connection will be placed in the
-	 * default zone as defined by the firewall.
+	 * The trust level of a the connection.  Free form case-insensitive string
+	 * (for example "Home", "Work", "Public").  %NULL or unspecified zone means
+	 * the connection will be placed in the default zone as defined by the
+	 * firewall.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_ZONE,
@@ -1106,7 +1317,7 @@ nm_setting_connection_class_init (NMSettingConnectionClass *setting_class)
 						  "placed in the default zone as defined by the "
 						  "firewall.",
 						  NULL,
-						  G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_FUZZY_IGNORE));
+						  G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE));
 
 	/**
 	 * NMSettingConnection:master:
@@ -1120,13 +1331,14 @@ nm_setting_connection_class_init (NMSettingConnectionClass *setting_class)
 		                      "Interface name of the master device or UUID of "
 		                      "the master connection",
 		                      NULL,
-		                      G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_FUZZY_IGNORE));
+		                      G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | NM_SETTING_PARAM_INFERRABLE));
 
 	/**
 	 * NMSettingConnection:slave-type:
 	 *
-	 * Setting name describing the type of slave device (ie
-	 * #NM_SETTING_BOND_SETTING_NAME) or NULL if this connection is not a slave.
+	 * Setting name of the device type of this slave's master connection (eg,
+	 * %NM_SETTING_BOND_SETTING_NAME), or %NULL if this connection is not a
+	 * slave.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_SLAVE_TYPE,
@@ -1136,13 +1348,14 @@ nm_setting_connection_class_init (NMSettingConnectionClass *setting_class)
 		                      "this connection is (ie, 'bond') or NULL if this "
 		                      "connection is not a slave.",
 		                      NULL,
-		                      G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_FUZZY_IGNORE));
+		                      G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE | NM_SETTING_PARAM_INFERRABLE));
 
 	/**
 	 * NMSettingConnection:secondaries:
 	 *
-	 * List of connection UUIDs that should be activated when the base connection
-	 * itself is activated.
+	 * List of connection UUIDs that should be activated when the base
+	 * connection itself is activated. Currently only VPN connections are
+	 * supported.
 	 *
 	 * Since: 0.9.8
 	 **/
@@ -1151,7 +1364,26 @@ nm_setting_connection_class_init (NMSettingConnectionClass *setting_class)
 		 _nm_param_spec_specialized (NM_SETTING_CONNECTION_SECONDARIES,
 		                             "Secondaries",
 		                             "List of connection UUIDs that should be activated "
-		                             "when the base connection itself is activated.",
+		                             "when the base connection itself is activated.  "
+		                             "Currently only VPN connections are supported.",
 		                             DBUS_TYPE_G_LIST_OF_STRING,
-		                             G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_FUZZY_IGNORE));
+		                             G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE));
+
+	/**
+	 * NMSettingConnection:gateway-ping-timeout:
+	 *
+	 * If greater than zero, delay success of IP addressing until either the
+	 * timeout is reached, or an IP gateway replies to a ping.
+	 *
+	 * Since: 0.9.10
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_GATEWAY_PING_TIMEOUT,
+		 g_param_spec_uint (NM_SETTING_CONNECTION_GATEWAY_PING_TIMEOUT,
+		                    "Gateway Ping Timeout",
+		                    "If greater than zero, delay success of IP "
+		                    "addressing until either the timeout is reached, or "
+		                    "an IP gateway replies to a ping.",
+		                    0, 30, 0,
+		                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 }
diff --git a/libnm-util/nm-setting-connection.h b/libnm-util/nm-setting-connection.h
index 73c598cb..ff2af7a2 100644
--- a/libnm-util/nm-setting-connection.h
+++ b/libnm-util/nm-setting-connection.h
@@ -19,7 +19,7 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2007 - 2012 Red Hat, Inc.
+ * (C) Copyright 2007 - 2014 Red Hat, Inc.
  * (C) Copyright 2007 - 2008 Novell, Inc.
  */
 
@@ -68,17 +68,19 @@ typedef enum
 #define NM_SETTING_CONNECTION_ERROR nm_setting_connection_error_quark ()
 GQuark nm_setting_connection_error_quark (void);
 
-#define NM_SETTING_CONNECTION_ID          "id"
-#define NM_SETTING_CONNECTION_UUID        "uuid"
-#define NM_SETTING_CONNECTION_TYPE        "type"
-#define NM_SETTING_CONNECTION_AUTOCONNECT "autoconnect"
-#define NM_SETTING_CONNECTION_TIMESTAMP   "timestamp"
-#define NM_SETTING_CONNECTION_READ_ONLY   "read-only"
-#define NM_SETTING_CONNECTION_PERMISSIONS "permissions"
-#define NM_SETTING_CONNECTION_ZONE        "zone"
-#define NM_SETTING_CONNECTION_MASTER      "master"
-#define NM_SETTING_CONNECTION_SLAVE_TYPE  "slave-type"
-#define NM_SETTING_CONNECTION_SECONDARIES "secondaries"
+#define NM_SETTING_CONNECTION_ID             "id"
+#define NM_SETTING_CONNECTION_UUID           "uuid"
+#define NM_SETTING_CONNECTION_INTERFACE_NAME "interface-name"
+#define NM_SETTING_CONNECTION_TYPE           "type"
+#define NM_SETTING_CONNECTION_AUTOCONNECT    "autoconnect"
+#define NM_SETTING_CONNECTION_TIMESTAMP      "timestamp"
+#define NM_SETTING_CONNECTION_READ_ONLY      "read-only"
+#define NM_SETTING_CONNECTION_PERMISSIONS    "permissions"
+#define NM_SETTING_CONNECTION_ZONE           "zone"
+#define NM_SETTING_CONNECTION_MASTER         "master"
+#define NM_SETTING_CONNECTION_SLAVE_TYPE     "slave-type"
+#define NM_SETTING_CONNECTION_SECONDARIES    "secondaries"
+#define NM_SETTING_CONNECTION_GATEWAY_PING_TIMEOUT "gateway-ping-timeout"
 
 /**
  * NMSettingConnection:
@@ -105,6 +107,8 @@ GType nm_setting_connection_get_type (void);
 NMSetting * nm_setting_connection_new                  (void);
 const char *nm_setting_connection_get_id               (NMSettingConnection *setting);
 const char *nm_setting_connection_get_uuid             (NMSettingConnection *setting);
+NM_AVAILABLE_IN_0_9_10
+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);
 guint64     nm_setting_connection_get_timestamp        (NMSettingConnection *setting);
@@ -124,14 +128,26 @@ gboolean    nm_setting_connection_add_permission       (NMSettingConnection *set
                                                         const char *detail);
 void        nm_setting_connection_remove_permission    (NMSettingConnection *setting,
                                                         guint32 idx);
+NM_AVAILABLE_IN_0_9_10
+gboolean    nm_setting_connection_remove_permission_by_value (NMSettingConnection *setting,
+                                                              const char *ptype,
+                                                              const char *pitem,
+                                                              const char *detail);
+
 const char *nm_setting_connection_get_master           (NMSettingConnection *setting);
 gboolean    nm_setting_connection_is_slave_type        (NMSettingConnection *setting,
 							const char *type);
 const char *nm_setting_connection_get_slave_type       (NMSettingConnection *setting);
+
 guint32     nm_setting_connection_get_num_secondaries  (NMSettingConnection *setting);
 const char *nm_setting_connection_get_secondary        (NMSettingConnection *setting, guint32 idx);
 gboolean    nm_setting_connection_add_secondary        (NMSettingConnection *setting, const char *sec_uuid);
 void        nm_setting_connection_remove_secondary     (NMSettingConnection *setting, guint32 idx);
+NM_AVAILABLE_IN_0_9_10
+gboolean    nm_setting_connection_remove_secondary_by_value (NMSettingConnection *setting, const char *sec_uuid);
+
+NM_AVAILABLE_IN_0_9_10
+guint32     nm_setting_connection_get_gateway_ping_timeout (NMSettingConnection *setting);
 
 G_END_DECLS
 
diff --git a/libnm-util/nm-setting-dcb.c b/libnm-util/nm-setting-dcb.c
new file mode 100644
index 00000000..54b115dd
--- /dev/null
+++ b/libnm-util/nm-setting-dcb.c
@@ -0,0 +1,1268 @@
+/* -*- 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.
+ *
+ * (C) Copyright 2013 Red Hat, Inc.
+ */
+
+#include <string.h>
+#include <dbus/dbus-glib.h>
+#include <glib/gi18n.h>
+
+#include "nm-setting-dcb.h"
+#include "nm-param-spec-specialized.h"
+#include "nm-utils.h"
+#include "nm-utils-private.h"
+#include "nm-dbus-glib-types.h"
+#include "nm-setting-private.h"
+
+/**
+ * SECTION:nm-setting-dcb
+ * @short_description: Connection properties for Data Center Bridging
+ * @include: nm-setting-dcb.h
+ *
+ * The #NMSettingDcb object is a #NMSetting subclass that describes properties
+ * for enabling and using Data Center Bridging (DCB) on Ethernet networks.
+ * DCB is a set of protocols (including 802.1Qbb, 802.1Qaz, 802.1Qau, and
+ * 802.1AB) to eliminate packet loss in Ethernet networks and support the use
+ * of storage technologies like Fibre Channel over Ethernet (FCoE) and iSCSI.
+ *
+ * Since: 0.9.10
+ **/
+
+/**
+ * nm_setting_dcb_error_quark:
+ *
+ * Registers an error quark for #NMSettingDcb if necessary.
+ *
+ * Returns: the error quark used for #NMSettingDcb errors.
+ *
+ * Since: 0.9.10
+ **/
+GQuark
+nm_setting_dcb_error_quark (void)
+{
+	static GQuark quark;
+
+	if (G_UNLIKELY (!quark))
+		quark = g_quark_from_static_string ("nm-setting-dcb-error-quark");
+	return quark;
+}
+
+
+G_DEFINE_TYPE_WITH_CODE (NMSettingDcb, nm_setting_dcb, NM_TYPE_SETTING,
+                         _nm_register_setting (NM_SETTING_DCB_SETTING_NAME,
+                                               g_define_type_id,
+                                               2,
+                                               NM_SETTING_DCB_ERROR))
+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;
+	gint              app_fcoe_priority;
+	const char *      app_fcoe_mode;
+
+	NMSettingDcbFlags app_iscsi_flags;
+	gint              app_iscsi_priority;
+
+	NMSettingDcbFlags app_fip_flags;
+	gint              app_fip_priority;
+
+	/* Priority Flow Control */
+	NMSettingDcbFlags pfc_flags;
+	guint             pfc[8];
+
+	/* Priority Groups */
+	NMSettingDcbFlags priority_group_flags;
+	guint             priority_group_id[8];
+	guint             priority_group_bandwidth[8];
+	guint             priority_bandwidth[8];
+	guint             priority_strict[8];
+	guint             priority_traffic_class[8];
+} NMSettingDcbPrivate;
+
+enum {
+	PROP_0,
+	PROP_APP_FCOE_FLAGS,
+	PROP_APP_FCOE_PRIORITY,
+	PROP_APP_FCOE_MODE,
+
+	PROP_APP_ISCSI_FLAGS,
+	PROP_APP_ISCSI_PRIORITY,
+
+	PROP_APP_FIP_FLAGS,
+	PROP_APP_FIP_PRIORITY,
+
+	PROP_PFC_FLAGS,
+	PROP_PFC,
+
+	PROP_PRIORITY_GROUP_FLAGS,
+	PROP_PRIORITY_GROUP_ID,
+	PROP_PRIORITY_GROUP_BANDWIDTH,
+	PROP_PRIORITY_BANDWIDTH,
+	PROP_PRIORITY_STRICT,
+	PROP_PRIORITY_TRAFFIC_CLASS,
+
+	LAST_PROP
+};
+
+/**
+ * nm_setting_dcb_new:
+ *
+ * Creates a new #NMSettingDcb object with default values.
+ *
+ * Returns: (transfer full): the new empty #NMSettingDcb object
+ *
+ * Since: 0.9.10
+ **/
+NMSetting *
+nm_setting_dcb_new (void)
+{
+	return (NMSetting *) g_object_new (NM_TYPE_SETTING_DCB, NULL);
+}
+
+/**
+ * nm_setting_dcb_get_app_fcoe_flags:
+ * @setting: the #NMSettingDcb
+ *
+ * Returns: the #NMSettingDcb:app-fcoe-flags property of the setting
+ *
+ * Since: 0.9.10
+ **/
+NMSettingDcbFlags
+nm_setting_dcb_get_app_fcoe_flags (NMSettingDcb *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_DCB (setting), 0);
+
+	return NM_SETTING_DCB_GET_PRIVATE (setting)->app_fcoe_flags;
+}
+
+/**
+ * nm_setting_dcb_get_app_fcoe_priority:
+ * @setting: the #NMSettingDcb
+ *
+ * Returns: the #NMSettingDcb:app-fcoe-priority property of the setting
+ *
+ * Since: 0.9.10
+ **/
+gint
+nm_setting_dcb_get_app_fcoe_priority (NMSettingDcb *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_DCB (setting), 0);
+
+	return NM_SETTING_DCB_GET_PRIVATE (setting)->app_fcoe_priority;
+}
+
+/**
+ * nm_setting_dcb_get_app_fcoe_mode:
+ * @setting: the #NMSettingDcb
+ *
+ * Returns: the #NMSettingDcb:app-fcoe-mode property of the setting
+ *
+ * Since: 0.9.10
+ **/
+const char *
+nm_setting_dcb_get_app_fcoe_mode (NMSettingDcb *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_DCB (setting), NULL);
+
+	return NM_SETTING_DCB_GET_PRIVATE (setting)->app_fcoe_mode;
+}
+
+/**
+ * nm_setting_dcb_get_app_iscsi_flags:
+ * @setting: the #NMSettingDcb
+ *
+ * Returns: the #NMSettingDcb:app-iscsi-flags property of the setting
+ *
+ * Since: 0.9.10
+ **/
+NMSettingDcbFlags
+nm_setting_dcb_get_app_iscsi_flags (NMSettingDcb *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_DCB (setting), 0);
+
+	return NM_SETTING_DCB_GET_PRIVATE (setting)->app_iscsi_flags;
+}
+
+/**
+ * nm_setting_dcb_get_app_iscsi_priority:
+ * @setting: the #NMSettingDcb
+ *
+ * Returns: the #NMSettingDcb:app-iscsi-priority property of the setting
+ *
+ * Since: 0.9.10
+ **/
+gint
+nm_setting_dcb_get_app_iscsi_priority (NMSettingDcb *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_DCB (setting), 0);
+
+	return NM_SETTING_DCB_GET_PRIVATE (setting)->app_iscsi_priority;
+}
+
+/**
+ * nm_setting_dcb_get_app_fip_flags:
+ * @setting: the #NMSettingDcb
+ *
+ * Returns: the #NMSettingDcb:app-fip-flags property of the setting
+ *
+ * Since: 0.9.10
+ **/
+NMSettingDcbFlags
+nm_setting_dcb_get_app_fip_flags (NMSettingDcb *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_DCB (setting), 0);
+
+	return NM_SETTING_DCB_GET_PRIVATE (setting)->app_fip_flags;
+}
+
+/**
+ * nm_setting_dcb_get_app_fip_priority:
+ * @setting: the #NMSettingDcb
+ *
+ * Returns: the #NMSettingDcb:app-fip-priority property of the setting
+ *
+ * Since: 0.9.10
+ **/
+gint
+nm_setting_dcb_get_app_fip_priority (NMSettingDcb *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_DCB (setting), 0);
+
+	return NM_SETTING_DCB_GET_PRIVATE (setting)->app_fip_priority;
+}
+
+/**
+ * nm_setting_dcb_get_priority_flow_control_flags:
+ * @setting: the #NMSettingDcb
+ *
+ * Returns: the #NMSettingDcb:priority-flow-control-flags property of the setting
+ *
+ * Since: 0.9.10
+ **/
+NMSettingDcbFlags
+nm_setting_dcb_get_priority_flow_control_flags (NMSettingDcb *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_DCB (setting), 0);
+
+	return NM_SETTING_DCB_GET_PRIVATE (setting)->pfc_flags;
+}
+
+/**
+ * nm_setting_dcb_get_priority_flow_control:
+ * @setting: the #NMSettingDcb
+ * @user_priority: the User Priority (0 - 7) to retrieve flow control for
+ *
+ * Returns: %TRUE if flow control is enabled for the given @user_priority,
+ * %FALSE if not enabled
+ *
+ * Since: 0.9.10
+ **/
+gboolean
+nm_setting_dcb_get_priority_flow_control (NMSettingDcb *setting, guint user_priority)
+{
+	g_return_val_if_fail (NM_IS_SETTING_DCB (setting), FALSE);
+	g_return_val_if_fail (user_priority <= 7, FALSE);
+
+	return !!NM_SETTING_DCB_GET_PRIVATE (setting)->pfc[user_priority];
+}
+
+/**
+ * nm_setting_dcb_set_priority_flow_control:
+ * @setting: the #NMSettingDcb
+ * @user_priority: the User Priority (0 - 7) to set flow control for
+ * @enabled: %TRUE to enable flow control for this priority, %FALSE to disable it
+ *
+ * These values are only valid when #NMSettingDcb:priority-flow-control includes
+ * the %NM_SETTING_DCB_FLAG_ENABLE flag.
+ *
+ * Since: 0.9.10
+ **/
+void
+nm_setting_dcb_set_priority_flow_control (NMSettingDcb *setting,
+                                          guint user_priority,
+                                          gboolean enabled)
+{
+	NMSettingDcbPrivate *priv;
+	guint uint_enabled = enabled ? 1 : 0;
+
+	g_return_if_fail (NM_IS_SETTING_DCB (setting));
+	g_return_if_fail (user_priority <= 7);
+
+	priv = NM_SETTING_DCB_GET_PRIVATE (setting);
+	if (priv->pfc[user_priority] != uint_enabled) {
+		priv->pfc[user_priority] = uint_enabled;
+		g_object_notify (G_OBJECT (setting), NM_SETTING_DCB_PRIORITY_FLOW_CONTROL);
+	}
+}
+
+/**
+ * nm_setting_dcb_get_priority_group_flags:
+ * @setting: the #NMSettingDcb
+ *
+ * Returns: the #NMSettingDcb:priority-group-flags property of the setting
+ *
+ * Since: 0.9.10
+ **/
+NMSettingDcbFlags
+nm_setting_dcb_get_priority_group_flags (NMSettingDcb *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_DCB (setting), 0);
+
+	return NM_SETTING_DCB_GET_PRIVATE (setting)->priority_group_flags;
+}
+
+/**
+ * nm_setting_dcb_get_priority_group_id:
+ * @setting: the #NMSettingDcb
+ * @user_priority: the User Priority (0 - 7) to retrieve the group ID for
+ *
+ * Returns: the group number @user_priority is assigned to.  These values are
+ * only valid when #NMSettingDcb:priority-group-flags includes the
+ * %NM_SETTING_DCB_FLAG_ENABLE flag.
+ *
+ * Since: 0.9.10
+ **/
+guint
+nm_setting_dcb_get_priority_group_id (NMSettingDcb *setting, guint user_priority)
+{
+	g_return_val_if_fail (NM_IS_SETTING_DCB (setting), 0);
+	g_return_val_if_fail (user_priority <= 7, 0);
+
+	return NM_SETTING_DCB_GET_PRIVATE (setting)->priority_group_id[user_priority];
+}
+
+/**
+ * nm_setting_dcb_set_priority_group_id:
+ * @setting: the #NMSettingDcb
+ * @user_priority: the User Priority (0 - 7) to set flow control for
+ * @group_id: the group (0 - 7) to assign @user_priority to, or 15 for the
+ * unrestricted group.
+ *
+ * These values are only valid when #NMSettingDcb:priority-group-flags includes
+ * the %NM_SETTING_DCB_FLAG_ENABLE flag.
+ *
+ * Since: 0.9.10
+ **/
+void
+nm_setting_dcb_set_priority_group_id (NMSettingDcb *setting,
+                                      guint user_priority,
+                                      guint group_id)
+{
+	NMSettingDcbPrivate *priv;
+
+	g_return_if_fail (NM_IS_SETTING_DCB (setting));
+	g_return_if_fail (user_priority <= 7);
+	g_return_if_fail (group_id <= 7 || group_id == 15);
+
+	priv = NM_SETTING_DCB_GET_PRIVATE (setting);
+	if (priv->priority_group_id[user_priority] != group_id) {
+		priv->priority_group_id[user_priority] = group_id;
+		g_object_notify (G_OBJECT (setting), NM_SETTING_DCB_PRIORITY_GROUP_ID);
+	}
+}
+
+/**
+ * nm_setting_dcb_get_priority_group_bandwidth:
+ * @setting: the #NMSettingDcb
+ * @group_id: the priority group (0 - 7) to retrieve the bandwidth percentage for
+ *
+ * Returns: the bandwidth percentage assigned to @group_id.  These values are
+ * only valid when #NMSettingDcb:priority-group-flags includes the
+ * %NM_SETTING_DCB_FLAG_ENABLE flag.
+ *
+ * Since: 0.9.10
+ **/
+guint
+nm_setting_dcb_get_priority_group_bandwidth (NMSettingDcb *setting, guint group_id)
+{
+	g_return_val_if_fail (NM_IS_SETTING_DCB (setting), 0);
+	g_return_val_if_fail (group_id <= 7, FALSE);
+
+	return NM_SETTING_DCB_GET_PRIVATE (setting)->priority_group_bandwidth[group_id];
+}
+
+/**
+ * nm_setting_dcb_set_priority_group_bandwidth:
+ * @setting: the #NMSettingDcb
+ * @group_id: the priority group (0 - 7) to set the bandwidth percentage for
+ * @bandwidth_percent: the bandwidth percentage (0 - 100) to assign to @group_id to
+ *
+ * These values are only valid when #NMSettingDcb:priority-group-flags includes
+ * the %NM_SETTING_DCB_FLAG_ENABLE flag.
+ *
+ * Since: 0.9.10
+ **/
+void
+nm_setting_dcb_set_priority_group_bandwidth (NMSettingDcb *setting,
+                                             guint group_id,
+                                             guint bandwidth_percent)
+{
+	NMSettingDcbPrivate *priv;
+
+	g_return_if_fail (NM_IS_SETTING_DCB (setting));
+	g_return_if_fail (group_id <= 7);
+	g_return_if_fail (bandwidth_percent <= 100);
+
+	priv = NM_SETTING_DCB_GET_PRIVATE (setting);
+	if (priv->priority_group_bandwidth[group_id] != bandwidth_percent) {
+		priv->priority_group_bandwidth[group_id] = bandwidth_percent;
+		g_object_notify (G_OBJECT (setting), NM_SETTING_DCB_PRIORITY_GROUP_BANDWIDTH);
+	}
+}
+
+/**
+ * nm_setting_dcb_get_priority_bandwidth:
+ * @setting: the #NMSettingDcb
+ * @user_priority: the User Priority (0 - 7) to retrieve the group bandwidth percentage for
+ *
+ * Returns: the allowed bandwidth percentage of @user_priority in its priority group.
+ * These values are only valid when #NMSettingDcb:priority-group-flags includes the
+ * %NM_SETTING_DCB_FLAG_ENABLE flag.
+ *
+ * Since: 0.9.10
+ **/
+guint
+nm_setting_dcb_get_priority_bandwidth (NMSettingDcb *setting, guint user_priority)
+{
+	g_return_val_if_fail (NM_IS_SETTING_DCB (setting), 0);
+	g_return_val_if_fail (user_priority <= 7, FALSE);
+
+	return NM_SETTING_DCB_GET_PRIVATE (setting)->priority_bandwidth[user_priority];
+}
+
+/**
+ * nm_setting_dcb_set_priority_bandwidth:
+ * @setting: the #NMSettingDcb
+ * @user_priority: the User Priority (0 - 7) to set the bandwidth percentage for
+ * @bandwidth_percent: the bandwidth percentage (0 - 100) that @user_priority is
+ * allowed to use within its priority group
+ *
+ * These values are only valid when #NMSettingDcb:priority-group-flags includes
+ * the %NM_SETTING_DCB_FLAG_ENABLE flag.
+ *
+ * Since: 0.9.10
+ **/
+void
+nm_setting_dcb_set_priority_bandwidth (NMSettingDcb *setting,
+                                       guint user_priority,
+                                       guint bandwidth_percent)
+{
+	NMSettingDcbPrivate *priv;
+
+	g_return_if_fail (NM_IS_SETTING_DCB (setting));
+	g_return_if_fail (user_priority <= 7);
+	g_return_if_fail (bandwidth_percent <= 100);
+
+	priv = NM_SETTING_DCB_GET_PRIVATE (setting);
+	if (priv->priority_bandwidth[user_priority] != bandwidth_percent) {
+		priv->priority_bandwidth[user_priority] = bandwidth_percent;
+		g_object_notify (G_OBJECT (setting), NM_SETTING_DCB_PRIORITY_BANDWIDTH);
+	}
+}
+
+/**
+ * nm_setting_dcb_get_priority_strict_bandwidth:
+ * @setting: the #NMSettingDcb
+ * @user_priority: the User Priority (0 - 7) to retrieve strict bandwidth for
+ *
+ * Returns: %TRUE if @user_priority may use all of the bandwidth allocated to its
+ * assigned group, or %FALSE if not. These values are only valid when
+ * #NMSettingDcb:priority-group-flags includes the %NM_SETTING_DCB_FLAG_ENABLE flag.
+ *
+ * Since: 0.9.10
+ **/
+gboolean
+nm_setting_dcb_get_priority_strict_bandwidth (NMSettingDcb *setting, guint user_priority)
+{
+	g_return_val_if_fail (NM_IS_SETTING_DCB (setting), 0);
+	g_return_val_if_fail (user_priority <= 7, FALSE);
+
+	return !!NM_SETTING_DCB_GET_PRIVATE (setting)->priority_strict[user_priority];
+}
+
+/**
+ * nm_setting_dcb_set_priority_strict_bandwidth:
+ * @setting: the #NMSettingDcb
+ * @user_priority: the User Priority (0 - 7) to set strict bandwidth for
+ * @strict: %TRUE to allow @user_priority to use all the bandwidth allocated to
+ * its priority group, or %FALSE if not
+ *
+ * These values are only valid when #NMSettingDcb:priority-group-flags includes
+ * the %NM_SETTING_DCB_FLAG_ENABLE flag.
+ *
+ * Since: 0.9.10
+ **/
+void
+nm_setting_dcb_set_priority_strict_bandwidth (NMSettingDcb *setting,
+                                              guint user_priority,
+                                              gboolean strict)
+{
+	NMSettingDcbPrivate *priv;
+	guint uint_strict = strict ? 1 : 0;
+
+	g_return_if_fail (NM_IS_SETTING_DCB (setting));
+	g_return_if_fail (user_priority <= 7);
+
+	priv = NM_SETTING_DCB_GET_PRIVATE (setting);
+	if (priv->priority_strict[user_priority] != uint_strict) {
+		priv->priority_strict[user_priority] = uint_strict;
+		g_object_notify (G_OBJECT (setting), NM_SETTING_DCB_PRIORITY_STRICT_BANDWIDTH);
+	}
+}
+
+/**
+ * nm_setting_dcb_get_priority_traffic_class:
+ * @setting: the #NMSettingDcb
+ * @user_priority: the User Priority (0 - 7) to retrieve the traffic class for
+ *
+ * Returns: the traffic class assigned to @user_priority. These values are only
+ * valid when #NMSettingDcb:priority-group-flags includes the
+ * %NM_SETTING_DCB_FLAG_ENABLE flag.
+ *
+ * Since: 0.9.10
+ **/
+guint
+nm_setting_dcb_get_priority_traffic_class (NMSettingDcb *setting, guint user_priority)
+{
+	g_return_val_if_fail (NM_IS_SETTING_DCB (setting), 0);
+	g_return_val_if_fail (user_priority <= 7, FALSE);
+
+	return NM_SETTING_DCB_GET_PRIVATE (setting)->priority_traffic_class[user_priority];
+}
+
+/**
+ * nm_setting_dcb_set_priority_traffic_clas:
+ * @setting: the #NMSettingDcb
+ * @user_priority: the User Priority (0 - 7) to set the bandwidth percentage for
+ * @traffic_class: the traffic_class (0 - 7) that @user_priority should map to
+ *
+ * These values are only valid when #NMSettingDcb:priority-group-flags includes
+ * the %NM_SETTING_DCB_FLAG_ENABLE flag.
+ *
+ * Since: 0.9.10
+ **/
+void
+nm_setting_dcb_set_priority_traffic_class (NMSettingDcb *setting,
+                                           guint user_priority,
+                                           guint traffic_class)
+{
+	NMSettingDcbPrivate *priv;
+
+	g_return_if_fail (NM_IS_SETTING_DCB (setting));
+	g_return_if_fail (user_priority <= 7);
+	g_return_if_fail (traffic_class <= 7);
+
+	priv = NM_SETTING_DCB_GET_PRIVATE (setting);
+	if (priv->priority_traffic_class[user_priority] != traffic_class) {
+		priv->priority_traffic_class[user_priority] = traffic_class;
+		g_object_notify (G_OBJECT (setting), NM_SETTING_DCB_PRIORITY_TRAFFIC_CLASS);
+	}
+}
+
+/******************************************************************/
+
+#define DCB_FLAGS_ALL (NM_SETTING_DCB_FLAG_ENABLE | \
+                       NM_SETTING_DCB_FLAG_ADVERTISE | \
+                       NM_SETTING_DCB_FLAG_WILLING)
+
+static gboolean
+check_dcb_flags (NMSettingDcbFlags flags, const char *prop_name, GError **error)
+{
+	if (flags & ~DCB_FLAGS_ALL) {
+		g_set_error_literal (error,
+		                     NM_SETTING_DCB_ERROR,
+		                     NM_SETTING_DCB_ERROR_INVALID_PROPERTY,
+		                     _("flags invalid"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_DCB_SETTING_NAME, prop_name);
+		return FALSE;
+	}
+
+	if (!(flags & NM_SETTING_DCB_FLAG_ENABLE) && (flags & ~NM_SETTING_DCB_FLAG_ENABLE)) {
+		g_set_error_literal (error,
+		                     NM_SETTING_DCB_ERROR,
+		                     NM_SETTING_DCB_ERROR_INVALID_PROPERTY,
+		                     _("flags invalid - disabled"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_DCB_SETTING_NAME, prop_name);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static gboolean
+check_uint_array (const guint *array,
+                  guint len,
+                  NMSettingDcbFlags flags,
+                  guint max,
+                  guint extra,
+                  gboolean sum_pct,
+                  const char *prop_name,
+                  GError **error)
+{
+	guint i, sum = 0;
+
+	/* Ensure each element is <= to max or equals extra */
+	for (i = 0; i < len; i++) {
+		if (!(flags & NM_SETTING_DCB_FLAG_ENABLE) && array[i]) {
+			g_set_error_literal (error,
+			                     NM_SETTING_DCB_ERROR,
+			                     NM_SETTING_DCB_ERROR_INVALID_PROPERTY,
+			                     _("property invalid (not enabled)"));
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_DCB_SETTING_NAME, prop_name);
+			return FALSE;
+		}
+
+		if ((array[i] > max) && (array[i] != extra)) {
+			g_set_error_literal (error,
+			                     NM_SETTING_DCB_ERROR,
+			                     NM_SETTING_DCB_ERROR_INVALID_PROPERTY,
+			                     _("element invalid"));
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_DCB_SETTING_NAME, prop_name);
+			return FALSE;
+		}
+		sum += array[i];
+	}
+
+	/* Verify sum of percentages */
+	if (sum_pct) {
+		if (flags & NM_SETTING_DCB_FLAG_ENABLE) {
+			/* If the feature is enabled, sum must equal 100% */
+			if (sum != 100) {
+				g_set_error_literal (error,
+				                     NM_SETTING_DCB_ERROR,
+				                     NM_SETTING_DCB_ERROR_INVALID_PROPERTY,
+				                     _("sum not 100%"));
+				g_prefix_error (error, "%s.%s: ", NM_SETTING_DCB_SETTING_NAME, prop_name);
+				return FALSE;
+			}
+		} else {
+			/* If the feature is disabled, sum must equal 0%, which was checked
+			 * by the for() loop above.
+			 */
+			g_assert_cmpint (sum, ==, 0);
+		}
+	}
+
+	return TRUE;
+}
+
+static gboolean
+check_priority (gint val,
+                NMSettingDcbFlags flags,
+                const char *prop_name,
+                GError **error)
+{
+	if (!(flags & NM_SETTING_DCB_FLAG_ENABLE) && (val >= 0)) {
+		g_set_error_literal (error,
+		                     NM_SETTING_DCB_ERROR,
+		                     NM_SETTING_DCB_ERROR_INVALID_PROPERTY,
+		                     _("property invalid (not enabled)"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_DCB_SETTING_NAME, prop_name);
+		return FALSE;
+	}
+
+	if (val < -1 || val > 7) {
+		g_set_error_literal (error,
+		                     NM_SETTING_DCB_ERROR,
+		                     NM_SETTING_DCB_ERROR_INVALID_PROPERTY,
+		                     _("property invalid"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_DCB_SETTING_NAME, prop_name);
+		return FALSE;
+	}
+	return TRUE;
+}
+
+static gboolean
+verify (NMSetting *setting, GSList *all_settings, GError **error)
+{
+	NMSettingDcbPrivate *priv = NM_SETTING_DCB_GET_PRIVATE (setting);
+
+	if (!check_dcb_flags (priv->app_fcoe_flags, NM_SETTING_DCB_APP_FCOE_FLAGS, error))
+		return FALSE;
+
+	if (!check_priority (priv->app_fcoe_priority, priv->app_fcoe_flags, NM_SETTING_DCB_APP_FCOE_PRIORITY, error))
+		return FALSE;
+
+	if (!priv->app_fcoe_mode) {
+		g_set_error_literal (error,
+		                     NM_SETTING_DCB_ERROR,
+		                     NM_SETTING_DCB_ERROR_MISSING_PROPERTY,
+		                     _("property missing"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_DCB_SETTING_NAME, NM_SETTING_DCB_APP_FCOE_MODE);
+		return FALSE;
+	}
+
+	if (strcmp (priv->app_fcoe_mode, NM_SETTING_DCB_FCOE_MODE_FABRIC) &&
+	    strcmp (priv->app_fcoe_mode, NM_SETTING_DCB_FCOE_MODE_VN2VN)) {
+		g_set_error_literal (error,
+		                     NM_SETTING_DCB_ERROR,
+		                     NM_SETTING_DCB_ERROR_INVALID_PROPERTY,
+		                     _("property invalid"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_DCB_SETTING_NAME, NM_SETTING_DCB_APP_FCOE_MODE);
+		return FALSE;
+	}
+
+	if (!check_dcb_flags (priv->app_iscsi_flags, NM_SETTING_DCB_APP_ISCSI_FLAGS, error))
+		return FALSE;
+
+	if (!check_priority (priv->app_iscsi_priority, priv->app_iscsi_flags, NM_SETTING_DCB_APP_ISCSI_PRIORITY, error))
+		return FALSE;
+
+	if (!check_dcb_flags (priv->app_fip_flags, NM_SETTING_DCB_APP_FIP_FLAGS, error))
+		return FALSE;
+
+	if (!check_priority (priv->app_fip_priority, priv->app_fip_flags, NM_SETTING_DCB_APP_FIP_PRIORITY, error))
+		return FALSE;
+
+	if (!check_dcb_flags (priv->pfc_flags, NM_SETTING_DCB_PRIORITY_FLOW_CONTROL_FLAGS, error))
+		return FALSE;
+
+	if (!check_uint_array (priv->pfc, G_N_ELEMENTS (priv->pfc), priv->pfc_flags, 1, 0, FALSE, NM_SETTING_DCB_PRIORITY_FLOW_CONTROL, error))
+		return FALSE;
+
+	if (!check_dcb_flags (priv->priority_group_flags, NM_SETTING_DCB_PRIORITY_GROUP_FLAGS, error))
+		return FALSE;
+
+	if (!check_uint_array (priv->priority_group_id,
+	                       G_N_ELEMENTS (priv->priority_group_id),
+	                       priv->priority_group_flags,
+	                       7,
+	                       15,
+	                       FALSE,
+	                       NM_SETTING_DCB_PRIORITY_GROUP_ID,
+	                       error))
+		return FALSE;
+
+	if (!check_uint_array (priv->priority_group_bandwidth,
+	                       G_N_ELEMENTS (priv->priority_group_bandwidth),
+	                       priv->priority_group_flags,
+	                       100,
+	                       0,
+	                       TRUE,
+	                       NM_SETTING_DCB_PRIORITY_GROUP_BANDWIDTH,
+	                       error))
+		return FALSE;
+
+	/* FIXME: sum bandwidths in each group */
+	if (!check_uint_array (priv->priority_bandwidth,
+	                       G_N_ELEMENTS (priv->priority_bandwidth),
+	                       priv->priority_group_flags,
+	                       100,
+	                       0,
+	                       FALSE,
+	                       NM_SETTING_DCB_PRIORITY_BANDWIDTH,
+	                       error))
+		return FALSE;
+
+	if (!check_uint_array (priv->priority_strict,
+	                       G_N_ELEMENTS (priv->priority_strict),
+	                       priv->priority_group_flags,
+	                       1,
+	                       0,
+	                       FALSE,
+	                       NM_SETTING_DCB_PRIORITY_STRICT_BANDWIDTH,
+	                       error))
+		return FALSE;
+
+	if (!check_uint_array (priv->priority_traffic_class,
+	                       G_N_ELEMENTS (priv->priority_traffic_class),
+	                       priv->priority_group_flags,
+	                       7,
+	                       0,
+	                       FALSE,
+	                       NM_SETTING_DCB_PRIORITY_TRAFFIC_CLASS,
+	                       error))
+		return FALSE;
+
+	return TRUE;
+}
+
+/******************************************************************/
+
+static void
+nm_setting_dcb_init (NMSettingDcb *setting)
+{
+}
+
+static inline void
+set_uint_array (const GValue *v, uint *a, size_t len)
+{
+	GArray *src = g_value_get_boxed (v);
+	const guint total_len = len * sizeof (a[0]);
+
+	memset (a, 0, total_len);
+	if (src) {
+		g_return_if_fail (g_array_get_element_size (src) == sizeof (a[0]));
+		g_return_if_fail (src->len == len);
+		memcpy (a, src->data, total_len);
+	}
+}
+#define SET_UINT_ARRAY(v, a)  set_uint_array (v, a, G_N_ELEMENTS (a))
+
+static void
+set_property (GObject *object, guint prop_id,
+              const GValue *value, GParamSpec *pspec)
+{
+	NMSettingDcbPrivate *priv = NM_SETTING_DCB_GET_PRIVATE (object);
+
+	switch (prop_id) {
+	case PROP_APP_FCOE_FLAGS:
+		priv->app_fcoe_flags = g_value_get_uint (value);
+		break;
+	case PROP_APP_FCOE_PRIORITY:
+		priv->app_fcoe_priority = g_value_get_int (value);
+		break;
+	case PROP_APP_FCOE_MODE:
+		priv->app_fcoe_mode = g_value_dup_string (value);
+		break;
+	case PROP_APP_ISCSI_FLAGS:
+		priv->app_iscsi_flags = g_value_get_uint (value);
+		break;
+	case PROP_APP_ISCSI_PRIORITY:
+		priv->app_iscsi_priority = g_value_get_int (value);
+		break;
+	case PROP_APP_FIP_FLAGS:
+		priv->app_fip_flags = g_value_get_uint (value);
+		break;
+	case PROP_APP_FIP_PRIORITY:
+		priv->app_fip_priority = g_value_get_int (value);
+		break;
+	case PROP_PFC_FLAGS:
+		priv->pfc_flags = g_value_get_uint (value);
+		break;
+	case PROP_PFC:
+		SET_UINT_ARRAY (value, priv->pfc);
+		break;
+	case PROP_PRIORITY_GROUP_FLAGS:
+		priv->priority_group_flags = g_value_get_uint (value);
+		break;
+	case PROP_PRIORITY_GROUP_ID:
+		SET_UINT_ARRAY (value, priv->priority_group_id);
+		break;
+	case PROP_PRIORITY_GROUP_BANDWIDTH:
+		SET_UINT_ARRAY (value, priv->priority_group_bandwidth);
+		break;
+	case PROP_PRIORITY_BANDWIDTH:
+		SET_UINT_ARRAY (value, priv->priority_bandwidth);
+		break;
+	case PROP_PRIORITY_STRICT:
+		SET_UINT_ARRAY (value, priv->priority_strict);
+		break;
+	case PROP_PRIORITY_TRAFFIC_CLASS:
+		SET_UINT_ARRAY (value, priv->priority_traffic_class);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+#define TAKE_UINT_ARRAY(v, a) \
+{ \
+	guint len = G_N_ELEMENTS (a); \
+	GArray *dst = g_array_sized_new (FALSE, TRUE, sizeof (guint), len); \
+	g_array_append_vals (dst, (a), len); \
+	g_value_take_boxed (v, dst); \
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+              GValue *value, GParamSpec *pspec)
+{
+	NMSettingDcb *setting = NM_SETTING_DCB (object);
+	NMSettingDcbPrivate *priv = NM_SETTING_DCB_GET_PRIVATE (setting);
+
+	switch (prop_id) {
+	case PROP_APP_FCOE_FLAGS:
+		g_value_set_uint (value, priv->app_fcoe_flags);
+		break;
+	case PROP_APP_FCOE_PRIORITY:
+		g_value_set_int (value, priv->app_fcoe_priority);
+		break;
+	case PROP_APP_FCOE_MODE:
+		g_value_set_string (value, priv->app_fcoe_mode);
+		break;
+	case PROP_APP_ISCSI_FLAGS:
+		g_value_set_uint (value, priv->app_iscsi_flags);
+		break;
+	case PROP_APP_ISCSI_PRIORITY:
+		g_value_set_int (value, priv->app_iscsi_priority);
+		break;
+	case PROP_APP_FIP_FLAGS:
+		g_value_set_uint (value, priv->app_fip_flags);
+		break;
+	case PROP_APP_FIP_PRIORITY:
+		g_value_set_int (value, priv->app_fip_priority);
+		break;
+	case PROP_PFC_FLAGS:
+		g_value_set_uint (value, priv->pfc_flags);
+		break;
+	case PROP_PFC:
+		TAKE_UINT_ARRAY (value, priv->pfc);
+		break;
+	case PROP_PRIORITY_GROUP_FLAGS:
+		g_value_set_uint (value, priv->priority_group_flags);
+		break;
+	case PROP_PRIORITY_GROUP_ID:
+		TAKE_UINT_ARRAY (value, priv->priority_group_id);
+		break;
+	case PROP_PRIORITY_GROUP_BANDWIDTH:
+		TAKE_UINT_ARRAY (value, priv->priority_group_bandwidth);
+		break;
+	case PROP_PRIORITY_BANDWIDTH:
+		TAKE_UINT_ARRAY (value, priv->priority_bandwidth);
+		break;
+	case PROP_PRIORITY_STRICT:
+		TAKE_UINT_ARRAY (value, priv->priority_strict);
+		break;
+	case PROP_PRIORITY_TRAFFIC_CLASS:
+		TAKE_UINT_ARRAY (value, priv->priority_traffic_class);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+nm_setting_dcb_class_init (NMSettingDcbClass *setting_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+	NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
+
+	g_type_class_add_private (setting_class, sizeof (NMSettingDcbPrivate));
+
+	/* virtual methods */
+	object_class->set_property = set_property;
+	object_class->get_property = get_property;
+	parent_class->verify       = verify;
+
+	/* Properties */
+	/**
+	 * NMSettingDcb:app-fcoe-flags:
+	 *
+	 * Specifies the #NMSettingDcbFlags for the DCB FCoE application.  Flags may
+	 * be any combination of %NM_SETTING_DCB_FLAG_ENABLE,
+	 * %NM_SETTING_DCB_FLAG_ADVERTISE, and %NM_SETTING_DCB_FLAG_WILLING.
+	 *
+	 * Since: 0.9.10
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_APP_FCOE_FLAGS,
+		 g_param_spec_uint (NM_SETTING_DCB_APP_FCOE_FLAGS,
+		                    "App FCoE Flags",
+		                    "Specifies the flags for the DCB FCoE application. "
+		                    "Flags may be any combination of 0x1 (enable), 0x2 "
+		                    "(advertise), and 0x4 (willing).",
+		                    0, DCB_FLAGS_ALL, 0,
+		                    G_PARAM_READWRITE));
+
+	/**
+	 * NMSettingDcb:app-fcoe-priority:
+	 *
+	 * The highest User Priority (0 - 7) which FCoE frames should use, or -1 for
+	 * default priority.  Only used when the #NMSettingDcb:app-fcoe-flags
+	 * property includes the %NM_SETTING_DCB_FLAG_ENABLE flag.
+	 *
+	 * Since: 0.9.10
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_APP_FCOE_PRIORITY,
+		 g_param_spec_int (NM_SETTING_DCB_APP_FCOE_PRIORITY,
+		                   "App FCoE Priority",
+		                   "The highest User Priority (0 - 7) which FCoE "
+		                   "frames should use, or -1 for default priority. Only "
+		                   "used when the 'app-fcoe-flags' property includes "
+		                   "the 'enabled' flag.",
+		                   -1, 7, -1,
+		                   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+	/**
+	 * NMSettingDcb:app-fcoe-mode:
+	 *
+	 * The FCoE controller mode; either %NM_SETTING_DCB_FCOE_MODE_FABRIC
+	 * (default) or %NM_SETTING_DCB_FCOE_MODE_VN2VN.
+	 *
+	 * Since: 0.9.10
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_APP_FCOE_MODE,
+		 g_param_spec_string (NM_SETTING_DCB_APP_FCOE_MODE,
+		                      "App FCoE Mode",
+		                      "The FCoe controller mode; either 'fabric' (default) "
+		                      "or 'vn2vn'.",
+		                      NM_SETTING_DCB_FCOE_MODE_FABRIC,
+		                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+	/**
+	 * NMSettingDcb:app-iscsi-flags:
+	 *
+	 * Specifies the #NMSettingDcbFlags for the DCB iSCSI application.  Flags
+	 * may be any combination of %NM_SETTING_DCB_FLAG_ENABLE,
+	 * %NM_SETTING_DCB_FLAG_ADVERTISE, and %NM_SETTING_DCB_FLAG_WILLING.
+	 *
+	 * Since: 0.9.10
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_APP_ISCSI_FLAGS,
+		 g_param_spec_uint (NM_SETTING_DCB_APP_ISCSI_FLAGS,
+		                    "App iSCSI Flags",
+		                    "Specifies the flags for the DCB iSCSI application. "
+		                    "Flags may be any combination of 0x1 (enable), 0x2 "
+		                    "(advertise), and 0x4 (willing).",
+		                    0, DCB_FLAGS_ALL, 0,
+		                    G_PARAM_READWRITE));
+
+	/**
+	 * NMSettingDcb:app-iscsi-priority:
+	 *
+	 * The highest User Priority (0 - 7) which iSCSI frames should use, or -1
+	 * for default priority. Only used when the #NMSettingDcb:app-iscsi-flags
+	 * property includes the %NM_SETTING_DCB_FLAG_ENABLE flag.
+	 *
+	 * Since: 0.9.10
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_APP_ISCSI_PRIORITY,
+		 g_param_spec_int (NM_SETTING_DCB_APP_ISCSI_PRIORITY,
+		                   "App iSCSI Priority",
+		                   "The highest User Priority (0 - 7) which iSCSI "
+		                   "frames should use, or -1 for default priority. Only "
+		                   "used when the 'app-iscsi-flags' property includes "
+		                   "the 'enabled' flag.",
+		                   -1, 7, -1,
+		                   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+	/**
+	 * NMSettingDcb:app-fip-flags:
+	 *
+	 * Specifies the #NMSettingDcbFlags for the DCB FIP application.  Flags may
+	 * be any combination of %NM_SETTING_DCB_FLAG_ENABLE,
+	 * %NM_SETTING_DCB_FLAG_ADVERTISE, and %NM_SETTING_DCB_FLAG_WILLING.
+	 *
+	 * Since: 0.9.10
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_APP_FIP_FLAGS,
+		 g_param_spec_uint (NM_SETTING_DCB_APP_FIP_FLAGS,
+		                    "App FIP Flags",
+		                    "Specifies the flags for the DCB FIP application. "
+		                    "Flags may be any combination of 0x1 (enable), 0x2 "
+		                    "(advertise), and 0x4 (willing).",
+		                    0, DCB_FLAGS_ALL, 0,
+		                    G_PARAM_READWRITE));
+
+	/**
+	 * NMSettingDcb:app-fip-priority:
+	 *
+	 * The highest User Priority (0 - 7) which FIP frames should use, or -1 for
+	 * default priority.  Only used when the #NMSettingDcb:app-fip-flags
+	 * property includes the %NM_SETTING_DCB_FLAG_ENABLE flag.
+	 *
+	 * Since: 0.9.10
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_APP_FIP_PRIORITY,
+		 g_param_spec_int (NM_SETTING_DCB_APP_FIP_PRIORITY,
+		                   "App FIP Priority",
+		                   "The highest User Priority (0 - 7) which FIP "
+		                   "frames should use, or -1 for default priority. Only "
+		                   "used when the 'app-fip-flags' property includes "
+		                   "the 'enabled' flag.",
+		                   -1, 7, -1,
+		                   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+	/**
+	 * NMSettingDcb:priority-flow-control-flags:
+	 *
+	 * Specifies the #NMSettingDcbFlags for DCB Priority Flow Control (PFC).
+	 * Flags may be any combination of %NM_SETTING_DCB_FLAG_ENABLE,
+	 * %NM_SETTING_DCB_FLAG_ADVERTISE, and %NM_SETTING_DCB_FLAG_WILLING.
+	 *
+	 * Since: 0.9.10
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_PFC_FLAGS,
+		 g_param_spec_uint (NM_SETTING_DCB_PRIORITY_FLOW_CONTROL_FLAGS,
+		                    "Priority Flow Control Flags",
+		                    "Specifies the flags for DCB Priority Flow Control. "
+		                    "Flags may be any combination of 0x1 (enable), 0x2 "
+		                    "(advertise), and 0x4 (willing).",
+		                    0, DCB_FLAGS_ALL, 0,
+		                    G_PARAM_READWRITE));
+
+	/**
+	 * NMSettingDcb:priority-flow-control:
+	 *
+	 * An array of 8 uint values, where the array index corresponds to the User
+	 * Priority (0 - 7) and the value indicates whether or not the corresponding
+	 * priority should transmit priority pause.  Allowed values are 0 (do not
+	 * transmit pause) and 1 (transmit pause).
+	 *
+	 * Since: 0.9.10
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_PFC,
+		 _nm_param_spec_specialized (NM_SETTING_DCB_PRIORITY_FLOW_CONTROL,
+		                             "Priority Flow Control",
+		                             "An array of 8 uint values, where the array index "
+		                             "corresponds to the User Priority (0 - 7) and the "
+		                             "value indicates whether or not the corresponding "
+		                             "priority should transmit priority pause.  Allowed "
+		                             "values are 0 (do not transmit pause) and 1 "
+		                             "(transmit pause).",
+		                             DBUS_TYPE_G_UINT_ARRAY,
+		                             G_PARAM_READWRITE));
+
+	/**
+	 * NMSettingDcb:priority-group-flags:
+	 *
+	 * Specifies the #NMSettingDcbFlags for DCB Priority Groups.  Flags may be
+	 * any combination of %NM_SETTING_DCB_FLAG_ENABLE,
+	 * %NM_SETTING_DCB_FLAG_ADVERTISE, and %NM_SETTING_DCB_FLAG_WILLING.
+	 *
+	 * Since: 0.9.10
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_PRIORITY_GROUP_FLAGS,
+		 g_param_spec_uint (NM_SETTING_DCB_PRIORITY_GROUP_FLAGS,
+		                    "Priority Group Flags",
+		                    "Specifies the flags for DCB Priority Groups. "
+		                    "Flags may be any combination of 0x1 (enable), 0x2 "
+		                    "(advertise), and 0x4 (willing).",
+		                    0, DCB_FLAGS_ALL, 0,
+		                    G_PARAM_READWRITE));
+
+	/**
+	 * NMSettingDcb:priority-group-id:
+	 *
+	 * An array of 8 uint values, where the array index corresponds to the User
+	 * Priority (0 - 7) and the value indicates the Priority Group ID.  Allowed
+	 * Priority Group ID values are 0 - 7 or 15 for the unrestricted group.
+	 *
+	 * Since: 0.9.10
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_PRIORITY_GROUP_ID,
+		 _nm_param_spec_specialized (NM_SETTING_DCB_PRIORITY_GROUP_ID,
+		                             "Priority Group ID",
+		                             "An array of 8 uint values, where the array "
+		                             "index corresponds to the User Priority (0 - 7) "
+		                             "and the value indicates the Priority Group ID. "
+		                             "Allowed Priority Group ID values are 0 - 7 or "
+		                             "15 for the unrestricted group.",
+		                             DBUS_TYPE_G_UINT_ARRAY,
+		                             G_PARAM_READWRITE));
+
+	/**
+	 * NMSettingDcb:priority-group-bandwidth:
+	 *
+	 * An array of 8 uint values, where the array index corresponds to the
+	 * Priority Group ID (0 - 7) and the value indicates the percentage of link
+	 * bandwidth allocated to that group.  Allowed values are 0 - 100, and the
+	 * sum of all values must total 100 percent.
+	 *
+	 * Since: 0.9.10
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_PRIORITY_GROUP_BANDWIDTH,
+		 _nm_param_spec_specialized (NM_SETTING_DCB_PRIORITY_GROUP_BANDWIDTH,
+		                             "Priority Group Bandwidth",
+		                             "An array of 8 uint values, where the array index "
+		                             "corresponds to the Priority Group ID (0 - 7) and "
+		                             "the value indicates the percentage of link bandwidth "
+		                             "allocated to that group.  Allowed values are 0 - 100, "
+		                             "and the sum of all values must total 100 percent.",
+		                             DBUS_TYPE_G_UINT_ARRAY,
+		                             G_PARAM_READWRITE));
+
+	/**
+	 * NMSettingDcb:priority-bandwidth:
+	 *
+	 * An array of 8 uint values, where the array index corresponds to the User
+	 * Priority (0 - 7) and the value indicates the percentage of bandwidth of
+	 * the priority's assigned group that the priority may use.  The sum of all
+	 * percentages for priorities which belong to the same group must total 100
+	 * percent.
+	 *
+	 * Since: 0.9.10
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_PRIORITY_BANDWIDTH,
+		 _nm_param_spec_specialized (NM_SETTING_DCB_PRIORITY_BANDWIDTH,
+		                             "Priority Bandwidth",
+		                             "An array of 8 uint values, where the array index "
+		                             "corresponds to the User Priority (0 - 7) and the "
+		                             "value indicates the percentage of bandwidth of "
+		                             "the priority's assigned group that the priority may "
+		                             "use.  The sum of all percentages for priorities which "
+		                             "belong to the same group must total 100 percent.",
+		                             DBUS_TYPE_G_UINT_ARRAY,
+		                             G_PARAM_READWRITE));
+
+	/**
+	 * NMSettingDcb:priority-strict-bandwidth:
+	 *
+	 * An array of 8 uint values, where the array index corresponds to the User
+	 * Priority (0 - 7) and the value indicates whether or not the priority may
+	 * use all of the bandwidth allocated to its assigned group.  Allowed values
+	 * are 0 (the priority may not utilize all bandwidth) or 1 (the priority may
+	 * utilize all bandwidth).
+	 *
+	 * Since: 0.9.10
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_PRIORITY_STRICT,
+		 _nm_param_spec_specialized (NM_SETTING_DCB_PRIORITY_STRICT_BANDWIDTH,
+		                             "Priority Strict Bandwidth",
+		                             "An array of 8 uint values, where the array index "
+		                             "corresponds to the User Priority (0 - 7) and the "
+		                             "value indicates whether or not the priority may "
+		                             "use all of the bandwidth allocated to its assigned "
+		                             "group. Allowed values are 0 (the priority may not "
+		                             "utilize all bandwidth) or 1 (the priority may "
+		                             "utilize all bandwidth).",
+		                             DBUS_TYPE_G_UINT_ARRAY,
+		                             G_PARAM_READWRITE));
+
+	/**
+	 * NMSettingDcb:priority-traffic-class:
+	 *
+	 * An array of 8 uint values, where the array index corresponds to the User
+	 * Priority (0 - 7) and the value indicates the traffic class (0 - 7) to
+	 * which the priority is mapped.
+	 *
+	 * Since: 0.9.10
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_PRIORITY_TRAFFIC_CLASS,
+		 _nm_param_spec_specialized (NM_SETTING_DCB_PRIORITY_TRAFFIC_CLASS,
+		                             "Priority Traffic Class",
+		                             "An array of 8 uint values, where the array index "
+		                             "corresponds to the User Priority (0 - 7) and the "
+		                             "value indicates the traffic class (0 - 7) to which "
+		                             "the priority is mapped.",
+		                             DBUS_TYPE_G_UINT_ARRAY,
+		                             G_PARAM_READWRITE));
+}
+
diff --git a/libnm-util/nm-setting-dcb.h b/libnm-util/nm-setting-dcb.h
new file mode 100644
index 00000000..37dd36e7
--- /dev/null
+++ b/libnm-util/nm-setting-dcb.h
@@ -0,0 +1,189 @@
+/* -*- 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.
+ *
+ * (C) Copyright 2013 Red Hat, Inc.
+ */
+
+#ifndef NM_SETTING_DCB_H
+#define NM_SETTING_DCB_H
+
+#include <nm-setting.h>
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_SETTING_DCB            (nm_setting_dcb_get_type ())
+#define NM_SETTING_DCB(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_DCB, NMSettingDcb))
+#define NM_SETTING_DCB_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_DCB, NMSettingDcbClass))
+#define NM_IS_SETTING_DCB(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_DCB))
+#define NM_IS_SETTING_DCB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_DCB))
+#define NM_SETTING_DCB_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_DCB, NMSettingDcbClass))
+
+#define NM_SETTING_DCB_SETTING_NAME "dcb"
+
+/**
+ * NMSettingDcbError:
+ * @NM_SETTING_DCB_ERROR_UNKNOWN: unknown or unclassified error
+ * @NM_SETTING_DCB_ERROR_INVALID_PROPERTY: the property was invalid
+ * @NM_SETTING_DCB_ERROR_MISSING_PROPERTY: the property was missing and is
+ * required
+ */
+typedef enum {
+	NM_SETTING_DCB_ERROR_UNKNOWN = 0,      /*< nick=UnknownError >*/
+	NM_SETTING_DCB_ERROR_INVALID_PROPERTY, /*< nick=InvalidProperty >*/
+	NM_SETTING_DCB_ERROR_MISSING_PROPERTY  /*< nick=MissingProperty >*/
+} NMSettingDcbError;
+
+#define NM_SETTING_DCB_ERROR nm_setting_dcb_error_quark ()
+GQuark nm_setting_dcb_error_quark (void);
+
+/**
+ * NMSettingDcbFlags:
+ * @NM_SETTING_DCB_FLAG_NONE: no flag
+ * @NM_SETTING_DCB_FLAG_ENABLE: the feature is enabled
+ * @NM_SETTING_DCB_FLAG_ADVERTISE: the feature is advertised
+ * @NM_SETTING_DCB_FLAG_WILLING: the feature is willing to change based on
+ * peer configuration advertisements
+ *
+ * DCB feature flags.
+ *
+ * Since: 0.9.10
+ **/
+typedef enum {
+	NM_SETTING_DCB_FLAG_NONE      = 0x00000000,
+	NM_SETTING_DCB_FLAG_ENABLE    = 0x00000001,
+	NM_SETTING_DCB_FLAG_ADVERTISE = 0x00000002,
+	NM_SETTING_DCB_FLAG_WILLING   = 0x00000004
+} NMSettingDcbFlags;
+
+/**
+ * NM_SETTING_DCB_FCOE_MODE_FABRIC:
+ *
+ * Indicates that the FCoE controller should use "fabric" mode (default)
+ *
+ * Since: 0.9.10
+ */
+#define NM_SETTING_DCB_FCOE_MODE_FABRIC  "fabric"
+
+/**
+ * NM_SETTING_DCB_FCOE_MODE_VN2VN:
+ *
+ * Indicates that the FCoE controller should use "VN2VN" mode.
+ *
+ * Since: 0.9.10
+ */
+#define NM_SETTING_DCB_FCOE_MODE_VN2VN   "vn2vn"
+
+
+/* Properties */
+#define NM_SETTING_DCB_APP_FCOE_FLAGS         "app-fcoe-flags"
+#define NM_SETTING_DCB_APP_FCOE_PRIORITY      "app-fcoe-priority"
+#define NM_SETTING_DCB_APP_FCOE_MODE          "app-fcoe-mode"
+
+#define NM_SETTING_DCB_APP_ISCSI_FLAGS        "app-iscsi-flags"
+#define NM_SETTING_DCB_APP_ISCSI_PRIORITY     "app-iscsi-priority"
+
+#define NM_SETTING_DCB_APP_FIP_FLAGS          "app-fip-flags"
+#define NM_SETTING_DCB_APP_FIP_PRIORITY       "app-fip-priority"
+
+#define NM_SETTING_DCB_PRIORITY_FLOW_CONTROL_FLAGS  "priority-flow-control-flags"
+#define NM_SETTING_DCB_PRIORITY_FLOW_CONTROL        "priority-flow-control"
+
+#define NM_SETTING_DCB_PRIORITY_GROUP_FLAGS      "priority-group-flags"
+#define NM_SETTING_DCB_PRIORITY_GROUP_ID         "priority-group-id"
+#define NM_SETTING_DCB_PRIORITY_GROUP_BANDWIDTH  "priority-group-bandwidth"
+#define NM_SETTING_DCB_PRIORITY_BANDWIDTH        "priority-bandwidth"
+#define NM_SETTING_DCB_PRIORITY_STRICT_BANDWIDTH "priority-strict-bandwidth"
+#define NM_SETTING_DCB_PRIORITY_TRAFFIC_CLASS    "priority-traffic-class"
+
+
+typedef struct {
+	NMSetting parent;
+} NMSettingDcb;
+
+typedef struct {
+	NMSettingClass parent;
+
+	/* Padding for future expansion */
+	void (*_reserved1) (void);
+	void (*_reserved2) (void);
+	void (*_reserved3) (void);
+	void (*_reserved4) (void);
+} NMSettingDcbClass;
+
+NM_AVAILABLE_IN_0_9_10
+GType nm_setting_dcb_get_type (void);
+
+NM_AVAILABLE_IN_0_9_10
+NMSetting *       nm_setting_dcb_new                      (void);
+
+NMSettingDcbFlags nm_setting_dcb_get_app_fcoe_flags     (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);
+gint              nm_setting_dcb_get_app_iscsi_priority (NMSettingDcb *setting);
+
+NMSettingDcbFlags nm_setting_dcb_get_app_fip_flags      (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);
+gboolean          nm_setting_dcb_get_priority_flow_control          (NMSettingDcb *setting,
+                                                                     guint user_priority);
+void              nm_setting_dcb_set_priority_flow_control          (NMSettingDcb *setting,
+                                                                     guint user_priority,
+                                                                     gboolean enabled);
+
+/* Priority Groups */
+NMSettingDcbFlags nm_setting_dcb_get_priority_group_flags (NMSettingDcb *setting);
+
+guint    nm_setting_dcb_get_priority_group_id         (NMSettingDcb *setting,
+                                                       guint user_priority);
+void     nm_setting_dcb_set_priority_group_id         (NMSettingDcb *setting,
+                                                       guint user_priority,
+                                                       guint group_id);
+
+guint    nm_setting_dcb_get_priority_group_bandwidth  (NMSettingDcb *setting,
+                                                       guint group_id);
+void     nm_setting_dcb_set_priority_group_bandwidth  (NMSettingDcb *setting,
+                                                       guint group_id,
+                                                       guint bandwidth_percent);
+
+guint    nm_setting_dcb_get_priority_bandwidth        (NMSettingDcb *setting,
+                                                       guint user_priority);
+void     nm_setting_dcb_set_priority_bandwidth        (NMSettingDcb *setting,
+                                                       guint user_priority,
+                                                       guint bandwidth_percent);
+
+gboolean nm_setting_dcb_get_priority_strict_bandwidth (NMSettingDcb *setting,
+                                                       guint user_priority);
+void     nm_setting_dcb_set_priority_strict_bandwidth (NMSettingDcb *setting,
+                                                       guint user_priority,
+                                                       gboolean strict);
+
+guint    nm_setting_dcb_get_priority_traffic_class    (NMSettingDcb *setting,
+                                                       guint user_priority);
+void     nm_setting_dcb_set_priority_traffic_class    (NMSettingDcb *setting,
+                                                       guint user_priority,
+                                                       guint traffic_class);
+
+G_END_DECLS
+
+#endif /* NM_SETTING_DCB_H */
diff --git a/libnm-util/nm-setting-generic.c b/libnm-util/nm-setting-generic.c
new file mode 100644
index 00000000..e32ae497
--- /dev/null
+++ b/libnm-util/nm-setting-generic.c
@@ -0,0 +1,100 @@
+/* -*- 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 2013 Red Hat, Inc.
+ */
+
+#include "config.h"
+
+#include "nm-setting-generic.h"
+#include "nm-setting-private.h"
+
+/**
+ * SECTION:nm-setting-generic
+ * @short_description: Describes connection properties for generic devices
+ * @include: nm-setting-generic.h
+ *
+ * The #NMSettingGeneric object is a #NMSetting subclass that describes
+ * optional properties that apply to "generic" devices (ie, devices that
+ * NetworkManager does not specifically recognize).
+ *
+ * There are currently no properties on this object; it exists only to be
+ * the "connection type" setting on #NMConnections for generic devices.
+ *
+ * Since: 0.9.10
+ **/
+
+/**
+ * nm_setting_generic_error_quark:
+ *
+ * Registers an error quark for #NMSettingGeneric if necessary.
+ *
+ * Returns: the error quark used for #NMSettingGeneric errors.
+ *
+ * Since: 0.9.10
+ **/
+GQuark
+nm_setting_generic_error_quark (void)
+{
+	static GQuark quark;
+
+	if (G_UNLIKELY (!quark))
+		quark = g_quark_from_static_string ("nm-setting-generic-error-quark");
+	return quark;
+}
+
+G_DEFINE_TYPE_WITH_CODE (NMSettingGeneric, nm_setting_generic, NM_TYPE_SETTING,
+                         _nm_register_setting (NM_SETTING_GENERIC_SETTING_NAME,
+                                               g_define_type_id,
+                                               1,
+                                               NM_SETTING_GENERIC_ERROR))
+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))
+
+typedef struct {
+	int dummy;
+} NMSettingGenericPrivate;
+
+/**************************************************************************/
+
+/**
+ * nm_setting_generic_new:
+ *
+ * Creates a new #NMSettingGeneric object with default values.
+ *
+ * Returns: (transfer full): the new empty #NMSettingGeneric object
+ *
+ * Since: 0.9.10
+ **/
+NMSetting *
+nm_setting_generic_new (void)
+{
+	return (NMSetting *) g_object_new (NM_TYPE_SETTING_GENERIC, NULL);
+}
+
+static void
+nm_setting_generic_init (NMSettingGeneric *setting)
+{
+}
+
+static void
+nm_setting_generic_class_init (NMSettingGenericClass *setting_class)
+{
+	g_type_class_add_private (setting_class, sizeof (NMSettingGenericPrivate));
+}
diff --git a/libnm-util/nm-setting-generic.h b/libnm-util/nm-setting-generic.h
new file mode 100644
index 00000000..1cabae08
--- /dev/null
+++ b/libnm-util/nm-setting-generic.h
@@ -0,0 +1,78 @@
+/* -*- 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 2013 Red Hat, Inc.
+ */
+
+#ifndef NM_SETTING_GENERIC_H
+#define NM_SETTING_GENERIC_H
+
+#include <nm-setting.h>
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_SETTING_GENERIC            (nm_setting_generic_get_type ())
+#define NM_SETTING_GENERIC(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_GENERIC, NMSettingGeneric))
+#define NM_SETTING_GENERIC_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_GENERIC, NMSettingGenericClass))
+#define NM_IS_SETTING_GENERIC(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_GENERIC))
+#define NM_IS_SETTING_GENERIC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_GENERIC))
+#define NM_SETTING_GENERIC_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_GENERIC, NMSettingGenericClass))
+
+#define NM_SETTING_GENERIC_SETTING_NAME "generic"
+
+/**
+ * NMSettingGenericError:
+ * @NM_SETTING_GENERIC_ERROR_UNKNOWN: unknown or unclassified error
+ * @NM_SETTING_GENERIC_ERROR_INVALID_PROPERTY: the property was invalid
+ * @NM_SETTING_GENERIC_ERROR_MISSING_PROPERTY: the property was missing and
+ * is required
+ *
+ * Since: 0.9.10
+ */
+typedef enum {
+	NM_SETTING_GENERIC_ERROR_UNKNOWN = 0,      /*< nick=UnknownError >*/
+	NM_SETTING_GENERIC_ERROR_INVALID_PROPERTY, /*< nick=InvalidProperty >*/
+	NM_SETTING_GENERIC_ERROR_MISSING_PROPERTY, /*< nick=MissingProperty >*/
+} NMSettingGenericError;
+
+#define NM_SETTING_GENERIC_ERROR nm_setting_generic_error_quark ()
+GQuark nm_setting_generic_error_quark (void);
+
+typedef struct {
+	NMSetting parent;
+} NMSettingGeneric;
+
+typedef struct {
+	NMSettingClass parent;
+
+	/* Padding for future expansion */
+	void (*_reserved1) (void);
+	void (*_reserved2) (void);
+	void (*_reserved3) (void);
+	void (*_reserved4) (void);
+} NMSettingGenericClass;
+
+NM_AVAILABLE_IN_0_9_10
+GType nm_setting_generic_get_type (void);
+
+NM_AVAILABLE_IN_0_9_10
+NMSetting * nm_setting_generic_new              (void);
+
+G_END_DECLS
+
+#endif /* NM_SETTING_GENERIC_H */
diff --git a/libnm-util/nm-setting-gsm.c b/libnm-util/nm-setting-gsm.c
index 41e080ba..f96a997b 100644
--- a/libnm-util/nm-setting-gsm.c
+++ b/libnm-util/nm-setting-gsm.c
@@ -19,11 +19,13 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2007 - 2011 Red Hat, Inc.
+ * (C) Copyright 2007 - 2013 Red Hat, Inc.
  * (C) Copyright 2007 - 2008 Novell, Inc.
  */
 
 #include <string.h>
+#include <glib/gi18n.h>
+
 #include "nm-setting-gsm.h"
 #include "nm-utils.h"
 #include "nm-setting-private.h"
@@ -201,6 +203,8 @@ nm_setting_gsm_get_network_id (NMSettingGsm *setting)
  * @setting: the #NMSettingGsm
  *
  * Returns: the #NMSettingGsm:network-type property of the setting
+ *
+ * Deprecated: 0.9.10: No longer used. Network type setting should be done talking to ModemManager directly.
  **/
 int
 nm_setting_gsm_get_network_type (NMSettingGsm *setting)
@@ -215,6 +219,8 @@ nm_setting_gsm_get_network_type (NMSettingGsm *setting)
  * @setting: the #NMSettingGsm
  *
  * Returns: the #NMSettingGsm:allowed-bands property of the setting
+ *
+ * Deprecated: 0.9.10: No longer used. Bands setting should be done talking to ModemManager directly.
  **/
 guint32
 nm_setting_gsm_get_allowed_bands (NMSettingGsm *setting)
@@ -272,10 +278,11 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 	NMSettingGsmPrivate *priv = NM_SETTING_GSM_GET_PRIVATE (setting);
 
 	if (priv->number && !priv->number[0]) {
-		g_set_error (error,
-		             NM_SETTING_GSM_ERROR,
-		             NM_SETTING_GSM_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_GSM_NUMBER);
+		g_set_error_literal (error,
+		                     NM_SETTING_GSM_ERROR,
+		                     NM_SETTING_GSM_ERROR_INVALID_PROPERTY,
+		                     _("property is empty"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_GSM_SETTING_NAME, NM_SETTING_GSM_NUMBER);
 		return FALSE;
 	}
 
@@ -287,7 +294,9 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 			g_set_error (error,
 			             NM_SETTING_GSM_ERROR,
 			             NM_SETTING_GSM_ERROR_INVALID_PROPERTY,
-			             NM_SETTING_GSM_APN);
+			             _("property value '%s' is empty or too long (>64)"),
+			             priv->apn);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_GSM_SETTING_NAME, NM_SETTING_GSM_APN);
 			return FALSE;
 		}
 
@@ -317,25 +326,29 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 				g_set_error (error,
 				             NM_SETTING_GSM_ERROR,
 				             NM_SETTING_GSM_ERROR_INVALID_PROPERTY,
-				             NM_SETTING_GSM_APN);
+				             _("'%s' contains invalid char(s) (use [A-Za-z._-])"),
+				             priv->apn);
+				g_prefix_error (error, "%s.%s: ", NM_SETTING_GSM_SETTING_NAME, NM_SETTING_GSM_APN);
 				return FALSE;
 			}
 		}
 	}
 
 	if (priv->username && !strlen (priv->username)) {
-		g_set_error (error,
-		             NM_SETTING_GSM_ERROR,
-		             NM_SETTING_GSM_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_GSM_USERNAME);
+		g_set_error_literal (error,
+		                     NM_SETTING_GSM_ERROR,
+		                     NM_SETTING_GSM_ERROR_INVALID_PROPERTY,
+		                     _("property is empty"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_GSM_SETTING_NAME, NM_SETTING_GSM_USERNAME);
 		return FALSE;
 	}
 
 	if (priv->password && !strlen (priv->password)) {
-		g_set_error (error,
-		             NM_SETTING_GSM_ERROR,
-		             NM_SETTING_GSM_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_GSM_USERNAME);
+		g_set_error_literal (error,
+		                     NM_SETTING_GSM_ERROR,
+		                     NM_SETTING_GSM_ERROR_INVALID_PROPERTY,
+		                     _("property is empty"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_GSM_SETTING_NAME, NM_SETTING_GSM_USERNAME);
 		return FALSE;
 	}
 
@@ -348,7 +361,9 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 			g_set_error (error,
 			             NM_SETTING_GSM_ERROR,
 			             NM_SETTING_GSM_ERROR_INVALID_PROPERTY,
-			             NM_SETTING_GSM_NETWORK_ID);
+			             _("'%s' length is invalid (should be 5 or 6 digits)"),
+			             priv->network_id);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_GSM_SETTING_NAME, NM_SETTING_GSM_NETWORK_ID);
 			return FALSE;
 		}
 
@@ -357,7 +372,9 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 				g_set_error (error,
 				             NM_SETTING_GSM_ERROR,
 				             NM_SETTING_GSM_ERROR_INVALID_PROPERTY,
-				             NM_SETTING_GSM_NETWORK_ID);
+				             _("'%s' is not a number"),
+				             priv->network_id);
+				g_prefix_error (error, "%s.%s: ", NM_SETTING_GSM_SETTING_NAME, NM_SETTING_GSM_NETWORK_ID);
 				return FALSE;
 			}
 		}
@@ -388,7 +405,6 @@ need_secrets (NMSetting *setting)
 static void
 nm_setting_gsm_init (NMSettingGsm *setting)
 {
-	g_object_set (setting, NM_SETTING_NAME, NM_SETTING_GSM_SETTING_NAME, NULL);
 }
 
 static void
@@ -491,10 +507,10 @@ get_property (GObject *object, guint prop_id,
 		g_value_set_string (value, nm_setting_gsm_get_network_id (setting));
 		break;
 	case PROP_NETWORK_TYPE:
-		g_value_set_int (value, nm_setting_gsm_get_network_type (setting));
+		g_value_set_int (value, NM_SETTING_GSM_GET_PRIVATE (setting)->network_type);
 		break;
 	case PROP_ALLOWED_BANDS:
-		g_value_set_uint (value, nm_setting_gsm_get_allowed_bands (setting));
+		g_value_set_uint (value, NM_SETTING_GSM_GET_PRIVATE (setting)->allowed_bands);
 		break;
 	case PROP_PIN:
 		g_value_set_string (value, nm_setting_gsm_get_pin (setting));
@@ -547,7 +563,7 @@ nm_setting_gsm_class_init (NMSettingGsmClass *setting_class)
 		                  "blank, which allows NetworkManager to select the "
 		                  "appropriate settings automatically.",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+						  G_PARAM_READWRITE));
 
 	/**
 	 * NMSettingGsm:username:
@@ -564,7 +580,7 @@ nm_setting_gsm_class_init (NMSettingGsmClass *setting_class)
 						  "required.  Note that many providers do not require "
 						  "a username or accept any username.",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+						  G_PARAM_READWRITE));
 
 	/**
 	 * NMSettingGsm:password:
@@ -581,12 +597,12 @@ nm_setting_gsm_class_init (NMSettingGsmClass *setting_class)
 						  "required.  Note that many providers do not require "
 						  "a password or accept any password.",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET));
+						  G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET));
 
 	/**
 	 * NMSettingGsm:password-flags:
 	 *
-	 * Flags indicating how to handle #NMSettingGsm:password:.
+	 * Flags indicating how to handle the #NMSettingGsm:password property.
 	 **/
 	g_object_class_install_property (object_class, PROP_PASSWORD_FLAGS,
 		 g_param_spec_uint (NM_SETTING_GSM_PASSWORD_FLAGS,
@@ -595,7 +611,7 @@ nm_setting_gsm_class_init (NMSettingGsmClass *setting_class)
 		                    NM_SETTING_SECRET_FLAG_NONE,
 		                    NM_SETTING_SECRET_FLAGS_ALL,
 		                    NM_SETTING_SECRET_FLAG_NONE,
-		                    G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+		                    G_PARAM_READWRITE));
 
 	/**
 	 * NMSettingGsm:apn:
@@ -605,8 +621,8 @@ nm_setting_gsm_class_init (NMSettingGsmClass *setting_class)
 	 * the user will be billed for their network usage and whether the user has
 	 * access to the Internet or just a provider-specific walled-garden, so it
 	 * is important to use the correct APN for the user's mobile broadband plan.
-	 * The APN may only be composed of the characters a-z, 0-9, ., and - per
-	 * GSM 03.60 Section 14.9.
+	 * The APN may only be composed of the characters a-z, 0-9, ., and - per GSM
+	 * 03.60 Section 14.9.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_APN,
@@ -622,7 +638,7 @@ nm_setting_gsm_class_init (NMSettingGsmClass *setting_class)
 						  "plan.  The APN may only be composed of the characters "
 						  "a-z, 0-9, ., and - per GSM 03.60 Section 14.9.",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+						  G_PARAM_READWRITE));
 
 	/**
 	 * NMSettingGsm:network-id:
@@ -645,29 +661,39 @@ nm_setting_gsm_class_init (NMSettingGsmClass *setting_class)
 						  "roam when direct roaming control of the device is "
 						  "not otherwise possible.",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+						  G_PARAM_READWRITE));
 
 	/**
 	 * NMSettingGsm:network-type:
 	 *
 	 * Network preference to force the device to only use specific network
-	 * technologies.  Permitted values are those specified by
-	 * #NMSettingGsmNetworkType.  Note that not all devices allow network
+	 * technologies. The permitted values are %NM_SETTING_GSM_NETWORK_TYPE_ANY,
+	 * %NM_SETTING_GSM_NETWORK_TYPE_UMTS_HSPA,
+	 * %NM_SETTING_GSM_NETWORK_TYPE_GPRS_EDGE,
+	 * %NM_SETTING_GSM_NETWORK_TYPE_PREFER_UMTS_HSPA,
+	 * %NM_SETTING_GSM_NETWORK_TYPE_PREFER_GPRS_EDGE,
+	 * %NM_SETTING_GSM_NETWORK_TYPE_PREFER_4G, and
+	 * %NM_SETTING_GSM_NETWORK_TYPE_4G.  Note that not all devices allow network
 	 * preference control.
+	 *
+	 * Deprecated: 0.9.10: No longer used. Network type setting should be done
+	 * by talking to ModemManager directly.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_NETWORK_TYPE,
 		 g_param_spec_int (NM_SETTING_GSM_NETWORK_TYPE,
-					    "Network type",
-					    "Network preference to force the device to only use "
-					    "specific network technologies.  The permitted values "
-					    "are: -1: any, 0: 3G only, 1: GPRS/EDGE only, "
-					    "2: prefer 3G, 3: prefer 2G, 4: prefer 4G/LTE, 5: 4G/LTE only. "
-					    "Note that not all devices allow network preference control.",
-					    NM_SETTING_GSM_NETWORK_TYPE_ANY,
-					    NM_SETTING_GSM_NETWORK_TYPE_4G,
-					    NM_SETTING_GSM_NETWORK_TYPE_ANY,
-					    G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+		                   "Network type",
+		                   "Network preference to force the device to only use "
+		                   "specific network technologies.  The permitted values "
+		                   "are: -1: any, 0: 3G only, 1: GPRS/EDGE only, "
+		                   "2: prefer 3G, 3: prefer 2G, 4: prefer 4G/LTE, 5: 4G/LTE only. "
+		                   "Notes: This property is deprecated and NetworkManager from 0.9.10 "
+		                   "onwards doesn't use this property when talking to ModemManager."
+		                   "Also, not all devices allow network preference control.",
+		                   NM_SETTING_GSM_NETWORK_TYPE_ANY,
+		                   NM_SETTING_GSM_NETWORK_TYPE_4G,
+		                   NM_SETTING_GSM_NETWORK_TYPE_ANY,
+		                   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
 	/**
 	 * NMSettingGsm:allowed-bands:
@@ -675,38 +701,29 @@ nm_setting_gsm_class_init (NMSettingGsmClass *setting_class)
 	 * Bitfield of allowed frequency bands.  Note that not all devices allow
 	 * frequency band control.  Permitted values are those specified by
 	 * #NMSettingGsmNetworkBand.
+	 *
+	 * Deprecated: 0.9.10: No longer used. Band setting should be done by
+	 * talking to ModemManager directly.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_ALLOWED_BANDS,
 		 g_param_spec_uint (NM_SETTING_GSM_ALLOWED_BANDS,
 		                    "Allowed Bands",
-		                    "Bitfield of allowed frequency bands.  Note that "
-		                    "not all devices allow frequency band control.",
+		                    "Bitfield of allowed frequency bands."
+		                    "Notes: This property is deprecated and NetworkManager from 0.9.10 "
+		                    "onwards doesn't use this property when talking to ModemManager."
+		                    "Also, not all devices allow frequency band control.",
 		                    NM_SETTING_GSM_BAND_UNKNOWN,
-		                    NM_SETTING_GSM_BAND_UNKNOWN
-		                     | NM_SETTING_GSM_BAND_ANY
-		                     | NM_SETTING_GSM_BAND_EGSM
-		                     | NM_SETTING_GSM_BAND_DCS
-		                     | NM_SETTING_GSM_BAND_PCS
-		                     | NM_SETTING_GSM_BAND_G850
-		                     | NM_SETTING_GSM_BAND_U2100
-		                     | NM_SETTING_GSM_BAND_U1800
-		                     | NM_SETTING_GSM_BAND_U17IV
-		                     | NM_SETTING_GSM_BAND_U800
-		                     | NM_SETTING_GSM_BAND_U850
-		                     | NM_SETTING_GSM_BAND_U900
-		                     | NM_SETTING_GSM_BAND_U17IX
-		                     | NM_SETTING_GSM_BAND_U1900
-		                     | NM_SETTING_GSM_BAND_U2600,
+		                    NM_SETTING_GSM_BANDS_MAX,
 		                    NM_SETTING_GSM_BAND_ANY,
-		                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+		                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
 	/**
 	 * NMSettingGsm:pin:
 	 *
 	 * If the SIM is locked with a PIN it must be unlocked before any other
-	 * operations are requested.  Specify the PIN here to allow operation of
-	 * the device.
+	 * operations are requested.  Specify the PIN here to allow operation of the
+	 * device.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_PIN,
@@ -716,12 +733,12 @@ nm_setting_gsm_class_init (NMSettingGsmClass *setting_class)
 						  "before any other operations are requested.  Specify "
 						  "the PIN here to allow operation of the device.",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET));
+						  G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET));
 
 	/**
 	 * NMSettingGsm:pin-flags:
 	 *
-	 * Flags indicating how to handle #NMSettingGsm:pin.
+	 * Flags indicating how to handle the #NMSettingGsm:pin property.
 	 **/
 	g_object_class_install_property (object_class, PROP_PIN_FLAGS,
 		 g_param_spec_uint (NM_SETTING_GSM_PIN_FLAGS,
@@ -730,12 +747,12 @@ nm_setting_gsm_class_init (NMSettingGsmClass *setting_class)
 		                    NM_SETTING_SECRET_FLAG_NONE,
 		                    NM_SETTING_SECRET_FLAGS_ALL,
 		                    NM_SETTING_SECRET_FLAG_NONE,
-		                    G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+		                    G_PARAM_READWRITE));
 
 	/**
 	 * NMSettingGsm:home-only:
 	 *
-	 * When TRUE, only connections to the home network will be allowed.
+	 * When %TRUE, only connections to the home network will be allowed.
 	 * Connections to roaming networks will not be made.
 	 **/
 	g_object_class_install_property
@@ -746,5 +763,5 @@ nm_setting_gsm_class_init (NMSettingGsmClass *setting_class)
 						  "be allowed.  Connections to roaming networks will "
 						  "not be made.",
 						  FALSE,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+						  G_PARAM_READWRITE));
 }
diff --git a/libnm-util/nm-setting-gsm.h b/libnm-util/nm-setting-gsm.h
index 2303f762..6d8e46d0 100644
--- a/libnm-util/nm-setting-gsm.h
+++ b/libnm-util/nm-setting-gsm.h
@@ -64,12 +64,14 @@ GQuark nm_setting_gsm_error_quark (void);
 #define NM_SETTING_GSM_PASSWORD_FLAGS "password-flags"
 #define NM_SETTING_GSM_APN            "apn"
 #define NM_SETTING_GSM_NETWORK_ID     "network-id"
-#define NM_SETTING_GSM_NETWORK_TYPE   "network-type"
-#define NM_SETTING_GSM_ALLOWED_BANDS  "allowed-bands"
 #define NM_SETTING_GSM_PIN            "pin"
 #define NM_SETTING_GSM_PIN_FLAGS      "pin-flags"
 #define NM_SETTING_GSM_HOME_ONLY      "home-only"
 
+/* Deprecated */
+#define NM_SETTING_GSM_ALLOWED_BANDS  "allowed-bands"
+#define NM_SETTING_GSM_NETWORK_TYPE   "network-type"
+
 /**
  * NMSettingGsmNetworkType:
  * @NM_SETTING_GSM_NETWORK_TYPE_ANY: any access technology may be used
@@ -88,6 +90,8 @@ GQuark nm_setting_gsm_error_quark (void);
  *
  * #NMSettingGsmNetworkType values indicate the allowed access technologies
  * the device may use when connecting to this network.
+ *
+ * Deprecated: 0.9.10: No longer used.
  */
 typedef enum {
 	NM_SETTING_GSM_NETWORK_TYPE_ANY = -1,
@@ -119,6 +123,8 @@ typedef enum {
  *
  * #NMSettingGsmNetworkBand values indicate the allowed frequency bands
  * the device may use when connecting to this network.
+ *
+ * Deprecated: 0.9.10: No longer used.
  */
 typedef enum {
 	NM_SETTING_GSM_BAND_UNKNOWN      = 0x00000000,
@@ -138,6 +144,30 @@ typedef enum {
 	NM_SETTING_GSM_BAND_U2600        = 0x00002000, /* WCDMA 3GPP UMTS 2600 MHz     (Class VII, internal) */
 } NMSettingGsmNetworkBand;
 
+/**
+ * NM_SETTING_GSM_BANDS_MAX:
+ *
+ * #NM_SETTING_GSM_BANDS_MAX macro indicate the maximal value that can be used
+ * as the allowed frequency bands (#NMSettingGsm:allowed-bands property).
+ *
+ * Deprecated: 0.9.10: No longer used.
+ */
+#define NM_SETTING_GSM_BANDS_MAX (  NM_SETTING_GSM_BAND_UNKNOWN \
+                                  | NM_SETTING_GSM_BAND_ANY \
+                                  | NM_SETTING_GSM_BAND_EGSM \
+                                  | NM_SETTING_GSM_BAND_DCS \
+                                  | NM_SETTING_GSM_BAND_PCS \
+                                  | NM_SETTING_GSM_BAND_G850 \
+                                  | NM_SETTING_GSM_BAND_U2100 \
+                                  | NM_SETTING_GSM_BAND_U1800 \
+                                  | NM_SETTING_GSM_BAND_U17IV \
+                                  | NM_SETTING_GSM_BAND_U800 \
+                                  | NM_SETTING_GSM_BAND_U850 \
+                                  | NM_SETTING_GSM_BAND_U900 \
+                                  | NM_SETTING_GSM_BAND_U17IX \
+                                  | NM_SETTING_GSM_BAND_U1900 \
+                                  | NM_SETTING_GSM_BAND_U2600)
+
 typedef struct {
 	NMSetting parent;
 } NMSettingGsm;
@@ -160,14 +190,18 @@ const char *nm_setting_gsm_get_username      (NMSettingGsm *setting);
 const char *nm_setting_gsm_get_password      (NMSettingGsm *setting);
 const char *nm_setting_gsm_get_apn           (NMSettingGsm *setting);
 const char *nm_setting_gsm_get_network_id    (NMSettingGsm *setting);
-int         nm_setting_gsm_get_network_type  (NMSettingGsm *setting);
-guint32     nm_setting_gsm_get_allowed_bands (NMSettingGsm *setting);
 const char *nm_setting_gsm_get_pin           (NMSettingGsm *setting);
 gboolean    nm_setting_gsm_get_home_only     (NMSettingGsm *setting);
 
 NMSettingSecretFlags nm_setting_gsm_get_pin_flags      (NMSettingGsm *setting);
 NMSettingSecretFlags nm_setting_gsm_get_password_flags (NMSettingGsm *setting);
 
+/* Deprecated */
+NM_DEPRECATED_IN_0_9_10
+int     nm_setting_gsm_get_network_type  (NMSettingGsm *setting);
+NM_DEPRECATED_IN_0_9_10
+guint32 nm_setting_gsm_get_allowed_bands (NMSettingGsm *setting);
+
 G_END_DECLS
 
 #endif /* NM_SETTING_GSM_H */
diff --git a/libnm-util/nm-setting-infiniband.c b/libnm-util/nm-setting-infiniband.c
index ee40aa0e..5af50448 100644
--- a/libnm-util/nm-setting-infiniband.c
+++ b/libnm-util/nm-setting-infiniband.c
@@ -16,16 +16,20 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * Copyright 2011 Red Hat, Inc.
+ * Copyright 2011 - 2013 Red Hat, Inc.
  */
 
+#include <stdlib.h>
 #include <dbus/dbus-glib.h>
 #include <linux/if_infiniband.h>
+#include <glib/gi18n.h>
 
 #include "nm-setting-infiniband.h"
 #include "nm-param-spec-specialized.h"
+#include "nm-utils.h"
 #include "nm-utils-private.h"
 #include "nm-setting-private.h"
+#include "nm-setting-connection.h"
 
 /**
  * SECTION:nm-setting-infiniband
@@ -66,6 +70,8 @@ typedef struct {
 	GByteArray *mac_address;
 	char *transport_mode;
 	guint32 mtu;
+	int p_key;
+	char *parent, *virtual_iface_name;
 } NMSettingInfinibandPrivate;
 
 enum {
@@ -73,6 +79,8 @@ enum {
 	PROP_MAC_ADDRESS,
 	PROP_MTU,
 	PROP_TRANSPORT_MODE,
+	PROP_P_KEY,
+	PROP_PARENT,
 
 	LAST_PROP
 };
@@ -135,6 +143,53 @@ nm_setting_infiniband_get_transport_mode (NMSettingInfiniband *setting)
 	return NM_SETTING_INFINIBAND_GET_PRIVATE (setting)->transport_mode;
 }
 
+/**
+ * nm_setting_infiniband_get_p_key:
+ * @setting: the #NMSettingInfiniband
+ *
+ * Returns the P_Key to use for this device. A value of -1 means to
+ * use the default P_Key (aka "the P_Key at index 0"). Otherwise it is
+ * a 16-bit unsigned integer.
+ *
+ * Returns: the IPoIB P_Key
+ **/
+int
+nm_setting_infiniband_get_p_key (NMSettingInfiniband *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_INFINIBAND (setting), -1);
+
+	return NM_SETTING_INFINIBAND_GET_PRIVATE (setting)->p_key;
+}
+
+/**
+ * nm_setting_infiniband_get_parent:
+ * @setting: the #NMSettingInfiniband
+ *
+ * Returns the parent interface name for this device, if set.
+ *
+ * Returns: the parent interface name
+ **/
+const char *
+nm_setting_infiniband_get_parent (NMSettingInfiniband *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_INFINIBAND (setting), NULL);
+
+	return NM_SETTING_INFINIBAND_GET_PRIVATE (setting)->parent;
+}
+
+static const char *
+get_virtual_iface_name (NMSetting *setting)
+{
+	NMSettingInfinibandPrivate *priv = NM_SETTING_INFINIBAND_GET_PRIVATE (setting);
+
+	if (priv->p_key == -1 || !priv->parent)
+		return NULL;
+
+	if (!priv->virtual_iface_name)
+		priv->virtual_iface_name = g_strdup_printf ("%s.%04x", priv->parent, priv->p_key);
+
+	return NM_SETTING_INFINIBAND_GET_PRIVATE (setting)->virtual_iface_name;
+}
 
 static gboolean
 verify (NMSetting *setting, GSList *all_settings, GError **error)
@@ -142,10 +197,11 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 	NMSettingInfinibandPrivate *priv = NM_SETTING_INFINIBAND_GET_PRIVATE (setting);
 
 	if (priv->mac_address && priv->mac_address->len != INFINIBAND_ALEN) {
-		g_set_error (error,
-		             NM_SETTING_INFINIBAND_ERROR,
-		             NM_SETTING_INFINIBAND_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_INFINIBAND_MAC_ADDRESS);
+		g_set_error_literal (error,
+		                     NM_SETTING_INFINIBAND_ERROR,
+		                     NM_SETTING_INFINIBAND_ERROR_INVALID_PROPERTY,
+		                     _("property is invalid"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_INFINIBAND_SETTING_NAME, NM_SETTING_INFINIBAND_MAC_ADDRESS);
 		return FALSE;
 	}
 
@@ -156,20 +212,49 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 		if (priv->mtu > 65520)
 			priv->mtu = 65520;
 	} else {
-		g_set_error (error,
-		             NM_SETTING_INFINIBAND_ERROR,
-		             NM_SETTING_INFINIBAND_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_INFINIBAND_TRANSPORT_MODE);
+		g_set_error_literal (error,
+		                     NM_SETTING_INFINIBAND_ERROR,
+		                     NM_SETTING_INFINIBAND_ERROR_INVALID_PROPERTY,
+		                     _("property is invalid"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_INFINIBAND_SETTING_NAME, NM_SETTING_INFINIBAND_TRANSPORT_MODE);
 		return FALSE;
 	}
 
+	if (priv->parent) {
+		if (!nm_utils_iface_valid_name (priv->parent)) {
+			g_set_error_literal (error,
+			                     NM_SETTING_INFINIBAND_ERROR,
+			                     NM_SETTING_INFINIBAND_ERROR_INVALID_PROPERTY,
+			                     _("not a valid interface name"));
+			g_prefix_error (error, "%s: ", NM_SETTING_INFINIBAND_PARENT);
+			return FALSE;
+		}
+		if (priv->p_key == -1) {
+			g_set_error_literal (error,
+			                     NM_SETTING_INFINIBAND_ERROR,
+			                     NM_SETTING_INFINIBAND_ERROR_INVALID_PROPERTY,
+			                     _("Must specify a P_Key if specifying parent"));
+			g_prefix_error (error, "%s: ", NM_SETTING_INFINIBAND_PARENT);
+		}
+	}
+
+	if (priv->p_key != -1) {
+		if (!priv->mac_address && !priv->parent) {
+			g_set_error_literal (error,
+			                     NM_SETTING_INFINIBAND_ERROR,
+			                     NM_SETTING_INFINIBAND_ERROR_MISSING_PROPERTY,
+			                     _("InfiniBand P_Key connection did not specify parent interface name"));
+			g_prefix_error (error, "%s: ", NM_SETTING_INFINIBAND_PARENT);
+			return FALSE;
+		}
+	}
+
 	return TRUE;
 }
 
 static void
 nm_setting_infiniband_init (NMSettingInfiniband *setting)
 {
-	g_object_set (setting, NM_SETTING_NAME, NM_SETTING_INFINIBAND_SETTING_NAME, NULL);
 }
 
 static void
@@ -180,6 +265,8 @@ finalize (GObject *object)
 	g_free (priv->transport_mode);
 	if (priv->mac_address)
 		g_byte_array_free (priv->mac_address, TRUE);
+	g_free (priv->parent);
+	g_free (priv->virtual_iface_name);
 
 	G_OBJECT_CLASS (nm_setting_infiniband_parent_class)->finalize (object);
 }
@@ -203,6 +290,15 @@ set_property (GObject *object, guint prop_id,
 		g_free (priv->transport_mode);
 		priv->transport_mode = g_value_dup_string (value);
 		break;
+	case PROP_P_KEY:
+		priv->p_key = g_value_get_int (value);
+		g_clear_pointer (&priv->virtual_iface_name, g_free);
+		break;
+	case PROP_PARENT:
+		g_free (priv->parent);
+		priv->parent = g_value_dup_string (value);
+		g_clear_pointer (&priv->virtual_iface_name, g_free);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -225,6 +321,12 @@ get_property (GObject *object, guint prop_id,
 	case PROP_TRANSPORT_MODE:
 		g_value_set_string (value, nm_setting_infiniband_get_transport_mode (setting));
 		break;
+	case PROP_P_KEY:
+		g_value_set_int (value, nm_setting_infiniband_get_p_key (setting));
+		break;
+	case PROP_PARENT:
+		g_value_set_string (value, nm_setting_infiniband_get_parent (setting));
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -243,15 +345,17 @@ nm_setting_infiniband_class_init (NMSettingInfinibandClass *setting_class)
 	object_class->set_property = set_property;
 	object_class->get_property = get_property;
 	object_class->finalize     = finalize;
-	parent_class->verify       = verify;
+
+	parent_class->verify                 = verify;
+	parent_class->get_virtual_iface_name = get_virtual_iface_name;
 
 	/* Properties */
 	/**
 	 * NMSettingInfiniband:mac-address:
 	 *
-	 * If specified, this connection will only apply to the IPoIB
-	 * device whose permanent MAC address matches. This property does
-	 * not change the MAC address of the device (i.e. MAC spoofing).
+	 * If specified, this connection will only apply to the IPoIB device whose
+	 * permanent MAC address matches. This property does not change the MAC
+	 * address of the device (i.e. MAC spoofing).
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_MAC_ADDRESS,
@@ -262,7 +366,7 @@ nm_setting_infiniband_class_init (NMSettingInfinibandClass *setting_class)
 		                             "This property does not change the MAC address "
 		                             "of the device (i.e. MAC spoofing).",
 		                             DBUS_TYPE_G_UCHAR_ARRAY,
-		                             G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+		                             G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE));
 
 	/**
 	 * NMSettingInfiniband:mtu:
@@ -278,20 +382,53 @@ nm_setting_infiniband_class_init (NMSettingInfinibandClass *setting_class)
 		                    "size or smaller, breaking larger packets up into "
 		                    "multiple frames.",
 		                    0, G_MAXUINT32, 0,
-		                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_FUZZY_IGNORE));
+		                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE));
 
 	/**
 	 * NMSettingInfiniband:transport-mode:
 	 *
-	 * The IP-over-InfiniBand transport mode. Either 'datagram' or
-	 * 'connected'.
+	 * The IP-over-InfiniBand transport mode. Either "datagram" or
+	 * "connected".
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_TRANSPORT_MODE,
 		 g_param_spec_string (NM_SETTING_INFINIBAND_TRANSPORT_MODE,
-							  "Transport Mode",
-							  "The IPoIB transport mode. Either 'datagram' or 'connected'.",
-							  NULL,
-							  G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
-}
+		                      "Transport Mode",
+		                      "The IPoIB transport mode. Either 'datagram' or 'connected'.",
+		                      NULL,
+		                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE));
 
+	/**
+	 * NMSettingInfiniband:p-key:
+	 *
+	 * The InfiniBand P_Key to use for this device. A value of -1 means to use
+	 * the default P_Key (aka "the P_Key at index 0").  Otherwise it is a 16-bit
+	 * unsigned integer, whose high bit is set if it is a "full membership"
+	 * P_Key.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_P_KEY,
+		 g_param_spec_int (NM_SETTING_INFINIBAND_P_KEY,
+		                   "P_Key",
+		                   "The InfiniBand P_Key. Either -1 for the "
+		                   "default, or a 16-bit unsigned integer.",
+		                   -1, 0xFFFF, -1,
+		                   G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE));
+
+	/**
+	 * NMSettingInfiniband:parent:
+	 *
+	 * The interface name of the parent device of this device. Normally %NULL,
+	 * but if the #NMSettingInfiniband:p_key property is set, then you must
+	 * specify the base device by setting either this property or
+	 * #NMSettingInfiniband:mac-address.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_PARENT,
+		 g_param_spec_string (NM_SETTING_INFINIBAND_PARENT,
+		                      "Parent",
+		                      "The interface name of the parent device, or NULL",
+		                      NULL,
+		                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE));
+
+}
diff --git a/libnm-util/nm-setting-infiniband.h b/libnm-util/nm-setting-infiniband.h
index 98a3dd5e..dff38450 100644
--- a/libnm-util/nm-setting-infiniband.h
+++ b/libnm-util/nm-setting-infiniband.h
@@ -54,6 +54,8 @@ GQuark nm_setting_infiniband_error_quark (void);
 #define NM_SETTING_INFINIBAND_MAC_ADDRESS    "mac-address"
 #define NM_SETTING_INFINIBAND_MTU            "mtu"
 #define NM_SETTING_INFINIBAND_TRANSPORT_MODE "transport-mode"
+#define NM_SETTING_INFINIBAND_P_KEY          "p-key"
+#define NM_SETTING_INFINIBAND_PARENT         "parent"
 
 typedef struct {
 	NMSetting parent;
@@ -75,6 +77,8 @@ NMSetting *       nm_setting_infiniband_new                (void);
 const GByteArray *nm_setting_infiniband_get_mac_address    (NMSettingInfiniband *setting);
 guint32           nm_setting_infiniband_get_mtu            (NMSettingInfiniband *setting);
 const char *      nm_setting_infiniband_get_transport_mode (NMSettingInfiniband *setting);
+int               nm_setting_infiniband_get_p_key          (NMSettingInfiniband *setting);
+const char *      nm_setting_infiniband_get_parent         (NMSettingInfiniband *setting);
 
 G_END_DECLS
 
diff --git a/libnm-util/nm-setting-ip4-config.c b/libnm-util/nm-setting-ip4-config.c
index 34f5c8fb..a2c104d5 100644
--- a/libnm-util/nm-setting-ip4-config.c
+++ b/libnm-util/nm-setting-ip4-config.c
@@ -19,13 +19,14 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2007 - 2010 Red Hat, Inc.
+ * (C) Copyright 2007 - 2014 Red Hat, Inc.
  * (C) Copyright 2007 - 2008 Novell, Inc.
  */
 
 #include <string.h>
-
 #include <dbus/dbus-glib.h>
+#include <glib/gi18n.h>
+
 #include "nm-setting-ip4-config.h"
 #include "nm-param-spec-specialized.h"
 #include "nm-utils.h"
@@ -77,6 +78,7 @@ typedef struct {
 	GArray *dns;        /* array of guint32; elements in network byte order */
 	GSList *dns_search; /* list of strings */
 	GSList *addresses;  /* array of NMIP4Address */
+	GSList *address_labels; /* list of strings */
 	GSList *routes;     /* array of NMIP4Route */
 	gboolean ignore_auto_routes;
 	gboolean ignore_auto_dns;
@@ -93,6 +95,7 @@ enum {
 	PROP_DNS,
 	PROP_DNS_SEARCH,
 	PROP_ADDRESSES,
+	PROP_ADDRESS_LABELS,
 	PROP_ROUTES,
 	PROP_IGNORE_AUTO_ROUTES,
 	PROP_IGNORE_AUTO_DNS,
@@ -192,6 +195,7 @@ nm_setting_ip4_config_add_dns (NMSettingIP4Config *setting, guint32 dns)
 	}
 
 	g_array_append_val (priv->dns, dns);
+	g_object_notify (G_OBJECT (setting), NM_SETTING_IP4_CONFIG_DNS);
 	return TRUE;
 }
 
@@ -213,6 +217,38 @@ nm_setting_ip4_config_remove_dns (NMSettingIP4Config *setting, guint32 i)
 	g_return_if_fail (i <= priv->dns->len);
 
 	g_array_remove_index (priv->dns, i);
+	g_object_notify (G_OBJECT (setting), NM_SETTING_IP4_CONFIG_DNS);
+}
+
+/**
+ * nm_setting_ip4_config_remove_dns_by_value:
+ * @setting: the #NMSettingIP4Config
+ * @dns: the DNS server to remove
+ *
+ * Removes the DNS server @dns.
+ *
+ * Returns: %TRUE if the DNS server was found and removed; %FALSE if it was not.
+ * domain was already known
+ *
+ * Since: 0.9.10
+ **/
+gboolean
+nm_setting_ip4_config_remove_dns_by_value (NMSettingIP4Config *setting, guint32 dns)
+{
+	NMSettingIP4ConfigPrivate *priv;
+	int i;
+
+	g_return_val_if_fail (NM_IS_SETTING_IP4_CONFIG (setting), FALSE);
+
+	priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting);
+	for (i = 0; i < priv->dns->len; i++) {
+		if (dns == g_array_index (priv->dns, guint32, i)) {
+			g_array_remove_index (priv->dns, i);
+			g_object_notify (G_OBJECT (setting), NM_SETTING_IP4_CONFIG_DNS);
+			return TRUE;
+		}
+	}
+	return FALSE;
 }
 
 /**
@@ -230,6 +266,7 @@ nm_setting_ip4_config_clear_dns (NMSettingIP4Config *setting)
 
 	priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting);
 	g_array_remove_range (priv->dns, 0, priv->dns->len);
+	g_object_notify (G_OBJECT (setting), NM_SETTING_IP4_CONFIG_DNS);
 }
 
 /**
@@ -294,6 +331,7 @@ nm_setting_ip4_config_add_dns_search (NMSettingIP4Config *setting,
 	}
 
 	priv->dns_search = g_slist_append (priv->dns_search, g_strdup (dns_search));
+	g_object_notify (G_OBJECT (setting), NM_SETTING_IP4_CONFIG_DNS_SEARCH);
 	return TRUE;
 }
 
@@ -318,6 +356,40 @@ nm_setting_ip4_config_remove_dns_search (NMSettingIP4Config *setting, guint32 i)
 
 	g_free (elt->data);
 	priv->dns_search = g_slist_delete_link (priv->dns_search, elt);
+	g_object_notify (G_OBJECT (setting), NM_SETTING_IP4_CONFIG_DNS_SEARCH);
+}
+
+/**
+ * nm_setting_ip4_config_remove_dns_search_by_value:
+ * @setting: the #NMSettingIP4Config
+ * @dns_search: the search domain to remove
+ *
+ * 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_ip4_config_remove_dns_search_by_value (NMSettingIP4Config *setting,
+                                                  const char *dns_search)
+{
+	NMSettingIP4ConfigPrivate *priv;
+	GSList *iter;
+
+	g_return_val_if_fail (NM_IS_SETTING_IP4_CONFIG (setting), FALSE);
+	g_return_val_if_fail (dns_search != NULL, FALSE);
+	g_return_val_if_fail (dns_search[0] != '\0', FALSE);
+
+	priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting);
+	for (iter = priv->dns_search; iter; iter = g_slist_next (iter)) {
+		if (!strcmp (dns_search, (char *) iter->data)) {
+			priv->dns_search = g_slist_delete_link (priv->dns_search, iter);
+			g_object_notify (G_OBJECT (setting), NM_SETTING_IP4_CONFIG_DNS_SEARCH);
+			return TRUE;
+		}
+	}
+	return FALSE;
 }
 
 /**
@@ -331,8 +403,9 @@ nm_setting_ip4_config_clear_dns_searches (NMSettingIP4Config *setting)
 {
 	g_return_if_fail (NM_IS_SETTING_IP4_CONFIG (setting));
 
-	nm_utils_slist_free (NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting)->dns_search, g_free);
+	g_slist_free_full (NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting)->dns_search, g_free);
 	NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting)->dns_search = NULL;
+	g_object_notify (G_OBJECT (setting), NM_SETTING_IP4_CONFIG_DNS_SEARCH);
 }
 
 /**
@@ -369,6 +442,19 @@ nm_setting_ip4_config_get_address (NMSettingIP4Config *setting, guint32 i)
 	return (NMIP4Address *) g_slist_nth_data (priv->addresses, i);
 }
 
+const char *
+nm_setting_ip4_config_get_address_label (NMSettingIP4Config *setting, guint32 i)
+{
+	NMSettingIP4ConfigPrivate *priv;
+
+	g_return_val_if_fail (NM_IS_SETTING_IP4_CONFIG (setting), NULL);
+
+	priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting);
+	g_return_val_if_fail (i <= g_slist_length (priv->address_labels), NULL);
+
+	return (const char *) g_slist_nth_data (priv->address_labels, i);
+}
+
 /**
  * nm_setting_ip4_config_add_address:
  * @setting: the #NMSettingIP4Config
@@ -384,6 +470,14 @@ gboolean
 nm_setting_ip4_config_add_address (NMSettingIP4Config *setting,
                                    NMIP4Address *address)
 {
+	return nm_setting_ip4_config_add_address_with_label (setting, address, NULL);
+}
+
+gboolean
+nm_setting_ip4_config_add_address_with_label (NMSettingIP4Config *setting,
+                                              NMIP4Address *address,
+                                              const char *label)
+{
 	NMSettingIP4ConfigPrivate *priv;
 	NMIP4Address *copy;
 	GSList *iter;
@@ -398,9 +492,10 @@ nm_setting_ip4_config_add_address (NMSettingIP4Config *setting,
 	}
 
 	copy = nm_ip4_address_dup (address);
-	g_return_val_if_fail (copy != NULL, FALSE);
-
 	priv->addresses = g_slist_append (priv->addresses, copy);
+	priv->address_labels = g_slist_append (priv->address_labels, g_strdup (label));
+
+	g_object_notify (G_OBJECT (setting), NM_SETTING_IP4_CONFIG_ADDRESSES);
 	return TRUE;
 }
 
@@ -415,16 +510,55 @@ void
 nm_setting_ip4_config_remove_address (NMSettingIP4Config *setting, guint32 i)
 {
 	NMSettingIP4ConfigPrivate *priv;
-	GSList *elt;
+	GSList *addr, *label;
 
 	g_return_if_fail (NM_IS_SETTING_IP4_CONFIG (setting));
 
 	priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting);
-	elt = g_slist_nth (priv->addresses, i);
-	g_return_if_fail (elt != NULL);
+	addr = g_slist_nth (priv->addresses, i);
+	label = g_slist_nth (priv->address_labels, i);
+	g_return_if_fail (addr != NULL && label != NULL);
+
+	nm_ip4_address_unref ((NMIP4Address *) addr->data);
+	priv->addresses = g_slist_delete_link (priv->addresses, addr);
+	if (label->data)
+		g_free (label->data);
+	priv->address_labels = g_slist_delete_link (priv->address_labels, label);
 
-	nm_ip4_address_unref ((NMIP4Address *) elt->data);
-	priv->addresses = g_slist_delete_link (priv->addresses, elt);
+	g_object_notify (G_OBJECT (setting), NM_SETTING_IP4_CONFIG_ADDRESSES);
+}
+
+/**
+ * nm_setting_ip4_config_remove_address_by_value:
+ * @setting: the #NMSettingIP4Config
+ * @address: the IP address to remove
+ *
+ * Removes the address @address.
+ *
+ * Returns: %TRUE if the address was found and removed; %FALSE if it was not.
+ *
+ * Since: 0.9.10
+ **/
+gboolean
+nm_setting_ip4_config_remove_address_by_value (NMSettingIP4Config *setting,
+                                               NMIP4Address *address)
+{
+	NMSettingIP4ConfigPrivate *priv;
+	GSList *iter;
+
+	g_return_val_if_fail (NM_IS_SETTING_IP4_CONFIG (setting), FALSE);
+	g_return_val_if_fail (address != NULL, FALSE);
+
+	priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting);
+	for (iter = priv->addresses; iter; iter = g_slist_next (iter)) {
+		if (nm_ip4_address_compare ((NMIP4Address *) iter->data, address)) {
+			nm_ip4_address_unref ((NMIP4Address *) iter->data);
+			priv->addresses = g_slist_delete_link (priv->addresses, iter);
+			g_object_notify (G_OBJECT (setting), NM_SETTING_IP4_CONFIG_ADDRESSES);
+			return TRUE;
+		}
+	}
+	return FALSE;
 }
 
 /**
@@ -440,8 +574,11 @@ nm_setting_ip4_config_clear_addresses (NMSettingIP4Config *setting)
 
 	g_return_if_fail (NM_IS_SETTING_IP4_CONFIG (setting));
 
-	nm_utils_slist_free (priv->addresses, (GDestroyNotify) nm_ip4_address_unref);
+	g_slist_free_full (priv->addresses, (GDestroyNotify) nm_ip4_address_unref);
 	priv->addresses = NULL;
+	g_slist_free_full (priv->address_labels, g_free);
+	priv->address_labels = NULL;
+	g_object_notify (G_OBJECT (setting), NM_SETTING_IP4_CONFIG_ADDRESSES);
 }
 
 /**
@@ -506,9 +643,8 @@ nm_setting_ip4_config_add_route (NMSettingIP4Config *setting,
 	}
 
 	copy = nm_ip4_route_dup (route);
-	g_return_val_if_fail (copy != NULL, FALSE);
-
 	priv->routes = g_slist_append (priv->routes, copy);
+	g_object_notify (G_OBJECT (setting), NM_SETTING_IP4_CONFIG_ROUTES);
 	return TRUE;
 }
 
@@ -533,6 +669,40 @@ nm_setting_ip4_config_remove_route (NMSettingIP4Config *setting, guint32 i)
 
 	nm_ip4_route_unref ((NMIP4Route *) elt->data);
 	priv->routes = g_slist_delete_link (priv->routes, elt);
+	g_object_notify (G_OBJECT (setting), NM_SETTING_IP4_CONFIG_ROUTES);
+}
+
+/**
+ * nm_setting_ip4_config_remove_route_by_value:
+ * @setting: the #NMSettingIP4Config
+ * @route: the route to remove
+ *
+ * Removes the route @route.
+ *
+ * Returns: %TRUE if the route was found and removed; %FALSE if it was not.
+ *
+ * Since: 0.9.10
+ **/
+gboolean
+nm_setting_ip4_config_remove_route_by_value (NMSettingIP4Config *setting,
+                                             NMIP4Route *route)
+{
+	NMSettingIP4ConfigPrivate *priv;
+	GSList *iter;
+
+	g_return_val_if_fail (NM_IS_SETTING_IP4_CONFIG (setting), FALSE);
+	g_return_val_if_fail (route != NULL, FALSE);
+
+	priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting);
+	for (iter = priv->routes; iter; iter = g_slist_next (iter)) {
+		if (nm_ip4_route_compare ((NMIP4Route *) iter->data, route)) {
+			nm_ip4_route_unref ((NMIP4Route *) iter->data);
+			priv->routes = g_slist_delete_link (priv->routes, iter);
+			g_object_notify (G_OBJECT (setting), NM_SETTING_IP4_CONFIG_ROUTES);
+			return TRUE;
+		}
+	}
+	return FALSE;
 }
 
 /**
@@ -548,8 +718,9 @@ nm_setting_ip4_config_clear_routes (NMSettingIP4Config *setting)
 
 	g_return_if_fail (NM_IS_SETTING_IP4_CONFIG (setting));
 
-	nm_utils_slist_free (priv->routes, (GDestroyNotify) nm_ip4_route_unref);
+	g_slist_free_full (priv->routes, (GDestroyNotify) nm_ip4_route_unref);
 	priv->routes = NULL;
+	g_object_notify (G_OBJECT (setting), NM_SETTING_IP4_CONFIG_ROUTES);
 }
 
 /**
@@ -678,27 +849,43 @@ nm_setting_ip4_config_get_may_fail (NMSettingIP4Config *setting)
 	return NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting)->may_fail;
 }
 
-static gint
-find_setting_by_name (gconstpointer a, gconstpointer b)
+static gboolean
+verify_label (const char *label)
 {
-	NMSetting *setting = NM_SETTING (a);
-	const char *str = (const char *) b;
+	const char *p;
+	char *iface;
+
+	p = strchr (label, ':');
+	if (!p)
+		return FALSE;
+	iface = g_strndup (label, p - label);
+	if (!nm_utils_iface_valid_name (iface)) {
+		g_free (iface);
+		return FALSE;
+	}
+	g_free (iface);
 
-	return strcmp (nm_setting_get_name (setting), str);
+	for (p++; *p; p++) {
+		if (!g_ascii_isalnum (*p) && *p != '_')
+			return FALSE;
+	}
+
+	return TRUE;
 }
 
 static gboolean
 verify (NMSetting *setting, GSList *all_settings, GError **error)
 {
 	NMSettingIP4ConfigPrivate *priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting);
-	GSList *iter;
+	GSList *iter, *l_iter;
 	int i;
 
 	if (!priv->method) {
-		g_set_error (error,
-		             NM_SETTING_IP4_CONFIG_ERROR,
-		             NM_SETTING_IP4_CONFIG_ERROR_MISSING_PROPERTY,
-		             NM_SETTING_IP4_CONFIG_METHOD);
+		g_set_error_literal (error,
+		                     NM_SETTING_IP4_CONFIG_ERROR,
+		                     NM_SETTING_IP4_CONFIG_ERROR_MISSING_PROPERTY,
+		                     _("property is missing"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_SETTING_IP4_CONFIG_METHOD);
 		return FALSE;
 	}
 
@@ -707,7 +894,9 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 			g_set_error (error,
 			             NM_SETTING_IP4_CONFIG_ERROR,
 			             NM_SETTING_IP4_CONFIG_ERROR_MISSING_PROPERTY,
-			             NM_SETTING_IP4_CONFIG_ADDRESSES);
+			             _("this property cannot be empty for '%s=%s'"),
+			             NM_SETTING_IP4_CONFIG_METHOD, priv->method);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_SETTING_IP4_CONFIG_ADDRESSES);
 			return FALSE;
 		}
 	} else if (   !strcmp (priv->method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL)
@@ -717,7 +906,9 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 			g_set_error (error,
 			             NM_SETTING_IP4_CONFIG_ERROR,
 			             NM_SETTING_IP4_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD,
-			             NM_SETTING_IP4_CONFIG_DNS);
+			             _("this property is not allowed for '%s=%s'"),
+			             NM_SETTING_IP4_CONFIG_METHOD, priv->method);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_SETTING_IP4_CONFIG_DNS);
 			return FALSE;
 		}
 
@@ -725,69 +916,68 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 			g_set_error (error,
 			             NM_SETTING_IP4_CONFIG_ERROR,
 			             NM_SETTING_IP4_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD,
-			             NM_SETTING_IP4_CONFIG_DNS_SEARCH);
+			             _("this property is not allowed for '%s=%s'"),
+			             NM_SETTING_IP4_CONFIG_METHOD, priv->method);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_SETTING_IP4_CONFIG_DNS_SEARCH);
 			return FALSE;
 		}
 
-		if (g_slist_length (priv->addresses)) {
-			g_set_error (error,
-			             NM_SETTING_IP4_CONFIG_ERROR,
-			             NM_SETTING_IP4_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD,
-			             NM_SETTING_IP4_CONFIG_ADDRESSES);
-			return FALSE;
-		}
-	} else if (!strcmp (priv->method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) {
-		/* nothing to do */
-	} else {
-		g_set_error (error,
-		             NM_SETTING_IP4_CONFIG_ERROR,
-		             NM_SETTING_IP4_CONFIG_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_IP4_CONFIG_METHOD);
-		return FALSE;
-	}
-
-	/* Disabled method is not allowed when IPv6 is set to 'ignore' */
-	if (!strcmp (priv->method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) {
-		GSList *list = g_slist_find_custom (all_settings, NM_SETTING_IP6_CONFIG_SETTING_NAME, find_setting_by_name);
-		if (list) {
-			NMSettingIP6Config *s_ip6 = g_slist_nth_data (list, 0);
-			if (   s_ip6
-			    && !g_strcmp0 (nm_setting_ip6_config_get_method (s_ip6), NM_SETTING_IP6_CONFIG_METHOD_IGNORE)) {
+		/* Shared allows IP addresses; link-local and disabled do not */
+		if (strcmp (priv->method, NM_SETTING_IP4_CONFIG_METHOD_SHARED) != 0) {
+			if (g_slist_length (priv->addresses)) {
 				g_set_error (error,
 				             NM_SETTING_IP4_CONFIG_ERROR,
-				             NM_SETTING_IP4_CONFIG_ERROR_INVALID_PROPERTY,
-				             NM_SETTING_IP4_CONFIG_METHOD);
+				             NM_SETTING_IP4_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD,
+				             _("this property is not allowed for '%s=%s'"),
+				             NM_SETTING_IP4_CONFIG_METHOD, priv->method);
+				g_prefix_error (error, "%s.%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_SETTING_IP4_CONFIG_ADDRESSES);
 				return FALSE;
 			}
 		}
+	} else if (!strcmp (priv->method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) {
+		/* nothing to do */
+	} else {
+		g_set_error_literal (error,
+		                     NM_SETTING_IP4_CONFIG_ERROR,
+		                     NM_SETTING_IP4_CONFIG_ERROR_INVALID_PROPERTY,
+		                     _("property is invalid"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_SETTING_IP4_CONFIG_METHOD);
+		return FALSE;
 	}
 
 	if (priv->dhcp_client_id && !strlen (priv->dhcp_client_id)) {
-		g_set_error (error,
-		             NM_SETTING_IP4_CONFIG_ERROR,
-		             NM_SETTING_IP4_CONFIG_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID);
+		g_set_error_literal (error,
+		                     NM_SETTING_IP4_CONFIG_ERROR,
+		                     NM_SETTING_IP4_CONFIG_ERROR_INVALID_PROPERTY,
+		                     _("property is empty"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID);
 		return FALSE;
 	}
 
 	if (priv->dhcp_hostname && !strlen (priv->dhcp_hostname)) {
-		g_set_error (error,
-		             NM_SETTING_IP4_CONFIG_ERROR,
-		             NM_SETTING_IP4_CONFIG_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_IP4_CONFIG_DHCP_HOSTNAME);
+		g_set_error_literal (error,
+		                     NM_SETTING_IP4_CONFIG_ERROR,
+		                     NM_SETTING_IP4_CONFIG_ERROR_INVALID_PROPERTY,
+		                     _("property is empty"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_SETTING_IP4_CONFIG_DHCP_HOSTNAME);
 		return FALSE;
 	}
 
 	/* Validate addresses */
-	for (iter = priv->addresses, i = 0; iter; iter = g_slist_next (iter), i++) {
+	for (iter = priv->addresses, l_iter = priv->address_labels, i = 0;
+	     iter && l_iter;
+	     iter = g_slist_next (iter), l_iter = g_slist_next (l_iter), i++) {
 		NMIP4Address *addr = (NMIP4Address *) iter->data;
+		const char *label = (const char *) l_iter->data;
 		guint32 prefix = nm_ip4_address_get_prefix (addr);
 
 		if (!nm_ip4_address_get_address (addr)) {
 			g_set_error (error,
 			             NM_SETTING_IP4_CONFIG_ERROR,
 			             NM_SETTING_IP4_CONFIG_ERROR_INVALID_PROPERTY,
-			             NM_SETTING_IP4_CONFIG_ADDRESSES);
+			             _("%d. IPv4 address is invalid"),
+			             i+1);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_SETTING_IP4_CONFIG_ADDRESSES);
 			return FALSE;
 		}
 
@@ -795,11 +985,34 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 			g_set_error (error,
 			             NM_SETTING_IP4_CONFIG_ERROR,
 			             NM_SETTING_IP4_CONFIG_ERROR_INVALID_PROPERTY,
-			             NM_SETTING_IP4_CONFIG_ADDRESSES);
+			             _("%d. IPv4 address has invalid prefix"),
+			             i+1);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_SETTING_IP4_CONFIG_ADDRESSES);
+			return FALSE;
+		}
+
+		if (label && !verify_label (label)) {
+			g_set_error (error,
+			             NM_SETTING_IP4_CONFIG_ERROR,
+			             NM_SETTING_IP4_CONFIG_ERROR_INVALID_PROPERTY,
+			             _("%d. IPv4 address has invalid label '%s'"),
+			             i+1, label);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME, "address-labels");
 			return FALSE;
 		}
 	}
 
+	if (iter || l_iter) {
+		g_set_error (error,
+		             NM_SETTING_IP4_CONFIG_ERROR,
+		             NM_SETTING_IP4_CONFIG_ERROR_INVALID_PROPERTY,
+		             _("IPv4 address / label count mismatch (%d vs %d)"),
+		             g_slist_length (priv->addresses),
+		             g_slist_length (priv->address_labels));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME, "address-labels");
+		return FALSE;
+	}
+
 	/* Validate routes */
 	for (iter = priv->routes, i = 0; iter; iter = g_slist_next (iter), i++) {
 		NMIP4Route *route = (NMIP4Route *) iter->data;
@@ -809,7 +1022,9 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 			g_set_error (error,
 			             NM_SETTING_IP4_CONFIG_ERROR,
 			             NM_SETTING_IP4_CONFIG_ERROR_INVALID_PROPERTY,
-			             NM_SETTING_IP4_CONFIG_ROUTES);
+			             _("%d. route is invalid"),
+			             i+1);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_SETTING_IP4_CONFIG_ROUTES);
 			return FALSE;
 		}
 
@@ -817,7 +1032,9 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 			g_set_error (error,
 			             NM_SETTING_IP4_CONFIG_ERROR,
 			             NM_SETTING_IP4_CONFIG_ERROR_INVALID_PROPERTY,
-			             NM_SETTING_IP4_CONFIG_ROUTES);
+			             _("%d. route has invalid prefix"),
+			             i+1);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_SETTING_IP4_CONFIG_ROUTES);
 			return FALSE;
 		}
 	}
@@ -831,7 +1048,6 @@ nm_setting_ip4_config_init (NMSettingIP4Config *setting)
 {
 	NMSettingIP4ConfigPrivate *priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting);
 
-	g_object_set (setting, NM_SETTING_NAME, NM_SETTING_IP4_CONFIG_SETTING_NAME, NULL);
 
 	priv->dns = g_array_sized_new (FALSE, TRUE, sizeof (guint32), 3);
 }
@@ -848,9 +1064,10 @@ finalize (GObject *object)
 
 	g_array_free (priv->dns, TRUE);
 
-	nm_utils_slist_free (priv->dns_search, g_free);
-	nm_utils_slist_free (priv->addresses, (GDestroyNotify) nm_ip4_address_unref);
-	nm_utils_slist_free (priv->routes, (GDestroyNotify) nm_ip4_route_unref);
+	g_slist_free_full (priv->dns_search, g_free);
+	g_slist_free_full (priv->addresses, (GDestroyNotify) nm_ip4_address_unref);
+	g_slist_free_full (priv->address_labels, g_free);
+	g_slist_free_full (priv->routes, (GDestroyNotify) nm_ip4_route_unref);
 
 	G_OBJECT_CLASS (nm_setting_ip4_config_parent_class)->finalize (object);
 }
@@ -861,6 +1078,7 @@ set_property (GObject *object, guint prop_id,
 {
 	NMSettingIP4Config *setting = NM_SETTING_IP4_CONFIG (object);
 	NMSettingIP4ConfigPrivate *priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting);
+	GSList *iter;
 
 	switch (prop_id) {
 	case PROP_METHOD:
@@ -871,18 +1089,36 @@ set_property (GObject *object, guint prop_id,
 		g_array_free (priv->dns, TRUE);
 		priv->dns = g_value_dup_boxed (value);
 		if (!priv->dns)
-			priv->dns = g_array_sized_new (FALSE, TRUE, sizeof (guint32), 3);			
+			priv->dns = g_array_sized_new (FALSE, TRUE, sizeof (guint32), 3);
 		break;
 	case PROP_DNS_SEARCH:
-		nm_utils_slist_free (priv->dns_search, g_free);
+		g_slist_free_full (priv->dns_search, g_free);
 		priv->dns_search = g_value_dup_boxed (value);
 		break;
 	case PROP_ADDRESSES:
-		nm_utils_slist_free (priv->addresses, (GDestroyNotify) nm_ip4_address_unref);
+		g_slist_free_full (priv->addresses, (GDestroyNotify) nm_ip4_address_unref);
 		priv->addresses = nm_utils_ip4_addresses_from_gvalue (value);
+
+		if (g_slist_length (priv->addresses) != g_slist_length (priv->address_labels)) {
+			g_slist_free_full (priv->address_labels, g_free);
+			priv->address_labels = NULL;
+			for (iter = priv->addresses; iter; iter = iter->next)
+				priv->address_labels = g_slist_prepend (priv->address_labels, NULL);
+		}
+		break;
+	case PROP_ADDRESS_LABELS:
+		g_slist_free_full (priv->address_labels, g_free);
+		priv->address_labels = g_value_dup_boxed (value);
+		/* NULLs get converted to "" when this is sent over D-Bus. */
+		for (iter = priv->address_labels; iter; iter = iter->next) {
+			if (!g_strcmp0 (iter->data, "")) {
+				g_free (iter->data);
+				iter->data = NULL;
+			}
+		}
 		break;
 	case PROP_ROUTES:
-		nm_utils_slist_free (priv->routes, (GDestroyNotify) nm_ip4_route_unref);
+		g_slist_free_full (priv->routes, (GDestroyNotify) nm_ip4_route_unref);
 		priv->routes = nm_utils_ip4_routes_from_gvalue (value);
 		break;
 	case PROP_IGNORE_AUTO_ROUTES:
@@ -934,6 +1170,9 @@ get_property (GObject *object, guint prop_id,
 	case PROP_ADDRESSES:
 		nm_utils_ip4_addresses_to_gvalue (priv->addresses, value);
 		break;
+	case PROP_ADDRESS_LABELS:
+		g_value_set_boxed (value, priv->address_labels);
+		break;
 	case PROP_ROUTES:
 		nm_utils_ip4_routes_to_gvalue (priv->routes, value);
 		break;
@@ -982,17 +1221,17 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *setting_class)
 	/**
 	 * NMSettingIP4Config:method:
 	 *
-	 * IPv4 configuration method.  If 'auto' is specified then the appropriate
+	 * IPv4 configuration method.  If "auto" is specified then the appropriate
 	 * automatic method (DHCP, PPP, etc) is used for the interface and most
-	 * other properties can be left unset.  If 'link-local' is specified, then a
+	 * other properties can be left unset.  If "link-local" is specified, then a
 	 * link-local address in the 169.254/16 range will be assigned to the
-	 * interface.  If 'manual' is specified, static IP addressing is used and at
-	 * least one IP address must be given in the 'addresses' property.  If
-	 * 'shared' is specified (indicating that this connection will provide
+	 * interface.  If "manual" is specified, static IP addressing is used and at
+	 * least one IP address must be given in the "addresses" property.  If
+	 * "shared" is specified (indicating that this connection will provide
 	 * network access to other computers) then the interface is assigned an
 	 * address in the 10.42.x.1/24 range and a DHCP and forwarding DNS server
 	 * are started, and the interface is NAT-ed to the current default network
-	 * connection.  'disabled' means IPv4 will not be used on this connection.
+	 * connection.  "disabled" means IPv4 will not be used on this connection.
 	 * This property must be set.
 	 **/
 	g_object_class_install_property
@@ -1017,17 +1256,17 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *setting_class)
 						      "connection.  'disabled' means IPv4 will not be "
 						      "used on this connection.  This property must be set.",
 						      NULL,
-						      G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+						      G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE));
 
 	/**
 	 * NMSettingIP4Config:dns:
 	 *
-	 * List of DNS servers (network byte order).  For the 'auto' method, these
+	 * List of DNS servers (network byte order).  For the "auto" method, these
 	 * DNS servers are appended to those (if any) returned by automatic
-	 * configuration.  DNS servers cannot be used with the 'shared', 'link-local',
-	 * or 'disabled' methods as there is no upstream network.  In all other
-	 * methods, these DNS servers are used as the only DNS servers for this
-	 * connection.
+	 * configuration.  DNS servers cannot be used with the "shared",
+	 * "link-local", or "disabled" methods as there is no upstream network.  In
+	 * all other methods, these DNS servers are used as the only DNS servers for
+	 * this connection.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_DNS,
@@ -1042,14 +1281,14 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *setting_class)
 							   "other methods, these DNS servers are used as the "
 							   "only DNS servers for this connection.",
 							   DBUS_TYPE_G_UINT_ARRAY,
-							   G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+							   G_PARAM_READWRITE));
 
 	/**
 	 * NMSettingIP4Config:dns-search:
 	 *
-	 * List of DNS search domains.  For the 'auto' method, these search domains
+	 * List of DNS search domains.  For the "auto" method, these search domains
 	 * are appended to those returned by automatic configuration. Search domains
-	 * cannot be used with the 'shared', 'link-local', or 'disabled' methods as
+	 * cannot be used with the "shared", "link-local", or "disabled" methods as
 	 * there is no upstream network.  In all other methods, these search domains
 	 * are used as the only search domains for this connection.
 	 **/
@@ -1066,7 +1305,7 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *setting_class)
 							   "search domains are used as the only search domains "
 							   "for this connection.",
 							   DBUS_TYPE_G_LIST_OF_STRING,
-							   G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+							   G_PARAM_READWRITE));
 
 	/**
 	 * NMSettingIP4Config:addresses:
@@ -1075,9 +1314,9 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *setting_class)
 	 * composed of 3 32-bit values; the first being the IPv4 address (network
 	 * byte order), the second the prefix (1 - 32), and last the IPv4 gateway
 	 * (network byte order). The gateway may be left as 0 if no gateway exists
-	 * for that subnet.  For the 'auto' method, given IP addresses are appended
+	 * for that subnet.  For the "auto" method, given IP addresses are appended
 	 * to those returned by automatic configuration.  Addresses cannot be used
-	 * with the 'shared', 'link-local', or 'disabled' methods as addressing is
+	 * with the "shared", "link-local", or "disabled" methods as addressing is
 	 * either automatic or disabled with these methods.
 	 **/
 	g_object_class_install_property
@@ -1097,19 +1336,32 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *setting_class)
 							   "'disabled' methods as addressing is either "
 							   "automatic or disabled with these methods.",
 							   DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT,
-							   G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+							   G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE));
+
+	/**
+	 * NMSettingIP4Config:address-labels:
+	 *
+	 * Internal use only.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_ADDRESS_LABELS,
+		 _nm_param_spec_specialized ("address-labels",
+		                             "Address labels",
+		                             "Internal use only",
+		                             DBUS_TYPE_G_LIST_OF_STRING,
+		                             G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE));
 
 	/**
 	 * NMSettingIP4Config:routes:
 	 *
-	 * Array of IPv4 route structures.  Each IPv4 route structure is composed
-	 * of 4 32-bit values; the first being the destination IPv4 network or
-	 * address (network byte order), the second the destination network or
-	 * address prefix (1 - 32), the third being the next-hop (network byte
-	 * order) if any, and the fourth being the route metric. For the 'auto'
-	 * method, given IP routes are appended to those returned by automatic
-	 * configuration.  Routes cannot be used with the 'shared', 'link-local',
-	 * or 'disabled' methods because there is no upstream network.
+	 * Array of IPv4 route structures.  Each IPv4 route structure is composed of
+	 * 4 32-bit values; the first being the destination IPv4 network or address
+	 * (network byte order), the second the destination network or address
+	 * prefix (1 - 32), the third being the next-hop (network byte order) if
+	 * any, and the fourth being the route metric. For the "auto" method, given
+	 * IP routes are appended to those returned by automatic configuration.
+	 * Routes cannot be used with the "shared", "link-local", or "disabled"
+	 * methods because there is no upstream network.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_ROUTES,
@@ -1128,14 +1380,14 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *setting_class)
 							   "'shared', 'link-local', or 'disabled', methods "
 							   "as there is no upstream network.",
 							   DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT,
-							   G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+							   G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE));
 
 	/**
 	 * NMSettingIP4Config:ignore-auto-routes:
 	 *
-	 * When the method is set to 'auto' and this property to TRUE, automatically
-	 * configured routes are ignored and only routes specified in
-	 * #NMSettingIP4Config:routes, if any, are used.
+	 * When the method is set to "auto" and this property to %TRUE,
+	 * automatically configured routes are ignored and only routes specified in
+	 * the #NMSettingIP4Config:routes property, if any, are used.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_IGNORE_AUTO_ROUTES,
@@ -1146,15 +1398,16 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *setting_class)
 						   "ignored and only routes specified in the 'routes' "
 						   "property, if any, are used.",
 						   FALSE,
-						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
 	/**
 	 * NMSettingIP4Config:ignore-auto-dns:
 	 *
-	 * When the method is set to 'auto' and this property to TRUE, automatically
-	 * configured nameservers and search domains are ignored and only nameservers
-	 * and search domains specified in #NMSettingIP4Config:dns and
-	 * #NMSettingIP4Config:dns-search, if any, are used.
+	 * When the method is set to "auto" and this property to %TRUE,
+	 * automatically configured nameservers and search domains are ignored and
+	 * only nameservers and search domains specified in the
+	 * #NMSettingIP4Config:dns and #NMSettingIP4Config:dns-search properties, if
+	 * any, are used.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_IGNORE_AUTO_DNS,
@@ -1166,7 +1419,7 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *setting_class)
 						   "search domains specified in the 'dns' and 'dns-search' "
 						   "properties, if any, are used.",
 						   FALSE,
-						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
 	/**
 	 * NMSettingIP4Config:dhcp-client-id:
@@ -1182,16 +1435,16 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *setting_class)
 						   "local machine which the DHCP server may use to "
 						   "customize the DHCP lease and options.",
 						   NULL,
-						   G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+						   G_PARAM_READWRITE));
 
 	/**
 	 * NMSettingIP4Config:dhcp-send-hostname:
 	 *
-	 * If TRUE, a hostname is sent to the DHCP server when acquiring a lease.
+	 * If %TRUE, a hostname is sent to the DHCP server when acquiring a lease.
 	 * Some DHCP servers use this hostname to update DNS databases, essentially
-	 * providing a static hostname for the computer.  If
-	 * #NMSettingIP4Config:dhcp-hostname is empty and this property is TRUE,
-	 * the current persistent hostname of the computer is sent.
+	 * providing a static hostname for the computer.  If the
+	 * #NMSettingIP4Config:dhcp-hostname property is empty and this property is
+	 * %TRUE, the current persistent hostname of the computer is sent.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_DHCP_SEND_HOSTNAME,
@@ -1205,12 +1458,12 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *setting_class)
 						   "property is TRUE, the current persistent hostname "
 						   "of the computer is sent.",
 						   TRUE,
-						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
 	/**
 	 * NMSettingIP4Config:dhcp-hostname:
 	 *
-	 * If the #NMSettingIP4Config:dhcp-send-hostname property is TRUE, then the
+	 * If the #NMSettingIP4Config:dhcp-send-hostname property is %TRUE, then the
 	 * specified name will be sent to the DHCP server when acquiring a lease.
 	 **/
 	g_object_class_install_property
@@ -1221,12 +1474,12 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *setting_class)
 						   "the specified name will be sent to the DHCP server "
 						   "when acquiring a lease.",
 						   NULL,
-						   G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+						   G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE));
 
 	/**
 	 * NMSettingIP4Config:never-default:
 	 *
-	 * If TRUE, this connection will never be the default IPv4 connection,
+	 * If %TRUE, this connection will never be the default IPv4 connection,
 	 * meaning it will never be assigned the default route by NetworkManager.
 	 **/
 	g_object_class_install_property
@@ -1237,17 +1490,17 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *setting_class)
 						   "IPv4 connection, meaning it will never be assigned "
 						   "the default route by NetworkManager.",
 						   FALSE,
-						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
 	/**
 	 * NMSettingIP4Config:may-fail:
 	 *
-	 * If TRUE, allow overall network configuration to proceed even if IPv4
-	 * configuration times out.  Note that at least one IP configuration
-	 * must succeed or overall network configuration will still fail.  For
-	 * example, in IPv6-only networks, setting this property to TRUE allows
-	 * the overall network configuration to succeed if IPv4 configuration fails
-	 * but IPv6 configuration completes successfully.
+	 * If %TRUE, allow overall network configuration to proceed even if IPv4
+	 * configuration times out.  Note that at least one IP configuration must
+	 * succeed or overall network configuration will still fail.  For example,
+	 * in IPv6-only networks, setting this property to %TRUE allows the overall
+	 * network configuration to succeed if IPv4 configuration fails but IPv6
+	 * configuration completes successfully.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_MAY_FAIL,
@@ -1262,7 +1515,7 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *setting_class)
 						   "configuration to succeed if IPv4 configuration "
 						   "fails but IPv6 configuration completes successfully.",
 						   TRUE,
-						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 }
 
 
diff --git a/libnm-util/nm-setting-ip4-config.h b/libnm-util/nm-setting-ip4-config.h
index 5f7f3d00..3f0d006b 100644
--- a/libnm-util/nm-setting-ip4-config.h
+++ b/libnm-util/nm-setting-ip4-config.h
@@ -19,7 +19,7 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2007 - 2010 Red Hat, Inc.
+ * (C) Copyright 2007 - 2014 Red Hat, Inc.
  * (C) Copyright 2007 - 2008 Novell, Inc.
  */
 
@@ -189,24 +189,32 @@ guint32       nm_setting_ip4_config_get_num_dns            (NMSettingIP4Config *
 guint32       nm_setting_ip4_config_get_dns                (NMSettingIP4Config *setting, guint32 i);
 gboolean      nm_setting_ip4_config_add_dns                (NMSettingIP4Config *setting, guint32 dns);
 void          nm_setting_ip4_config_remove_dns             (NMSettingIP4Config *setting, guint32 i);
+NM_AVAILABLE_IN_0_9_10
+gboolean      nm_setting_ip4_config_remove_dns_by_value    (NMSettingIP4Config *setting, guint32 dns);
 void          nm_setting_ip4_config_clear_dns              (NMSettingIP4Config *setting);
 
-guint32       nm_setting_ip4_config_get_num_dns_searches   (NMSettingIP4Config *setting);
-const char *  nm_setting_ip4_config_get_dns_search         (NMSettingIP4Config *setting, guint32 i);
-gboolean      nm_setting_ip4_config_add_dns_search         (NMSettingIP4Config *setting, const char *dns_search);
-void          nm_setting_ip4_config_remove_dns_search      (NMSettingIP4Config *setting, guint32 i);
-void          nm_setting_ip4_config_clear_dns_searches     (NMSettingIP4Config *setting);
-
-guint32       nm_setting_ip4_config_get_num_addresses      (NMSettingIP4Config *setting);
-NMIP4Address *nm_setting_ip4_config_get_address            (NMSettingIP4Config *setting, guint32 i);
-gboolean      nm_setting_ip4_config_add_address            (NMSettingIP4Config *setting, NMIP4Address *address);
-void          nm_setting_ip4_config_remove_address         (NMSettingIP4Config *setting, guint32 i);
-void          nm_setting_ip4_config_clear_addresses        (NMSettingIP4Config *setting);
+guint32       nm_setting_ip4_config_get_num_dns_searches       (NMSettingIP4Config *setting);
+const char *  nm_setting_ip4_config_get_dns_search             (NMSettingIP4Config *setting, guint32 i);
+gboolean      nm_setting_ip4_config_add_dns_search             (NMSettingIP4Config *setting, const char *dns_search);
+void          nm_setting_ip4_config_remove_dns_search          (NMSettingIP4Config *setting, guint32 i);
+NM_AVAILABLE_IN_0_9_10
+gboolean      nm_setting_ip4_config_remove_dns_search_by_value (NMSettingIP4Config *setting, const char *dns_search);
+void          nm_setting_ip4_config_clear_dns_searches         (NMSettingIP4Config *setting);
+
+guint32       nm_setting_ip4_config_get_num_addresses       (NMSettingIP4Config *setting);
+NMIP4Address *nm_setting_ip4_config_get_address             (NMSettingIP4Config *setting, guint32 i);
+gboolean      nm_setting_ip4_config_add_address             (NMSettingIP4Config *setting, NMIP4Address *address);
+void          nm_setting_ip4_config_remove_address          (NMSettingIP4Config *setting, guint32 i);
+NM_AVAILABLE_IN_0_9_10
+gboolean      nm_setting_ip4_config_remove_address_by_value (NMSettingIP4Config *setting, NMIP4Address *address);
+void          nm_setting_ip4_config_clear_addresses         (NMSettingIP4Config *setting);
 
 guint32       nm_setting_ip4_config_get_num_routes         (NMSettingIP4Config *setting);
 NMIP4Route *  nm_setting_ip4_config_get_route              (NMSettingIP4Config *setting, guint32 i);
 gboolean      nm_setting_ip4_config_add_route              (NMSettingIP4Config *setting, NMIP4Route *route);
 void          nm_setting_ip4_config_remove_route           (NMSettingIP4Config *setting, guint32 i);
+NM_AVAILABLE_IN_0_9_10
+gboolean      nm_setting_ip4_config_remove_route_by_value  (NMSettingIP4Config *setting, NMIP4Route *route);
 void          nm_setting_ip4_config_clear_routes           (NMSettingIP4Config *setting);
 
 gboolean      nm_setting_ip4_config_get_ignore_auto_routes (NMSettingIP4Config *setting);
diff --git a/libnm-util/nm-setting-ip6-config.c b/libnm-util/nm-setting-ip6-config.c
index b9a0ea30..b027ee96 100644
--- a/libnm-util/nm-setting-ip6-config.c
+++ b/libnm-util/nm-setting-ip6-config.c
@@ -19,12 +19,13 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2007 - 2012 Red Hat, Inc.
+ * (C) Copyright 2007 - 2014 Red Hat, Inc.
  */
 
 #include <string.h>
-
 #include <dbus/dbus-glib.h>
+#include <glib/gi18n.h>
+
 #include "nm-setting-ip6-config.h"
 #include "nm-param-spec-specialized.h"
 #include "nm-utils.h"
@@ -211,6 +212,7 @@ nm_setting_ip6_config_add_dns (NMSettingIP6Config *setting, const struct in6_add
 	copy = g_malloc0 (sizeof (struct in6_addr));
 	memcpy (copy, addr, sizeof (struct in6_addr));
 	priv->dns = g_slist_append (priv->dns, copy);
+	g_object_notify (G_OBJECT (setting), NM_SETTING_IP6_CONFIG_DNS);
 
 	return TRUE;
 }
@@ -236,6 +238,38 @@ nm_setting_ip6_config_remove_dns (NMSettingIP6Config *setting, guint32 i)
 
 	g_free (elt->data);
 	priv->dns = g_slist_delete_link (priv->dns, elt);
+	g_object_notify (G_OBJECT (setting), NM_SETTING_IP6_CONFIG_DNS);
+}
+
+/**
+ * nm_setting_ip6_config_remove_dns_by_value:
+ * @setting: the #NMSettingIP6Config
+ * @dns: the IPv6 address of the DNS server to remove
+ *
+ * Removes the DNS server at index @i.
+ *
+ * Returns: %TRUE if the DNS server was found and removed; %FALSE if it was not.
+ *
+ * Since: 0.9.10
+ **/
+gboolean
+nm_setting_ip6_config_remove_dns_by_value (NMSettingIP6Config *setting,
+                                           const struct in6_addr *addr)
+{
+	NMSettingIP6ConfigPrivate *priv;
+	GSList *iter;
+
+	g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), FALSE);
+
+	priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting);
+	for (iter = priv->dns; iter; iter = g_slist_next (iter)) {
+		if (!memcmp (addr, (struct in6_addr *) iter->data, sizeof (struct in6_addr))) {
+			priv->dns = g_slist_delete_link (priv->dns, iter);
+			g_object_notify (G_OBJECT (setting), NM_SETTING_IP6_CONFIG_DNS);
+			return TRUE;
+		}
+	}
+	return FALSE;
 }
 
 /**
@@ -249,8 +283,9 @@ nm_setting_ip6_config_clear_dns (NMSettingIP6Config *setting)
 {
 	g_return_if_fail (NM_IS_SETTING_IP6_CONFIG (setting));
 
-	nm_utils_slist_free (NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->dns, g_free);
+	g_slist_free_full (NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->dns, g_free);
 	NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->dns = NULL;
+	g_object_notify (G_OBJECT (setting), NM_SETTING_IP6_CONFIG_DNS);
 }
 
 /**
@@ -315,6 +350,7 @@ nm_setting_ip6_config_add_dns_search (NMSettingIP6Config *setting,
 	}
 
 	priv->dns_search = g_slist_append (priv->dns_search, g_strdup (dns_search));
+	g_object_notify (G_OBJECT (setting), NM_SETTING_IP6_CONFIG_DNS_SEARCH);
 	return TRUE;
 }
 
@@ -339,6 +375,40 @@ nm_setting_ip6_config_remove_dns_search (NMSettingIP6Config *setting, guint32 i)
 
 	g_free (elt->data);
 	priv->dns_search = g_slist_delete_link (priv->dns_search, elt);
+	g_object_notify (G_OBJECT (setting), NM_SETTING_IP6_CONFIG_DNS_SEARCH);
+}
+
+/**
+ * nm_setting_ip6_config_remove_dns_search_by_value:
+ * @setting: the #NMSettingIP6Config
+ * @dns_search: the search domain to remove
+ *
+ * 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_ip6_config_remove_dns_search_by_value (NMSettingIP6Config *setting,
+                                                  const char *dns_search)
+{
+	NMSettingIP6ConfigPrivate *priv;
+	GSList *iter;
+
+	g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), FALSE);
+	g_return_val_if_fail (dns_search != NULL, FALSE);
+	g_return_val_if_fail (dns_search[0] != '\0', FALSE);
+
+	priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting);
+	for (iter = priv->dns_search; iter; iter = g_slist_next (iter)) {
+		if (!strcmp (dns_search, (char *) iter->data)) {
+			priv->dns_search = g_slist_delete_link (priv->dns_search, iter);
+			g_object_notify (G_OBJECT (setting), NM_SETTING_IP6_CONFIG_DNS_SEARCH);
+			return TRUE;
+		}
+	}
+	return FALSE;
 }
 
 /**
@@ -352,8 +422,9 @@ nm_setting_ip6_config_clear_dns_searches (NMSettingIP6Config *setting)
 {
 	g_return_if_fail (NM_IS_SETTING_IP6_CONFIG (setting));
 
-	nm_utils_slist_free (NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->dns_search, g_free);
+	g_slist_free_full (NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->dns_search, g_free);
 	NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->dns_search = NULL;
+	g_object_notify (G_OBJECT (setting), NM_SETTING_IP6_CONFIG_DNS_SEARCH);
 }
 
 /**
@@ -419,9 +490,8 @@ nm_setting_ip6_config_add_address (NMSettingIP6Config *setting,
 	}
 
 	copy = nm_ip6_address_dup (address);
-	g_return_val_if_fail (copy != NULL, FALSE);
-
 	priv->addresses = g_slist_append (priv->addresses, copy);
+	g_object_notify (G_OBJECT (setting), NM_SETTING_IP6_CONFIG_ADDRESSES);
 	return TRUE;
 }
 
@@ -446,6 +516,39 @@ nm_setting_ip6_config_remove_address (NMSettingIP6Config *setting, guint32 i)
 
 	nm_ip6_address_unref ((NMIP6Address *) elt->data);
 	priv->addresses = g_slist_delete_link (priv->addresses, elt);
+	g_object_notify (G_OBJECT (setting), NM_SETTING_IP6_CONFIG_ADDRESSES);
+}
+
+/**
+ * nm_setting_ip6_config_remove_address_by_value:
+ * @setting: the #NMSettingIP6Config
+ * @address: the address to remove
+ *
+ * Removes the address @address.
+ *
+ * Returns: %TRUE if the address was found and removed; %FALSE if it was not.
+ *
+ * Since: 0.9.10
+ **/
+gboolean
+nm_setting_ip6_config_remove_address_by_value (NMSettingIP6Config *setting,
+                                               NMIP6Address *address)
+{
+	NMSettingIP6ConfigPrivate *priv;
+	GSList *iter;
+
+	g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), FALSE);
+	g_return_val_if_fail (address != NULL, FALSE);
+
+	priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting);
+	for (iter = priv->addresses; iter; iter = g_slist_next (iter)) {
+		if (nm_ip6_address_compare ((NMIP6Address *) iter->data, address)) {
+			priv->addresses = g_slist_delete_link (priv->addresses, iter);
+			g_object_notify (G_OBJECT (setting), NM_SETTING_IP6_CONFIG_ADDRESSES);
+			return TRUE;
+		}
+	}
+	return FALSE;
 }
 
 /**
@@ -461,8 +564,9 @@ nm_setting_ip6_config_clear_addresses (NMSettingIP6Config *setting)
 
 	g_return_if_fail (NM_IS_SETTING_IP6_CONFIG (setting));
 
-	nm_utils_slist_free (priv->addresses, (GDestroyNotify) nm_ip6_address_unref);
+	g_slist_free_full (priv->addresses, (GDestroyNotify) nm_ip6_address_unref);
 	priv->addresses = NULL;
+	g_object_notify (G_OBJECT (setting), NM_SETTING_IP6_CONFIG_ADDRESSES);
 }
 
 /**
@@ -527,9 +631,8 @@ nm_setting_ip6_config_add_route (NMSettingIP6Config *setting,
 	}
 
 	copy = nm_ip6_route_dup (route);
-	g_return_val_if_fail (copy != NULL, FALSE);
-
 	priv->routes = g_slist_append (priv->routes, copy);
+	g_object_notify (G_OBJECT (setting), NM_SETTING_IP6_CONFIG_ROUTES);
 	return TRUE;
 }
 
@@ -554,6 +657,40 @@ nm_setting_ip6_config_remove_route (NMSettingIP6Config *setting, guint32 i)
 
 	nm_ip6_route_unref ((NMIP6Route *) elt->data);
 	priv->routes = g_slist_delete_link (priv->routes, elt);
+	g_object_notify (G_OBJECT (setting), NM_SETTING_IP6_CONFIG_ROUTES);
+}
+
+/**
+ * nm_setting_ip6_config_remove_route_by_value:
+ * @setting: the #NMSettingIP6Config
+ * @route: the route to remove
+ *
+ * Removes the route @route.
+ *
+ * Returns: %TRUE if the route was found and removed; %FALSE if it was not.
+ *
+ * Since: 0.9.10
+ **/
+gboolean
+nm_setting_ip6_config_remove_route_by_value (NMSettingIP6Config *setting,
+                                             NMIP6Route *route)
+{
+	NMSettingIP6ConfigPrivate *priv;
+	GSList *iter;
+
+	g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), FALSE);
+	g_return_val_if_fail (route != NULL, FALSE);
+
+	priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting);
+	for (iter = priv->routes; iter; iter = g_slist_next (iter)) {
+		if (nm_ip6_route_compare ((NMIP6Route *) iter->data, route)) {
+			nm_ip6_route_unref ((NMIP6Route *) iter->data);
+			priv->routes = g_slist_delete_link (priv->routes, iter);
+			g_object_notify (G_OBJECT (setting), NM_SETTING_IP6_CONFIG_ROUTES);
+			return TRUE;
+		}
+	}
+	return FALSE;
 }
 
 /**
@@ -569,8 +706,9 @@ nm_setting_ip6_config_clear_routes (NMSettingIP6Config *setting)
 
 	g_return_if_fail (NM_IS_SETTING_IP6_CONFIG (setting));
 
-	nm_utils_slist_free (priv->routes, (GDestroyNotify) nm_ip6_route_unref);
+	g_slist_free_full (priv->routes, (GDestroyNotify) nm_ip6_route_unref);
 	priv->routes = NULL;
+	g_object_notify (G_OBJECT (setting), NM_SETTING_IP6_CONFIG_ROUTES);
 }
 
 /**
@@ -662,25 +800,17 @@ nm_setting_ip6_config_get_ip6_privacy (NMSettingIP6Config *setting)
 	return NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->ip6_privacy;
 }
 
-static gint
-find_setting_by_name (gconstpointer a, gconstpointer b)
-{
-	NMSetting *setting = NM_SETTING (a);
-	const char *str = (const char *) b;
-
-	return strcmp (nm_setting_get_name (setting), str);
-}
-
 static gboolean
 verify (NMSetting *setting, GSList *all_settings, GError **error)
 {
 	NMSettingIP6ConfigPrivate *priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting);
 
 	if (!priv->method) {
-		g_set_error (error,
-		             NM_SETTING_IP6_CONFIG_ERROR,
-		             NM_SETTING_IP6_CONFIG_ERROR_MISSING_PROPERTY,
-		             NM_SETTING_IP6_CONFIG_METHOD);
+		g_set_error_literal (error,
+		                     NM_SETTING_IP6_CONFIG_ERROR,
+		                     NM_SETTING_IP6_CONFIG_ERROR_MISSING_PROPERTY,
+		                     _("property is missing"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_SETTING_IP6_CONFIG_METHOD);
 		return FALSE;
 	}
 
@@ -689,7 +819,9 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 			g_set_error (error,
 			             NM_SETTING_IP6_CONFIG_ERROR,
 			             NM_SETTING_IP6_CONFIG_ERROR_MISSING_PROPERTY,
-			             NM_SETTING_IP6_CONFIG_ADDRESSES);
+			             _("this property cannot be empty for '%s=%s'"),
+			             NM_SETTING_IP6_CONFIG_METHOD, priv->method);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_SETTING_IP6_CONFIG_ADDRESSES);
 			return FALSE;
 		}
 	} else if (   !strcmp (priv->method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE)
@@ -699,7 +831,10 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 			g_set_error (error,
 			             NM_SETTING_IP6_CONFIG_ERROR,
 			             NM_SETTING_IP6_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD,
-			             NM_SETTING_IP6_CONFIG_DNS);
+			             _("'%s' not allowed for %s=%s"),
+			             _("this property is not allowed for '%s=%s'"),
+			             NM_SETTING_IP6_CONFIG_METHOD, priv->method);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_SETTING_IP6_CONFIG_DNS);
 			return FALSE;
 		}
 
@@ -707,7 +842,9 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 			g_set_error (error,
 			             NM_SETTING_IP6_CONFIG_ERROR,
 			             NM_SETTING_IP6_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD,
-			             NM_SETTING_IP6_CONFIG_DNS_SEARCH);
+			             _("this property is not allowed for '%s=%s'"),
+			             NM_SETTING_IP6_CONFIG_METHOD, priv->method);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_SETTING_IP6_CONFIG_DNS_SEARCH);
 			return FALSE;
 		}
 
@@ -715,41 +852,29 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 			g_set_error (error,
 			             NM_SETTING_IP6_CONFIG_ERROR,
 			             NM_SETTING_IP6_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD,
-			             NM_SETTING_IP6_CONFIG_ADDRESSES);
+			             _("this property is not allowed for '%s=%s'"),
+			             NM_SETTING_IP6_CONFIG_METHOD, priv->method);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_SETTING_IP6_CONFIG_ADDRESSES);
 			return FALSE;
 		}
 	} else if (   !strcmp (priv->method, NM_SETTING_IP6_CONFIG_METHOD_AUTO)
 	           || !strcmp (priv->method, NM_SETTING_IP6_CONFIG_METHOD_DHCP)) {
 		/* nothing to do */
 	} else {
-		g_set_error (error,
-		             NM_SETTING_IP6_CONFIG_ERROR,
-		             NM_SETTING_IP6_CONFIG_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_IP6_CONFIG_METHOD);
+		g_set_error_literal (error,
+		                     NM_SETTING_IP6_CONFIG_ERROR,
+		                     NM_SETTING_IP6_CONFIG_ERROR_INVALID_PROPERTY,
+		                     _("property is invalid"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_SETTING_IP6_CONFIG_METHOD);
 		return FALSE;
 	}
 
-	/* Method 'ignore' is not allowed when IPv4 is set to 'disabled' */
-	if (!strcmp (priv->method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE)) {
-		GSList *list = g_slist_find_custom (all_settings, NM_SETTING_IP4_CONFIG_SETTING_NAME, find_setting_by_name);
-		if (list) {
-			NMSettingIP4Config *s_ip4 = g_slist_nth_data (list, 0);
-			if (   s_ip4
-			    && !g_strcmp0 (nm_setting_ip4_config_get_method (s_ip4), NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) {
-				g_set_error (error,
-				             NM_SETTING_IP6_CONFIG_ERROR,
-				             NM_SETTING_IP6_CONFIG_ERROR_INVALID_PROPERTY,
-				             NM_SETTING_IP6_CONFIG_METHOD);
-				return FALSE;
-			}
-		}
-	}
-
 	if (priv->dhcp_hostname && !strlen (priv->dhcp_hostname)) {
-		g_set_error (error,
-		             NM_SETTING_IP6_CONFIG_ERROR,
-		             NM_SETTING_IP6_CONFIG_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_IP6_CONFIG_DHCP_HOSTNAME);
+		g_set_error_literal (error,
+		                     NM_SETTING_IP6_CONFIG_ERROR,
+		                     NM_SETTING_IP6_CONFIG_ERROR_INVALID_PROPERTY,
+		                     _("property is missing"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_SETTING_IP6_CONFIG_DHCP_HOSTNAME);
 		return FALSE;
 	}
 
@@ -760,7 +885,6 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 static void
 nm_setting_ip6_config_init (NMSettingIP6Config *setting)
 {
-	g_object_set (setting, NM_SETTING_NAME, NM_SETTING_IP6_CONFIG_SETTING_NAME, NULL);
 }
 
 static void
@@ -771,11 +895,10 @@ finalize (GObject *object)
 	g_free (priv->method);
 	g_free (priv->dhcp_hostname);
 
-	g_slist_free (priv->dns);
-
-	nm_utils_slist_free (priv->dns_search, g_free);
-	nm_utils_slist_free (priv->addresses, g_free);
-	nm_utils_slist_free (priv->routes, g_free);
+	g_slist_free_full (priv->dns, g_free);
+	g_slist_free_full (priv->dns_search, g_free);
+	g_slist_free_full (priv->addresses, g_free);
+	g_slist_free_full (priv->routes, g_free);
 
 	G_OBJECT_CLASS (nm_setting_ip6_config_parent_class)->finalize (object);
 }
@@ -789,25 +912,22 @@ set_property (GObject *object, guint prop_id,
 	switch (prop_id) {
 	case PROP_METHOD:
 		g_free (priv->method);
-		if (g_strcmp0 (g_value_get_string (value), "disabled") == 0)
-			priv->method = g_strdup (NM_SETTING_IP6_CONFIG_METHOD_IGNORE);
-		else
-			priv->method = g_value_dup_string (value);
+		priv->method = g_value_dup_string (value);
 		break;
 	case PROP_DNS:
-		nm_utils_slist_free (priv->dns, g_free);
+		g_slist_free_full (priv->dns, g_free);
 		priv->dns = nm_utils_ip6_dns_from_gvalue (value);
 		break;
 	case PROP_DNS_SEARCH:
-		nm_utils_slist_free (priv->dns_search, g_free);
+		g_slist_free_full (priv->dns_search, g_free);
 		priv->dns_search = g_value_dup_boxed (value);
 		break;
 	case PROP_ADDRESSES:
-		nm_utils_slist_free (priv->addresses, g_free);
+		g_slist_free_full (priv->addresses, g_free);
 		priv->addresses = nm_utils_ip6_addresses_from_gvalue (value);
 		break;
 	case PROP_ROUTES:
-		nm_utils_slist_free (priv->routes, g_free);
+		g_slist_free_full (priv->routes, g_free);
 		priv->routes = nm_utils_ip6_routes_from_gvalue (value);
 		break;
 	case PROP_IGNORE_AUTO_ROUTES:
@@ -899,16 +1019,16 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *setting_class)
 	/**
 	 * NMSettingIP6Config:method:
 	 *
-	 * IPv6 configuration method.  If 'auto' is specified then the appropriate
-	 * automatic method (DHCP, PPP, advertisement, etc) is used for the
-	 * interface and most other properties can be left unset.  To force the use
-	 * of DHCP only, specify 'dhcp'; this  method is only valid for ethernet-
-	 * based hardware.  If 'link-local' is specified, then an IPv6 link-local
-	 * address will be assigned to the interface.  If 'manual' is specified,
-	 * static IP addressing is used and at least one IP address must be given
-	 * in the 'addresses' property.  If 'ignore' is specified, IPv6
-	 * configuration is not done. This property must be set.  NOTE: the 'shared'
-	 * method are not yet supported.
+	 * IPv6 configuration method.  If "auto" is specified then the appropriate
+	 * automatic method (PPP, router advertisement, etc) is used for the device
+	 * and most other properties can be left unset.  To force the use of DHCP
+	 * only, specify "dhcp"; this method is only valid for Ethernet- based
+	 * hardware.  If "link-local" is specified, then an IPv6 link-local address
+	 * will be assigned to the interface.  If "manual" is specified, static IP
+	 * addressing is used and at least one IP address must be given in the
+	 * "addresses" property.  If "ignore" is specified, IPv6 configuration is
+	 * not done. This property must be set.  Note: the "shared" method is not
+	 * yet supported.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_METHOD,
@@ -919,22 +1039,23 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *setting_class)
 						      "advertisement, etc) is used for the device and "
 						      "most other properties can be left unset.  To force "
 						      "the use of DHCP only, specify 'dhcp'; this method "
-						      "is only valid for ethernet-based hardware.  If "
+						      "is only valid for Ethernet-based hardware.  If "
 						      "'link-local' is specified, then an IPv6 link-local "
 						      "address will be assigned to the interface.  If "
 						      "'manual' is specified, static IP addressing is "
 						      "used and at least one IP address must be given in "
 						      " the 'addresses' property.  If 'ignore' is "
 						      "specified, IPv6 configuration is not done. This "
-						      "property must be set.  NOTE: the 'shared' method"
+						      "property must be set.  Note: the 'shared' method "
 						      "is not yet supported.",
 						      NULL,
-						      G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+						      G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE));
 
 	/**
 	 * NMSettingIP6Config:dhcp-hostname:
 	 *
-	 * The specified name will be sent to the DHCP server when acquiring a lease.
+	 * The specified name will be sent to the DHCP server when acquiring a
+	 * lease.
 	 *
 	 * Since: 0.9.8
 	 **/
@@ -945,17 +1066,17 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *setting_class)
 		                      "The specified name will be sent to the DHCP server "
 		                      "when acquiring a lease.",
 		                      NULL,
-		                      G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+		                      G_PARAM_READWRITE));
 
 	/**
 	 * NMSettingIP6Config:dns:
 	 *
 	 * Array of DNS servers, where each member of the array is a byte array
 	 * containing the IPv6 address of the DNS server (in network byte order).
-	 * For the 'auto' method, these DNS servers are appended to those (if any)
-	 * returned by automatic configuration.  DNS servers cannot be used with
-	 * the 'shared' or 'link-local' methods as there is no usptream network. In
-	 * all other methods, these DNS servers are used as the only DNS servers for
+	 * For the "auto" method, these DNS servers are appended to those (if any)
+	 * returned by automatic configuration.  DNS servers cannot be used with the
+	 * "shared" or "link-local" methods as there is no usptream network. In all
+	 * other methods, these DNS servers are used as the only DNS servers for
 	 * this connection.
 	 **/
 	g_object_class_install_property
@@ -973,16 +1094,16 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *setting_class)
 							   "these DNS servers are used as the only DNS "
 							   "servers for this connection.",
 							   DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UCHAR,
-							   G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+							   G_PARAM_READWRITE));
 
 	/**
 	 * NMSettingIP6Config:dns-search:
 	 *
-	 * List of DNS search domains.  For the 'auto' method, these search domains
+	 * List of DNS search domains.  For the "auto" method, these search domains
 	 * are appended to those returned by automatic configuration. Search domains
-	 * cannot be used with the 'shared' or 'link-local' methods as there is no
-	 * upstream network.  In all other methods, these search domains are used
-	 * as the only search domains for this connection.
+	 * cannot be used with the "shared" or "link-local" methods as there is no
+	 * upstream network.  In all other methods, these search domains are used as
+	 * the only search domains for this connection.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_DNS_SEARCH,
@@ -997,7 +1118,7 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *setting_class)
 							   "domains are used as the only search domains for "
 							   "this connection.",
 							   DBUS_TYPE_G_LIST_OF_STRING,
-							   G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+							   G_PARAM_READWRITE));
 
 	/**
 	 * NMSettingIP6Config:addresses:
@@ -1007,10 +1128,10 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *setting_class)
 	 * address (network byte order), the second a 32-bit integer containing the
 	 * IPv6 address prefix, and the third a byte array containing the IPv6
 	 * address (network byte order) of the gateway associated with this address,
-	 * if any.  If no gateway is given, the third element should be given as
-	 * all zeros.  For the 'auto' method, given IP addresses are appended to
-	 * those returned by automatic configuration.  Addresses cannot be used with
-	 * the 'shared' or 'link-local' methods as the interface is automatically
+	 * if any.  If no gateway is given, the third element should be given as all
+	 * zeros.  For the "auto" method, given IP addresses are appended to those
+	 * returned by automatic configuration.  Addresses cannot be used with the
+	 * "shared" or "link-local" methods as the interface is automatically
 	 * assigned an address with these methods.
 	 **/
 	g_object_class_install_property
@@ -1033,19 +1154,19 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *setting_class)
 							   "as the interface is automatically assigned an "
 							   "address with these methods.",
 							   DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS,
-							   G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+							   G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE));
 
 	/**
 	 * NMSettingIP6Config:routes:
 	 *
-	 * Array of IPv6 route structures.  Each IPv6 route structure is composed
-	 * of 4 members; the first being the destination IPv6 network or
-	 * address (network byte order) as a byte array, the second the destination
-	 * network or address IPv6 prefix, the third being the next-hop IPv6 address
+	 * Array of IPv6 route structures.  Each IPv6 route structure is composed of
+	 * 4 members; the first being the destination IPv6 network or address
+	 * (network byte order) as a byte array, the second the destination network
+	 * or address IPv6 prefix, the third being the next-hop IPv6 address
 	 * (network byte order) if any, and the fourth being the route metric. For
-	 * the 'auto' method, given IP routes are appended to those returned by
-	 * automatic configuration.  Routes cannot be used with the 'shared' or
-	 * 'link-local' methods because there is no upstream network.
+	 * the "auto" method, given IP routes are appended to those returned by
+	 * automatic configuration.  Routes cannot be used with the "shared" or
+	 * "link-local" methods because there is no upstream network.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_ROUTES,
@@ -1064,14 +1185,14 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *setting_class)
 							   "used with the 'shared' or 'link-local' methods "
 							   "because there is no upstream network.",
 							   DBUS_TYPE_G_ARRAY_OF_IP6_ROUTE,
-							   G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+							   G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE));
 
 	/**
 	 * NMSettingIP6Config:ignore-auto-routes:
 	 *
-	 * When the method is set to 'auto' or 'dhcp' and this property is set to
-	 * TRUE, automatically configured routes are ignored and only routes
-	 * specified in #NMSettingIP6Config:routes, if any, are used.
+	 * When the method is set to "auto" or "dhcp" and this property is set to
+	 * %TRUE, automatically configured routes are ignored and only routes
+	 * specified in the #NMSettingIP6Config:routes property, if any, are used.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_IGNORE_AUTO_ROUTES,
@@ -1082,16 +1203,16 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *setting_class)
 						   "routes are ignored and only routes specified in the "
 						   "'routes' property, if any, are used.",
 						   FALSE,
-						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
 	/**
 	 * NMSettingIP6Config:ignore-auto-dns:
 	 *
-	 * When the method is set to 'auto' or 'dhcp' and this property is set to
-	 * TRUE, automatically configured nameservers and search domains are ignored
-	 * and only nameservers and search domains specified in
-	 * #NMSettingIP6Config:dns and #NMSettingIP6Config:dns-search, if any, are
-	 * used.
+	 * When the method is set to "auto" or "dhcp" and this property is set to
+	 * %TRUE, automatically configured nameservers and search domains are
+	 * ignored and only nameservers and search domains specified in the
+	 * #NMSettingIP6Config:dns and #NMSettingIP6Config:dns-search properties, if
+	 * any, are used.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_IGNORE_AUTO_DNS,
@@ -1103,13 +1224,14 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *setting_class)
 						   "nameservers and search domains specified in the 'dns' "
 						   "and 'dns-search' properties, if any, are used.",
 						   FALSE,
-						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
 	/**
 	 * NMSettingIP6Config:never-default:
 	 *
-	 * If TRUE, this connection will never be the default IPv6 connection,
-	 * meaning it will never be assigned the default IPv6 route by NetworkManager.
+	 * If %TRUE, this connection will never be the default IPv6 connection,
+	 * meaning it will never be assigned the default IPv6 route by
+	 * NetworkManager.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_NEVER_DEFAULT,
@@ -1119,17 +1241,17 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *setting_class)
 						   "IPv6 connection, meaning it will never be assigned "
 						   "the default IPv6 route by NetworkManager.",
 						   FALSE,
-						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
 	/**
 	 * NMSettingIP6Config:may-fail:
 	 *
-	 * If TRUE, allow overall network configuration to proceed even if IPv6
-	 * configuration times out.  Note that at least one IP configuration
-	 * must succeed or overall network configuration will still fail.  For
-	 * example, in IPv4-only networks, setting this property to TRUE allows
-	 * the overall network configuration to succeed if IPv6 configuration fails
-	 * but IPv4 configuration completes successfully.
+	 * If %TRUE, allow overall network configuration to proceed even if IPv6
+	 * configuration times out.  Note that at least one IP configuration must
+	 * succeed or overall network configuration will still fail.  For example,
+	 * in IPv4-only networks, setting this property to %TRUE allows the overall
+	 * network configuration to succeed if IPv6 configuration fails but IPv4
+	 * configuration completes successfully.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_MAY_FAIL,
@@ -1144,18 +1266,18 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *setting_class)
 						   "configuration to succeed if IPv6 configuration "
 						   "fails but IPv4 configuration completes successfully.",
 						   TRUE,
-						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
 	/**
 	 * NMSettingIP6Config:ip6-privacy:
 	 *
-	 * Configure IPv6 Privacy Extensions for SLAAC, described in RFC4941.
-	 * If enabled, it makes the kernel generate a temporary IPv6 address
-	 * in addition to the public one generated from MAC address via
-	 * modified EUI-64.  This enhances privacy, but could cause problems
-	 * in some applications, on the other hand.  The permitted values
-	 * are: 0: disabled, 1: enabled (prefer public address),
-	 * 2: enabled (prefer temporary addresses).
+	 * Configure IPv6 Privacy Extensions for SLAAC, described in RFC4941.  If
+	 * enabled, it makes the kernel generate a temporary IPv6 address in
+	 * addition to the public one generated from MAC address via modified
+	 * EUI-64.  This enhances privacy, but could cause problems in some
+	 * applications, on the other hand.  The permitted values are: 0: disabled,
+	 * 1: enabled (prefer public address), 2: enabled (prefer temporary
+	 * addresses).
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_IP6_PRIVACY,
@@ -1172,8 +1294,7 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *setting_class)
 		                   NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN,
 		                   NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR,
 		                   NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN,
-		                   G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
-
+		                   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 }
 
 /********************************************************************/
diff --git a/libnm-util/nm-setting-ip6-config.h b/libnm-util/nm-setting-ip6-config.h
index 29650486..d1f4ca84 100644
--- a/libnm-util/nm-setting-ip6-config.h
+++ b/libnm-util/nm-setting-ip6-config.h
@@ -19,7 +19,7 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2007 - 2012 Red Hat, Inc.
+ * (C) Copyright 2007 - 2014 Red Hat, Inc.
  */
 
 #ifndef NM_SETTING_IP6_CONFIG_H
@@ -219,24 +219,32 @@ guint32                nm_setting_ip6_config_get_num_dns            (NMSettingIP
 const struct in6_addr *nm_setting_ip6_config_get_dns                (NMSettingIP6Config *setting, guint32 i);
 gboolean               nm_setting_ip6_config_add_dns                (NMSettingIP6Config *setting, const struct in6_addr *dns);
 void                   nm_setting_ip6_config_remove_dns             (NMSettingIP6Config *setting, guint32 i);
+NM_AVAILABLE_IN_0_9_10
+gboolean               nm_setting_ip6_config_remove_dns_by_value    (NMSettingIP6Config *setting, const struct in6_addr *dns);
 void                   nm_setting_ip6_config_clear_dns              (NMSettingIP6Config *setting);
 
-guint32                nm_setting_ip6_config_get_num_dns_searches   (NMSettingIP6Config *setting);
-const char *           nm_setting_ip6_config_get_dns_search         (NMSettingIP6Config *setting, guint32 i);
-gboolean               nm_setting_ip6_config_add_dns_search         (NMSettingIP6Config *setting, const char *dns_search);
-void                   nm_setting_ip6_config_remove_dns_search      (NMSettingIP6Config *setting, guint32 i);
-void                   nm_setting_ip6_config_clear_dns_searches     (NMSettingIP6Config *setting);
-
-guint32                nm_setting_ip6_config_get_num_addresses      (NMSettingIP6Config *setting);
-NMIP6Address *         nm_setting_ip6_config_get_address            (NMSettingIP6Config *setting, guint32 i);
-gboolean               nm_setting_ip6_config_add_address            (NMSettingIP6Config *setting, NMIP6Address *address);
-void                   nm_setting_ip6_config_remove_address         (NMSettingIP6Config *setting, guint32 i);
-void                   nm_setting_ip6_config_clear_addresses        (NMSettingIP6Config *setting);
+guint32                nm_setting_ip6_config_get_num_dns_searches       (NMSettingIP6Config *setting);
+const char *           nm_setting_ip6_config_get_dns_search             (NMSettingIP6Config *setting, guint32 i);
+gboolean               nm_setting_ip6_config_add_dns_search             (NMSettingIP6Config *setting, const char *dns_search);
+void                   nm_setting_ip6_config_remove_dns_search          (NMSettingIP6Config *setting, guint32 i);
+NM_AVAILABLE_IN_0_9_10
+gboolean               nm_setting_ip6_config_remove_dns_search_by_value (NMSettingIP6Config *setting, const char *dns_search);
+void                   nm_setting_ip6_config_clear_dns_searches         (NMSettingIP6Config *setting);
+
+guint32                nm_setting_ip6_config_get_num_addresses       (NMSettingIP6Config *setting);
+NMIP6Address *         nm_setting_ip6_config_get_address             (NMSettingIP6Config *setting, guint32 i);
+gboolean               nm_setting_ip6_config_add_address             (NMSettingIP6Config *setting, NMIP6Address *address);
+void                   nm_setting_ip6_config_remove_address          (NMSettingIP6Config *setting, guint32 i);
+NM_AVAILABLE_IN_0_9_10
+gboolean               nm_setting_ip6_config_remove_address_by_value (NMSettingIP6Config *setting, NMIP6Address *address);
+void                   nm_setting_ip6_config_clear_addresses         (NMSettingIP6Config *setting);
 
 guint32                nm_setting_ip6_config_get_num_routes         (NMSettingIP6Config *setting);
 NMIP6Route *           nm_setting_ip6_config_get_route              (NMSettingIP6Config *setting, guint32 i);
 gboolean               nm_setting_ip6_config_add_route              (NMSettingIP6Config *setting, NMIP6Route *route);
 void                   nm_setting_ip6_config_remove_route           (NMSettingIP6Config *setting, guint32 i);
+NM_AVAILABLE_IN_0_9_10
+gboolean               nm_setting_ip6_config_remove_route_by_value  (NMSettingIP6Config *setting, NMIP6Route *route);
 void                   nm_setting_ip6_config_clear_routes           (NMSettingIP6Config *setting);
 gboolean               nm_setting_ip6_config_get_ignore_auto_routes (NMSettingIP6Config *setting);
 
diff --git a/libnm-util/nm-setting-olpc-mesh.c b/libnm-util/nm-setting-olpc-mesh.c
index bf87aa57..d344fa04 100644
--- a/libnm-util/nm-setting-olpc-mesh.c
+++ b/libnm-util/nm-setting-olpc-mesh.c
@@ -20,7 +20,7 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2007 - 2008 Red Hat, Inc.
+ * (C) Copyright 2007 - 2013 Red Hat, Inc.
  * (C) Copyright 2007 - 2008 Novell, Inc.
  * (C) Copyright 2009 One Laptop per Child
  */
@@ -28,6 +28,7 @@
 #include <string.h>
 #include <netinet/ether.h>
 #include <dbus/dbus-glib.h>
+#include <glib/gi18n.h>
 
 #include "NetworkManager.h"
 #include "nm-setting-olpc-mesh.h"
@@ -88,7 +89,6 @@ NMSetting *nm_setting_olpc_mesh_new (void)
 static void
 nm_setting_olpc_mesh_init (NMSettingOlpcMesh *setting)
 {
-	g_object_set (setting, NM_SETTING_NAME, NM_SETTING_OLPC_MESH_SETTING_NAME, NULL);
 }
 
 const GByteArray *
@@ -121,18 +121,20 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 	NMSettingOlpcMeshPrivate *priv = NM_SETTING_OLPC_MESH_GET_PRIVATE (setting);
 
 	if (!priv->ssid) {
-		g_set_error (error,
-		             NM_SETTING_OLPC_MESH_ERROR,
-		             NM_SETTING_OLPC_MESH_ERROR_MISSING_PROPERTY,
-		             NM_SETTING_OLPC_MESH_SSID);
+		g_set_error_literal (error,
+		                     NM_SETTING_OLPC_MESH_ERROR,
+		                     NM_SETTING_OLPC_MESH_ERROR_MISSING_PROPERTY,
+		                     _("property is missing"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_OLPC_MESH_SETTING_NAME, NM_SETTING_OLPC_MESH_SSID);
 		return FALSE;
 	}
 
 	if (!priv->ssid->len || priv->ssid->len > 32) {
-		g_set_error (error,
-		             NM_SETTING_OLPC_MESH_ERROR,
-		             NM_SETTING_OLPC_MESH_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_OLPC_MESH_SSID);
+		g_set_error_literal (error,
+		                     NM_SETTING_OLPC_MESH_ERROR,
+		                     NM_SETTING_OLPC_MESH_ERROR_INVALID_PROPERTY,
+		                     _("SSID length is out of range <1-32> bytes"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_OLPC_MESH_SETTING_NAME, NM_SETTING_OLPC_MESH_SSID);
 		return FALSE;
 	}
 
@@ -140,15 +142,18 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 		g_set_error (error,
 		             NM_SETTING_OLPC_MESH_ERROR,
 		             NM_SETTING_OLPC_MESH_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_OLPC_MESH_CHANNEL);
+		             _("'%d' is not a valid channel"),
+		             priv->channel);
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_OLPC_MESH_SETTING_NAME, NM_SETTING_OLPC_MESH_CHANNEL);
 		return FALSE;
 	}
 
 	if (priv->dhcp_anycast_addr && priv->dhcp_anycast_addr->len != ETH_ALEN) {
-		g_set_error (error,
-		             NM_SETTING_OLPC_MESH_ERROR,
-		             NM_SETTING_OLPC_MESH_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_OLPC_MESH_DHCP_ANYCAST_ADDRESS);
+		g_set_error_literal (error,
+		                     NM_SETTING_OLPC_MESH_ERROR,
+		                     NM_SETTING_OLPC_MESH_ERROR_INVALID_PROPERTY,
+		                     _("property is invalid"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_OLPC_MESH_SETTING_NAME, NM_SETTING_OLPC_MESH_DHCP_ANYCAST_ADDRESS);
 		return FALSE;
 	}
 
@@ -242,7 +247,7 @@ nm_setting_olpc_mesh_class_init (NMSettingOlpcMeshClass *setting_class)
 		                             "SSID",
 		                             "SSID of the mesh network to join.",
 		                             DBUS_TYPE_G_UCHAR_ARRAY,
-		                             G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+		                             G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE));
 
 	/**
 	 * NMSettingOlpcMesh:channel:
@@ -255,14 +260,14 @@ nm_setting_olpc_mesh_class_init (NMSettingOlpcMeshClass *setting_class)
 		                    "Channel",
 		                    "Channel on which the mesh network to join is located.",
 		                    0, G_MAXUINT32, 0,
-		                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+		                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE));
 
 	/**
 	 * NMSettingOlpcMesh:dhcp-anycast-address:
 	 *
-	 * Anycast DHCP address used when requesting an IP address via DHCP.  The
-	 * specific anycast address used determines which DHCP server class answers
-	 * the request.
+	 * Anycast DHCP MAC address used when requesting an IP address via DHCP.
+	 * The specific anycast address used determines which DHCP server class
+	 * answers the request.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_DHCP_ANYCAST_ADDRESS,
@@ -274,6 +279,5 @@ nm_setting_olpc_mesh_class_init (NMSettingOlpcMeshClass *setting_class)
 		                             "which DHCP server class answers the "
 		                             "the request.",
 		                             DBUS_TYPE_G_UCHAR_ARRAY,
-		                             G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
-
+		                             G_PARAM_READWRITE));
 }
diff --git a/libnm-util/nm-setting-ppp.c b/libnm-util/nm-setting-ppp.c
index 09cf3de6..237af9c8 100644
--- a/libnm-util/nm-setting-ppp.c
+++ b/libnm-util/nm-setting-ppp.c
@@ -19,10 +19,12 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2007 - 2008 Red Hat, Inc.
+ * (C) Copyright 2007 - 2013 Red Hat, Inc.
  * (C) Copyright 2007 - 2008 Novell, Inc.
  */
 
+#include <glib/gi18n.h>
+
 #include "nm-setting-ppp.h"
 #include "nm-setting-private.h"
 
@@ -385,7 +387,9 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 			g_set_error (error,
 			             NM_SETTING_PPP_ERROR,
 			             NM_SETTING_PPP_ERROR_INVALID_PROPERTY,
-			             NM_SETTING_PPP_MRU);
+			             _("'%d' is out of valid range <128-16384>"),
+			             priv->mru);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_PPP_SETTING_NAME, NM_SETTING_PPP_MRU);
 			return FALSE;
 		}
 	}
@@ -396,7 +400,9 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 			g_set_error (error,
 			             NM_SETTING_PPP_ERROR,
 			             NM_SETTING_PPP_ERROR_INVALID_PROPERTY,
-			             NM_SETTING_PPP_LCP_ECHO_FAILURE);
+			             _("setting this property requires non-zero '%s' property"),
+			             NM_SETTING_PPP_LCP_ECHO_INTERVAL);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_PPP_SETTING_NAME, NM_SETTING_PPP_LCP_ECHO_FAILURE);
 			return FALSE;
 		}
 	}
@@ -407,7 +413,6 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 static void
 nm_setting_ppp_init (NMSettingPPP *setting)
 {
-	g_object_set (setting, NM_SETTING_NAME, NM_SETTING_PPP_SETTING_NAME, NULL);
 }
 
 static void
@@ -561,9 +566,9 @@ nm_setting_ppp_class_init (NMSettingPPPClass *setting_class)
 	/**
 	 * NMSettingPPP:noauth:
 	 *
-	 * If TRUE, do not require the other side (usually the PPP server) to
-	 * authenticate itself to the client.  If FALSE, require authentication from
-	 * the remote side.  In almost all cases, this should be TRUE.
+	 * If %TRUE, do not require the other side (usually the PPP server) to
+	 * authenticate itself to the client.  If %FALSE, require authentication
+	 * from the remote side.  In almost all cases, this should be %TRUE.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_NOAUTH,
@@ -574,12 +579,12 @@ nm_setting_ppp_class_init (NMSettingPPPClass *setting_class)
 						   "If FALSE, require authentication from the remote "
 						   "side.  In almost all cases, this should be TRUE.",
 						   TRUE,
-						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
 	/**
 	 * NMSettingPPP:refuse-eap:
 	 *
-	 * If TRUE, the EAP authentication method will not be used.
+	 * If %TRUE, the EAP authentication method will not be used.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_REFUSE_EAP,
@@ -587,12 +592,12 @@ nm_setting_ppp_class_init (NMSettingPPPClass *setting_class)
 						   "Refuse EAP",
 						   "If TRUE, the EAP authentication method will not be used.",
 						   FALSE,
-						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
 	/**
 	 * NMSettingPPP:refuse-pap:
 	 *
-	 * If TRUE, the PAP authentication method will not be used.
+	 * If %TRUE, the PAP authentication method will not be used.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_REFUSE_PAP,
@@ -600,12 +605,12 @@ nm_setting_ppp_class_init (NMSettingPPPClass *setting_class)
 						   "Refuse PAP",
 						   "If TRUE, the PAP authentication method will not be used.",
 						   FALSE,
-						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
 	/**
 	 * NMSettingPPP:refuse-chap:
 	 *
-	 * If TRUE, the CHAP authentication method will not be used.
+	 * If %TRUE, the CHAP authentication method will not be used.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_REFUSE_CHAP,
@@ -613,12 +618,12 @@ nm_setting_ppp_class_init (NMSettingPPPClass *setting_class)
 						   "Refuse CHAP",
 						   "If TRUE, the CHAP authentication method will not be used.",
 						   FALSE,
-						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
 	/**
 	 * NMSettingPPP:refuse-mschap:
 	 *
-	 * If TRUE, the MSCHAP authentication method will not be used.
+	 * If %TRUE, the MSCHAP authentication method will not be used.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_REFUSE_MSCHAP,
@@ -626,12 +631,12 @@ nm_setting_ppp_class_init (NMSettingPPPClass *setting_class)
 						   "Refuse MSCHAP",
 						   "If TRUE, the MSCHAP authentication method will not be used.",
 						   FALSE,
-						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
 	/**
 	 * NMSettingPPP:refuse-mschapv2:
 	 *
-	 * If TRUE, the MSCHAPv2 authentication method will not be used.
+	 * If %TRUE, the MSCHAPv2 authentication method will not be used.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_REFUSE_MSCHAPV2,
@@ -639,12 +644,12 @@ nm_setting_ppp_class_init (NMSettingPPPClass *setting_class)
 						   "Refuse MSCHAPv2",
 						   "If TRUE, the MSCHAPv2 authentication method will not be used.",
 						   FALSE,
-						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
 	/**
 	 * NMSettingPPP:nobsdcomp:
 	 *
-	 * If TRUE, BSD compression will not be requested.
+	 * If %TRUE, BSD compression will not be requested.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_NOBSDCOMP,
@@ -652,12 +657,12 @@ nm_setting_ppp_class_init (NMSettingPPPClass *setting_class)
 						   "No BSD compression",
 						   "If TRUE, BSD compression will not be requested.",
 						   FALSE,
-						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_FUZZY_IGNORE));
+						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE));
 
 	/**
 	 * NMSettingPPP:nodeflate:
 	 *
-	 * If TRUE, 'deflate' compression will not be requested.
+	 * If %TRUE, "deflate" compression will not be requested.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_NODEFLATE,
@@ -665,12 +670,12 @@ nm_setting_ppp_class_init (NMSettingPPPClass *setting_class)
 						   "No deflate",
 						   "If TRUE, 'deflate' compression will not be requested.",
 						   FALSE,
-						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_FUZZY_IGNORE));
+						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE));
 
 	/**
 	 * NMSettingPPP:no-vj-comp:
 	 *
-	 * If TRUE, Van Jacobsen TCP header compression will not be requested.
+	 * If %TRUE, Van Jacobsen TCP header compression will not be requested.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_NO_VJ_COMP,
@@ -678,12 +683,12 @@ nm_setting_ppp_class_init (NMSettingPPPClass *setting_class)
 						   "No VJ compression",
 						   "If TRUE, Van Jacobsen TCP header compression will not be requested.",
 						   FALSE,
-						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_FUZZY_IGNORE));
+						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE));
 
 	/**
 	 * NMSettingPPP:require-mppe:
 	 *
-	 * If TRUE, MPPE (Microsoft Point-to-Point Encrpytion) will be required for
+	 * If %TRUE, MPPE (Microsoft Point-to-Point Encrpytion) will be required for
 	 * the PPP session.  If either 64-bit or 128-bit MPPE is not available the
 	 * session will fail.  Note that MPPE is not used on mobile broadband
 	 * connections.
@@ -698,14 +703,14 @@ nm_setting_ppp_class_init (NMSettingPPPClass *setting_class)
 						   "will fail.  Note that MPPE is not used on mobile "
 						   "broadband connections.",
 						   FALSE,
-						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
 	/**
 	 * NMSettingPPP:require-mppe-128:
 	 *
-	 * If TRUE, 128-bit MPPE (Microsoft Point-to-Point Encrpytion) will be
-	 * required for the PPP session, and the 'require-mppe' property must also
-	 * be set to TRUE.  If 128-bit MPPE is not available the session will fail.
+	 * If %TRUE, 128-bit MPPE (Microsoft Point-to-Point Encrpytion) will be
+	 * required for the PPP session, and the "require-mppe" property must also
+	 * be set to %TRUE.  If 128-bit MPPE is not available the session will fail.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_REQUIRE_MPPE_128,
@@ -717,13 +722,13 @@ nm_setting_ppp_class_init (NMSettingPPPClass *setting_class)
 						   "must also be set to TRUE.  If 128-bit MPPE is not "
 						   "available the session will fail.",
 						   FALSE,
-						   G_PARAM_READWRITE  | G_PARAM_CONSTRUCT| NM_SETTING_PARAM_SERIALIZE));
+						   G_PARAM_READWRITE  | G_PARAM_CONSTRUCT));
 
 	/**
 	 * NMSettingPPP:mppe-stateful:
 	 *
-	 * If TRUE, stateful MPPE is used.  See pppd documentation for more
-	 * information on stateful MPPE.",
+	 * If %TRUE, stateful MPPE is used.  See pppd documentation for more
+	 * information on stateful MPPE.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_MPPE_STATEFUL,
@@ -732,14 +737,14 @@ nm_setting_ppp_class_init (NMSettingPPPClass *setting_class)
 						   "If TRUE, stateful MPPE is used.  See pppd documentation "
 						   "for more information on stateful MPPE.",
 						   FALSE,
-						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
 	/**
 	 * NMSettingPPP:crtscts:
 	 *
-	 * If TRUE, specify that pppd should set the serial port to use hardware
-	 * flow control with RTS and CTS signals.  This value should normally be
-	 * set to FALSE.
+	 * If %TRUE, specify that pppd should set the serial port to use hardware
+	 * flow control with RTS and CTS signals.  This value should normally be set
+	 * to %FALSE.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_CRTSCTS,
@@ -750,7 +755,7 @@ nm_setting_ppp_class_init (NMSettingPPPClass *setting_class)
 						   "signals.  This value should normally be set to "
 						   "FALSE.",
 						   FALSE,
-						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
 	/**
 	 * NMSettingPPP:baud:
@@ -767,7 +772,7 @@ nm_setting_ppp_class_init (NMSettingPPPClass *setting_class)
 						"the specified baudrate.  This value should normally be "
 						"left as 0 to automatically choose the speed.",
 						0, G_MAXUINT32, 0,
-						G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_FUZZY_IGNORE));
+						G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE));
 
 	/**
 	 * NMSettingPPP:mru:
@@ -784,7 +789,7 @@ nm_setting_ppp_class_init (NMSettingPPPClass *setting_class)
 						"send packets no larger than the specified size.  If "
 						"non-zero, the MRU should be between 128 and 16384.",
 						0, 16384, 0,
-						G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+						G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
 	/**
 	 * NMSettingPPP:mtu:
@@ -799,14 +804,14 @@ nm_setting_ppp_class_init (NMSettingPPPClass *setting_class)
 						"If non-zero, instruct pppd to send packets no larger "
 						"than the specified size.",
 						0, G_MAXUINT32, 0,
-						G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_FUZZY_IGNORE));
+						G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE));
 
 	/**
 	 * NMSettingPPP:lcp-echo-failure:
 	 *
 	 * If non-zero, instruct pppd to presume the connection to the peer has
 	 * failed if the specified number of LCP echo-requests go unanswered by the
-	 * peer.  The 'lcp-echo-interval' property must also be set to a non-zero
+	 * peer.  The "lcp-echo-interval" property must also be set to a non-zero
 	 * value if this property is used.
 	 **/
 	g_object_class_install_property
@@ -820,7 +825,7 @@ nm_setting_ppp_class_init (NMSettingPPPClass *setting_class)
 						"also be set to a non-zero value if this property is "
 						"used.",
 						0, G_MAXUINT32, 0,
-						G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_FUZZY_IGNORE));
+						G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE));
 
 	/**
 	 * NMSettingPPP:lcp-echo-interval:
@@ -840,5 +845,5 @@ nm_setting_ppp_class_init (NMSettingPPPClass *setting_class)
 						"to echo requests and some will not, and it is not "
 						"possible to autodetect this.",
 						0, G_MAXUINT32, 0,
-						G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_FUZZY_IGNORE));
+						G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE));
 }
diff --git a/libnm-util/nm-setting-pppoe.c b/libnm-util/nm-setting-pppoe.c
index f37ec000..fdae691b 100644
--- a/libnm-util/nm-setting-pppoe.c
+++ b/libnm-util/nm-setting-pppoe.c
@@ -19,11 +19,13 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2007 - 2011 Red Hat, Inc.
+ * (C) Copyright 2007 - 2013 Red Hat, Inc.
  * (C) Copyright 2007 - 2008 Novell, Inc.
  */
 
 #include <string.h>
+#include <glib/gi18n.h>
+
 #include "nm-setting-pppoe.h"
 #include "nm-setting-ppp.h"
 #include "nm-setting-private.h"
@@ -157,24 +159,27 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 	NMSettingPPPOEPrivate *priv = NM_SETTING_PPPOE_GET_PRIVATE (setting);
 
 	if (!priv->username) {
-		g_set_error (error,
-		             NM_SETTING_PPPOE_ERROR,
-		             NM_SETTING_PPPOE_ERROR_MISSING_PROPERTY,
-		             NM_SETTING_PPPOE_USERNAME);
+		g_set_error_literal (error,
+		                     NM_SETTING_PPPOE_ERROR,
+		                     NM_SETTING_PPPOE_ERROR_MISSING_PROPERTY,
+		                     _("property is missing"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_PPPOE_SETTING_NAME, NM_SETTING_PPPOE_USERNAME);
 		return FALSE;
 	} else if (!strlen (priv->username)) {
-		g_set_error (error,
-		             NM_SETTING_PPPOE_ERROR,
-		             NM_SETTING_PPPOE_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_PPPOE_USERNAME);
+		g_set_error_literal (error,
+		                     NM_SETTING_PPPOE_ERROR,
+		                     NM_SETTING_PPPOE_ERROR_INVALID_PROPERTY,
+		                     _("property is empty"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_PPPOE_SETTING_NAME, NM_SETTING_PPPOE_USERNAME);
 		return FALSE;
 	}
 
 	if (priv->service && !strlen (priv->service)) {
-		g_set_error (error,
-		             NM_SETTING_PPPOE_ERROR,
-		             NM_SETTING_PPPOE_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_PPPOE_SERVICE);
+		g_set_error_literal (error,
+		                     NM_SETTING_PPPOE_ERROR,
+		                     NM_SETTING_PPPOE_ERROR_INVALID_PROPERTY,
+		                     _("property is empty"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_PPPOE_SETTING_NAME, NM_SETTING_PPPOE_SERVICE);
 		return FALSE;
 	}
 
@@ -201,7 +206,6 @@ need_secrets (NMSetting *setting)
 static void
 nm_setting_pppoe_init (NMSettingPPPOE *setting)
 {
-	g_object_set (setting, NM_SETTING_NAME, NM_SETTING_PPPOE_SETTING_NAME, NULL);
 }
 
 static void
@@ -289,7 +293,7 @@ nm_setting_pppoe_class_init (NMSettingPPPOEClass *setting_class)
 	 * NMSettingPPPOE:service:
 	 *
 	 * If specified, instruct PPPoE to only initiate sessions with access
-	 * concentrators that provide the specified serivce.  For most providers,
+	 * concentrators that provide the specified service.  For most providers,
 	 * this should be left blank.  It is only required if there are multiple
 	 * access concentrators or a specific service is known to be required.
 	 **/
@@ -299,12 +303,12 @@ nm_setting_pppoe_class_init (NMSettingPPPOEClass *setting_class)
 						  "Service",
 						  "If specified, instruct PPPoE to only initiate sessions "
 						  "with access concentrators that provide the specified "
-						  "serivce.  For most providers, this should be left "
+						  "service.  For most providers, this should be left "
 						  "blank.  It is only required if there are multiple "
 						  "access concentrators or a specific service is known "
 						  "to be required.",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+						  G_PARAM_READWRITE));
 
 	/**
 	 * NMSettingPPPOE:username:
@@ -317,7 +321,7 @@ nm_setting_pppoe_class_init (NMSettingPPPOEClass *setting_class)
 						  "Username",
 						  "Username used to authenticate with the PPPoE service.",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+						  G_PARAM_READWRITE));
 
 	/**
 	 * NMSettingPPPOE:password:
@@ -330,12 +334,12 @@ nm_setting_pppoe_class_init (NMSettingPPPOEClass *setting_class)
 						  "Password",
 						  "Password used to authenticate with the PPPoE service.",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET));
+						  G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET));
 
 	/**
 	 * NMSettingPPPOE:password-flags:
 	 *
-	 * Flags indicating how to handle #NMSettingPPPOE:password:.
+	 * Flags indicating how to handle the #NMSettingPPPOE:password property.
 	 **/
 	g_object_class_install_property (object_class, PROP_PASSWORD_FLAGS,
 		 g_param_spec_uint (NM_SETTING_PPPOE_PASSWORD_FLAGS,
@@ -344,5 +348,5 @@ nm_setting_pppoe_class_init (NMSettingPPPOEClass *setting_class)
 		                    NM_SETTING_SECRET_FLAG_NONE,
 		                    NM_SETTING_SECRET_FLAGS_ALL,
 		                    NM_SETTING_SECRET_FLAG_NONE,
-		                    G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+		                    G_PARAM_READWRITE));
 }
diff --git a/libnm-util/nm-setting-private.h b/libnm-util/nm-setting-private.h
index 1460841c..c3ec9d19 100644
--- a/libnm-util/nm-setting-private.h
+++ b/libnm-util/nm-setting-private.h
@@ -21,6 +21,7 @@
 #ifndef NM_SETTING_PRIVATE_H
 #define NM_SETTING_PRIVATE_H
 
+#include "nm-setting.h"
 #include "nm-glib-compat.h"
 
 #define NM_SETTING_SECRET_FLAGS_ALL \
@@ -34,10 +35,62 @@ void _nm_register_setting (const char *name,
                            const guint32 priority,
                            const GQuark error_quark);
 
+/* Ensure, that name is a compile time constant string. Put the function name in parenthesis to suppress expansion. */
+#define _nm_register_setting(name, type, priority, error_quark)    _nm_register_setting ((name ""), type, priority, error_quark)
+
+gboolean _nm_setting_is_base_type (NMSetting *setting);
+gboolean _nm_setting_type_is_base_type (GType type);
+GType _nm_setting_lookup_setting_type (const char *name);
+GType _nm_setting_lookup_setting_type_by_quark (GQuark error_quark);
+gint _nm_setting_compare_priority (gconstpointer a, gconstpointer b);
+
+typedef enum NMSettingUpdateSecretResult {
+	NM_SETTING_UPDATE_SECRET_ERROR              = FALSE,
+	NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED   = TRUE,
+	NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED  = 2,
+} NMSettingUpdateSecretResult;
+
+NMSettingUpdateSecretResult _nm_setting_update_secrets (NMSetting *setting,
+                                                        GHashTable *secrets,
+                                                        GError **error);
+gboolean _nm_setting_clear_secrets (NMSetting *setting);
+gboolean _nm_setting_clear_secrets_with_flags (NMSetting *setting,
+                                               NMSettingClearSecretsWithFlagsFn func,
+                                               gpointer user_data);
+
+
+/* NM_SETTING_COMPARE_FLAG_INFERRABLE: check whether a device-generated
+ * connection can be replaced by a already-defined connection. This flag only
+ * takes into account properties marked with the %NM_SETTING_PARAM_INFERRABLE
+ * flag.
+ */
+#define NM_SETTING_COMPARE_FLAG_INFERRABLE 0x80000000
+
+/* The property of the #NMSetting should be considered during comparisons that
+ * use the %NM_SETTING_COMPARE_FLAG_INFERRABLE flag. Properties that don't have
+ * this flag, are ignored when doing an infrerrable comparison.  This flag should
+ * be set on all properties that are read from the kernel or the system when a
+ * connection is generated.  eg, IP addresses/routes can be read from the
+ * kernel, but the 'autoconnect' property cannot, so
+ * %NM_SETTING_IP4_CONFIG_ADDRESSES gets the INFERRABLE flag, but
+ * %NM_SETTING_CONNECTION_AUTOCONNECT would not.
+ *
+ * This flag should not be used with properties where the default cannot be
+ * read separately from the current value, like MTU or wired duplex mode.
+ */
+#define NM_SETTING_PARAM_INFERRABLE (1 << (4 + 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_init (); g_type_ensure (x); }
 
+NMSetting *nm_setting_find_in_list (GSList *settings_list, const char *setting_name);
+
+/* Private NMSettingIP4Config methods */
+#include "nm-setting-ip4-config.h"
+const char *nm_setting_ip4_config_get_address_label      (NMSettingIP4Config *setting, guint32 i);
+gboolean    nm_setting_ip4_config_add_address_with_label (NMSettingIP4Config *setting, NMIP4Address *address, const char *label);
+
 #endif  /* NM_SETTING_PRIVATE_H */
 
diff --git a/libnm-util/nm-setting-serial.c b/libnm-util/nm-setting-serial.c
index 203f5748..70152bb3 100644
--- a/libnm-util/nm-setting-serial.c
+++ b/libnm-util/nm-setting-serial.c
@@ -179,7 +179,6 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 static void
 nm_setting_serial_init (NMSettingSerial *setting)
 {
-	g_object_set (setting, NM_SETTING_NAME, NM_SETTING_SERIAL_SETTING_NAME, NULL);
 }
 
 static void
@@ -256,8 +255,8 @@ nm_setting_serial_class_init (NMSettingSerialClass *setting_class)
 	/**
 	 * NMSettingSerial:baud:
 	 *
-	 * Speed to use for communication over the serial port.  Note that this value
-	 * usually has no effect for mobile broadband modems as they generally
+	 * Speed to use for communication over the serial port.  Note that this
+	 * value usually has no effect for mobile broadband modems as they generally
 	 * ignore speed settings and use the highest available speed.
 	 **/
 	g_object_class_install_property
@@ -269,12 +268,12 @@ nm_setting_serial_class_init (NMSettingSerialClass *setting_class)
 						"broadband modems as they generally ignore speed "
 						"settings and use the highest available speed.",
 						0, G_MAXUINT, 57600,
-						G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+						G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
 	/**
 	 * NMSettingSerial:bits:
 	 *
-	 * Byte-width of the serial communication.
+	 * Byte-width of the serial communication. The 8 in "8n1" for example.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_BITS,
@@ -283,7 +282,7 @@ nm_setting_serial_class_init (NMSettingSerialClass *setting_class)
 						"Byte-width of the serial communication.  The 8 in "
 						"'8n1' for example.",
 						5, 8, 8,
-						G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+						G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
 	/**
 	 * NMSettingSerial:parity:
@@ -298,13 +297,13 @@ nm_setting_serial_class_init (NMSettingSerialClass *setting_class)
 						"Parity setting of the serial port.  Either 'E' for even "
 						"parity, 'o' for odd parity, or 'n' for no parity.",
 						'E', 'o', 'n',
-						G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+						G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
 	/**
 	 * NMSettingSerial:stopbits:
 	 *
 	 * Number of stop bits for communication on the serial port.  Either 1 or 2.
-	 * The 1 in '8n1' for example.
+	 * The 1 in "8n1" for example.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_STOPBITS,
@@ -313,7 +312,7 @@ nm_setting_serial_class_init (NMSettingSerialClass *setting_class)
 						"Number of stop bits for communication on the serial "
 						"port.  Either 1 or 2.  The 1 in '8n1' for example.",
 						1, 2, 1,
-						G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+						G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
 	/**
 	 * NMSettingSerial:send-delay:
@@ -327,5 +326,5 @@ nm_setting_serial_class_init (NMSettingSerialClass *setting_class)
 						  "Time to delay between each byte sent to the modem, "
 						  "in microseconds.",
 						  0, G_MAXUINT64, 0,
-						  G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+						  G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 }
diff --git a/libnm-util/nm-setting-team-port.c b/libnm-util/nm-setting-team-port.c
new file mode 100644
index 00000000..c0b7748b
--- /dev/null
+++ b/libnm-util/nm-setting-team-port.c
@@ -0,0 +1,188 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2013 Jiri Pirko <jiri@resnulli.us>
+ *
+ * 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.
+ */
+
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <dbus/dbus-glib.h>
+#include <glib/gi18n.h>
+
+#include "nm-setting-team-port.h"
+#include "nm-utils.h"
+#include "nm-utils-private.h"
+#include "nm-setting-private.h"
+
+/**
+ * SECTION:nm-setting-team-port
+ * @short_description: Describes connection properties for team ports
+ * @include: nm-setting-team-port.h
+ *
+ * The #NMSettingTeamPort object is a #NMSetting subclass that describes
+ * optional properties that apply to team ports.
+ *
+ * Since: 0.9.10
+ **/
+
+/**
+ * nm_setting_team_port_error_quark:
+ *
+ * Registers an error quark for #NMSettingTeamPort if necessary.
+ *
+ * Returns: the error quark used for #NMSettingTeamPort errors.
+ *
+ * Since: 0.9.10
+ **/
+GQuark
+nm_setting_team_port_error_quark (void)
+{
+	static GQuark quark;
+
+	if (G_UNLIKELY (!quark))
+		quark = g_quark_from_static_string ("nm-setting-team-port-error-quark");
+	return quark;
+}
+
+G_DEFINE_TYPE_WITH_CODE (NMSettingTeamPort, nm_setting_team_port, NM_TYPE_SETTING,
+                         _nm_register_setting (NM_SETTING_TEAM_PORT_SETTING_NAME,
+                                               g_define_type_id,
+                                               3,
+                                               NM_SETTING_TEAM_PORT_ERROR))
+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))
+
+typedef struct {
+	char *config;
+} NMSettingTeamPortPrivate;
+
+enum {
+	PROP_0,
+	PROP_CONFIG,
+	LAST_PROP
+};
+
+/**
+ * nm_setting_team_port_new:
+ *
+ * Creates a new #NMSettingTeamPort object with default values.
+ *
+ * Returns: (transfer full): the new empty #NMSettingTeamPort object
+ *
+ * Since: 0.9.10
+ **/
+NMSetting *
+nm_setting_team_port_new (void)
+{
+	return (NMSetting *) g_object_new (NM_TYPE_SETTING_TEAM_PORT, NULL);
+}
+
+/**
+ * nm_setting_team_port_get_config:
+ * @setting: the #NMSettingTeamPort
+ *
+ * Returns: the #NMSettingTeamPort:config property of the setting
+ *
+ * Since: 0.9.10
+ **/
+const char *
+nm_setting_team_port_get_config (NMSettingTeamPort *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_TEAM_PORT (setting), NULL);
+
+	return NM_SETTING_TEAM_PORT_GET_PRIVATE (setting)->config;
+}
+
+static gboolean
+verify (NMSetting *setting, GSList *all_settings, GError **error)
+{
+	return TRUE;
+}
+
+static void
+nm_setting_team_port_init (NMSettingTeamPort *setting)
+{
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+              const GValue *value, GParamSpec *pspec)
+{
+	NMSettingTeamPortPrivate *priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (object);
+
+	switch (prop_id) {
+	case PROP_CONFIG:
+		priv->config = 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)
+{
+	NMSettingTeamPort *setting = NM_SETTING_TEAM_PORT (object);
+
+	switch (prop_id) {
+	case PROP_CONFIG:
+		g_value_set_string (value, nm_setting_team_port_get_config (setting));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+nm_setting_team_port_class_init (NMSettingTeamPortClass *setting_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+	NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
+
+	g_type_class_add_private (setting_class, sizeof (NMSettingTeamPortPrivate));
+
+	/* virtual methods */
+	object_class->set_property = set_property;
+	object_class->get_property = get_property;
+	parent_class->verify       = verify;
+
+	/* Properties */
+	/**
+	 * NMSettingTeamPort:config:
+	 *
+	 * The JSON configuration for the team port. The property should contain raw
+	 * JSON configuration data suitable for teamd, because the value is passed
+	 * directly to teamd. If not specified, the default configuration is
+	 * used. See man teamd.conf for the format details.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_CONFIG,
+		 g_param_spec_string (NM_SETTING_TEAM_PORT_CONFIG,
+		                      "Config",
+		                      "JSON configuration for the team port. "
+		                      "The property should contain raw JSON configuration data "
+		                      "suitable for teamd, because the value is passed directly to "
+		                      "teamd. If not specified, the dafault configuration is used. "
+		                      "See man teamd.conf for the format details.",
+		                      NULL,
+		                      G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE));
+}
diff --git a/libnm-util/nm-setting-team-port.h b/libnm-util/nm-setting-team-port.h
new file mode 100644
index 00000000..50b9f7e3
--- /dev/null
+++ b/libnm-util/nm-setting-team-port.h
@@ -0,0 +1,79 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2013 Jiri Pirko <jiri@resnulli.us>
+ *
+ * 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.
+ */
+
+#ifndef NM_SETTING_TEAM_PORT_H
+#define NM_SETTING_TEAM_PORT_H
+
+#include <nm-setting.h>
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_SETTING_TEAM_PORT            (nm_setting_team_port_get_type ())
+#define NM_SETTING_TEAM_PORT(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_TEAM_PORT, NMSettingTeamPort))
+#define NM_SETTING_TEAM_PORT_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_TEAM_PORT, NMSettingTeamPortClass))
+#define NM_IS_SETTING_TEAM_PORT(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_TEAM_PORT))
+#define NM_IS_SETTING_TEAM_PORT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_TEAM_PORT))
+#define NM_SETTING_TEAM_PORT_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_TEAM_PORT, NMSettingTeamPortClass))
+
+#define NM_SETTING_TEAM_PORT_SETTING_NAME "team-port"
+
+/**
+ * NMSettingTeamPortError:
+ * @NM_SETTING_TEAM_PORT_ERROR_UNKNOWN: unknown or unclassified error
+ * @NM_SETTING_TEAM_PORT_ERROR_INVALID_PROPERTY: the property was invalid
+ * @NM_SETTING_TEAM_PORT_ERROR_MISSING_PROPERTY: the property was missing and
+ * is required
+ */
+typedef enum {
+	NM_SETTING_TEAM_PORT_ERROR_UNKNOWN = 0,      /*< nick=UnknownError >*/
+	NM_SETTING_TEAM_PORT_ERROR_INVALID_PROPERTY, /*< nick=InvalidProperty >*/
+	NM_SETTING_TEAM_PORT_ERROR_MISSING_PROPERTY, /*< nick=MissingProperty >*/
+} NMSettingTeamPortError;
+
+#define NM_SETTING_TEAM_PORT_ERROR nm_setting_team_port_error_quark ()
+GQuark nm_setting_team_port_error_quark (void);
+
+#define NM_SETTING_TEAM_PORT_CONFIG     "config"
+
+typedef struct {
+	NMSetting parent;
+} NMSettingTeamPort;
+
+typedef struct {
+	NMSettingClass parent;
+
+	/* Padding for future expansion */
+	void (*_reserved1) (void);
+	void (*_reserved2) (void);
+	void (*_reserved3) (void);
+	void (*_reserved4) (void);
+} NMSettingTeamPortClass;
+
+NM_AVAILABLE_IN_0_9_10
+GType nm_setting_team_port_get_type (void);
+
+NM_AVAILABLE_IN_0_9_10
+NMSetting *  nm_setting_team_port_new (void);
+
+const char * nm_setting_team_port_get_config (NMSettingTeamPort *setting);
+
+G_END_DECLS
+
+#endif /* NM_SETTING_TEAM_PORT_H */
diff --git a/libnm-util/nm-setting-team.c b/libnm-util/nm-setting-team.c
new file mode 100644
index 00000000..af9da62c
--- /dev/null
+++ b/libnm-util/nm-setting-team.c
@@ -0,0 +1,270 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2013 Jiri Pirko <jiri@resnulli.us>
+ *
+ * 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.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <dbus/dbus-glib.h>
+#include <glib/gi18n.h>
+
+#include "nm-setting-team.h"
+#include "nm-param-spec-specialized.h"
+#include "nm-utils.h"
+#include "nm-utils-private.h"
+#include "nm-dbus-glib-types.h"
+#include "nm-setting-private.h"
+
+/**
+ * SECTION:nm-setting-team
+ * @short_description: Describes connection properties for teams
+ * @include: nm-setting-team.h
+ *
+ * The #NMSettingTeam object is a #NMSetting subclass that describes properties
+ * necessary for team connections.
+ *
+ * Since: 0.9.10
+ **/
+
+/**
+ * nm_setting_team_error_quark:
+ *
+ * Registers an error quark for #NMSettingTeam if necessary.
+ *
+ * Returns: the error quark used for #NMSettingTeam errors.
+ *
+ * Since: 0.9.10
+ **/
+GQuark
+nm_setting_team_error_quark (void)
+{
+	static GQuark quark;
+
+	if (G_UNLIKELY (!quark))
+		quark = g_quark_from_static_string ("nm-setting-team-error-quark");
+	return quark;
+}
+
+
+G_DEFINE_TYPE_WITH_CODE (NMSettingTeam, nm_setting_team, NM_TYPE_SETTING,
+                         _nm_register_setting (NM_SETTING_TEAM_SETTING_NAME,
+                                               g_define_type_id,
+                                               1,
+                                               NM_SETTING_TEAM_ERROR))
+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 *interface_name;
+	char *config;
+} NMSettingTeamPrivate;
+
+enum {
+	PROP_0,
+	PROP_INTERFACE_NAME,
+	PROP_CONFIG,
+	LAST_PROP
+};
+
+/**
+ * nm_setting_team_new:
+ *
+ * Creates a new #NMSettingTeam object with default values.
+ *
+ * Returns: (transfer full): the new empty #NMSettingTeam object
+ *
+ * Since: 0.9.10
+ **/
+NMSetting *
+nm_setting_team_new (void)
+{
+	return (NMSetting *) g_object_new (NM_TYPE_SETTING_TEAM, NULL);
+}
+
+/**
+ * nm_setting_team_get_interface_name:
+ * @setting: the #NMSettingTeam
+ *
+ * Returns: the #NMSettingTeam:interface-name property of the setting
+ *
+ * Since: 0.9.10
+ **/
+const char *
+nm_setting_team_get_interface_name (NMSettingTeam *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_TEAM (setting), NULL);
+
+	return NM_SETTING_TEAM_GET_PRIVATE (setting)->interface_name;
+}
+
+/**
+ * nm_setting_team_get_config:
+ * @setting: the #NMSettingTeam
+ *
+ * Returns: the #NMSettingTeam:config property of the setting
+ *
+ * Since: 0.9.10
+ **/
+const char *
+nm_setting_team_get_config (NMSettingTeam *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_TEAM (setting), NULL);
+
+	return NM_SETTING_TEAM_GET_PRIVATE (setting)->config;
+}
+
+static gboolean
+verify (NMSetting *setting, GSList *all_settings, GError **error)
+{
+	NMSettingTeamPrivate *priv = NM_SETTING_TEAM_GET_PRIVATE (setting);
+
+	if (!priv->interface_name || !strlen(priv->interface_name)) {
+		g_set_error_literal (error,
+		                     NM_SETTING_TEAM_ERROR,
+		                     NM_SETTING_TEAM_ERROR_MISSING_PROPERTY,
+		                     _("property is missing"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_TEAM_SETTING_NAME, NM_SETTING_TEAM_INTERFACE_NAME);
+		return FALSE;
+	}
+
+	if (!nm_utils_iface_valid_name (priv->interface_name)) {
+		g_set_error_literal (error,
+		                     NM_SETTING_TEAM_ERROR,
+		                     NM_SETTING_TEAM_ERROR_INVALID_PROPERTY,
+		                     _("property is invalid"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_TEAM_SETTING_NAME, NM_SETTING_TEAM_INTERFACE_NAME);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static const char *
+get_virtual_iface_name (NMSetting *setting)
+{
+	NMSettingTeam *self = NM_SETTING_TEAM (setting);
+
+	return nm_setting_team_get_interface_name (self);
+}
+
+static void
+nm_setting_team_init (NMSettingTeam *setting)
+{
+}
+
+static void
+finalize (GObject *object)
+{
+	NMSettingTeamPrivate *priv = NM_SETTING_TEAM_GET_PRIVATE (object);
+
+	g_free (priv->interface_name);
+	g_free (priv->config);
+
+	G_OBJECT_CLASS (nm_setting_team_parent_class)->finalize (object);
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+              const GValue *value, GParamSpec *pspec)
+{
+	NMSettingTeamPrivate *priv = NM_SETTING_TEAM_GET_PRIVATE (object);
+
+	switch (prop_id) {
+	case PROP_INTERFACE_NAME:
+		g_free (priv->interface_name);
+		priv->interface_name = g_value_dup_string (value);
+		break;
+	case PROP_CONFIG:
+		g_free (priv->config);
+		priv->config = 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)
+{
+	NMSettingTeam *setting = NM_SETTING_TEAM (object);
+
+	switch (prop_id) {
+	case PROP_INTERFACE_NAME:
+		g_value_set_string (value, nm_setting_team_get_interface_name (setting));
+		break;
+	case PROP_CONFIG:
+		g_value_set_string (value, nm_setting_team_get_config (setting));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+nm_setting_team_class_init (NMSettingTeamClass *setting_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+	NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
+
+	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->verify       = verify;
+	parent_class->get_virtual_iface_name = get_virtual_iface_name;
+
+	/* Properties */
+	/**
+	 * NMSettingTeam:interface-name:
+	 *
+	 * The name of the virtual in-kernel team network interface
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_INTERFACE_NAME,
+		 g_param_spec_string (NM_SETTING_TEAM_INTERFACE_NAME,
+		                      "InterfaceName",
+		                      "The name of the virtual in-kernel team network interface",
+		                      NULL,
+		                      G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE));
+
+	/**
+	 * NMSettingTeam:config:
+	 *
+	 * The JSON configuration for the team network interface.  The property
+	 * should contain raw JSON configuration data suitable for teamd, because
+	 * the value is passed directly to teamd. If not specified, the default
+	 * configuration is used.  See man teamd.conf for the format details.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_CONFIG,
+		 g_param_spec_string (NM_SETTING_TEAM_CONFIG,
+		                      "Config",
+		                      "JSON configuration for the team network interface. "
+		                      "The property should contain raw JSON configuration data "
+		                      "suitable for teamd, because the value is passed directly to "
+		                      "teamd. If not specified, the default configuration is used. "
+		                      "See man teamd.conf for the format details.",
+		                      NULL,
+		                      G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE));
+}
diff --git a/libnm-util/nm-setting-team.h b/libnm-util/nm-setting-team.h
new file mode 100644
index 00000000..978eed07
--- /dev/null
+++ b/libnm-util/nm-setting-team.h
@@ -0,0 +1,81 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2013 Jiri Pirko <jiri@resnulli.us>
+ *
+ * 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.
+ */
+
+#ifndef NM_SETTING_TEAM_H
+#define NM_SETTING_TEAM_H
+
+#include <nm-setting.h>
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_SETTING_TEAM            (nm_setting_team_get_type ())
+#define NM_SETTING_TEAM(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_TEAM, NMSettingTeam))
+#define NM_SETTING_TEAM_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_TEAM, NMSettingTeamClass))
+#define NM_IS_SETTING_TEAM(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_TEAM))
+#define NM_IS_SETTING_TEAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_TEAM))
+#define NM_SETTING_TEAM_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_TEAM, NMSettingTeamClass))
+
+#define NM_SETTING_TEAM_SETTING_NAME "team"
+
+/**
+ * NMSettingTeamError:
+ * @NM_SETTING_TEAM_ERROR_UNKNOWN: unknown or unclassified error
+ * @NM_SETTING_TEAM_ERROR_INVALID_PROPERTY: the property was invalid
+ * @NM_SETTING_TEAM_ERROR_MISSING_PROPERTY: the property was missing and is
+ * required
+ */
+typedef enum {
+	NM_SETTING_TEAM_ERROR_UNKNOWN = 0,      /*< nick=UnknownError >*/
+	NM_SETTING_TEAM_ERROR_INVALID_PROPERTY, /*< nick=InvalidProperty >*/
+	NM_SETTING_TEAM_ERROR_MISSING_PROPERTY, /*< nick=MissingProperty >*/
+} NMSettingTeamError;
+
+#define NM_SETTING_TEAM_ERROR nm_setting_team_error_quark ()
+GQuark nm_setting_team_error_quark (void);
+
+#define NM_SETTING_TEAM_INTERFACE_NAME "interface-name"
+#define NM_SETTING_TEAM_CONFIG "config"
+
+typedef struct {
+	NMSetting parent;
+} NMSettingTeam;
+
+typedef struct {
+	NMSettingClass parent;
+
+	/* Padding for future expansion */
+	void (*_reserved1) (void);
+	void (*_reserved2) (void);
+	void (*_reserved3) (void);
+	void (*_reserved4) (void);
+} NMSettingTeamClass;
+
+NM_AVAILABLE_IN_0_9_10
+GType nm_setting_team_get_type (void);
+
+NM_AVAILABLE_IN_0_9_10
+NMSetting *  nm_setting_team_new                (void);
+
+const char * nm_setting_team_get_interface_name (NMSettingTeam *setting);
+const char * nm_setting_team_get_config (NMSettingTeam *setting);
+
+G_END_DECLS
+
+#endif /* NM_SETTING_TEAM_H */
diff --git a/libnm-util/nm-setting-vlan.c b/libnm-util/nm-setting-vlan.c
index da6dd628..ef91b5f1 100644
--- a/libnm-util/nm-setting-vlan.c
+++ b/libnm-util/nm-setting-vlan.c
@@ -18,12 +18,13 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2011 - 2012 Red Hat, Inc.
+ * (C) Copyright 2011 - 2014 Red Hat, Inc.
  */
 
 #include <stdlib.h>
 #include <string.h>
 #include <dbus/dbus-glib.h>
+#include <glib/gi18n.h>
 
 #include "nm-setting-vlan.h"
 #include "nm-param-spec-specialized.h"
@@ -68,7 +69,7 @@ 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))
 
 typedef struct {
-	char *iface_name;
+	char *interface_name;
 	char *parent;
 	guint32 id;
 	guint32 flags;
@@ -78,7 +79,7 @@ typedef struct {
 
 enum {
 	PROP_0,
-	PROP_IFACE_NAME,
+	PROP_INTERFACE_NAME,
 	PROP_PARENT,
 	PROP_ID,
 	PROP_FLAGS,
@@ -118,7 +119,7 @@ const char *
 nm_setting_vlan_get_interface_name (NMSettingVlan *setting)
 {
 	g_return_val_if_fail (NM_IS_SETTING_VLAN (setting), NULL);
-	return NM_SETTING_VLAN_GET_PRIVATE (setting)->iface_name;
+	return NM_SETTING_VLAN_GET_PRIVATE (setting)->interface_name;
 }
 
 /**
@@ -221,11 +222,13 @@ get_map (NMSettingVlan *self, NMVlanPriorityMap map)
 static void
 set_map (NMSettingVlan *self, NMVlanPriorityMap map, GSList *list)
 {
-	if (map == NM_VLAN_INGRESS_MAP)
+	if (map == NM_VLAN_INGRESS_MAP) {
 		NM_SETTING_VLAN_GET_PRIVATE (self)->ingress_priority_map = list;
-	else if (map == NM_VLAN_EGRESS_MAP)
+		g_object_notify (G_OBJECT (self), NM_SETTING_VLAN_INGRESS_PRIORITY_MAP);
+	} else if (map == NM_VLAN_EGRESS_MAP) {
 		NM_SETTING_VLAN_GET_PRIVATE (self)->egress_priority_map = list;
-	else
+		g_object_notify (G_OBJECT (self), NM_SETTING_VLAN_EGRESS_PRIORITY_MAP);
+	} else
 		g_assert_not_reached ();
 }
 
@@ -247,7 +250,6 @@ nm_setting_vlan_add_priority_str (NMSettingVlan *setting,
                                   NMVlanPriorityMap map,
                                   const char *str)
 {
-	NMSettingVlanPrivate *priv = NULL;
 	GSList *list = NULL, *iter = NULL;
 	PriorityMap *item = NULL;
 
@@ -255,7 +257,6 @@ nm_setting_vlan_add_priority_str (NMSettingVlan *setting,
 	g_return_val_if_fail (map == NM_VLAN_INGRESS_MAP || map == NM_VLAN_EGRESS_MAP, FALSE);
 	g_return_val_if_fail (str && str[0], FALSE);
 
-	priv = NM_SETTING_VLAN_GET_PRIVATE (setting);
 	list = get_map (setting, map);
 
 	item = priority_map_new_from_str (map, str);
@@ -268,6 +269,10 @@ nm_setting_vlan_add_priority_str (NMSettingVlan *setting,
 		if (p->from == item->from) {
 			p->to = item->to;
 			g_free (item);
+			if (map == NM_VLAN_INGRESS_MAP)
+				g_object_notify (G_OBJECT (setting), NM_SETTING_VLAN_INGRESS_PRIORITY_MAP);
+			else
+				g_object_notify (G_OBJECT (setting), NM_SETTING_VLAN_EGRESS_PRIORITY_MAP);
 			return TRUE;
 		}
 	}
@@ -372,6 +377,10 @@ nm_setting_vlan_add_priority (NMSettingVlan *setting,
 		item = iter->data;
 		if (item->from == from) {
 			item->to = to;
+			if (map == NM_VLAN_INGRESS_MAP)
+				g_object_notify (G_OBJECT (setting), NM_SETTING_VLAN_INGRESS_PRIORITY_MAP);
+			else
+				g_object_notify (G_OBJECT (setting), NM_SETTING_VLAN_EGRESS_PRIORITY_MAP);
 			return TRUE;
 		}
 	}
@@ -413,6 +422,79 @@ nm_setting_vlan_remove_priority (NMSettingVlan *setting,
 }
 
 /**
+ * nm_setting_vlan_remove_priority_by_value:
+ * @setting: the #NMSettingVlan
+ * @map: the type of priority map
+ * @from: the priority to map to @to
+ * @to: the priority to map @from to
+ *
+ * Removes the priority map @form:@to from the #NMSettingVlan:ingress_priority_map
+ * or #NMSettingVlan:egress_priority_map (according to @map argument)
+ * properties.
+ *
+ * Returns: %TRUE if the priority mapping was found and removed; %FALSE if it was not.
+ *
+ * Since: 0.9.10
+ */
+gboolean
+nm_setting_vlan_remove_priority_by_value (NMSettingVlan *setting,
+                                          NMVlanPriorityMap map,
+                                          guint32 from,
+                                          guint32 to)
+{
+	GSList *list = NULL, *iter = NULL;
+	PriorityMap *item;
+
+	g_return_val_if_fail (NM_IS_SETTING_VLAN (setting), FALSE);
+	g_return_val_if_fail (map == NM_VLAN_INGRESS_MAP || map == NM_VLAN_EGRESS_MAP, FALSE);
+
+	list = get_map (setting, map);
+	for (iter = list; iter; iter = g_slist_next (iter)) {
+		item = iter->data;
+		if (item->from == from && item->to == to) {
+			priority_map_free ((PriorityMap *) (iter->data));
+			set_map (setting, map, g_slist_delete_link (list, iter));
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
+
+/**
+ * nm_setting_vlan_remove_priority_str_by_value:
+ * @setting: the #NMSettingVlan
+ * @map: the type of priority map
+ * @str: the string which contains a priority map, like "3:7"
+ *
+ * Removes the priority map @str from the #NMSettingVlan:ingress_priority_map
+ * or #NMSettingVlan:egress_priority_map (according to @map argument)
+ * properties.
+ *
+ * Returns: %TRUE if the priority mapping was found and removed; %FALSE if it was not.
+ *
+ * Since: 0.9.10
+ */
+gboolean
+nm_setting_vlan_remove_priority_str_by_value (NMSettingVlan *setting,
+                                              NMVlanPriorityMap map,
+                                              const char *str)
+{
+	PriorityMap *item;
+	gboolean found;
+
+	g_return_val_if_fail (NM_IS_SETTING_VLAN (setting), FALSE);
+	g_return_val_if_fail (map == NM_VLAN_INGRESS_MAP || map == NM_VLAN_EGRESS_MAP, FALSE);
+
+	item = priority_map_new_from_str (map, str);
+	if (!item)
+		return FALSE;
+
+	found = nm_setting_vlan_remove_priority_by_value (setting, map, item->from, item->to);
+	g_free (item);
+	return found;
+}
+
+/**
  * nm_setting_vlan_clear_priorities:
  * @setting: the #NMSettingVlan
  * @map: the type of priority map
@@ -429,7 +511,7 @@ nm_setting_vlan_clear_priorities (NMSettingVlan *setting, NMVlanPriorityMap map)
 	g_return_if_fail (map == NM_VLAN_INGRESS_MAP || map == NM_VLAN_EGRESS_MAP);
 
 	list = get_map (setting, map);
-	nm_utils_slist_free (list, g_free);
+	g_slist_free_full (list, g_free);
 	set_map (setting, map, NULL);
 }
 
@@ -438,7 +520,6 @@ nm_setting_vlan_clear_priorities (NMSettingVlan *setting, NMVlanPriorityMap map)
 static void
 nm_setting_vlan_init (NMSettingVlan *setting)
 {
-	g_object_set (setting, NM_SETTING_NAME, NM_SETTING_VLAN_SETTING_NAME, NULL);
 }
 
 static gboolean
@@ -456,15 +537,17 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 			s_wired = iter->data;
 	}
 
-	/* If iface_name is specified, it must be a valid interface name. We
+	/* If interface_name is specified, it must be a valid interface name. We
 	 * don't check that it matches parent and/or id, because we allowing
 	 * renaming vlans to arbitrary names.
 	 */
-	if (priv->iface_name && !nm_utils_iface_valid_name (priv->iface_name)) {
+	if (priv->interface_name && !nm_utils_iface_valid_name (priv->interface_name)) {
 		g_set_error (error,
 		             NM_SETTING_VLAN_ERROR,
 		             NM_SETTING_VLAN_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_VLAN_INTERFACE_NAME);
+		             _("'%s' is not a valid interface name"),
+		             priv->interface_name);
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_VLAN_SETTING_NAME, NM_SETTING_VLAN_INTERFACE_NAME);
 		return FALSE;
 	}
 
@@ -484,7 +567,9 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 					g_set_error (error,
 					             NM_SETTING_VLAN_ERROR,
 					             NM_SETTING_VLAN_ERROR_INVALID_PARENT,
-					             NM_SETTING_CONNECTION_MASTER);
+					             _("'%s' value doesn't match '%s=%s'"),
+					             priv->parent, NM_SETTING_CONNECTION_MASTER, master);
+					g_prefix_error (error, "%s.%s: ", NM_SETTING_VLAN_SETTING_NAME, NM_SETTING_VLAN_PARENT);
 					return FALSE;
 				}
 			}
@@ -493,7 +578,9 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 			g_set_error (error,
 			             NM_SETTING_VLAN_ERROR,
 			             NM_SETTING_VLAN_ERROR_INVALID_PROPERTY,
-			             NM_SETTING_VLAN_PARENT);
+			             _("'%s' is neither an UUID nor an interface name"),
+			             priv->parent);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_VLAN_SETTING_NAME, NM_SETTING_VLAN_PARENT);
 			return FALSE;
 		} 
 	} else {
@@ -504,7 +591,9 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 			g_set_error (error,
 			             NM_SETTING_VLAN_ERROR,
 			             NM_SETTING_VLAN_ERROR_MISSING_PROPERTY,
-			             NM_SETTING_VLAN_PARENT);
+			             _("property is not specified and neither is '%s:%s'"),
+			             NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_WIRED_MAC_ADDRESS);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_VLAN_SETTING_NAME, NM_SETTING_VLAN_PARENT);
 			return FALSE;
 		}
 	}
@@ -512,10 +601,11 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 	if (priv->flags & ~(NM_VLAN_FLAG_REORDER_HEADERS |
 	                    NM_VLAN_FLAG_GVRP |
 	                    NM_VLAN_FLAG_LOOSE_BINDING)) {
-		g_set_error (error,
-		             NM_SETTING_VLAN_ERROR,
-		             NM_SETTING_VLAN_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_VLAN_FLAGS);
+		g_set_error_literal (error,
+		                     NM_SETTING_VLAN_ERROR,
+		                     NM_SETTING_VLAN_ERROR_INVALID_PROPERTY,
+		                     _("flags are invalid"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_VLAN_SETTING_NAME, NM_SETTING_VLAN_FLAGS);
 		return FALSE;
 	}
 
@@ -551,9 +641,9 @@ set_property (GObject *object, guint prop_id,
 	NMSettingVlanPrivate *priv = NM_SETTING_VLAN_GET_PRIVATE (setting);
 
 	switch (prop_id) {
-	case PROP_IFACE_NAME:
-		g_free (priv->iface_name);
-		priv->iface_name = g_value_dup_string (value);
+	case PROP_INTERFACE_NAME:
+		g_free (priv->interface_name);
+		priv->interface_name = g_value_dup_string (value);
 		break;
 	case PROP_PARENT:
 		g_free (priv->parent);
@@ -566,12 +656,12 @@ set_property (GObject *object, guint prop_id,
 		priv->flags = g_value_get_uint (value);
 		break;
 	case PROP_INGRESS_PRIORITY_MAP:
-		nm_utils_slist_free (priv->ingress_priority_map, g_free);
+		g_slist_free_full (priv->ingress_priority_map, g_free);
 		priv->ingress_priority_map =
 			priority_stringlist_to_maplist (NM_VLAN_INGRESS_MAP, g_value_get_boxed (value));
 		break;
 	case PROP_EGRESS_PRIORITY_MAP:
-		nm_utils_slist_free (priv->egress_priority_map, g_free);
+		g_slist_free_full (priv->egress_priority_map, g_free);
 		priv->egress_priority_map =
 			priority_stringlist_to_maplist (NM_VLAN_EGRESS_MAP, g_value_get_boxed (value));
 		break;
@@ -602,8 +692,8 @@ get_property (GObject *object, guint prop_id,
 	NMSettingVlanPrivate *priv = NM_SETTING_VLAN_GET_PRIVATE (setting);
 
 	switch (prop_id) {
-	case PROP_IFACE_NAME:
-		g_value_set_string (value, priv->iface_name);
+	case PROP_INTERFACE_NAME:
+		g_value_set_string (value, priv->interface_name);
 		break;
 	case PROP_PARENT:
 		g_value_set_string (value, priv->parent);
@@ -632,10 +722,10 @@ finalize (GObject *object)
 	NMSettingVlan *setting = NM_SETTING_VLAN (object);
 	NMSettingVlanPrivate *priv = NM_SETTING_VLAN_GET_PRIVATE (setting);
 
-	g_free (priv->iface_name);
+	g_free (priv->interface_name);
 	g_free (priv->parent);
-	nm_utils_slist_free (priv->ingress_priority_map, g_free);
-	nm_utils_slist_free (priv->egress_priority_map, g_free);
+	g_slist_free_full (priv->ingress_priority_map, g_free);
+	g_slist_free_full (priv->egress_priority_map, g_free);
 
 	G_OBJECT_CLASS (nm_setting_vlan_parent_class)->finalize (object);
 }
@@ -662,12 +752,12 @@ nm_setting_vlan_class_init (NMSettingVlanClass *setting_class)
 	 *
 	 * If given, specifies the kernel name of the VLAN interface. If not given,
 	 * a default name will be constructed from the interface described by the
-	 * parent interface and the #NMSettingVlan:id , ex 'eth2.1'. The parent
-	 * interface may be given by the #NMSettingVlan:parent property or by a
-	 * hardware address property, eg #NMSettingWired:mac-address.
+	 * parent interface and the #NMSettingVlan:id property, eg "eth2.1". The
+	 * parent interface may be given by the #NMSettingVlan:parent property or by
+	 * the #NMSettingWired:mac-address property of an #NMSettingWired setting.
 	 **/
 	g_object_class_install_property
-		(object_class, PROP_IFACE_NAME,
+		(object_class, PROP_INTERFACE_NAME,
 		g_param_spec_string (NM_SETTING_VLAN_INTERFACE_NAME,
 		                     "InterfaceName",
 		                     "If given, specifies the kernel name of the VLAN "
@@ -675,19 +765,18 @@ nm_setting_vlan_class_init (NMSettingVlanClass *setting_class)
 		                     "constructed from the interface described by the "
 		                     "parent interface and the 'id' property, ex "
 		                     "'eth2.1'. The parent interface may be given by "
-		                     "the 'parent' property or by a hardware address "
-		                     "property, eg the 'wired' settings' 'mac-address' "
-		                     "property.",
+		                     "the 'parent' property or by the 'mac-address' "
+		                     "property of a 'wired' setting.",
 		                     NULL,
-		                     G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+		                     G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE));
 
 	/**
 	 * NMSettingVlan:parent:
 	 *
 	 * If given, specifies the parent interface name or parent connection UUID
 	 * from which this VLAN interface should be created.  If this property is
-	 * not specified, the connection must contain a hardware address in a
-	 * hardware-specific setting, like #NMSettingWired:mac-address.
+	 * not specified, the connection must contain an #NMSettingWired setting
+	 * with a #NMSettingWired:mac-address property.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_PARENT,
@@ -697,16 +786,15 @@ nm_setting_vlan_class_init (NMSettingVlanClass *setting_class)
 		                     "parent connection UUID from which this VLAN "
 		                     "interface should be created.  If this property is "
 		                     "not specified, the connection must contain a "
-		                     "hardware address in a hardware-specific setting, "
-		                     "like the 'wired' settings' 'mac-address' property.",
+		                     "'wired' setting with a 'mac-address' property.",
 		                     NULL,
-		                     G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+		                     G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE));
 
 	/**
 	 * NMSettingVlan:id:
 	 *
-	 * The VLAN identifier the interface created by this connection should be
-	 * assigned.
+	 * The VLAN identifier that the interface created by this connection should
+	 * be assigned.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_ID,
@@ -715,13 +803,16 @@ nm_setting_vlan_class_init (NMSettingVlanClass *setting_class)
 		                    "The VLAN indentifier the interface created by "
 		                    "this connection should be assigned.",
 		                    0, 4095, 0,
-		                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+		                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE));
 
 	/**
 	 * NMSettingVlan:flags:
 	 *
-	 * One or more of %NMVlanFlags which control the behavior and features of
-	 * the VLAN interface.
+	 * One or more flags which control the behavior and features of the VLAN
+	 * interface.  Flags include %NM_VLAN_FLAG_REORDER_HEADERS (reordering of
+	 * output packet headers), %NM_VLAN_FLAG_GVRP (use of the GVRP protocol),
+	 * and %NM_VLAN_FLAG_LOOSE_BINDING (loose binding of the interface to its
+	 * master device's operating state).
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_FLAGS,
@@ -734,14 +825,14 @@ nm_setting_vlan_class_init (NMSettingVlanClass *setting_class)
 		                    "of the interface to its master device's operating "
 		                    "state (0x04).",
 		                    0, G_MAXUINT32, 0,
-		                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+		                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_INFERRABLE));
 
 	/**
 	 * NMSettingVlan:ingress-priority-map:
 	 *
 	 * For incoming packets, a list of mappings from 802.1p priorities to Linux
-	 * SKB priorities.  The mapping is given in the format 'from:to' where both
-	 * 'from' and 'to' are unsigned integers, ie '7:3'.
+	 * SKB priorities.  The mapping is given in the format "from:to" where both
+	 * "from" and "to" are unsigned integers, ie "7:3".
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_INGRESS_PRIORITY_MAP,
@@ -753,14 +844,14 @@ nm_setting_vlan_class_init (NMSettingVlanClass *setting_class)
 		                            "format 'from:to' where both 'from' and "
 		                            "'to' are unsigned integers, ie '7:3'.",
 		                            DBUS_TYPE_G_LIST_OF_STRING,
-		                            G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+		                            G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE));
 
 	/**
 	 * NMSettingVlan:egress-priority-map:
 	 *
 	 * For outgoing packets, a list of mappings from Linux SKB priorities to
-	 * 802.1p priorities.  The mapping is given in the format 'from:to'
-	 * where both 'from' and 'to' are unsigned integers, ie '7:3'.
+	 * 802.1p priorities.  The mapping is given in the format "from:to" where
+	 * both "from" and "to" are unsigned integers, ie "7:3".
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_EGRESS_PRIORITY_MAP,
@@ -772,5 +863,5 @@ nm_setting_vlan_class_init (NMSettingVlanClass *setting_class)
 		                            "format 'from:to' where both 'from' and "
 		                            "'to' are unsigned integers, ie '7:3'.",
 		                            DBUS_TYPE_G_LIST_OF_STRING,
-		                            G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+		                            G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE));
 }
diff --git a/libnm-util/nm-setting-vlan.h b/libnm-util/nm-setting-vlan.h
index 019c6da0..ca77f6fe 100644
--- a/libnm-util/nm-setting-vlan.h
+++ b/libnm-util/nm-setting-vlan.h
@@ -18,7 +18,7 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2011 Red Hat, Inc.
+ * (C) Copyright 2011 - 2014 Red Hat, Inc.
  */
 
 #ifndef NM_SETTING_VLAN_H
@@ -94,7 +94,7 @@ typedef enum {
 /**
  * NMVlanFlags:
  * @NM_VLAN_FLAG_REORDER_HEADERS: indicates that this interface should reorder
- *  outgoing packet headers to look more like a non-VLAN ethernet interface
+ *  outgoing packet headers to look more like a non-VLAN Ethernet interface
  * @NM_VLAN_FLAG_GVRP: indicates that this interface should use GVRP to register
  *  itself with it's switch
  * @NM_VLAN_FLAG_LOOSE_BINDING: indicates that this interface's operating
@@ -136,6 +136,17 @@ void     nm_setting_vlan_remove_priority    (NMSettingVlan *setting,
                                              NMVlanPriorityMap map,
                                              guint32 idx);
 
+NM_AVAILABLE_IN_0_9_10
+gboolean nm_setting_vlan_remove_priority_by_value (NMSettingVlan *setting,
+                                                   NMVlanPriorityMap map,
+                                                   guint32 from,
+                                                   guint32 to);
+
+NM_AVAILABLE_IN_0_9_10
+gboolean nm_setting_vlan_remove_priority_str_by_value (NMSettingVlan *setting,
+                                                       NMVlanPriorityMap map,
+                                                       const char *str);
+
 void     nm_setting_vlan_clear_priorities   (NMSettingVlan *setting, NMVlanPriorityMap map);
 
 gboolean nm_setting_vlan_add_priority_str   (NMSettingVlan *setting,
diff --git a/libnm-util/nm-setting-vpn.c b/libnm-util/nm-setting-vpn.c
index 0acd9a52..4b479b8f 100644
--- a/libnm-util/nm-setting-vpn.c
+++ b/libnm-util/nm-setting-vpn.c
@@ -18,7 +18,7 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2007 - 2012 Red Hat, Inc.
+ * (C) Copyright 2007 - 2013 Red Hat, Inc.
  * (C) Copyright 2007 - 2008 Novell, Inc.
  */
 
@@ -26,6 +26,8 @@
 #include <errno.h>
 #include <stdlib.h>
 #include <dbus/dbus-glib.h>
+#include <glib/gi18n.h>
+
 #include "nm-setting-vpn.h"
 #include "nm-param-spec-specialized.h"
 #include "nm-utils.h"
@@ -194,6 +196,7 @@ nm_setting_vpn_add_data_item (NMSettingVPN *setting,
 
 	g_hash_table_insert (NM_SETTING_VPN_GET_PRIVATE (setting)->data,
 	                     g_strdup (key), g_strdup (item));
+	g_object_notify (G_OBJECT (setting), NM_SETTING_VPN_DATA);
 }
 
 /**
@@ -221,13 +224,21 @@ nm_setting_vpn_get_data_item (NMSettingVPN *setting, const char *key)
  *
  * Deletes a key/value relationship previously established by
  * nm_setting_vpn_add_data_item().
+ *
+ * Returns: %TRUE if the data item was found and removed from the internal list,
+ * %FALSE if it was not.
  **/
-void
+gboolean
 nm_setting_vpn_remove_data_item (NMSettingVPN *setting, const char *key)
 {
-	g_return_if_fail (NM_IS_SETTING_VPN (setting));
+	gboolean found;
 
-	g_hash_table_remove (NM_SETTING_VPN_GET_PRIVATE (setting)->data, key);
+	g_return_val_if_fail (NM_IS_SETTING_VPN (setting), FALSE);
+
+	found = g_hash_table_remove (NM_SETTING_VPN_GET_PRIVATE (setting)->data, key);
+	if (found)
+		g_object_notify (G_OBJECT (setting), NM_SETTING_VPN_DATA);
+	return found;
 }
 
 static void
@@ -256,8 +267,7 @@ foreach_item_helper (GHashTable *hash,
 		func (siter->data, value, user_data);
 	}
 
-	g_slist_foreach (copied, (GFunc) g_free, NULL);
-	g_slist_free (copied);
+	g_slist_free_full (copied, g_free);
 }
 
 /**
@@ -275,7 +285,6 @@ nm_setting_vpn_foreach_data_item (NMSettingVPN *setting,
                                   NMVPNIterFunc func,
                                   gpointer user_data)
 {
-	g_return_if_fail (setting != NULL);
 	g_return_if_fail (NM_IS_SETTING_VPN (setting));
 
 	foreach_item_helper (NM_SETTING_VPN_GET_PRIVATE (setting)->data, func, user_data);
@@ -319,6 +328,7 @@ nm_setting_vpn_add_secret (NMSettingVPN *setting,
 
 	g_hash_table_insert (NM_SETTING_VPN_GET_PRIVATE (setting)->secrets,
 	                     g_strdup (key), g_strdup (secret));
+	g_object_notify (G_OBJECT (setting), NM_SETTING_VPN_SECRETS);
 }
 
 /**
@@ -346,13 +356,21 @@ nm_setting_vpn_get_secret (NMSettingVPN *setting, const char *key)
  *
  * Deletes a key/value relationship previously established by
  * nm_setting_vpn_add_secret().
+ *
+ * Returns: %TRUE if the secret was found and removed from the internal list,
+ * %FALSE if it was not.
  **/
-void
+gboolean
 nm_setting_vpn_remove_secret (NMSettingVPN *setting, const char *key)
 {
-	g_return_if_fail (NM_IS_SETTING_VPN (setting));
+	gboolean found;
 
-	g_hash_table_remove (NM_SETTING_VPN_GET_PRIVATE (setting)->secrets, key);
+	g_return_val_if_fail (NM_IS_SETTING_VPN (setting), FALSE);
+
+	found = g_hash_table_remove (NM_SETTING_VPN_GET_PRIVATE (setting)->secrets, key);
+	if (found)
+		g_object_notify (G_OBJECT (setting), NM_SETTING_VPN_SECRETS);
+	return found;
 }
 
 /**
@@ -370,7 +388,6 @@ nm_setting_vpn_foreach_secret (NMSettingVPN *setting,
                                NMVPNIterFunc func,
                                gpointer user_data)
 {
-	g_return_if_fail (setting != NULL);
 	g_return_if_fail (NM_IS_SETTING_VPN (setting));
 
 	foreach_item_helper (NM_SETTING_VPN_GET_PRIVATE (setting)->secrets, func, user_data);
@@ -382,34 +399,37 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 	NMSettingVPNPrivate *priv = NM_SETTING_VPN_GET_PRIVATE (setting);
 
 	if (!priv->service_type) {
-		g_set_error (error,
-		             NM_SETTING_VPN_ERROR,
-		             NM_SETTING_VPN_ERROR_MISSING_PROPERTY,
-		             NM_SETTING_VPN_SERVICE_TYPE);
+		g_set_error_literal (error,
+		                     NM_SETTING_VPN_ERROR,
+		                     NM_SETTING_VPN_ERROR_MISSING_PROPERTY,
+		                     _("property is missing"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_VPN_SETTING_NAME, NM_SETTING_VPN_SERVICE_TYPE);
 		return FALSE;
 	}
 
 	if (!strlen (priv->service_type)) {
-		g_set_error (error,
-		             NM_SETTING_VPN_ERROR,
-		             NM_SETTING_VPN_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_VPN_SERVICE_TYPE);
+		g_set_error_literal (error,
+		                     NM_SETTING_VPN_ERROR,
+		                     NM_SETTING_VPN_ERROR_INVALID_PROPERTY,
+		                     _("property is empty"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_VPN_SETTING_NAME, NM_SETTING_VPN_SERVICE_TYPE);
 		return FALSE;
 	}
 
 	/* default username can be NULL, but can't be zero-length */
 	if (priv->user_name && !strlen (priv->user_name)) {
-		g_set_error (error,
-		             NM_SETTING_VPN_ERROR,
-		             NM_SETTING_VPN_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_VPN_USER_NAME);
+		g_set_error_literal (error,
+		                     NM_SETTING_VPN_ERROR,
+		                     NM_SETTING_VPN_ERROR_INVALID_PROPERTY,
+		                     _("property is empty"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_VPN_SETTING_NAME, NM_SETTING_VPN_USER_NAME);
 		return FALSE;
 	}
 
 	return TRUE;
 }
 
-static gboolean
+static NMSettingUpdateSecretResult
 update_secret_string (NMSetting *setting,
                       const char *key,
                       const char *value,
@@ -417,21 +437,24 @@ update_secret_string (NMSetting *setting,
 {
 	NMSettingVPNPrivate *priv = NM_SETTING_VPN_GET_PRIVATE (setting);
 
-	g_return_val_if_fail (key != NULL, FALSE);
-	g_return_val_if_fail (value != NULL, FALSE);
+	g_return_val_if_fail (key != NULL, NM_SETTING_UPDATE_SECRET_ERROR);
+	g_return_val_if_fail (value != NULL, NM_SETTING_UPDATE_SECRET_ERROR);
 
 	if (!value || !strlen (value)) {
 		g_set_error (error, NM_SETTING_ERROR,
 		             NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH,
 		             "Secret %s was empty", key);
-		return FALSE;
+		return NM_SETTING_UPDATE_SECRET_ERROR;
 	}
 
+	if (g_strcmp0 (g_hash_table_lookup (priv->secrets, key), value) == 0)
+		return NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED;
+
 	g_hash_table_insert (priv->secrets, g_strdup (key), g_strdup (value));
-	return TRUE;
+	return NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED;
 }
 
-static gboolean
+static NMSettingUpdateSecretResult
 update_secret_hash (NMSetting *setting,
                     GHashTable *secrets,
                     GError **error)
@@ -439,8 +462,9 @@ update_secret_hash (NMSetting *setting,
 	NMSettingVPNPrivate *priv = NM_SETTING_VPN_GET_PRIVATE (setting);
 	GHashTableIter iter;
 	const char *name, *value;
+	NMSettingUpdateSecretResult result = NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED;
 
-	g_return_val_if_fail (secrets != NULL, FALSE);
+	g_return_val_if_fail (secrets != NULL, NM_SETTING_UPDATE_SECRET_ERROR);
 
 	/* Make sure the items are valid */
 	g_hash_table_iter_init (&iter, secrets);
@@ -449,14 +473,14 @@ update_secret_hash (NMSetting *setting,
 			g_set_error_literal (error, NM_SETTING_ERROR,
 			                     NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH,
 			                     "Secret name was empty");
-			return FALSE;
+			return NM_SETTING_UPDATE_SECRET_ERROR;
 		}
 
 		if (!value || !strlen (value)) {
 			g_set_error (error, NM_SETTING_ERROR,
 			             NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH,
 				         "Secret %s value was empty", name);
-			return FALSE;
+			return NM_SETTING_UPDATE_SECRET_ERROR;
 		}
 	}
 
@@ -472,19 +496,23 @@ update_secret_hash (NMSetting *setting,
 			continue;
 		}
 
+		if (g_strcmp0 (g_hash_table_lookup (priv->secrets, name), value) == 0)
+			continue;
+
 		g_hash_table_insert (priv->secrets, g_strdup (name), g_strdup (value));
+		result = NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED;
 	}
 
-	return TRUE;
+	return result;
 }
 
-static gboolean
+static int
 update_one_secret (NMSetting *setting, const char *key, GValue *value, GError **error)
 {
-	gboolean success = FALSE;
+	NMSettingUpdateSecretResult success = NM_SETTING_UPDATE_SECRET_ERROR;
 
-	g_return_val_if_fail (key != NULL, FALSE);
-	g_return_val_if_fail (value != NULL, FALSE);
+	g_return_val_if_fail (key != NULL, NM_SETTING_UPDATE_SECRET_ERROR);
+	g_return_val_if_fail (value != NULL, NM_SETTING_UPDATE_SECRET_ERROR);
 
 	if (G_VALUE_HOLDS_STRING (value)) {
 		/* Passing the string properties individually isn't correct, and won't
@@ -502,6 +530,9 @@ update_one_secret (NMSetting *setting, const char *key, GValue *value, GError **
 	} else
 		g_set_error_literal (error, NM_SETTING_ERROR, NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH, key);
 
+	if (success == NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED)
+		g_object_notify (G_OBJECT (setting), NM_SETTING_VPN_SECRETS);
+
 	return success;
 }
 
@@ -553,6 +584,7 @@ set_secret_flags (NMSetting *setting,
 	g_hash_table_insert (NM_SETTING_VPN_GET_PRIVATE (setting)->data,
 	                     g_strdup_printf ("%s-flags", secret_name),
 	                     g_strdup_printf ("%u", flags));
+	g_object_notify (G_OBJECT (setting), NM_SETTING_VPN_SECRETS);
 	return TRUE;
 }
 
@@ -625,7 +657,7 @@ compare_property (NMSetting *setting,
 	return same;
 }
 
-static void
+static gboolean
 clear_secrets_with_flags (NMSetting *setting,
 	                      GParamSpec *pspec,
 	                      NMSettingClearSecretsWithFlagsFn func,
@@ -634,9 +666,10 @@ clear_secrets_with_flags (NMSetting *setting,
 	NMSettingVPNPrivate *priv = NM_SETTING_VPN_GET_PRIVATE (setting);
 	GHashTableIter iter;
 	const char *secret;
+	gboolean changed = TRUE;
 
 	if (priv->secrets == NULL)
-		return;
+		return FALSE;
 
 	/* Iterate through secrets hash and check each entry */
 	g_hash_table_iter_init (&iter, priv->secrets);
@@ -644,9 +677,16 @@ clear_secrets_with_flags (NMSetting *setting,
 		NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE;
 
 		nm_setting_get_secret_flags (setting, secret, &flags, NULL);
-		if (func (setting, pspec->name, flags, user_data) == TRUE)
+		if (func (setting, pspec->name, flags, user_data) == TRUE) {
 			g_hash_table_iter_remove (&iter);
+			changed = TRUE;
+		}
 	}
+
+	if (changed)
+		g_object_notify (G_OBJECT (setting), NM_SETTING_VPN_SECRETS);
+
+	return changed;
 }
 
 static void
@@ -664,7 +704,6 @@ nm_setting_vpn_init (NMSettingVPN *setting)
 {
 	NMSettingVPNPrivate *priv = NM_SETTING_VPN_GET_PRIVATE (setting);
 
-	g_object_set (setting, NM_SETTING_NAME, NM_SETTING_VPN_SETTING_NAME, NULL);
 	priv->data = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
 	priv->secrets = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, destroy_one_secret);
 }
@@ -777,8 +816,8 @@ nm_setting_vpn_class_init (NMSettingVPNClass *setting_class)
 	/**
 	 * NMSettingVPN:service-type:
 	 *
-	 * D-Bus service name of the VPN plugin that this setting uses to connect
-	 * to its network.  i.e. org.freedesktop.NetworkManager.vpnc for the vpnc
+	 * D-Bus service name of the VPN plugin that this setting uses to connect to
+	 * its network.  i.e. org.freedesktop.NetworkManager.vpnc for the vpnc
 	 * plugin.
 	 **/
 	g_object_class_install_property
@@ -790,14 +829,14 @@ nm_setting_vpn_class_init (NMSettingVPNClass *setting_class)
 						  "org.freedesktop.NetworkManager.vpnc for the vpnc "
 						  "plugin.",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+						  G_PARAM_READWRITE));
 
 	/**
 	 * NMSettingVPN:user-name:
 	 *
 	 * If the VPN connection requires a user name for authentication, that name
-	 * should be provided here.  If the connection is available to more than
-	 * one user, and the VPN requires each user to supply a different name, then
+	 * should be provided here.  If the connection is available to more than one
+	 * user, and the VPN requires each user to supply a different name, then
 	 * leave this property empty.  If this property is empty, NetworkManager
 	 * will automatically supply the username of the user which requested the
 	 * VPN connection.
@@ -815,13 +854,13 @@ nm_setting_vpn_class_init (NMSettingVPNClass *setting_class)
 		                      "automatically supply the username of the user which "
 		                      "requested the VPN connection.",
 		                      NULL,
-		                      G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+		                      G_PARAM_READWRITE));
 
 	/**
 	 * NMSettingVPN:data:
 	 *
-	 * Dictionary of key/value pairs of VPN plugin specific data.  Both keys
-	 * and values must be strings.
+	 * Dictionary of key/value pairs of VPN plugin specific data.  Both keys and
+	 * values must be strings.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_DATA,
@@ -831,7 +870,7 @@ nm_setting_vpn_class_init (NMSettingVPNClass *setting_class)
 							   "specific data.  Both keys and values must be "
 							   "strings.",
 							   DBUS_TYPE_G_MAP_OF_STRING,
-							   G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+							   G_PARAM_READWRITE));
 
 	/**
 	 * NMSettingVPN:secrets:
@@ -847,6 +886,6 @@ nm_setting_vpn_class_init (NMSettingVPNClass *setting_class)
 							   "specific secrets like passwords or private keys."
 							   "  Both keys and values must be strings.",
 							   DBUS_TYPE_G_MAP_OF_STRING,
-							   G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET));
+							   G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET));
 }
 
diff --git a/libnm-util/nm-setting-vpn.h b/libnm-util/nm-setting-vpn.h
index dfd98105..259384bf 100644
--- a/libnm-util/nm-setting-vpn.h
+++ b/libnm-util/nm-setting-vpn.h
@@ -19,7 +19,7 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2007 - 2011 Red Hat, Inc.
+ * (C) Copyright 2007 - 2013 Red Hat, Inc.
  * (C) Copyright 2007 - 2008 Novell, Inc.
  */
 
@@ -95,7 +95,7 @@ void              nm_setting_vpn_add_data_item     (NMSettingVPN *setting,
                                                     const char *item);
 const char *      nm_setting_vpn_get_data_item     (NMSettingVPN *setting,
                                                     const char *key);
-void              nm_setting_vpn_remove_data_item  (NMSettingVPN *setting,
+gboolean          nm_setting_vpn_remove_data_item  (NMSettingVPN *setting,
                                                     const char *key);
 void              nm_setting_vpn_foreach_data_item (NMSettingVPN *setting,
                                                     NMVPNIterFunc func,
@@ -107,7 +107,7 @@ void              nm_setting_vpn_add_secret        (NMSettingVPN *setting,
                                                     const char *secret);
 const char *      nm_setting_vpn_get_secret        (NMSettingVPN *setting,
                                                     const char *key);
-void              nm_setting_vpn_remove_secret     (NMSettingVPN *setting,
+gboolean          nm_setting_vpn_remove_secret     (NMSettingVPN *setting,
                                                     const char *key);
 void              nm_setting_vpn_foreach_secret    (NMSettingVPN *setting,
                                                     NMVPNIterFunc func,
diff --git a/libnm-util/nm-setting-wimax.c b/libnm-util/nm-setting-wimax.c
index b4a0d418..8bf16b3d 100644
--- a/libnm-util/nm-setting-wimax.c
+++ b/libnm-util/nm-setting-wimax.c
@@ -16,13 +16,14 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2011 Red Hat, Inc.
+ * (C) Copyright 2011 - 2013 Red Hat, Inc.
  * (C) Copyright 2009 Novell, Inc.
  */
 
 #include <string.h>
 #include <net/ethernet.h>
 #include <dbus/dbus-glib.h>
+#include <glib/gi18n.h>
 
 #include "nm-setting-wimax.h"
 #include "nm-param-spec-specialized.h"
@@ -130,28 +131,29 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 	NMSettingWimaxPrivate *priv = NM_SETTING_WIMAX_GET_PRIVATE (setting);
 
 	if (!priv->network_name) {
-		g_set_error (error,
-					 NM_SETTING_WIMAX_ERROR,
-					 NM_SETTING_WIMAX_ERROR_MISSING_PROPERTY,
-					 NM_SETTING_WIMAX_NETWORK_NAME);
-
+		g_set_error_literal (error,
+		                     NM_SETTING_WIMAX_ERROR,
+		                     NM_SETTING_WIMAX_ERROR_MISSING_PROPERTY,
+		                     _("property is missing"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIMAX_SETTING_NAME, NM_SETTING_WIMAX_NETWORK_NAME);
 		return FALSE;
 	}
 
 	if (!strlen (priv->network_name)) {
-		g_set_error (error,
-					 NM_SETTING_WIMAX_ERROR,
-					 NM_SETTING_WIMAX_ERROR_INVALID_PROPERTY,
-					 NM_SETTING_WIMAX_NETWORK_NAME);
-
+		g_set_error_literal (error,
+		                     NM_SETTING_WIMAX_ERROR,
+		                     NM_SETTING_WIMAX_ERROR_INVALID_PROPERTY,
+		                     _("property is empty"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIMAX_SETTING_NAME, NM_SETTING_WIMAX_NETWORK_NAME);
 		return FALSE;
 	}
 
 	if (priv->mac_address && priv->mac_address->len != ETH_ALEN) {
-		g_set_error (error,
-		             NM_SETTING_WIMAX_ERROR,
-		             NM_SETTING_WIMAX_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_WIMAX_MAC_ADDRESS);
+		g_set_error_literal (error,
+		                     NM_SETTING_WIMAX_ERROR,
+		                     NM_SETTING_WIMAX_ERROR_INVALID_PROPERTY,
+		                     _("property is invalid"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIMAX_SETTING_NAME, NM_SETTING_WIMAX_MAC_ADDRESS);
 		return FALSE;
 	}
 
@@ -161,7 +163,6 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 static void
 nm_setting_wimax_init (NMSettingWimax *setting)
 {
-	g_object_set (setting, NM_SETTING_NAME, NM_SETTING_WIMAX_SETTING_NAME, NULL);
 }
 
 static void
@@ -245,14 +246,14 @@ nm_setting_wimax_class_init (NMSettingWimaxClass *setting_class)
 							  "Network Service Provider (NSP) name of the WiMAX "
 							  "network this connection should use.",
 							  NULL,
-							  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+							  G_PARAM_READWRITE));
 
 	/**
 	 * NMSettingWimax:mac-address:
 	 *
-	 * If specified, this connection will only apply to the WiMAX device
-	 * whose MAC address matches. This property does not change the MAC address
-	 * of the device (known as MAC spoofing).
+	 * If specified, this connection will only apply to the WiMAX device whose
+	 * MAC address matches. This property does not change the MAC address of the
+	 * device (known as MAC spoofing).
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_MAC_ADDRESS,
@@ -263,5 +264,5 @@ nm_setting_wimax_class_init (NMSettingWimaxClass *setting_class)
 							   "This property does not change the MAC address "
 							   "of the device (known as MAC spoofing).",
 							   DBUS_TYPE_G_UCHAR_ARRAY,
-							   G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+							   G_PARAM_READWRITE));
 }
diff --git a/libnm-util/nm-setting-wired.c b/libnm-util/nm-setting-wired.c
index 6d1afc67..a956a52f 100644
--- a/libnm-util/nm-setting-wired.c
+++ b/libnm-util/nm-setting-wired.c
@@ -19,14 +19,15 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2007 - 2011 Red Hat, Inc.
+ * (C) Copyright 2007 - 2014 Red Hat, Inc.
  * (C) Copyright 2007 - 2008 Novell, Inc.
  */
 
 #include <string.h>
 #include <net/ethernet.h>
-#include <dbus/dbus-glib.h>
 #include <netinet/ether.h>
+#include <dbus/dbus-glib.h>
+#include <glib/gi18n.h>
 
 #include "nm-setting-wired.h"
 #include "nm-param-spec-specialized.h"
@@ -225,6 +226,162 @@ nm_setting_wired_get_mac_address_blacklist (NMSettingWired *setting)
 }
 
 /**
+ * nm_setting_wired_get_num_mac_blacklist_items:
+ * @setting: the #NMSettingWired
+ *
+ * Returns: the number of blacklisted MAC addresses
+ *
+ * Since: 0.9.10
+ **/
+guint32
+nm_setting_wired_get_num_mac_blacklist_items (NMSettingWired *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), 0);
+
+	return g_slist_length (NM_SETTING_WIRED_GET_PRIVATE (setting)->mac_address_blacklist);
+}
+
+/**
+ * nm_setting_wired_get_mac_blacklist_item:
+ * @setting: the #NMSettingWired
+ * @idx: the zero-based index of the MAC address entry
+ *
+ * Returns: the blacklisted MAC address string (hex-digits-and-colons notation)
+ * at index @idx
+ *
+ * Since: 0.9.10
+ **/
+const char *
+nm_setting_wired_get_mac_blacklist_item (NMSettingWired *setting, guint32 idx)
+{
+	NMSettingWiredPrivate *priv;
+
+	g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), NULL);
+
+	priv = NM_SETTING_WIRED_GET_PRIVATE (setting);
+	g_return_val_if_fail (idx <= g_slist_length (priv->mac_address_blacklist), NULL);
+
+	return (const char *) g_slist_nth_data (priv->mac_address_blacklist, idx);
+}
+
+/**
+ * nm_setting_wired_add_mac_blacklist_item:
+ * @setting: the #NMSettingWired
+ * @mac: the MAC address string (hex-digits-and-colons notation) to blacklist
+ *
+ * Adds a new MAC address to the #NMSettingWired:mac-address-blacklist property.
+ *
+ * Returns: %TRUE if the MAC address was added; %FALSE if the MAC address
+ * is invalid or was already present
+ *
+ * Since: 0.9.10
+ **/
+gboolean
+nm_setting_wired_add_mac_blacklist_item (NMSettingWired *setting, const char *mac)
+{
+	NMSettingWiredPrivate *priv;
+	GSList *iter;
+	guint8 buf[32];
+
+	g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), FALSE);
+	g_return_val_if_fail (mac != NULL, FALSE);
+
+	if (!nm_utils_hwaddr_aton (mac, ARPHRD_ETHER, buf))
+		return FALSE;
+
+	priv = NM_SETTING_WIRED_GET_PRIVATE (setting);
+	for (iter = priv->mac_address_blacklist; iter; iter = g_slist_next (iter)) {
+		if (!strcasecmp (mac, (char *) iter->data))
+			return FALSE;
+	}
+
+	priv->mac_address_blacklist = g_slist_append (priv->mac_address_blacklist,
+	                                              g_ascii_strup (mac, -1));
+	g_object_notify (G_OBJECT (setting), NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST);
+	return TRUE;
+}
+
+/**
+ * nm_setting_wired_remove_mac_blacklist_item:
+ * @setting: the #NMSettingWired
+ * @idx: index number of the MAC address
+ *
+ * Removes the MAC address at index @idx from the blacklist.
+ *
+ * Since: 0.9.10
+ **/
+void
+nm_setting_wired_remove_mac_blacklist_item (NMSettingWired *setting, guint32 idx)
+{
+	NMSettingWiredPrivate *priv;
+	GSList *elt;
+
+	g_return_if_fail (NM_IS_SETTING_WIRED (setting));
+
+	priv = NM_SETTING_WIRED_GET_PRIVATE (setting);
+	elt = g_slist_nth (priv->mac_address_blacklist, idx);
+	g_return_if_fail (elt != NULL);
+
+	g_free (elt->data);
+	priv->mac_address_blacklist = g_slist_delete_link (priv->mac_address_blacklist, elt);
+	g_object_notify (G_OBJECT (setting), NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST);
+}
+
+/**
+ * nm_setting_wired_remove_mac_blacklist_item_by_value:
+ * @setting: the #NMSettingWired
+ * @mac: the MAC address string (hex-digits-and-colons notation) to remove from
+ * the blacklist
+ *
+ * Removes the MAC address @mac from the blacklist.
+ *
+ * Returns: %TRUE if the MAC address was found and removed; %FALSE if it was not.
+ *
+ * Since: 0.9.10
+ **/
+gboolean
+nm_setting_wired_remove_mac_blacklist_item_by_value (NMSettingWired *setting, const char *mac)
+{
+	NMSettingWiredPrivate *priv;
+	GSList *iter;
+	guint8 buf[32];
+
+	g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), FALSE);
+	g_return_val_if_fail (mac != NULL, FALSE);
+
+	if (!nm_utils_hwaddr_aton (mac, ARPHRD_ETHER, buf))
+		return FALSE;
+
+	priv = NM_SETTING_WIRED_GET_PRIVATE (setting);
+	for (iter = priv->mac_address_blacklist; iter; iter = g_slist_next (iter)) {
+		if (!strcasecmp (mac, (char *) iter->data)) {
+			priv->mac_address_blacklist = g_slist_delete_link (priv->mac_address_blacklist, iter);
+			g_object_notify (G_OBJECT (setting), NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST);
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
+
+/**
+ * nm_setting_wired_clear_mac_blacklist_items:
+ * @setting: the #NMSettingWired
+ *
+ * Removes all blacklisted MAC addresses.
+ *
+ * Since: 0.9.10
+ **/
+void
+nm_setting_wired_clear_mac_blacklist_items (NMSettingWired *setting)
+{
+	g_return_if_fail (NM_IS_SETTING_WIRED (setting));
+
+	g_slist_free_full (NM_SETTING_WIRED_GET_PRIVATE (setting)->mac_address_blacklist, g_free);
+	NM_SETTING_WIRED_GET_PRIVATE (setting)->mac_address_blacklist = NULL;
+	g_object_notify (G_OBJECT (setting), NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST);
+}
+
+/**
  * nm_setting_wired_get_mtu:
  * @setting: the #NMSettingWired
  *
@@ -364,7 +521,7 @@ nm_setting_wired_get_s390_option_by_key (NMSettingWired *setting,
 }
 
 /**
- * nm_setting_wired_add_s390_options:
+ * nm_setting_wired_add_s390_option:
  * @setting: the #NMSettingWired
  * @key: key name for the option
  * @value: value for the option
@@ -377,9 +534,10 @@ nm_setting_wired_get_s390_option_by_key (NMSettingWired *setting,
  * Returns: %TRUE if the option was valid and was added to the internal option
  * list, %FALSE if it was not.
  **/
-gboolean nm_setting_wired_add_s390_option (NMSettingWired *setting,
-                                           const char *key,
-                                           const char *value)
+gboolean
+nm_setting_wired_add_s390_option (NMSettingWired *setting,
+                                  const char *key,
+                                  const char *value)
 {
 	size_t value_len;
 
@@ -395,11 +553,12 @@ gboolean nm_setting_wired_add_s390_option (NMSettingWired *setting,
 	g_hash_table_insert (NM_SETTING_WIRED_GET_PRIVATE (setting)->s390_options,
 	                     g_strdup (key),
 	                     g_strdup (value));
+	g_object_notify (G_OBJECT (setting), NM_SETTING_WIRED_S390_OPTIONS);
 	return TRUE;
 }
 
 /**
- * nm_setting_wired_remove_s390_options:
+ * nm_setting_wired_remove_s390_option:
  * @setting: the #NMSettingWired
  * @key: key name for the option to remove
  *
@@ -413,11 +572,32 @@ gboolean
 nm_setting_wired_remove_s390_option (NMSettingWired *setting,
                                      const char *key)
 {
+	gboolean found;
+
 	g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), FALSE);
 	g_return_val_if_fail (key != NULL, FALSE);
 	g_return_val_if_fail (strlen (key), FALSE);
 
-	return g_hash_table_remove (NM_SETTING_WIRED_GET_PRIVATE (setting)->s390_options, key);
+	found = g_hash_table_remove (NM_SETTING_WIRED_GET_PRIVATE (setting)->s390_options, key);
+	if (found)
+		g_object_notify (G_OBJECT (setting), NM_SETTING_WIRED_S390_OPTIONS);
+	return found;
+}
+
+/**
+ * nm_setting_wired_get_valid_s390_options:
+ * @setting: the #NMSettingWired
+ *
+ * Returns a list of valid s390 options.
+ *
+ * Returns: (transfer none): a %NULL-terminated array of strings of valid s390 options.
+ *
+ * Since: 0.9.10
+ **/
+const char **
+nm_setting_wired_get_valid_s390_options (NMSettingWired *setting)
+{
+	return valid_s390_opts;
 }
 
 static gboolean
@@ -435,7 +615,9 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 		g_set_error (error,
 		             NM_SETTING_WIRED_ERROR,
 		             NM_SETTING_WIRED_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_WIRED_PORT);
+		             _("'%s' is not a valid Ethernet port value"),
+		             priv->port);
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_WIRED_PORT);
 		return FALSE;
 	}
 
@@ -443,15 +625,18 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 		g_set_error (error,
 		             NM_SETTING_WIRED_ERROR,
 		             NM_SETTING_WIRED_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_WIRED_DUPLEX);
+		             _("'%s' is not a valid duplex value"),
+		             priv->duplex);
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_WIRED_DUPLEX);
 		return FALSE;
 	}
 
 	if (priv->device_mac_address && priv->device_mac_address->len != ETH_ALEN) {
-		g_set_error (error,
-		             NM_SETTING_WIRED_ERROR,
-		             NM_SETTING_WIRED_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_WIRED_MAC_ADDRESS);
+		g_set_error_literal (error,
+		                     NM_SETTING_WIRED_ERROR,
+		                     NM_SETTING_WIRED_ERROR_INVALID_PROPERTY,
+		                     _("is not a valid MAC address"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_WIRED_MAC_ADDRESS);
 		return FALSE;
 	}
 
@@ -463,25 +648,29 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 			g_set_error (error,
 			             NM_SETTING_WIRED_ERROR,
 			             NM_SETTING_WIRED_ERROR_INVALID_PROPERTY,
-			             NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST);
+			             _("'%s' is not a valid MAC address"),
+			             (const char *) mac_blacklist_iter->data);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST);
 			return FALSE;
 		}
 	}
 
 	if (   priv->s390_subchannels
 	    && !(priv->s390_subchannels->len == 3 || priv->s390_subchannels->len == 2)) {
-		g_set_error (error,
-		             NM_SETTING_WIRED_ERROR,
-		             NM_SETTING_WIRED_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_WIRED_S390_SUBCHANNELS);
+		g_set_error_literal (error,
+		                     NM_SETTING_WIRED_ERROR,
+		                     NM_SETTING_WIRED_ERROR_INVALID_PROPERTY,
+		                     _("property is invalid"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_WIRED_S390_SUBCHANNELS);
 		return FALSE;
 	}
 
 	if (priv->s390_nettype && !_nm_utils_string_in_list (priv->s390_nettype, valid_nettype)) {
-		g_set_error (error,
-			         NM_SETTING_WIRED_ERROR,
-			         NM_SETTING_WIRED_ERROR_INVALID_PROPERTY,
-			         NM_SETTING_WIRED_S390_NETTYPE);
+		g_set_error_literal (error,
+		                     NM_SETTING_WIRED_ERROR,
+		                     NM_SETTING_WIRED_ERROR_INVALID_PROPERTY,
+		                     _("property is invalid"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_WIRED_S390_NETTYPE);
 		return FALSE;
 	}
 
@@ -491,18 +680,21 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 		    || !strlen (value)
 		    || (strlen (value) > 200)) {
 			g_set_error (error,
-				         NM_SETTING_WIRED_ERROR,
-				         NM_SETTING_WIRED_ERROR_INVALID_PROPERTY,
-				         NM_SETTING_WIRED_S390_OPTIONS);
+			             NM_SETTING_WIRED_ERROR,
+			             NM_SETTING_WIRED_ERROR_INVALID_PROPERTY,
+			             _("invalid '%s' or its value '%s'"),
+			             key, value);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_WIRED_S390_OPTIONS);
 			return FALSE;
 		}
 	}
 
 	if (priv->cloned_mac_address && priv->cloned_mac_address->len != ETH_ALEN) {
-		g_set_error (error,
-		             NM_SETTING_WIRED_ERROR,
-		             NM_SETTING_WIRED_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_WIRED_CLONED_MAC_ADDRESS);
+		g_set_error_literal (error,
+		                     NM_SETTING_WIRED_ERROR,
+		                     NM_SETTING_WIRED_ERROR_INVALID_PROPERTY,
+		                     _("is not a valid MAC address"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_WIRED_CLONED_MAC_ADDRESS);
 		return FALSE;
 	}
 
@@ -514,7 +706,6 @@ nm_setting_wired_init (NMSettingWired *setting)
 {
 	NMSettingWiredPrivate *priv = NM_SETTING_WIRED_GET_PRIVATE (setting);
 
-	g_object_set (setting, NM_SETTING_NAME, NM_SETTING_WIRED_SETTING_NAME, NULL);
 	priv->s390_options = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
 }
 
@@ -535,10 +726,10 @@ finalize (GObject *object)
 	if (priv->cloned_mac_address)
 		g_byte_array_free (priv->cloned_mac_address, TRUE);
 
-	nm_utils_slist_free (priv->mac_address_blacklist, g_free);
+	g_slist_free_full (priv->mac_address_blacklist, g_free);
 
 	if (priv->s390_subchannels) {
-		g_ptr_array_foreach (priv->s390_subchannels, (GFunc) g_free, NULL);
+		g_ptr_array_set_free_func (priv->s390_subchannels, g_free);
 		g_ptr_array_free (priv->s390_subchannels, TRUE);
 	}
 
@@ -584,7 +775,7 @@ set_property (GObject *object, guint prop_id,
 		priv->cloned_mac_address = g_value_dup_boxed (value);
 		break;
 	case PROP_MAC_ADDRESS_BLACKLIST:
-		nm_utils_slist_free (priv->mac_address_blacklist, g_free);
+		g_slist_free_full (priv->mac_address_blacklist, g_free);
 		priv->mac_address_blacklist = g_value_dup_boxed (value);
 		break;
 	case PROP_MTU:
@@ -592,7 +783,7 @@ set_property (GObject *object, guint prop_id,
 		break;
 	case PROP_S390_SUBCHANNELS:
 		if (priv->s390_subchannels) {
-			g_ptr_array_foreach (priv->s390_subchannels, (GFunc) g_free, NULL);
+			g_ptr_array_set_free_func (priv->s390_subchannels, g_free);
 			g_ptr_array_free (priv->s390_subchannels, TRUE);
 		}
 		priv->s390_subchannels = g_value_dup_boxed (value);
@@ -680,8 +871,8 @@ nm_setting_wired_class_init (NMSettingWiredClass *setting_class)
 	 * NMSettingWired:port:
 	 *
 	 * Specific port type to use if multiple the device supports multiple
-	 * attachment methods.  One of 'tp' (Twisted Pair), 'aui' (Attachment Unit
-	 * Interface), 'bnc' (Thin Ethernet) or 'mii' (Media Independent Interface.
+	 * attachment methods.  One of "tp" (Twisted Pair), "aui" (Attachment Unit
+	 * Interface), "bnc" (Thin Ethernet) or "mii" (Media Independent Interface.
 	 * If the device supports only one port type, this setting is ignored.
 	 **/
 	g_object_class_install_property
@@ -695,13 +886,13 @@ nm_setting_wired_class_init (NMSettingWiredClass *setting_class)
 						  "Interface.  If the device supports only one port "
 						  "type, this setting is ignored.",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+						  G_PARAM_READWRITE));
 
 	/**
 	 * NMSettingWired:speed:
 	 *
-	 * If non-zero, request that the device use only the specified speed. 
-	 * In Mbit/s, ie 100 == 100Mbit/s.
+	 * If non-zero, request that the device use only the specified speed.  In
+	 * Mbit/s, ie 100 == 100Mbit/s.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_SPEED,
@@ -710,13 +901,13 @@ nm_setting_wired_class_init (NMSettingWiredClass *setting_class)
 						"If non-zero, request that the device use only the "
 						"specified speed.  In Mbit/s, ie 100 == 100Mbit/s.",
 						0, G_MAXUINT32, 0,
-						G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+						G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
 	/**
 	 * NMSettingWired:duplex:
 	 *
 	 * If specified, request that the device only use the specified duplex mode.
-	 * Either 'half' or 'full'.
+	 * Either "half" or "full".
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_DUPLEX,
@@ -725,14 +916,14 @@ nm_setting_wired_class_init (NMSettingWiredClass *setting_class)
 						  "If specified, request that the device only use the "
 						  "specified duplex mode.  Either 'half' or 'full'.",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+						  G_PARAM_READWRITE));
 
 	/**
-	 * NMSettingEthernet:auto-negotiate:
+	 * NMSettingWired:auto-negotiate:
 	 *
-	 * If TRUE, allow auto-negotiation of port speed and duplex mode.  If FALSE,
-	 * do not allow auto-negotiation, in which case the 'speed' and 'duplex'
-	 * properties should be set.
+	 * If %TRUE, allow auto-negotiation of port speed and duplex mode.  If
+	 * %FALSE, do not allow auto-negotiation, in which case the "speed" and
+	 * "duplex" properties should be set.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_AUTO_NEGOTIATE,
@@ -743,25 +934,25 @@ nm_setting_wired_class_init (NMSettingWiredClass *setting_class)
 						   "in which case the 'speed' and 'duplex' properties "
 						   "should be set.",
 						   TRUE,
-						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+						   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
 	/**
 	 * NMSettingWired:mac-address:
 	 *
-	 * If specified, this connection will only apply to the ethernet device
-	 * whose permanent MAC address matches. This property does not change the MAC address
-	 * of the device (i.e. MAC spoofing).
+	 * If specified, this connection will only apply to the Ethernet device
+	 * whose permanent MAC address matches. This property does not change the
+	 * MAC address of the device (i.e. MAC spoofing).
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_MAC_ADDRESS,
 		 _nm_param_spec_specialized (NM_SETTING_WIRED_MAC_ADDRESS,
 							   "Device MAC Address",
 							   "If specified, this connection will only apply to "
-							   "the ethernet device whose permanent MAC address matches.  "
+							   "the Ethernet device whose permanent MAC address matches.  "
 							   "This property does not change the MAC address "
 							   "of the device (i.e. MAC spoofing).",
 							   DBUS_TYPE_G_UCHAR_ARRAY,
-							   G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+							   G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE));
 
 	/**
 	 * NMSettingWired:cloned-mac-address:
@@ -777,14 +968,14 @@ nm_setting_wired_class_init (NMSettingWiredClass *setting_class)
 	                                     "this MAC address instead of its permanent MAC address.  "
 	                                     "This is known as MAC cloning or spoofing.",
 	                                     DBUS_TYPE_G_UCHAR_ARRAY,
-	                                     G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+	                                     G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE));
     
 	/**
 	 * NMSettingWired:mac-address-blacklist:
 	 *
-	 * If specified, this connection will never apply to the ethernet device
-	 * whose permanent MAC address matches an address in the list.  Each
-	 * MAC address is in the standard hex-digits-and-colons notation
+	 * If specified, this connection will never apply to the Ethernet device
+	 * whose permanent MAC address matches an address in the list.  Each MAC
+	 * address is in the standard hex-digits-and-colons notation
 	 * (00:11:22:33:44:55).
 	 **/
 	g_object_class_install_property
@@ -792,11 +983,11 @@ nm_setting_wired_class_init (NMSettingWiredClass *setting_class)
 		 _nm_param_spec_specialized (NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST,
 		                             "MAC Address Blacklist",
 		                             "If specified, this connection will never apply to "
-		                             "the ethernet device whose permanent MAC address matches "
+		                             "the Ethernet device whose permanent MAC address matches "
 		                             "an address in the list.  Each MAC address is in the "
 		                             "standard hex-digits-and-colons notation (00:11:22:33:44:55).",
 		                             DBUS_TYPE_G_LIST_OF_STRING,
-		                             G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_FUZZY_IGNORE));
+		                             G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE));
 
 	/**
 	 * NMSettingWired:mtu:
@@ -812,17 +1003,18 @@ nm_setting_wired_class_init (NMSettingWiredClass *setting_class)
 						"size or smaller, breaking larger packets up into "
 						"multiple Ethernet frames.",
 						0, G_MAXUINT32, 0,
-						G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_FUZZY_IGNORE));
+						G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE));
 
 	/**
 	 * NMSettingWired:s390-subchannels:
 	 *
 	 * Identifies specific subchannels that this network device uses for
-	 * communcation with z/VM or s390 host.  Like #NMSettingWired:mac-address
-	 * for non-z/VM devices, this property can be used to ensure this connection
-	 * only applies to the network device that uses these subchannels.  The
-	 * list should contain exactly 3 strings, and each string may only be
-	 * composed of hexadecimal characters and the period (.) character.
+	 * communication with z/VM or s390 host.  Like the
+	 * #NMSettingWired:mac-address property for non-z/VM devices, this property
+	 * can be used to ensure this connection only applies to the network device
+	 * that uses these subchannels.  The list should contain exactly 3 strings,
+	 * and each string may only be composed of hexadecimal characters and the
+	 * period (.) character.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_S390_SUBCHANNELS,
@@ -838,12 +1030,12 @@ nm_setting_wired_class_init (NMSettingWiredClass *setting_class)
 		                       "string may only be composed of hexadecimal "
 		                       "characters and the period (.) character.",
 		                       DBUS_TYPE_G_ARRAY_OF_STRING,
-		                       G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+		                       G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE));
 
 	/**
 	 * NMSettingWired:s390-nettype:
 	 *
-	 * s390 network device type; one of 'qeth', 'lcs', or 'ctc', representing
+	 * s390 network device type; one of "qeth", "lcs", or "ctc", representing
 	 * the different types of virtual network devices available on s390 systems.
 	 **/
 	g_object_class_install_property
@@ -854,14 +1046,14 @@ nm_setting_wired_class_init (NMSettingWiredClass *setting_class)
 						  "'ctc', representing the different types of virtual "
 						  "network devices available on s390 systems.",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+						  G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE));
 
 	/**
 	 * NMSettingWired:s390-options:
 	 *
 	 * Dictionary of key/value pairs of s390-specific device options.  Both keys
-	 * and values must be strings.  Allowed keys include 'portno', 'layer2',
-	 * 'portname', 'protocol', among others.  Key names must contain only
+	 * and values must be strings.  Allowed keys include "portno", "layer2",
+	 * "portname", "protocol", among others.  Key names must contain only
 	 * alphanumeric characters (ie, [a-zA-Z0-9]).
 	 **/
 	g_object_class_install_property
@@ -873,6 +1065,6 @@ nm_setting_wired_class_init (NMSettingWiredClass *setting_class)
 							   "strings.  Allowed keys include 'portno', "
 							   "'layer2', 'portname', 'protocol', among others.",
 							   DBUS_TYPE_G_MAP_OF_STRING,
-							   G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+							   G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE));
 }
 
diff --git a/libnm-util/nm-setting-wired.h b/libnm-util/nm-setting-wired.h
index e235d23c..9580b0a8 100644
--- a/libnm-util/nm-setting-wired.h
+++ b/libnm-util/nm-setting-wired.h
@@ -19,7 +19,7 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2007 - 2011 Red Hat, Inc.
+ * (C) Copyright 2007 - 2014 Red Hat, Inc.
  * (C) Copyright 2007 - 2008 Novell, Inc.
  */
 
@@ -90,7 +90,25 @@ const char *      nm_setting_wired_get_duplex           (NMSettingWired *setting
 gboolean          nm_setting_wired_get_auto_negotiate   (NMSettingWired *setting);
 const GByteArray *nm_setting_wired_get_mac_address      (NMSettingWired *setting);
 const GByteArray *nm_setting_wired_get_cloned_mac_address (NMSettingWired *setting);
-const GSList     *nm_setting_wired_get_mac_address_blacklist (NMSettingWired *setting);
+
+const GSList     *nm_setting_wired_get_mac_address_blacklist   (NMSettingWired *setting);
+NM_AVAILABLE_IN_0_9_10
+guint32           nm_setting_wired_get_num_mac_blacklist_items (NMSettingWired *setting);
+NM_AVAILABLE_IN_0_9_10
+const char *      nm_setting_wired_get_mac_blacklist_item      (NMSettingWired *setting,
+                                                                guint32 idx);
+NM_AVAILABLE_IN_0_9_10
+gboolean          nm_setting_wired_add_mac_blacklist_item      (NMSettingWired *setting,
+                                                                const char *mac);
+NM_AVAILABLE_IN_0_9_10
+void              nm_setting_wired_remove_mac_blacklist_item   (NMSettingWired *setting,
+                                                                guint32 idx);
+NM_AVAILABLE_IN_0_9_10
+gboolean          nm_setting_wired_remove_mac_blacklist_item_by_value (NMSettingWired *setting,
+                                                                       const char *mac);
+NM_AVAILABLE_IN_0_9_10
+void              nm_setting_wired_clear_mac_blacklist_items   (NMSettingWired *setting);
+
 guint32           nm_setting_wired_get_mtu              (NMSettingWired *setting);
 
 const GPtrArray * nm_setting_wired_get_s390_subchannels (NMSettingWired *setting);
@@ -105,9 +123,11 @@ const char *      nm_setting_wired_get_s390_option_by_key (NMSettingWired *setti
                                                            const char *key);
 gboolean          nm_setting_wired_add_s390_option      (NMSettingWired *setting,
                                                          const char *key,
-                                                         const char *item);
+                                                         const char *value);
 gboolean          nm_setting_wired_remove_s390_option   (NMSettingWired *setting,
                                                          const char *key);
+NM_AVAILABLE_IN_0_9_10
+const char **     nm_setting_wired_get_valid_s390_options (NMSettingWired *setting);
 
 G_END_DECLS
 
diff --git a/libnm-util/nm-setting-wireless-security.c b/libnm-util/nm-setting-wireless-security.c
index 9e4becca..40c56181 100644
--- a/libnm-util/nm-setting-wireless-security.c
+++ b/libnm-util/nm-setting-wireless-security.c
@@ -19,13 +19,15 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2007 - 2011 Red Hat, Inc.
+ * (C) Copyright 2007 - 2014 Red Hat, Inc.
  * (C) Copyright 2007 - 2008 Novell, Inc.
  */
 
 #include <config.h>
 #include <string.h>
 #include <dbus/dbus-glib.h>
+#include <glib/gi18n.h>
+
 #include "nm-setting-wireless-security.h"
 #include "nm-setting-8021x.h"
 #include "nm-param-spec-specialized.h"
@@ -36,17 +38,17 @@
 
 /**
  * SECTION:nm-setting-wireless-security
- * @short_description: Describes connection properties for WiFi networks that
+ * @short_description: Describes connection properties for Wi-Fi networks that
  * use WEP, LEAP, WPA or WPA2/RSN security
  * @include: nm-setting-wireless-security.h
  *
  * The #NMSettingWirelessSecurity object is a #NMSetting subclass that describes
- * properties necessary for connection to encrypted WiFi networks.
+ * properties necessary for connection to encrypted Wi-Fi networks.
  *
  * It's a good idea to read up on wpa_supplicant configuration before using this
  * setting extensively, since most of the options here correspond closely with
  * the relevant wpa_supplicant configuration options.  To get a better overview
- * of how WiFi security works, you may want to get copies of the following books.
+ * of how Wi-Fi security works, you may want to get copies of the following books.
  *
  *  802.11 Wireless Networks: The Definitive Guide, Second Edition
  *       Author: Matthew Gast
@@ -165,7 +167,7 @@ nm_setting_wireless_security_get_key_mgmt (NMSettingWirelessSecurity *setting)
  * @setting: the #NMSettingWirelessSecurity
  *
  * Returns: the number of security protocols this connection allows when
- * connecting to secure WiFi networks
+ * connecting to secure Wi-Fi networks
  **/
 guint32
 nm_setting_wireless_security_get_num_protos (NMSettingWirelessSecurity *setting)
@@ -200,9 +202,9 @@ nm_setting_wireless_security_get_proto (NMSettingWirelessSecurity *setting, guin
  * @setting: the #NMSettingWirelessSecurity
  * @proto: the protocol to add, one of "wpa" or "rsn"
  *
- * Adds a WiFi security protocol (one of "wpa" or "rsn") to the allowed list;
+ * Adds a Wi-Fi security protocol (one of "wpa" or "rsn") to the allowed list;
  * only protocols in this list will be used when finding and connecting to
- * the WiFi network specified by this connection.  For example, if the
+ * the Wi-Fi network specified by this connection.  For example, if the
  * protocol list contains only "wpa" but the access point for the SSID specified
  * by this connection only supports WPA2/RSN, the connection cannot be used
  * with the access point.
@@ -226,6 +228,7 @@ nm_setting_wireless_security_add_proto (NMSettingWirelessSecurity *setting, cons
 	}
 
 	priv->proto = g_slist_append (priv->proto, g_ascii_strdown (proto, -1));
+	g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_SECURITY_PROTO);
 	return TRUE;
 }
 
@@ -250,6 +253,39 @@ nm_setting_wireless_security_remove_proto (NMSettingWirelessSecurity *setting, g
 
 	g_free (elt->data);
 	priv->proto = g_slist_delete_link (priv->proto, elt);
+	g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_SECURITY_PROTO);
+}
+
+/**
+ * nm_setting_wireless_security_remove_proto_by_value:
+ * @setting: the #NMSettingWirelessSecurity
+ * @proto: the protocol to remove, one of "wpa" or "rsn"
+ *
+ * Removes a protocol from the allowed protocol list.
+ *
+ * Returns: %TRUE if the protocol was found and removed; %FALSE it it was not.
+ *
+ * Since: 0.9.10
+ **/
+gboolean
+nm_setting_wireless_security_remove_proto_by_value (NMSettingWirelessSecurity *setting,
+                                                    const char *proto)
+{
+	NMSettingWirelessSecurityPrivate *priv;
+	GSList *iter;
+
+	g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), FALSE);
+	g_return_val_if_fail (proto != NULL, FALSE);
+
+	priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting);
+	for (iter = priv->proto; iter; iter = g_slist_next (iter)) {
+		if (strcasecmp (proto, (char *) iter->data) == 0) {
+			priv->proto = g_slist_delete_link (priv->proto, iter);
+			g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_SECURITY_PROTO);
+			return TRUE;
+		}
+	}
+	return FALSE;
 }
 
 /**
@@ -267,8 +303,9 @@ nm_setting_wireless_security_clear_protos (NMSettingWirelessSecurity *setting)
 	g_return_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting));
 
 	priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting);
-	nm_utils_slist_free (priv->proto, g_free);
+	g_slist_free_full (priv->proto, g_free);
 	priv->proto = NULL;
+	g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_SECURITY_PROTO);
 }
 
 /**
@@ -311,8 +348,7 @@ nm_setting_wireless_security_get_pairwise (NMSettingWirelessSecurity *setting, g
 /**
  * nm_setting_wireless_security_add_pairwise:
  * @setting: the #NMSettingWirelessSecurity
- * @pairwise: the encryption algorithm to add, one of "wep40", "wep104",
- * "tkip", or "ccmp"
+ * @pairwise: the encryption algorithm to add, one of "tkip" or "ccmp"
  *
  * Adds an encryption algorithm to the list of allowed pairwise encryption
  * algorithms.  If the list is not empty, then only access points that support
@@ -338,6 +374,7 @@ nm_setting_wireless_security_add_pairwise (NMSettingWirelessSecurity *setting, c
 	}
 
 	priv->pairwise = g_slist_append (priv->pairwise, g_ascii_strdown (pairwise, -1));
+	g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_SECURITY_PAIRWISE);
 	return TRUE;
 }
 
@@ -363,6 +400,40 @@ nm_setting_wireless_security_remove_pairwise (NMSettingWirelessSecurity *setting
 
 	g_free (elt->data);
 	priv->pairwise = g_slist_delete_link (priv->pairwise, elt);
+	g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_SECURITY_PAIRWISE);
+}
+
+/**
+ * nm_setting_wireless_security_remove_pairwise_by_value:
+ * @setting: the #NMSettingWirelessSecurity
+ * @pairwise: the encryption algorithm to remove, one of "tkip" or "ccmp"
+ *
+ * Removes an encryption algorithm from the allowed pairwise encryption
+ * algorithm list.
+ *
+ * Returns: %TRUE if the encryption algorith was found and removed; %FALSE it it was not.
+ *
+ * Since: 0.9.10
+ **/
+gboolean
+nm_setting_wireless_security_remove_pairwise_by_value (NMSettingWirelessSecurity *setting,
+                                                       const char *pairwise)
+{
+	NMSettingWirelessSecurityPrivate *priv;
+	GSList *iter;
+
+	g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), FALSE);
+	g_return_val_if_fail (pairwise != NULL, FALSE);
+
+	priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting);
+	for (iter = priv->pairwise; iter; iter = g_slist_next (iter)) {
+		if (strcasecmp (pairwise, (char *) iter->data) == 0) {
+			priv->pairwise = g_slist_delete_link (priv->pairwise, iter);
+			g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_SECURITY_PAIRWISE);
+			return TRUE;
+		}
+	}
+	return FALSE;
 }
 
 /**
@@ -380,8 +451,9 @@ nm_setting_wireless_security_clear_pairwise (NMSettingWirelessSecurity *setting)
 	g_return_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting));
 
 	priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting);
-	nm_utils_slist_free (priv->pairwise, g_free);
+	g_slist_free_full (priv->pairwise, g_free);
 	priv->pairwise = NULL;
+	g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_SECURITY_PAIRWISE);
 }
 
 /**
@@ -451,6 +523,7 @@ nm_setting_wireless_security_add_group (NMSettingWirelessSecurity *setting, cons
 	}
 
 	priv->group = g_slist_append (priv->group, g_ascii_strdown (group, -1));
+	g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_SECURITY_GROUP);
 	return TRUE;
 }
 
@@ -476,6 +549,41 @@ nm_setting_wireless_security_remove_group (NMSettingWirelessSecurity *setting, g
 
 	g_free (elt->data);
 	priv->group = g_slist_delete_link (priv->group, elt);
+	g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_SECURITY_GROUP);
+}
+
+/**
+ * nm_setting_wireless_security_remove_group_by_value:
+ * @setting: the #NMSettingWirelessSecurity
+ * @group: the encryption algorithm to remove, one of "wep40", "wep104",
+ * "tkip", or "ccmp"
+ *
+ * Removes an encryption algorithm from the allowed groupwise encryption
+ * algorithm list.
+ *
+ * Returns: %TRUE if the algorithm was found and removed; %FALSE it it was not.
+ *
+ * Since: 0.9.10
+ **/
+gboolean
+nm_setting_wireless_security_remove_group_by_value (NMSettingWirelessSecurity *setting,
+                                                    const char *group)
+{
+	NMSettingWirelessSecurityPrivate *priv;
+	GSList *iter;
+
+	g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), FALSE);
+	g_return_val_if_fail (group != NULL, FALSE);
+
+	priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting);
+	for (iter = priv->group; iter; iter = g_slist_next (iter)) {
+		if (strcasecmp (group, (char *) iter->data) == 0) {
+			priv->group = g_slist_delete_link (priv->group, iter);
+			g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_SECURITY_GROUP);
+			return TRUE;
+		}
+	}
+	return FALSE;
 }
 
 /**
@@ -493,8 +601,9 @@ nm_setting_wireless_security_clear_groups (NMSettingWirelessSecurity *setting)
 	g_return_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting));
 
 	priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting);
-	nm_utils_slist_free (priv->group, g_free);
+	g_slist_free_full (priv->group, g_free);
 	priv->group = NULL;
+	g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_SECURITY_GROUP);
 }
 
 /**
@@ -621,18 +730,22 @@ nm_setting_wireless_security_set_wep_key (NMSettingWirelessSecurity *setting, gu
 	case 0:
 		g_free (priv->wep_key0);
 		priv->wep_key0 = g_strdup (key);
+		g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_SECURITY_WEP_KEY0);
 		break;
 	case 1:
 		g_free (priv->wep_key1);
 		priv->wep_key1 = g_strdup (key);
+		g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_SECURITY_WEP_KEY1);
 		break;
 	case 2:
 		g_free (priv->wep_key2);
 		priv->wep_key2 = g_strdup (key);
+		g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_SECURITY_WEP_KEY2);
 		break;
 	case 3:
 		g_free (priv->wep_key3);
 		priv->wep_key3 = g_strdup (key);
+		g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_SECURITY_WEP_KEY3);
 		break;
 	default:
 		g_assert_not_reached ();
@@ -703,10 +816,6 @@ need_secrets (NMSetting *setting)
 	GPtrArray *secrets;
 
 	secrets = g_ptr_array_sized_new (4);
-	if (!secrets) {
-		g_warning ("Not enough memory to create required secrets array.");
-		return NULL;
-	}
 
 	g_assert (priv->key_mgmt);
 
@@ -767,15 +876,6 @@ no_secrets:
 	return NULL;
 }
 
-static gint
-find_setting_by_name (gconstpointer a, gconstpointer b)
-{
-	NMSetting *setting = NM_SETTING (a);
-	const char *str = (const char *) b;
-
-	return strcmp (nm_setting_get_name (setting), str);
-}
-
 static gboolean
 verify (NMSetting *setting, GSList *all_settings, GError **error)
 {
@@ -784,14 +884,15 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 	const char *valid_key_mgmt[] = { "none", "ieee8021x", "wpa-none", "wpa-psk", "wpa-eap", NULL };
 	const char *valid_auth_algs[] = { "open", "shared", "leap", NULL };
 	const char *valid_protos[] = { "wpa", "rsn", NULL };
-	const char *valid_pairwise[] = { "wep40", "wep104", "tkip", "ccmp", NULL };
+	const char *valid_pairwise[] = { "tkip", "ccmp", NULL };
 	const char *valid_groups[] = { "wep40", "wep104", "tkip", "ccmp", NULL };
 
 	if (!priv->key_mgmt) {
-		g_set_error (error,
-		             NM_SETTING_WIRELESS_SECURITY_ERROR,
-		             NM_SETTING_WIRELESS_SECURITY_ERROR_MISSING_PROPERTY,
-		             NM_SETTING_WIRELESS_SECURITY_KEY_MGMT);
+		g_set_error_literal (error,
+		                     NM_SETTING_WIRELESS_SECURITY_ERROR,
+		                     NM_SETTING_WIRELESS_SECURITY_ERROR_MISSING_PROPERTY,
+		                     _("property is missing"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT);
 		return FALSE;
 	}
 
@@ -799,7 +900,9 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 		g_set_error (error,
 		             NM_SETTING_WIRELESS_SECURITY_ERROR,
 		             NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_WIRELESS_SECURITY_KEY_MGMT);
+		             _("'%s' is not a valid value for the property"),
+		             priv->key_mgmt);
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT);
 		return FALSE;
 	}
 
@@ -809,42 +912,49 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 			g_set_error (error,
 			             NM_SETTING_WIRELESS_SECURITY_ERROR,
 			             NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_802_1X,
-			             NM_SETTING_WIRELESS_SECURITY_AUTH_ALG);
+			             _("'%s' security requires '%s=%s'"),
+			             "leap", NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x");
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_AUTH_ALG);
 			return FALSE;
 		}
 		if (!priv->leap_username) {
-			g_set_error (error,
-			             NM_SETTING_WIRELESS_SECURITY_ERROR,
-			             NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_USERNAME,
-			             NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME);
+			g_set_error_literal (error,
+			                     NM_SETTING_WIRELESS_SECURITY_ERROR,
+			                     NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_USERNAME,
+			                     _("property is empty"));
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME);
 			return FALSE;
 		}
 		if (priv->leap_password && !strlen (priv->leap_password)) {
-			g_set_error (error,
-			             NM_SETTING_WIRELESS_SECURITY_ERROR,
-			             NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY,
-			             NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD);
+			g_set_error_literal (error,
+			                     NM_SETTING_WIRELESS_SECURITY_ERROR,
+			                     NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY,
+			                     _("property is empty"));
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD);
 			return FALSE;
 		}
 	} else {
 		if (   (strcmp (priv->key_mgmt, "ieee8021x") == 0)
 		    || (strcmp (priv->key_mgmt, "wpa-eap") == 0)) {
 			/* Need an 802.1x setting too */
-			if (!g_slist_find_custom (all_settings, NM_SETTING_802_1X_SETTING_NAME, find_setting_by_name)) {
+			if (!nm_setting_find_in_list (all_settings, NM_SETTING_802_1X_SETTING_NAME)) {
 				g_set_error (error,
 				             NM_SETTING_WIRELESS_SECURITY_ERROR,
 				             NM_SETTING_WIRELESS_SECURITY_ERROR_MISSING_802_1X_SETTING,
-				             NULL);
+				             _("'%s' security requires '%s' setting presence"),
+				             priv->key_mgmt, NM_SETTING_802_1X_SETTING_NAME);
+				g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT);
 				return FALSE;
 			}
 		}
 	}
 
 	if (priv->leap_username && !strlen (priv->leap_username)) {
-		g_set_error (error,
-		             NM_SETTING_WIRELESS_SECURITY_ERROR,
-		             NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME);
+		g_set_error_literal (error,
+		                     NM_SETTING_WIRELESS_SECURITY_ERROR,
+		                     NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY,
+		                     _("property is empty"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME);
 		return FALSE;
 	}
 
@@ -852,68 +962,78 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 		g_set_error (error,
 		             NM_SETTING_WIRELESS_SECURITY_ERROR,
 		             NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX);
+		             _("'%d' value is out of range <0-3>"),
+		             priv->wep_tx_keyidx);
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX);
 		return FALSE;
 	}
 
 	if (priv->wep_key_type > NM_WEP_KEY_TYPE_LAST) {
-		g_set_error (error,
-		             NM_SETTING_WIRELESS_SECURITY_ERROR,
-		             NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE);
+		g_set_error_literal (error,
+		                     NM_SETTING_WIRELESS_SECURITY_ERROR,
+		                     NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY,
+		                     _("property is invalid"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE);
 		return FALSE;
 	}
 
 	if (priv->wep_key0 && !nm_utils_wep_key_valid (priv->wep_key0, priv->wep_key_type)) {
-		g_set_error (error,
-		             NM_SETTING_WIRELESS_SECURITY_ERROR,
-		             NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_WIRELESS_SECURITY_WEP_KEY0);
+		g_set_error_literal (error,
+		                     NM_SETTING_WIRELESS_SECURITY_ERROR,
+		                     NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY,
+		                     _("property is invalid"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_WEP_KEY0);
 		return FALSE;
 	}
 	if (priv->wep_key1 && !nm_utils_wep_key_valid (priv->wep_key1, priv->wep_key_type)) {
-		g_set_error (error,
-		             NM_SETTING_WIRELESS_SECURITY_ERROR,
-		             NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_WIRELESS_SECURITY_WEP_KEY1);
+		g_set_error_literal (error,
+		                     NM_SETTING_WIRELESS_SECURITY_ERROR,
+		                     NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY,
+		                     _("property is invalid"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_WEP_KEY1);
 		return FALSE;
 	}
 	if (priv->wep_key2 && !nm_utils_wep_key_valid (priv->wep_key2, priv->wep_key_type)) {
-		g_set_error (error,
-		             NM_SETTING_WIRELESS_SECURITY_ERROR,
-		             NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_WIRELESS_SECURITY_WEP_KEY2);
+		g_set_error_literal (error,
+		                     NM_SETTING_WIRELESS_SECURITY_ERROR,
+		                     NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY,
+		                     _("property is invalid"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_WEP_KEY2);
 		return FALSE;
 	}
 	if (priv->wep_key3 && !nm_utils_wep_key_valid (priv->wep_key3, priv->wep_key_type)) {
-		g_set_error (error,
-		             NM_SETTING_WIRELESS_SECURITY_ERROR,
-		             NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_WIRELESS_SECURITY_WEP_KEY3);
+		g_set_error_literal (error,
+		                     NM_SETTING_WIRELESS_SECURITY_ERROR,
+		                     NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY,
+		                     _("property is invalid"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_WEP_KEY3);
 		return FALSE;
 	}
 
 	if (priv->auth_alg && !_nm_utils_string_in_list (priv->auth_alg, valid_auth_algs)) {
-		g_set_error (error,
-		             NM_SETTING_WIRELESS_SECURITY_ERROR,
-		             NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_WIRELESS_SECURITY_AUTH_ALG);
+		g_set_error_literal (error,
+		                     NM_SETTING_WIRELESS_SECURITY_ERROR,
+		                     NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY,
+		                     _("property is invalid"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_AUTH_ALG);
 		return FALSE;
 	}
 
 	if (priv->psk && !nm_utils_wpa_psk_valid (priv->psk)) {
-		g_set_error (error,
-		             NM_SETTING_WIRELESS_SECURITY_ERROR,
-		             NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_WIRELESS_SECURITY_PSK);
+		g_set_error_literal (error,
+		                     NM_SETTING_WIRELESS_SECURITY_ERROR,
+		                     NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY,
+		                     _("property is invalid"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_PSK);
 		return FALSE;
 	}
 
 	if (priv->proto && !_nm_utils_string_slist_validate (priv->proto, valid_protos)) {
-		g_set_error (error,
-		             NM_SETTING_WIRELESS_SECURITY_ERROR,
-		             NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_WIRELESS_SECURITY_PROTO);
+		g_set_error_literal (error,
+		                     NM_SETTING_WIRELESS_SECURITY_ERROR,
+		                     NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY,
+		                     _("property is invalid"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_PROTO);
 		return FALSE;
 	}
 
@@ -939,23 +1059,27 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 				g_set_error (error,
 				             NM_SETTING_WIRELESS_SECURITY_ERROR,
 				             NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY,
-				             NM_SETTING_WIRELESS_SECURITY_PAIRWISE);
+				             _("'%s' connections require '%s' in this property"),
+				             NM_SETTING_WIRELESS_MODE_ADHOC, "none");
+				g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_PAIRWISE);
 				return FALSE;
 			}
 		} else if (!_nm_utils_string_slist_validate (priv->pairwise, valid_pairwise)) {
-			g_set_error (error,
-			             NM_SETTING_WIRELESS_SECURITY_ERROR,
-			             NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY,
-			             NM_SETTING_WIRELESS_SECURITY_PAIRWISE);
+			g_set_error_literal (error,
+			                     NM_SETTING_WIRELESS_SECURITY_ERROR,
+			                     NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY,
+			                    _("property is invalid"));
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_PAIRWISE);
 			return FALSE;
 		}
 	}
 
 	if (priv->group && !_nm_utils_string_slist_validate (priv->group, valid_groups)) {
-		g_set_error (error,
-		             NM_SETTING_WIRELESS_SECURITY_ERROR,
-		             NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_WIRELESS_SECURITY_GROUP);
+		g_set_error_literal (error,
+		                     NM_SETTING_WIRELESS_SECURITY_ERROR,
+		                     NM_SETTING_WIRELESS_SECURITY_ERROR_INVALID_PROPERTY,
+		                     _("property is invalid"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_GROUP);
 		return FALSE;
 	}
 
@@ -965,7 +1089,9 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 			g_set_error (error,
 			             NM_SETTING_WIRELESS_SECURITY_ERROR,
 			             NM_SETTING_WIRELESS_SECURITY_ERROR_SHARED_KEY_REQUIRES_WEP,
-			             NM_SETTING_WIRELESS_SECURITY_AUTH_ALG);
+			             _("'%s' can only be used with '%s=%s' (WEP)"),
+			             "shared", NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "none");
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_AUTH_ALG);
 			return FALSE;
 		}
 	}
@@ -1028,7 +1154,6 @@ set_secret_flags (NMSetting *setting,
 static void
 nm_setting_wireless_security_init (NMSettingWirelessSecurity *setting)
 {
-	g_object_set (setting, NM_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NULL);
 }
 
 static void
@@ -1049,9 +1174,9 @@ finalize (GObject *object)
 	g_free (priv->psk);
 	g_free (priv->leap_password);
 
-	nm_utils_slist_free (priv->proto, g_free);
-	nm_utils_slist_free (priv->pairwise, g_free);
-	nm_utils_slist_free (priv->group, g_free);
+	g_slist_free_full (priv->proto, g_free);
+	g_slist_free_full (priv->pairwise, g_free);
+	g_slist_free_full (priv->group, g_free);
 
 	G_OBJECT_CLASS (nm_setting_wireless_security_parent_class)->finalize (object);
 }
@@ -1079,15 +1204,15 @@ set_property (GObject *object, guint prop_id,
 		priv->auth_alg = str ? g_ascii_strdown (str, -1) : NULL;
 		break;
 	case PROP_PROTO:
-		nm_utils_slist_free (priv->proto, g_free);
+		g_slist_free_full (priv->proto, g_free);
 		priv->proto = g_value_dup_boxed (value);
 		break;
 	case PROP_PAIRWISE:
-		nm_utils_slist_free (priv->pairwise, g_free);
+		g_slist_free_full (priv->pairwise, g_free);
 		priv->pairwise = g_value_dup_boxed (value);
 		break;
 	case PROP_GROUP:
-		nm_utils_slist_free (priv->group, g_free);
+		g_slist_free_full (priv->group, g_free);
 		priv->group = g_value_dup_boxed (value);
 		break;
 	case PROP_LEAP_USERNAME:
@@ -1095,16 +1220,20 @@ set_property (GObject *object, guint prop_id,
 		priv->leap_username = g_value_dup_string (value);
 		break;
 	case PROP_WEP_KEY0:
-		nm_setting_wireless_security_set_wep_key (setting, 0, g_value_get_string (value));
+		g_free (priv->wep_key0);
+		priv->wep_key0 = g_value_dup_string (value);
 		break;
 	case PROP_WEP_KEY1:
-		nm_setting_wireless_security_set_wep_key (setting, 1, g_value_get_string (value));
+		g_free (priv->wep_key1);
+		priv->wep_key1 = g_value_dup_string (value);
 		break;
 	case PROP_WEP_KEY2:
-		nm_setting_wireless_security_set_wep_key (setting, 2, g_value_get_string (value));
+		g_free (priv->wep_key2);
+		priv->wep_key2 = g_value_dup_string (value);
 		break;
 	case PROP_WEP_KEY3:
-		nm_setting_wireless_security_set_wep_key (setting, 3, g_value_get_string (value));
+		g_free (priv->wep_key3);
+		priv->wep_key3 = g_value_dup_string (value);
 		break;
 	case PROP_WEP_KEY_FLAGS:
 		priv->wep_key_flags = g_value_get_uint (value);
@@ -1219,10 +1348,10 @@ nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *setting
 	/**
 	 * NMSettingWirelessSecurity:key-mgmt:
 	 *
-	 * Key management used for the connection.  One of 'none' (WEP), 'ieee8021x'
-	 * (Dynamic WEP), 'wpa-none' (Ad-Hoc WPA-PSK), 'wpa-psk' (infrastructure
-	 * WPA-PSK), or 'wpa-eap' (WPA-Enterprise).  This property must be set for
-	 * any WiFi connection that uses security.
+	 * Key management used for the connection.  One of "none" (WEP), "ieee8021x"
+	 * (Dynamic WEP), "wpa-none" (Ad-Hoc WPA-PSK), "wpa-psk" (infrastructure
+	 * WPA-PSK), or "wpa-eap" (WPA-Enterprise).  This property must be set for
+	 * any Wi-Fi connection that uses security.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_KEY_MGMT,
@@ -1232,14 +1361,14 @@ nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *setting
 						  "'none' (WEP), 'ieee8021x' (Dynamic WEP), 'wpa-none' "
 						  "(WPA-PSK Ad-Hoc), 'wpa-psk' (infrastructure WPA-PSK), "
 						  "or 'wpa-eap' (WPA-Enterprise).  This property must "
-						  "be set for any WiFi connection that uses security.",
+						  "be set for any Wi-Fi connection that uses security.",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_REQUIRED));
+						  G_PARAM_READWRITE | NM_SETTING_PARAM_REQUIRED));
 
 	/**
 	 * NMSettingWirelessSecurity:wep-tx-keyidx:
 	 *
-	 * When static WEP is used (ie, key-mgmt = 'none') and a non-default WEP key
+	 * When static WEP is used (ie, key-mgmt = "none") and a non-default WEP key
 	 * index is used by the AP, put that WEP key index here.  Valid values are 0
 	 * (default key) through 3.  Note that some consumer access points (like the
 	 * Linksys WRT54G) number the keys 1 - 4.
@@ -1254,16 +1383,16 @@ nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *setting
 						"through 3.  Note that some consumer access points "
 						"(like the Linksys WRT54G) number the keys 1 - 4.",
 						0, 3, 0,
-						G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+						G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
 	/**
 	 * NMSettingWirelessSecurity:auth-alg:
 	 *
-	 * When WEP is used (ie, key-mgmt = 'none' or 'ieee8021x') indicate the
-	 * 802.11 authentication algorithm required by the AP here.  One of 'open'
-	 * for Open System, 'shared' for Shared Key, or 'leap' for Cisco LEAP.
-	 * When using Cisco LEAP (ie, key-mgmt = 'ieee8021x' and auth-alg = 'leap')
-	 * the 'leap-username' and 'leap-password' properties must be specified.
+	 * When WEP is used (ie, key-mgmt = "none" or "ieee8021x") indicate the
+	 * 802.11 authentication algorithm required by the AP here.  One of "open"
+	 * for Open System, "shared" for Shared Key, or "leap" for Cisco LEAP.  When
+	 * using Cisco LEAP (ie, key-mgmt = "ieee8021x" and auth-alg = "leap") the
+	 * "leap-username" and "leap-password" properties must be specified.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_AUTH_ALG,
@@ -1277,13 +1406,13 @@ nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *setting
 						  "'ieee8021x' and auth-alg = 'leap') the 'leap-username' "
 						  "and 'leap-password' properties must be specified.",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+						  G_PARAM_READWRITE));
 
 	/**
 	 * NMSettingWirelessSecurity:proto:
 	 *
 	 * List of strings specifying the allowed WPA protocol versions to use.
-	 * Each element may be one 'wpa' (allow WPA) or 'rsn' (allow WPA2/RSN).  If
+	 * Each element may be one "wpa" (allow WPA) or "rsn" (allow WPA2/RSN).  If
 	 * not specified, both WPA and RSN connections are allowed.
 	 **/
 	g_object_class_install_property
@@ -1296,15 +1425,15 @@ nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *setting
 							   "WPA2/RSN).  If not specified, both WPA and RSN "
 							   "connections are allowed.",
 							   DBUS_TYPE_G_LIST_OF_STRING,
-							   G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+							   G_PARAM_READWRITE));
 
 	/**
 	 * NMSettingWirelessSecurity:pairwise:
 	 *
 	 * A list of pairwise encryption algorithms which prevents connections to
-	 * Wi-Fi networks that do not utilize one of the algorithms in the list.  For
-	 * maximum compatibility leave this property empty.  Each list element may
-	 * be one of 'wep40', 'wep104', 'tkip', or 'ccmp'.
+	 * Wi-Fi networks that do not utilize one of the algorithms in the list.
+	 * For maximum compatibility leave this property empty.  Each list element
+	 * may be one of "tkip" or "ccmp".
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_PAIRWISE,
@@ -1314,10 +1443,10 @@ nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *setting
 		                       "prevents connections to Wi-Fi networks that do "
 		                       "not utilize one of the algorithms in the list. "
 		                       "For maximum compatibility leave this property "
-		                       "empty.  Each list element may be one of 'wep40', "
-		                       "'wep104', 'tkip' or 'ccmp'.",
+		                       "empty.  Each list element may be one of 'tkip' "
+		                       "or 'ccmp'.",
 		                       DBUS_TYPE_G_LIST_OF_STRING,
-		                       G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+		                       G_PARAM_READWRITE));
 
 	/**
 	 * NMSettingWirelessSecurity:group:
@@ -1325,7 +1454,7 @@ nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *setting
 	 * A list of group/broadcast encryption algorithms which prevents
 	 * connections to Wi-Fi networks that do not utilize one of the algorithms
 	 * in the list.  For maximum compatibility leave this property empty.  Each
-	 * list element may be one of 'wep40', 'wep104', 'tkip', or 'ccmp'.
+	 * list element may be one of "wep40", "wep104", "tkip", or "ccmp".
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_GROUP,
@@ -1338,13 +1467,13 @@ nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *setting
 		                       "property empty.  Each list element may be one "
 		                       " of 'wep40', 'wep104', 'tkip', or 'ccmp'.",
 		                       DBUS_TYPE_G_LIST_OF_STRING,
-		                       G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+		                       G_PARAM_READWRITE));
 
 	/**
 	 * NMSettingWirelessSecurity:leap-username:
 	 *
 	 * The login username for legacy LEAP connections (ie, key-mgmt =
-	 * 'ieee8021x' and auth-alg = 'leap').
+	 * "ieee8021x" and auth-alg = "leap").
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_LEAP_USERNAME,
@@ -1353,13 +1482,13 @@ nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *setting
 						  "The login username for legacy LEAP connections "
 						  "(ie, key-mgmt = 'ieee8021x' and auth-alg = 'leap').",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+						  G_PARAM_READWRITE));
 
 	/**
 	 * NMSettingWirelessSecurity:wep-key0:
 	 *
 	 * Index 0 WEP key.  This is the WEP key used in most networks.  See the
-	 * 'wep-key-type' property for a description of how this key is interpreted.
+	 * "wep-key-type" property for a description of how this key is interpreted.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_WEP_KEY0,
@@ -1369,13 +1498,13 @@ nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *setting
 						  "networks.  See the 'wep-key-type' property for a "
 						  "description of how this key is interpreted.",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET));
+						  G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET));
 
 	/**
 	 * NMSettingWirelessSecurity:wep-key1:
 	 *
 	 * Index 1 WEP key.  This WEP index is not used by most networks.  See the
-	 * 'wep-key-type' property for a description of how this key is interpreted.
+	 * "wep-key-type" property for a description of how this key is interpreted.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_WEP_KEY1,
@@ -1385,13 +1514,13 @@ nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *setting
 						  "networks.  See the 'wep-key-type' property for a "
 						  "description of how this key is interpreted.",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET));
+						  G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET));
 
 	/**
 	 * NMSettingWirelessSecurity:wep-key2:
 	 *
 	 * Index 2 WEP key.  This WEP index is not used by most networks.  See the
-	 * 'wep-key-type' property for a description of how this key is interpreted.
+	 * "wep-key-type" property for a description of how this key is interpreted.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_WEP_KEY2,
@@ -1401,13 +1530,13 @@ nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *setting
 						  "networks.  See the 'wep-key-type' property for a "
 						  "description of how this key is interpreted.",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET));
+						  G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET));
 
 	/**
 	 * NMSettingWirelessSecurity:wep-key3:
 	 *
 	 * Index 3 WEP key.  This WEP index is not used by most networks.  See the
-	 * 'wep-key-type' property for a description of how this key is interpreted.
+	 * "wep-key-type" property for a description of how this key is interpreted.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_WEP_KEY3,
@@ -1417,12 +1546,14 @@ nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *setting
 						  "networks.  See the 'wep-key-type' property for a "
 						  "description of how this key is interpreted.",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET));
+						  G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET));
 
 	/**
 	 * NMSettingWirelessSecurity:wep-key-flags:
 	 *
-	 * Flags indicating how to handle #NMSettingWirelessSecurity WEP keys.
+	 * Flags indicating how to handle the #NMSettingWirelessSecurity:wep-key0,
+	 * #NMSettingWirelessSecurity:wep-key1, #NMSettingWirelessSecurity:wep-key2,
+	 * and #NMSettingWirelessSecurity:wep-key3 properties.
 	 **/
 	g_object_class_install_property (object_class, PROP_WEP_KEY_FLAGS,
 		 g_param_spec_uint (NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS,
@@ -1431,7 +1562,7 @@ nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *setting
 		                    NM_SETTING_SECRET_FLAG_NONE,
 		                    NM_SETTING_SECRET_FLAGS_ALL,
 		                    NM_SETTING_SECRET_FLAG_NONE,
-		                    G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+		                    G_PARAM_READWRITE));
 
 	/**
 	 * NMSettingWirelessSecurity:psk:
@@ -1439,9 +1570,9 @@ nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *setting
 	 * Pre-Shared-Key for WPA networks.  If the key is 64-characters long, it
 	 * must contain only hexadecimal characters and is interpreted as a
 	 * hexadecimal WPA key.  Otherwise, the key must be between 8 and 63 ASCII
-	 * characters (as specified in the 802.11i standard) and is interpreted as
-	 * a WPA passphrase, and is hashed to derive the actual WPA-PSK used when
-	 * connecting to the WiFi network.
+	 * characters (as specified in the 802.11i standard) and is interpreted as a
+	 * WPA passphrase, and is hashed to derive the actual WPA-PSK used when
+	 * connecting to the Wi-Fi network.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_PSK,
@@ -1454,14 +1585,15 @@ nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *setting
 						  "ASCII characters (as specified in the 802.11i standard) "
 						  "and is interpreted as a WPA passphrase, and is hashed "
 						  "to derive the actual WPA-PSK used when connecting to "
-						  "the WiFi network.",
+						  "the Wi-Fi network.",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET));
+						  G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET));
 
 	/**
 	 * NMSettingWirelessSecurity:psk-flags:
 	 *
-	 * Flags indicating how to handle #NMSettingWirelessSecurity:psk
+	 * Flags indicating how to handle the #NMSettingWirelessSecurity:psk
+	 * property.
 	 **/
 	g_object_class_install_property (object_class, PROP_PSK_FLAGS,
 		 g_param_spec_uint (NM_SETTING_WIRELESS_SECURITY_PSK_FLAGS,
@@ -1470,13 +1602,13 @@ nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *setting
 		                    NM_SETTING_SECRET_FLAG_NONE,
 		                    NM_SETTING_SECRET_FLAGS_ALL,
 		                    NM_SETTING_SECRET_FLAG_NONE,
-		                    G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+		                    G_PARAM_READWRITE));
 
 	/**
 	 * NMSettingWirelessSecurity:leap-password:
 	 *
 	 * The login password for legacy LEAP connections (ie, key-mgmt =
-	 * 'ieee8021x' and auth-alg = 'leap').
+	 * "ieee8021x" and auth-alg = "leap").
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_LEAP_PASSWORD,
@@ -1485,12 +1617,13 @@ nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *setting
 						  "The login password for legacy LEAP connections "
 						  "(ie, key-mgmt = 'ieee8021x' and auth-alg = 'leap').",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET));
+						  G_PARAM_READWRITE | NM_SETTING_PARAM_SECRET));
 
 	/**
 	 * NMSettingWirelessSecurity:leap-password-flags:
 	 *
-	 * Flags indicating how to handle #NMSettingWirelessSecurity:leap-password.
+	 * Flags indicating how to handle the
+	 * #NMSettingWirelessSecurity:leap-password property.
 	 **/
 	g_object_class_install_property (object_class, PROP_LEAP_PASSWORD_FLAGS,
 		 g_param_spec_uint (NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD_FLAGS,
@@ -1499,17 +1632,17 @@ nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *setting
 		                    NM_SETTING_SECRET_FLAG_NONE,
 		                    NM_SETTING_SECRET_FLAGS_ALL,
 		                    NM_SETTING_SECRET_FLAG_NONE,
-		                    G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+		                    G_PARAM_READWRITE));
 
 	/**
 	 * NMSettingWirelessSecurity:wep-key-type:
 	 *
-	 * Controls the interpretation of WEP keys.  Allowed values are those given
-	 * by %NMWepKeyType.  If set to 1 and the keys are hexadecimal, they must be
-	 * either 10 or 26 characters in length.  If set to 1 and the keys are
-	 * ASCII keys, they must be either 5 or 13 characters in length.  If set to
-	 * 2, the passphrase is hashed using the de-facto MD5 method to derive the
-	 * actual WEP key.
+	 * Controls the interpretation of WEP keys.  Allowed values are
+	 * %NM_WEP_KEY_TYPE_KEY, in which case the key is either a 10- or
+	 * 26-character hexadecimal string, or a 5- or 13-character ASCII password;
+	 * or %NM_WEP_KEY_TYPE_PASSPHRASE, in which case the passphrase is provided
+	 * as a string and will be hashed using the de-facto MD5 method to derive
+	 * the actual WEP key.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_WEP_KEY_TYPE,
@@ -1526,5 +1659,5 @@ nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *setting
 						NM_WEP_KEY_TYPE_UNKNOWN,
 						NM_WEP_KEY_TYPE_LAST,
 						NM_WEP_KEY_TYPE_UNKNOWN,
-						G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+						G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 }
diff --git a/libnm-util/nm-setting-wireless-security.h b/libnm-util/nm-setting-wireless-security.h
index d9e972c0..df5d77ab 100644
--- a/libnm-util/nm-setting-wireless-security.h
+++ b/libnm-util/nm-setting-wireless-security.h
@@ -19,7 +19,7 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2007 - 2011 Red Hat, Inc.
+ * (C) Copyright 2007 - 2014 Red Hat, Inc.
  * (C) Copyright 2007 - 2008 Novell, Inc.
  */
 
@@ -137,23 +137,29 @@ NMSetting * nm_setting_wireless_security_new               (void);
 
 const char *nm_setting_wireless_security_get_key_mgmt      (NMSettingWirelessSecurity *setting);
 
-guint32     nm_setting_wireless_security_get_num_protos    (NMSettingWirelessSecurity *setting);
-const char *nm_setting_wireless_security_get_proto         (NMSettingWirelessSecurity *setting, guint32 i);
-gboolean    nm_setting_wireless_security_add_proto         (NMSettingWirelessSecurity *setting, const char *proto);
-void        nm_setting_wireless_security_remove_proto      (NMSettingWirelessSecurity *setting, guint32 i);
-void        nm_setting_wireless_security_clear_protos      (NMSettingWirelessSecurity *setting);
-
-guint32     nm_setting_wireless_security_get_num_pairwise  (NMSettingWirelessSecurity *setting);
-const char *nm_setting_wireless_security_get_pairwise      (NMSettingWirelessSecurity *setting, guint32 i);
-gboolean    nm_setting_wireless_security_add_pairwise      (NMSettingWirelessSecurity *setting, const char *pairwise);
-void        nm_setting_wireless_security_remove_pairwise   (NMSettingWirelessSecurity *setting, guint32 i);
-void        nm_setting_wireless_security_clear_pairwise    (NMSettingWirelessSecurity *setting);
-
-guint32     nm_setting_wireless_security_get_num_groups    (NMSettingWirelessSecurity *setting);
-const char *nm_setting_wireless_security_get_group         (NMSettingWirelessSecurity *setting, guint32 i);
-gboolean    nm_setting_wireless_security_add_group         (NMSettingWirelessSecurity *setting, const char *group);
-void        nm_setting_wireless_security_remove_group      (NMSettingWirelessSecurity *setting, guint32 i);
-void        nm_setting_wireless_security_clear_groups      (NMSettingWirelessSecurity *setting);
+guint32     nm_setting_wireless_security_get_num_protos        (NMSettingWirelessSecurity *setting);
+const char *nm_setting_wireless_security_get_proto             (NMSettingWirelessSecurity *setting, guint32 i);
+gboolean    nm_setting_wireless_security_add_proto             (NMSettingWirelessSecurity *setting, const char *proto);
+void        nm_setting_wireless_security_remove_proto          (NMSettingWirelessSecurity *setting, guint32 i);
+NM_AVAILABLE_IN_0_9_10
+gboolean    nm_setting_wireless_security_remove_proto_by_value (NMSettingWirelessSecurity *setting, const char *proto);
+void        nm_setting_wireless_security_clear_protos          (NMSettingWirelessSecurity *setting);
+
+guint32     nm_setting_wireless_security_get_num_pairwise         (NMSettingWirelessSecurity *setting);
+const char *nm_setting_wireless_security_get_pairwise             (NMSettingWirelessSecurity *setting, guint32 i);
+gboolean    nm_setting_wireless_security_add_pairwise             (NMSettingWirelessSecurity *setting, const char *pairwise);
+void        nm_setting_wireless_security_remove_pairwise          (NMSettingWirelessSecurity *setting, guint32 i);
+NM_AVAILABLE_IN_0_9_10
+gboolean    nm_setting_wireless_security_remove_pairwise_by_value (NMSettingWirelessSecurity *setting, const char *pairwise);
+void        nm_setting_wireless_security_clear_pairwise           (NMSettingWirelessSecurity *setting);
+
+guint32     nm_setting_wireless_security_get_num_groups        (NMSettingWirelessSecurity *setting);
+const char *nm_setting_wireless_security_get_group             (NMSettingWirelessSecurity *setting, guint32 i);
+gboolean    nm_setting_wireless_security_add_group             (NMSettingWirelessSecurity *setting, const char *group);
+void        nm_setting_wireless_security_remove_group          (NMSettingWirelessSecurity *setting, guint32 i);
+NM_AVAILABLE_IN_0_9_10
+gboolean    nm_setting_wireless_security_remove_group_by_value (NMSettingWirelessSecurity *setting, const char *group);
+void        nm_setting_wireless_security_clear_groups          (NMSettingWirelessSecurity *setting);
 
 const char *nm_setting_wireless_security_get_psk           (NMSettingWirelessSecurity *setting);
 NMSettingSecretFlags nm_setting_wireless_security_get_psk_flags (NMSettingWirelessSecurity *setting);
diff --git a/libnm-util/nm-setting-wireless.c b/libnm-util/nm-setting-wireless.c
index 1cd07c92..ca53d6f9 100644
--- a/libnm-util/nm-setting-wireless.c
+++ b/libnm-util/nm-setting-wireless.c
@@ -19,7 +19,7 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2007 - 2012 Red Hat, Inc.
+ * (C) Copyright 2007 - 2014 Red Hat, Inc.
  * (C) Copyright 2007 - 2008 Novell, Inc.
  */
 
@@ -27,6 +27,7 @@
 #include <net/ethernet.h>
 #include <netinet/ether.h>
 #include <dbus/dbus-glib.h>
+#include <glib/gi18n.h>
 
 #include "NetworkManager.h"
 #include "nm-setting-wireless.h"
@@ -38,11 +39,11 @@
 
 /**
  * SECTION:nm-setting-wireless
- * @short_description: Describes connection properties for 802.11 WiFi networks
+ * @short_description: Describes connection properties for 802.11 Wi-Fi networks
  * @include: nm-setting-wireless.h
  *
  * The #NMSettingWireless object is a #NMSetting subclass that describes properties
- * necessary for connection to 802.11 WiFi networks.
+ * necessary for connection to 802.11 Wi-Fi networks.
  **/
 
 /**
@@ -145,7 +146,7 @@ match_cipher (const char *cipher,
  *
  * Returns: %TRUE if the given settings are compatible with the access point's
  * security flags and mode, %FALSE if they are not.
- */ 
+ */
 gboolean
 nm_setting_wireless_ap_security_compatible (NMSettingWireless *s_wireless,
                                             NMSettingWirelessSecurity *s_wireless_sec,
@@ -154,16 +155,13 @@ nm_setting_wireless_ap_security_compatible (NMSettingWireless *s_wireless,
                                             NM80211ApSecurityFlags ap_rsn,
                                             NM80211Mode ap_mode)
 {
-	NMSettingWirelessPrivate *priv;
 	const char *key_mgmt = NULL, *cipher;
 	guint32 num, i;
 	gboolean found = FALSE;
 
 	g_return_val_if_fail (NM_IS_SETTING_WIRELESS (s_wireless), FALSE);
 
-	priv = NM_SETTING_WIRELESS_GET_PRIVATE (s_wireless);
-
-	if (!priv->security) {
+	if (!s_wireless_sec) {
 		if (   (ap_flags & NM_802_11_AP_FLAGS_PRIVACY)
 		    || (ap_wpa != NM_802_11_AP_SEC_NONE)
 		    || (ap_rsn != NM_802_11_AP_SEC_NONE))
@@ -171,13 +169,8 @@ nm_setting_wireless_ap_security_compatible (NMSettingWireless *s_wireless,
 		return TRUE;
 	}
 
-	if (strcmp (priv->security, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME) != 0)
-		return FALSE;
-
-	if (s_wireless_sec)
-		key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wireless_sec);
-
-	if (s_wireless_sec == NULL || !key_mgmt)
+	key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wireless_sec);
+	if (!key_mgmt)
 		return FALSE;
 
 	/* Static WEP */
@@ -469,6 +462,162 @@ nm_setting_wireless_get_mac_address_blacklist (NMSettingWireless *setting)
 }
 
 /**
+ * nm_setting_wireless_get_num_mac_blacklist_items:
+ * @setting: the #NMSettingWireless
+ *
+ * Returns: the number of blacklisted MAC addresses
+ *
+ * Since: 0.9.10
+ **/
+guint32
+nm_setting_wireless_get_num_mac_blacklist_items (NMSettingWireless *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), 0);
+
+	return g_slist_length (NM_SETTING_WIRELESS_GET_PRIVATE (setting)->mac_address_blacklist);
+}
+
+/**
+ * nm_setting_wireless_get_mac_blacklist_item:
+ * @setting: the #NMSettingWireless
+ * @idx: the zero-based index of the MAC address entry
+ *
+ * Returns: the blacklisted MAC address string (hex-digits-and-colons notation)
+ * at index @idx
+ *
+ * Since: 0.9.10
+ **/
+const char *
+nm_setting_wireless_get_mac_blacklist_item (NMSettingWireless *setting, guint32 idx)
+{
+	NMSettingWirelessPrivate *priv;
+
+	g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), NULL);
+
+	priv = NM_SETTING_WIRELESS_GET_PRIVATE (setting);
+	g_return_val_if_fail (idx <= g_slist_length (priv->mac_address_blacklist), NULL);
+
+	return (const char *) g_slist_nth_data (priv->mac_address_blacklist, idx);
+}
+
+/**
+ * nm_setting_wireless_add_mac_blacklist_item:
+ * @setting: the #NMSettingWireless
+ * @mac: the MAC address string (hex-digits-and-colons notation) to blacklist
+ *
+ * Adds a new MAC address to the #NMSettingWireless:mac-address-blacklist property.
+ *
+ * Returns: %TRUE if the MAC address was added; %FALSE if the MAC address
+ * is invalid or was already present
+ *
+ * Since: 0.9.10
+ **/
+gboolean
+nm_setting_wireless_add_mac_blacklist_item (NMSettingWireless *setting, const char *mac)
+{
+	NMSettingWirelessPrivate *priv;
+	GSList *iter;
+	guint8 buf[32];
+
+	g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), FALSE);
+	g_return_val_if_fail (mac != NULL, FALSE);
+
+	if (!nm_utils_hwaddr_aton (mac, ARPHRD_ETHER, buf))
+		return FALSE;
+
+	priv = NM_SETTING_WIRELESS_GET_PRIVATE (setting);
+	for (iter = priv->mac_address_blacklist; iter; iter = g_slist_next (iter)) {
+		if (!strcasecmp (mac, (char *) iter->data))
+			return FALSE;
+	}
+
+	priv->mac_address_blacklist = g_slist_append (priv->mac_address_blacklist,
+	                                              g_ascii_strup (mac, -1));
+	g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST);
+	return TRUE;
+}
+
+/**
+ * nm_setting_wireless_remove_mac_blacklist_item:
+ * @setting: the #NMSettingWireless
+ * @idx: index number of the MAC address
+ *
+ * Removes the MAC address at index @idx from the blacklist.
+ *
+ * Since: 0.9.10
+ **/
+void
+nm_setting_wireless_remove_mac_blacklist_item (NMSettingWireless *setting, guint32 idx)
+{
+	NMSettingWirelessPrivate *priv;
+	GSList *elt;
+
+	g_return_if_fail (NM_IS_SETTING_WIRELESS (setting));
+
+	priv = NM_SETTING_WIRELESS_GET_PRIVATE (setting);
+	elt = g_slist_nth (priv->mac_address_blacklist, idx);
+	g_return_if_fail (elt != NULL);
+
+	g_free (elt->data);
+	priv->mac_address_blacklist = g_slist_delete_link (priv->mac_address_blacklist, elt);
+	g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST);
+}
+
+/**
+ * nm_setting_wireless_remove_mac_blacklist_item_by_value:
+ * @setting: the #NMSettingWireless
+ * @mac: the MAC address string (hex-digits-and-colons notation) to remove from
+ * the blacklist
+ *
+ * Removes the MAC address @mac from the blacklist.
+ *
+ * Returns: %TRUE if the MAC address was found and removed; %FALSE if it was not.
+ *
+ * Since: 0.9.10
+ **/
+gboolean
+nm_setting_wireless_remove_mac_blacklist_item_by_value (NMSettingWireless *setting, const char *mac)
+{
+	NMSettingWirelessPrivate *priv;
+	GSList *iter;
+	guint8 buf[32];
+
+	g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), FALSE);
+	g_return_val_if_fail (mac != NULL, FALSE);
+
+	if (!nm_utils_hwaddr_aton (mac, ARPHRD_ETHER, buf))
+		return FALSE;
+
+	priv = NM_SETTING_WIRELESS_GET_PRIVATE (setting);
+	for (iter = priv->mac_address_blacklist; iter; iter = g_slist_next (iter)) {
+		if (!strcasecmp (mac, (char *) iter->data)) {
+			priv->mac_address_blacklist = g_slist_delete_link (priv->mac_address_blacklist, iter);
+			g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST);
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
+
+/**
+ * nm_setting_wireless_clear_mac_blacklist_items:
+ * @setting: the #NMSettingWireless
+ *
+ * Removes all blacklisted MAC addresses.
+ *
+ * Since: 0.9.10
+ **/
+void
+nm_setting_wireless_clear_mac_blacklist_items (NMSettingWireless *setting)
+{
+	g_return_if_fail (NM_IS_SETTING_WIRELESS (setting));
+
+	g_slist_free_full (NM_SETTING_WIRELESS_GET_PRIVATE (setting)->mac_address_blacklist, g_free);
+	NM_SETTING_WIRELESS_GET_PRIVATE (setting)->mac_address_blacklist = NULL;
+	g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST);
+}
+
+/**
  * nm_setting_wireless_get_mtu:
  * @setting: the #NMSettingWireless
  *
@@ -487,6 +636,9 @@ nm_setting_wireless_get_mtu (NMSettingWireless *setting)
  * @setting: the #NMSettingWireless
  *
  * Returns: the #NMSettingWireless:security property of the setting
+ *
+ * Deprecated: 0.9.10: No longer used. Security rescrictions are recognized by
+ * the presence of NM_SETTING_WIRELESS_SECURITY_SETTING_NAME in the connection.
  **/
 const char *
 nm_setting_wireless_get_security (NMSettingWireless *setting)
@@ -547,9 +699,10 @@ nm_setting_wireless_add_seen_bssid (NMSettingWireless *setting,
 		}
 	}
 
-	if (!found)
+	if (!found) {
 		priv->seen_bssids = g_slist_prepend (priv->seen_bssids, lower_bssid);
-	else
+		g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_SEEN_BSSIDS);
+	} else
 		g_free (lower_bssid);
 
 	return !found;
@@ -585,15 +738,6 @@ nm_setting_wireless_get_seen_bssid (NMSettingWireless *setting,
 	return (const char *) g_slist_nth_data (NM_SETTING_WIRELESS_GET_PRIVATE (setting)->seen_bssids, i);
 }
 
-static gint
-find_setting_by_name (gconstpointer a, gconstpointer b)
-{
-	NMSetting *setting = NM_SETTING (a);
-	const char *str = (const char *) b;
-
-	return strcmp (nm_setting_get_name (setting), str);
-}
-
 static gboolean
 verify (NMSetting *setting, GSList *all_settings, GError **error)
 {
@@ -603,18 +747,20 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 	GSList *iter;
 
 	if (!priv->ssid) {
-		g_set_error (error,
-		             NM_SETTING_WIRELESS_ERROR,
-		             NM_SETTING_WIRELESS_ERROR_MISSING_PROPERTY,
-		             NM_SETTING_WIRELESS_SSID);
+		g_set_error_literal (error,
+		                     NM_SETTING_WIRELESS_ERROR,
+		                     NM_SETTING_WIRELESS_ERROR_MISSING_PROPERTY,
+		                     _("property is missing"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SETTING_NAME, NM_SETTING_WIRELESS_SSID);
 		return FALSE;
 	}
 
 	if (!priv->ssid->len || priv->ssid->len > 32) {
-		g_set_error (error,
-		             NM_SETTING_WIRELESS_ERROR,
-		             NM_SETTING_WIRELESS_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_WIRELESS_SSID);
+		g_set_error_literal (error,
+		                     NM_SETTING_WIRELESS_ERROR,
+		                     NM_SETTING_WIRELESS_ERROR_INVALID_PROPERTY,
+		                     _("SSID length is out of range <1-32> bytes"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SETTING_NAME, NM_SETTING_WIRELESS_SSID);
 		return FALSE;
 	}
 
@@ -622,7 +768,9 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 		g_set_error (error,
 		             NM_SETTING_WIRELESS_ERROR,
 		             NM_SETTING_WIRELESS_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_WIRELESS_MODE);
+		             _("'%s' is not a valid Wi-Fi mode"),
+		             priv->mode);
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SETTING_NAME, NM_SETTING_WIRELESS_MODE);
 		return FALSE;
 	}
 
@@ -630,7 +778,9 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 		g_set_error (error,
 		             NM_SETTING_WIRELESS_ERROR,
 		             NM_SETTING_WIRELESS_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_WIRELESS_BAND);
+		             _("'%s' is not a valid band"),
+		             priv->band);
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SETTING_NAME, NM_SETTING_WIRELESS_BAND);
 		return FALSE;
 	}
 
@@ -638,7 +788,9 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 		g_set_error (error,
 		             NM_SETTING_WIRELESS_ERROR,
 		             NM_SETTING_WIRELESS_ERROR_CHANNEL_REQUIRES_BAND,
+		             _("requires setting '%s' property"),
 		             NM_SETTING_WIRELESS_BAND);
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SETTING_NAME, NM_SETTING_WIRELESS_CHANNEL);
 		return FALSE;
 	}
 
@@ -647,32 +799,37 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 			g_set_error (error,
 			             NM_SETTING_WIRELESS_ERROR,
 			             NM_SETTING_WIRELESS_ERROR_INVALID_PROPERTY,
-			             NM_SETTING_WIRELESS_CHANNEL);
+			             _("'%d' is not a valid channel"),
+			             priv->channel);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SETTING_NAME, NM_SETTING_WIRELESS_CHANNEL);
 			return FALSE;
 		}
 	}
 
 	if (priv->bssid && priv->bssid->len != ETH_ALEN) {
-		g_set_error (error,
-		             NM_SETTING_WIRELESS_ERROR,
-		             NM_SETTING_WIRELESS_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_WIRELESS_BSSID);
+		g_set_error_literal (error,
+		                     NM_SETTING_WIRELESS_ERROR,
+		                     NM_SETTING_WIRELESS_ERROR_INVALID_PROPERTY,
+		                     _("property is invalid"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SETTING_NAME, NM_SETTING_WIRELESS_BSSID);
 		return FALSE;
 	}
 
 	if (priv->device_mac_address && priv->device_mac_address->len != ETH_ALEN) {
-		g_set_error (error,
-		             NM_SETTING_WIRELESS_ERROR,
-		             NM_SETTING_WIRELESS_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_WIRELESS_MAC_ADDRESS);
+		g_set_error_literal (error,
+		                     NM_SETTING_WIRELESS_ERROR,
+		                     NM_SETTING_WIRELESS_ERROR_INVALID_PROPERTY,
+		                     _("property is invalid"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SETTING_NAME, NM_SETTING_WIRELESS_MAC_ADDRESS);
 		return FALSE;
 	}
 
 	if (priv->cloned_mac_address && priv->cloned_mac_address->len != ETH_ALEN) {
-		g_set_error (error,
-		             NM_SETTING_WIRELESS_ERROR,
-		             NM_SETTING_WIRELESS_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS);
+		g_set_error_literal (error,
+		                     NM_SETTING_WIRELESS_ERROR,
+		                     NM_SETTING_WIRELESS_ERROR_INVALID_PROPERTY,
+		                     _("property is invalid"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SETTING_NAME, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS);
 		return FALSE;
 	}
 
@@ -683,7 +840,9 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 			g_set_error (error,
 			             NM_SETTING_WIRELESS_ERROR,
 			             NM_SETTING_WIRELESS_ERROR_INVALID_PROPERTY,
-			             NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST);
+			             _("'%s' is not a valid MAC address"),
+			             (const char *) iter->data);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SETTING_NAME, NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST);
 			return FALSE;
 		}
 	}
@@ -695,27 +854,19 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 			g_set_error (error,
 			             NM_SETTING_WIRELESS_ERROR,
 			             NM_SETTING_WIRELESS_ERROR_INVALID_PROPERTY,
-			             NM_SETTING_WIRELESS_SEEN_BSSIDS);
+			             _("'%s' is not a valid MAC address"),
+			             (const char *) iter->data);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SETTING_NAME, NM_SETTING_WIRELESS_SEEN_BSSIDS);
 			return FALSE;
 		}
 	}
 
-	if (   priv->security
-	    && !g_slist_find_custom (all_settings, priv->security, find_setting_by_name)) {
-		g_set_error (error,
-		             NM_SETTING_WIRELESS_ERROR,
-		             NM_SETTING_WIRELESS_ERROR_MISSING_SECURITY_SETTING,
-		             NULL);
-		return FALSE;
-	}
-
 	return TRUE;
 }
 
 static void
 nm_setting_wireless_init (NMSettingWireless *setting)
 {
-	g_object_set (setting, NM_SETTING_NAME, NM_SETTING_WIRELESS_SETTING_NAME, NULL);
 }
 
 static void
@@ -735,8 +886,8 @@ finalize (GObject *object)
 		g_byte_array_free (priv->device_mac_address, TRUE);
 	if (priv->cloned_mac_address)
 		g_byte_array_free (priv->cloned_mac_address, TRUE);
-	nm_utils_slist_free (priv->mac_address_blacklist, g_free);
-	nm_utils_slist_free (priv->seen_bssids, g_free);
+	g_slist_free_full (priv->mac_address_blacklist, g_free);
+	g_slist_free_full (priv->seen_bssids, g_free);
 
 	G_OBJECT_CLASS (nm_setting_wireless_parent_class)->finalize (object);
 }
@@ -786,14 +937,14 @@ set_property (GObject *object, guint prop_id,
 		priv->cloned_mac_address = g_value_dup_boxed (value);
 		break;
 	case PROP_MAC_ADDRESS_BLACKLIST:
-		nm_utils_slist_free (priv->mac_address_blacklist, g_free);
+		g_slist_free_full (priv->mac_address_blacklist, g_free);
 		priv->mac_address_blacklist = g_value_dup_boxed (value);
 		break;
 	case PROP_MTU:
 		priv->mtu = g_value_get_uint (value);
 		break;
 	case PROP_SEEN_BSSIDS:
-		nm_utils_slist_free (priv->seen_bssids, g_free);
+		g_slist_free_full (priv->seen_bssids, g_free);
 		priv->seen_bssids = g_value_dup_boxed (value);
 		break;
 	case PROP_SEC:
@@ -853,7 +1004,7 @@ get_property (GObject *object, guint prop_id,
 		g_value_set_boxed (value, NM_SETTING_WIRELESS_GET_PRIVATE (setting)->seen_bssids);
 		break;
 	case PROP_SEC:
-		g_value_set_string (value, nm_setting_wireless_get_security (setting));
+		g_value_set_string (value, NM_SETTING_WIRELESS_GET_PRIVATE (setting)->security);
 		break;
 	case PROP_HIDDEN:
 		g_value_set_boolean (value, nm_setting_wireless_get_hidden (setting));
@@ -882,37 +1033,37 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *setting_class)
 	/**
 	 * NMSettingWireless:ssid:
 	 *
-	 * SSID of the WiFi network.
+	 * SSID of the Wi-Fi network. Must be specified.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_SSID,
 		 _nm_param_spec_specialized (NM_SETTING_WIRELESS_SSID,
 							   "SSID",
-							   "SSID of the WiFi network.  Must be specified.",
+							   "SSID of the Wi-Fi network.  Must be specified.",
 							   DBUS_TYPE_G_UCHAR_ARRAY,
-							   G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+							   G_PARAM_READWRITE));
 
 	/**
 	 * NMSettingWireless:mode:
 	 *
-	 * WiFi network mode; one of 'infrastructure', 'adhoc' or 'ap'.  If blank,
+	 * Wi-Fi network mode; one of "infrastructure", "adhoc" or "ap".  If blank,
 	 * infrastructure is assumed.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_MODE,
 		 g_param_spec_string (NM_SETTING_WIRELESS_MODE,
 						  "Mode",
-						  "WiFi network mode; one of 'infrastructure', "
+						  "Wi-Fi network mode; one of 'infrastructure', "
 						  "'adhoc' or 'ap'.  If blank, infrastructure is assumed.",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+						  G_PARAM_READWRITE));
 
 	/**
 	 * NMSettingWireless:band:
 	 *
-	 * 802.11 frequency band of the network.  One of 'a' for 5GHz 802.11a or
-	 * 'bg' for 2.4GHz 802.11.  This will lock associations to the WiFi network
-	 * to the specific band, i.e. if 'a' is specified, the device will not
+	 * 802.11 frequency band of the network.  One of "a" for 5GHz 802.11a or
+	 * "bg" for 2.4GHz 802.11.  This will lock associations to the Wi-Fi network
+	 * to the specific band, i.e. if "a" is specified, the device will not
 	 * associate with the same network in the 2.4GHz band even if the network's
 	 * settings are compatible.  This setting depends on specific driver
 	 * capability and may not work with all drivers.
@@ -923,34 +1074,34 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *setting_class)
 						  "Band",
 						  "802.11 frequency band of the network.  One of 'a' "
 						  "for 5GHz 802.11a or 'bg' for 2.4GHz 802.11.  This "
-						  "will lock associations to the WiFi network to the "
+						  "will lock associations to the Wi-Fi network to the "
 						  "specific band, i.e. if 'a' is specified, the device "
 						  "will not associate with the same network in the "
 						  "2.4GHz band even if the network's settings are "
 						  "compatible.  This setting depends on specific driver "
 						  "capability and may not work with all drivers.",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+						  G_PARAM_READWRITE));
 
 	/**
 	 * NMSettingWireless:channel:
 	 *
-	 * Wireless channel to use for the WiFi connection.  The device will only
-	 * join (or create for Ad-Hoc networks) a WiFi network on the specified
+	 * Wireless channel to use for the Wi-Fi connection.  The device will only
+	 * join (or create for Ad-Hoc networks) a Wi-Fi network on the specified
 	 * channel.  Because channel numbers overlap between bands, this property
-	 * also requires the 'band' property to be set.
+	 * also requires the "band" property to be set.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_CHANNEL,
 		 g_param_spec_uint (NM_SETTING_WIRELESS_CHANNEL,
 						"Channel",
-						"Wireless channel to use for the WiFi connection.  The "
+						"Wireless channel to use for the Wi-Fi connection.  The "
 						"device will only join (or create for Ad-Hoc networks) "
-						"a WiFi network on the specified channel.  Because "
+						"a Wi-Fi network on the specified channel.  Because "
 						"channel numbers overlap between bands, this property "
 						"also requires the 'band' property to be set.",
 						0, G_MAXUINT32, 0,
-						G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
+						G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
 	/**
 	 * NMSettingWireless:bssid:
@@ -971,7 +1122,7 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *setting_class)
 							   "the BSSID used when creating an Ad-Hoc network "
 							   "and is unlikely to in the future.",
 							   DBUS_TYPE_G_UCHAR_ARRAY,
-							   G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+							   G_PARAM_READWRITE));
 
 	/**
 	 * NMSettingWireless:rate:
@@ -991,7 +1142,7 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *setting_class)
 						"property is highly driver dependent and not all devices "
 						"support setting a static bitrate.",
 						0, G_MAXUINT32, 0,
-						G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_FUZZY_IGNORE));
+						G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE));
 
 	/**
 	 * NMSettingWireless:tx-power:
@@ -1009,48 +1160,48 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *setting_class)
 						"driver dependent and not all devices support setting a "
 						"static transmit power.",
 						0, G_MAXUINT32, 0,
-						G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_FUZZY_IGNORE));
+						G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE));
 
 	/**
 	 * NMSettingWireless:mac-address:
 	 *
-	 * If specified, this connection will only apply to the WiFi device
-	 * whose permanent MAC address matches. This property does not change the MAC address
-	 * of the device (i.e. MAC spoofing).
+	 * If specified, this connection will only apply to the Wi-Fi device whose
+	 * permanent MAC address matches. This property does not change the MAC
+	 * address of the device (i.e. MAC spoofing).
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_MAC_ADDRESS,
 		 _nm_param_spec_specialized (NM_SETTING_WIRELESS_MAC_ADDRESS,
 							   "Device MAC Address",
 							   "If specified, this connection will only apply to "
-							   "the WiFi device whose permanent MAC address matches.  "
+							   "the Wi-Fi device whose permanent MAC address matches.  "
 							   "This property does not change the MAC address "
 							   "of the device (i.e. MAC spoofing).",
 							   DBUS_TYPE_G_UCHAR_ARRAY,
-							   G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+							   G_PARAM_READWRITE));
 
 	/**
 	 * NMSettingWireless:cloned-mac-address:
 	 *
-	 * If specified, request that the Wifi device use this MAC address instead of its
-	 * permanent MAC address.  This is known as MAC cloning or spoofing.
+	 * If specified, request that the Wi-Fi device use this MAC address instead
+	 * of its permanent MAC address.  This is known as MAC cloning or spoofing.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_CLONED_MAC_ADDRESS,
 		 _nm_param_spec_specialized (NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS,
 	                                     "Spoof MAC Address",
-	                                     "If specified, request that the WiFi device use "
+	                                     "If specified, request that the Wi-Fi device use "
 	                                     "this MAC address instead of its permanent MAC address.  "
 	                                     "This is known as MAC cloning or spoofing.",
 	                                     DBUS_TYPE_G_UCHAR_ARRAY,
-	                                     G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+	                                     G_PARAM_READWRITE));
 
 	/**
 	 * NMSettingWireless:mac-address-blacklist:
 	 *
 	 * A list of permanent MAC addresses of Wi-Fi devices to which this
 	 * connection should never apply.  Each MAC address should be given in the
-	 * standard hex-digits-and-colons notation (eg '00:11:22:33:44:55').
+	 * standard hex-digits-and-colons notation (eg "00:11:22:33:44:55").
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_MAC_ADDRESS_BLACKLIST,
@@ -1062,16 +1213,17 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *setting_class)
 		                             "given in the standard hex-digits-and-colons "
 		                             "notation (eg '00:11:22:33:44:55').",
 		                             DBUS_TYPE_G_LIST_OF_STRING,
-		                             G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_FUZZY_IGNORE));
+		                             G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE));
 
 	/**
 	 * NMSettingWireless:seen-bssids:
 	 *
 	 * A list of BSSIDs (each BSSID formatted as a MAC address like
-	 * '00:11:22:33:44:55') that have been detected as part of the Wi-FI network.
-	 * NetworkManager internally tracks previously seen BSSIDs. The property is only
-	 * meant for reading and reflects the BBSID list of NetworkManager. The changes you
-	 * make to this property will not be preserved.
+	 * "00:11:22:33:44:55") that have been detected as part of the Wi-Fi
+	 * network.  NetworkManager internally tracks previously seen BSSIDs. The
+	 * property is only meant for reading and reflects the BSSID list of
+	 * NetworkManager. The changes you make to this property will not be
+	 * preserved.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_SEEN_BSSIDS,
@@ -1079,14 +1231,14 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *setting_class)
 		                             "Seen BSSIDS",
 		                             "A list of BSSIDs (each BSSID formatted as a MAC "
 		                             "address like 00:11:22:33:44:55') that have been "
-		                             "detected as part of the WiFI network. "
+		                             "detected as part of the Wi-Fi network. "
 		                             "NetworkManager internally tracks previously seen "
 		                             "BSSIDs. The property is only meant for reading "
-		                             "and reflects the BBSID list of NetworkManager. "
+		                             "and reflects the BSSID list of NetworkManager. "
 		                             "The changes you make to this property will not be "
 		                             "preserved.",
 		                             DBUS_TYPE_G_LIST_OF_STRING,
-		                             G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_FUZZY_IGNORE));
+		                             G_PARAM_READWRITE | NM_SETTING_PARAM_FUZZY_IGNORE));
 
 	/**
 	 * NMSettingWireless:mtu:
@@ -1102,14 +1254,19 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *setting_class)
 						"size or smaller, breaking larger packets up into "
 						"multiple Ethernet frames.",
 						0, G_MAXUINT32, 0,
-						G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_FUZZY_IGNORE));
+						G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_FUZZY_IGNORE));
 
 	/**
 	 * NMSettingWireless:security:
 	 *
 	 * If the wireless connection has any security restrictions, like 802.1x,
-	 * WEP, or WPA, set this property to '802-11-wireless-security' and ensure
-	 * the connection contains a valid 802-11-wireless-security setting.
+	 * WEP, or WPA, set this property to
+	 * %NM_SETTING_WIRELESS_SECURITY_SETTING_NAME and ensure the connection
+	 * contains a valid #NMSettingWirelessSecurity setting.
+	 *
+	 * Deprecated: 0.9.10: No longer used. Security restrictions are recognized
+	 * by the presence of a #NMSettingWirelessSecurity setting in the
+	 * connection.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_SEC,
@@ -1121,14 +1278,14 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *setting_class)
 						  "and ensure the connection contains a valid "
 						  NM_SETTING_WIRELESS_SECURITY_SETTING_NAME " setting.",
 						  NULL,
-						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+						  G_PARAM_READWRITE));
 
 	/**
 	 * NMSettingWireless:hidden:
 	 *
-	 * If %TRUE, indicates this network is a non-broadcasting network that
-	 * hides its SSID.  In this case various workarounds may take place, such
-	 * as probe-scanning the SSID for more reliable network discovery.  However,
+	 * If %TRUE, indicates this network is a non-broadcasting network that hides
+	 * its SSID.  In this case various workarounds may take place, such as
+	 * probe-scanning the SSID for more reliable network discovery.  However,
 	 * these workarounds expose inherent insecurities with hidden SSID networks,
 	 * and thus hidden SSID networks should be used with caution.
 	 **/
@@ -1144,5 +1301,5 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *setting_class)
 		                       "insecurities with hidden SSID networks, and thus "
 		                       "hidden SSID networks should be used with caution.",
 		                       FALSE,
-		                       G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+		                       G_PARAM_READWRITE));
 }
diff --git a/libnm-util/nm-setting-wireless.h b/libnm-util/nm-setting-wireless.h
index e75bb151..221a921a 100644
--- a/libnm-util/nm-setting-wireless.h
+++ b/libnm-util/nm-setting-wireless.h
@@ -19,7 +19,7 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2007 - 2011 Red Hat, Inc.
+ * (C) Copyright 2007 - 2014 Red Hat, Inc.
  * (C) Copyright 2007 - 2008 Novell, Inc.
  */
 
@@ -75,9 +75,11 @@ GQuark nm_setting_wireless_error_quark (void);
 #define NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST "mac-address-blacklist"
 #define NM_SETTING_WIRELESS_MTU         "mtu"
 #define NM_SETTING_WIRELESS_SEEN_BSSIDS "seen-bssids"
-#define NM_SETTING_WIRELESS_SEC         "security"
 #define NM_SETTING_WIRELESS_HIDDEN      "hidden"
 
+/* Deprecated */
+#define NM_SETTING_WIRELESS_SEC         "security"
+
 /**
  * NM_SETTING_WIRELESS_MODE_ADHOC:
  *
@@ -130,9 +132,26 @@ guint32           nm_setting_wireless_get_rate               (NMSettingWireless
 guint32           nm_setting_wireless_get_tx_power           (NMSettingWireless *setting);
 const GByteArray *nm_setting_wireless_get_mac_address        (NMSettingWireless *setting);
 const GByteArray *nm_setting_wireless_get_cloned_mac_address (NMSettingWireless *setting);
-const GSList     *nm_setting_wireless_get_mac_address_blacklist (NMSettingWireless *setting);
+
+const GSList     *nm_setting_wireless_get_mac_address_blacklist   (NMSettingWireless *setting);
+NM_AVAILABLE_IN_0_9_10
+guint32           nm_setting_wireless_get_num_mac_blacklist_items (NMSettingWireless *setting);
+NM_AVAILABLE_IN_0_9_10
+const char *      nm_setting_wireless_get_mac_blacklist_item      (NMSettingWireless *setting,
+                                                                   guint32 idx);
+NM_AVAILABLE_IN_0_9_10
+gboolean          nm_setting_wireless_add_mac_blacklist_item      (NMSettingWireless *setting,
+                                                                   const char *mac);
+NM_AVAILABLE_IN_0_9_10
+void              nm_setting_wireless_remove_mac_blacklist_item   (NMSettingWireless *setting,
+                                                                   guint32 idx);
+NM_AVAILABLE_IN_0_9_10
+gboolean          nm_setting_wireless_remove_mac_blacklist_item_by_value (NMSettingWireless *setting,
+                                                                          const char *mac);
+NM_AVAILABLE_IN_0_9_10
+void              nm_setting_wireless_clear_mac_blacklist_items   (NMSettingWireless *setting);
+
 guint32           nm_setting_wireless_get_mtu                (NMSettingWireless *setting);
-const char       *nm_setting_wireless_get_security           (NMSettingWireless *setting);
 gboolean          nm_setting_wireless_get_hidden             (NMSettingWireless *setting);
 
 gboolean          nm_setting_wireless_add_seen_bssid         (NMSettingWireless *setting,
@@ -149,6 +168,10 @@ gboolean          nm_setting_wireless_ap_security_compatible (NMSettingWireless
                                                               NM80211ApSecurityFlags ap_rsn,
                                                               NM80211Mode ap_mode);
 
+/* Deprecated */
+NM_DEPRECATED_IN_0_9_10
+const char *nm_setting_wireless_get_security (NMSettingWireless *setting);
+
 G_END_DECLS
 
 #endif /* NM_SETTING_WIRELESS_H */
diff --git a/libnm-util/nm-setting.c b/libnm-util/nm-setting.c
index a3186284..0e8a06c4 100644
--- a/libnm-util/nm-setting.c
+++ b/libnm-util/nm-setting.c
@@ -29,6 +29,7 @@
 #include "nm-setting-private.h"
 #include "nm-setting-connection.h"
 #include "nm-utils.h"
+#include "nm-utils-private.h"
 
 /**
  * SECTION:nm-setting
@@ -37,7 +38,7 @@
  *
  * Each #NMSetting contains properties that describe configuration that applies
  * to a specific network layer (like IPv4 or IPv6 configuration) or device type
- * (like Ethernet, or WiFi).  A collection of individual settings together
+ * (like Ethernet, or Wi-Fi).  A collection of individual settings together
  * make up an #NMConnection. Each property is strongly typed and usually has
  * a number of allowed values.  See each #NMSetting subclass for a description
  * of properties and allowed values.
@@ -65,7 +66,14 @@ G_DEFINE_ABSTRACT_TYPE (NMSetting, nm_setting, G_TYPE_OBJECT)
 #define NM_SETTING_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING, NMSettingPrivate))
 
 typedef struct {
-	char *name;
+	const char *name;
+	GType type;
+	guint32 priority;
+	GQuark error_quark;
+} SettingInfo;
+
+typedef struct {
+	const SettingInfo *info;
 } NMSettingPrivate;
 
 enum {
@@ -75,6 +83,197 @@ enum {
 	PROP_LAST
 };
 
+/*************************************************************/
+
+static GHashTable *registered_settings = NULL;
+static GHashTable *registered_settings_by_type = NULL;
+
+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 __attribute__((constructor))
+_ensure_registered (void)
+{
+	if (G_UNLIKELY (registered_settings == NULL)) {
+#if !GLIB_CHECK_VERSION (2, 35, 0)
+		g_type_init ();
+#endif
+		_nm_value_transforms_register ();
+		registered_settings = g_hash_table_new (g_str_hash, g_str_equal);
+		registered_settings_by_type = g_hash_table_new (_nm_gtype_hash, _nm_gtype_equal);
+	}
+}
+
+#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:
+ * @name: the name of the #NMSetting object to register
+ * @type: the #GType of the #NMSetting
+ * @priority: the sort priority of the setting, see below
+ * @error_quark: the setting's error quark
+ *
+ * INTERNAL ONLY: registers a setting's internal properties, like its priority
+ * and its error quark type, with libnm-util.
+ *
+ * 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 the Connection setting
+ *
+ * 1: 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.
+ *
+ * 2: hardware-related auxiliary settings that require a base setting to be
+ * successful first, like Wi-Fi security, 802.1x, etc.
+ *
+ * 3: hardware-independent settings that are required before IP connectivity
+ * can be established, like PPP, PPPoE, etc.
+ *
+ * 4: IP-level stuff
+ */
+void
+(_nm_register_setting) (const char *name,
+                        const GType type,
+                        const guint32 priority,
+                        const GQuark error_quark)
+{
+	SettingInfo *info;
+
+	g_return_if_fail (name != NULL && *name);
+	g_return_if_fail (type != G_TYPE_INVALID);
+	g_return_if_fail (type != G_TYPE_NONE);
+	g_return_if_fail (error_quark != 0);
+	g_return_if_fail (priority <= 4);
+
+	_ensure_registered ();
+
+	if (G_LIKELY ((info = g_hash_table_lookup (registered_settings, name)))) {
+		g_return_if_fail (info->type == type);
+		g_return_if_fail (info->error_quark == error_quark);
+		g_return_if_fail (info->priority == priority);
+		g_return_if_fail (g_strcmp0 (info->name, name) == 0);
+		return;
+	}
+	g_return_if_fail (g_hash_table_lookup (registered_settings_by_type, &type) == NULL);
+
+	if (priority == 0)
+		g_assert_cmpstr (name, ==, NM_SETTING_CONNECTION_SETTING_NAME);
+
+	info = g_slice_new0 (SettingInfo);
+	info->type = type;
+	info->priority = priority;
+	info->error_quark = error_quark;
+	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 guint32
+_get_setting_type_priority (GType type)
+{
+	const SettingInfo *info;
+
+	g_return_val_if_fail (g_type_is_a (type, NM_TYPE_SETTING), G_MAXUINT32);
+
+	info = _nm_setting_lookup_setting_by_type (type);
+	return info->priority;
+}
+
+gboolean
+_nm_setting_type_is_base_type (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.
+	 */
+	return _get_setting_type_priority (type) == 1 || (type == NM_TYPE_SETTING_PPPOE);
+}
+
+gboolean
+_nm_setting_is_base_type (NMSetting *setting)
+{
+	return _nm_setting_type_is_base_type (G_OBJECT_TYPE (setting));
+}
+
+GType
+_nm_setting_lookup_setting_type (const char *name)
+{
+	SettingInfo *info;
+
+	g_return_val_if_fail (name != NULL, G_TYPE_NONE);
+
+	_ensure_registered ();
+
+	info = g_hash_table_lookup (registered_settings, name);
+	return info ? info->type : G_TYPE_INVALID;
+}
+
+GType
+_nm_setting_lookup_setting_type_by_quark (GQuark error_quark)
+{
+	SettingInfo *info;
+	GHashTableIter iter;
+
+	_ensure_registered ();
+
+	g_hash_table_iter_init (&iter, registered_settings);
+	while (g_hash_table_iter_next (&iter, NULL, (gpointer) &info)) {
+		if (info->error_quark == error_quark)
+			return info->type;
+	}
+	return G_TYPE_INVALID;
+}
+
+gint
+_nm_setting_compare_priority (gconstpointer a, gconstpointer b)
+{
+	guint32 prio_a, prio_b;
+
+	prio_a = _get_setting_type_priority (G_OBJECT_TYPE (a));
+	prio_b = _get_setting_type_priority (G_OBJECT_TYPE (b));
+
+	if (prio_a < prio_b)
+		return -1;
+	else if (prio_a == prio_b)
+		return 0;
+	return 1;
+}
+
+/*************************************************************/
+
 static void
 destroy_gvalue (gpointer data)
 {
@@ -104,7 +303,6 @@ nm_setting_to_hash (NMSetting *setting, NMSettingHashFlags flags)
 	guint n_property_specs;
 	guint i;
 
-	g_return_val_if_fail (setting != NULL, NULL);
 	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);
@@ -121,7 +319,8 @@ nm_setting_to_hash (NMSetting *setting, NMSettingHashFlags flags)
 		GParamSpec *prop_spec = property_specs[i];
 		GValue *value;
 
-		if (!(prop_spec->flags & NM_SETTING_PARAM_SERIALIZE))
+		/* 'name' doesn't get serialized */
+		if (strcmp (g_param_spec_get_name (prop_spec), NM_SETTING_NAME) == 0)
 			continue;
 
 		if (   (flags & NM_SETTING_HASH_FLAG_NO_SECRETS)
@@ -144,8 +343,8 @@ nm_setting_to_hash (NMSetting *setting, NMSettingHashFlags flags)
 	}
 	g_free (property_specs);
 
-	/* Don't return empty hashes */
-	if (g_hash_table_size (hash) < 1) {
+	/* Don't return empty hashes, except for base types */
+	if (g_hash_table_size (hash) < 1 && !_nm_setting_is_base_type (setting)) {
 		g_hash_table_destroy (hash);
 		hash = NULL;
 	}
@@ -153,39 +352,6 @@ nm_setting_to_hash (NMSetting *setting, NMSettingHashFlags flags)
 	return hash;
 }
 
-typedef struct {
-	GObjectClass *class;
-	guint n_params;
-	GParameter *params;
-} NMSettingFromHashInfo;
-
-static void
-one_property_cb (gpointer key, gpointer val, gpointer user_data)
-{
-	const char *prop_name = (char *) key;
-	GValue *src_value = (GValue *) val;
-	NMSettingFromHashInfo *info = (NMSettingFromHashInfo *) user_data;
-	GValue *dst_value = &info->params[info->n_params].value;
-	GParamSpec *param_spec;
-
-	param_spec = g_object_class_find_property (info->class, prop_name);
-	if (!param_spec || !(param_spec->flags & NM_SETTING_PARAM_SERIALIZE)) {
-		/* Oh, we're so nice and only warn, maybe it should be a fatal error? */
-		g_warning ("Ignoring invalid property '%s'", prop_name);
-		return;
-	}
-
-	g_value_init (dst_value, G_VALUE_TYPE (src_value));
-	if (g_value_transform (src_value, dst_value)) {
-		info->params[info->n_params].name = prop_name;
-		info->n_params++;
-	} else {
-		g_warning ("Ignoring property '%s' with invalid type (%s)",
-		           prop_name, G_VALUE_TYPE_NAME (src_value));
-		g_value_unset (dst_value);
-	}
-}
-
 /**
  * nm_setting_new_from_hash:
  * @setting_type: the #NMSetting type which the hash contains properties for
@@ -205,28 +371,53 @@ one_property_cb (gpointer key, gpointer val, gpointer user_data)
 NMSetting *
 nm_setting_new_from_hash (GType setting_type, GHashTable *hash)
 {
+	GHashTableIter iter;
 	NMSetting *setting;
-	NMSettingFromHashInfo info;
+	const char *prop_name;
+	GValue *src_value;
+	GObjectClass *class;
+	guint n_params = 0;
+	GParameter *params;
 	int i;
 
 	g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (setting_type), NULL);
 	g_return_val_if_fail (hash != NULL, NULL);
 
-	info.class = g_type_class_ref (setting_type);
-	info.n_params = 0;
-	info.params = g_new0 (GParameter, g_hash_table_size (hash));
+	/* g_type_class_ref() ensures the setting class is created if it hasn't
+	 * already been used.
+	 */
+	class = g_type_class_ref (setting_type);
+	params = g_new0 (GParameter, g_hash_table_size (hash));
+
+	g_hash_table_iter_init (&iter, hash);
+	while (g_hash_table_iter_next (&iter, (gpointer) &prop_name, (gpointer) &src_value)) {
+		GValue *dst_value = &params[n_params].value;
+		GParamSpec *param_spec;
+
+		param_spec = g_object_class_find_property (class, prop_name);
+		if (!param_spec) {
+			/* Oh, we're so nice and only warn, maybe it should be a fatal error? */
+			g_warning ("Ignoring invalid property '%s'", prop_name);
+			continue;
+		}
 
-	g_hash_table_foreach (hash, one_property_cb, &info);
+		g_value_init (dst_value, G_VALUE_TYPE (src_value));
+		if (g_value_transform (src_value, dst_value))
+			params[n_params++].name = prop_name;
+		else {
+			g_warning ("Ignoring property '%s' with invalid type (%s)",
+				       prop_name, G_VALUE_TYPE_NAME (src_value));
+			g_value_unset (dst_value);
+		}
+	}
 
-	setting = (NMSetting *) g_object_newv (setting_type, info.n_params, info.params);
+	setting = (NMSetting *) g_object_newv (setting_type, n_params, params);
 
-	for (i = 0; i < info.n_params; i++) {
-		GValue *v = &info.params[i].value;
-		g_value_unset (v);
-	}
+	for (i = 0; i < n_params; i++)
+		g_value_unset (&params[i].value);
 
-	g_free (info.params);
-	g_type_class_unref (info.class);
+	g_free (params);
+	g_type_class_unref (class);
 
 	return setting;
 }
@@ -238,7 +429,7 @@ duplicate_setting (NMSetting *setting,
                    GParamFlags flags,
                    gpointer user_data)
 {
-	if (flags & G_PARAM_WRITABLE)
+	if ((flags & (G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)) == G_PARAM_WRITABLE)
 		g_object_set_property (G_OBJECT (user_data), name, value);
 }
 
@@ -267,6 +458,28 @@ nm_setting_duplicate (NMSetting *setting)
 	return NM_SETTING (dup);
 }
 
+static gint
+find_setting_by_name (gconstpointer a, gconstpointer b)
+{
+	NMSetting *setting = NM_SETTING (a);
+	const char *str = (const char *) b;
+
+	return strcmp (nm_setting_get_name (setting), str);
+}
+
+NMSetting *
+nm_setting_find_in_list (GSList     *settings_list,
+                         const char *setting_name)
+{
+	GSList *found;
+
+	found = g_slist_find_custom (settings_list, setting_name, find_setting_by_name);
+	if (found)
+		return found->data;
+	else
+		return NULL;
+}
+
 /**
  * nm_setting_get_name:
  * @setting: the #NMSetting
@@ -279,9 +492,12 @@ nm_setting_duplicate (NMSetting *setting)
 const char *
 nm_setting_get_name (NMSetting *setting)
 {
-	g_return_val_if_fail (NM_IS_SETTING (setting), NULL);
+	NMSettingPrivate *priv;
 
-	return NM_SETTING_GET_PRIVATE (setting)->name;
+	g_return_val_if_fail (NM_IS_SETTING (setting), NULL);
+	priv = NM_SETTING_GET_PRIVATE (setting);
+	_ensure_setting_info (setting, priv);
+	return priv->info->name;
 }
 
 /**
@@ -302,8 +518,7 @@ gboolean
 nm_setting_verify (NMSetting *setting, GSList *all_settings, GError **error)
 {
 	g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
-	if (error)
-		g_return_val_if_fail (*error == NULL, FALSE);
+	g_return_val_if_fail (!error || *error == NULL, FALSE);
 
 	if (NM_SETTING_GET_CLASS (setting)->verify)
 		return NM_SETTING_GET_CLASS (setting)->verify (setting, all_settings, error);
@@ -317,8 +532,8 @@ compare_property (NMSetting *setting,
 	              const GParamSpec *prop_spec,
 	              NMSettingCompareFlags flags)
 {
-	GValue value1 = { 0 };
-	GValue value2 = { 0 };
+	GValue value1 = G_VALUE_INIT;
+	GValue value2 = G_VALUE_INIT;
 	gboolean different;
 
 	/* Handle compare flags */
@@ -398,6 +613,9 @@ nm_setting_compare (NMSetting *a,
 			&& (prop_spec->flags & (NM_SETTING_PARAM_FUZZY_IGNORE | NM_SETTING_PARAM_SECRET)))
 			continue;
 
+		if ((flags & NM_SETTING_COMPARE_FLAG_INFERRABLE) && !(prop_spec->flags & NM_SETTING_PARAM_INFERRABLE))
+			continue;
+
 		if (   (flags & NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS)
 		    && (prop_spec->flags & NM_SETTING_PARAM_SECRET))
 			continue;
@@ -420,6 +638,9 @@ should_compare_prop (NMSetting *setting,
 	    && (prop_flags & (NM_SETTING_PARAM_FUZZY_IGNORE | NM_SETTING_PARAM_SECRET)))
 		return FALSE;
 
+	if ((comp_flags & NM_SETTING_COMPARE_FLAG_INFERRABLE) && !(prop_flags & NM_SETTING_PARAM_INFERRABLE))
+		return FALSE;
+
 	if (prop_flags & NM_SETTING_PARAM_SECRET) {
 		NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE;
 
@@ -481,7 +702,6 @@ nm_setting_diff (NMSetting *a,
 	gboolean results_created = FALSE;
 
 	g_return_val_if_fail (results != NULL, FALSE);
-	g_return_val_if_fail (a != NULL, FALSE);
 	g_return_val_if_fail (NM_IS_SETTING (a), FALSE);
 	if (b) {
 		g_return_val_if_fail (NM_IS_SETTING (b), FALSE);
@@ -512,7 +732,6 @@ nm_setting_diff (NMSetting *a,
 
 	for (i = 0; i < n_property_specs; i++) {
 		GParamSpec *prop_spec = property_specs[i];
-		GValue a_value = { 0 }, b_value = { 0 };
 		NMSettingDiffResult r = NM_SETTING_DIFF_RESULT_UNKNOWN, tmp;
 		gboolean different = TRUE;
 
@@ -523,22 +742,22 @@ nm_setting_diff (NMSetting *a,
 			continue;
 
 		if (b) {
-			g_value_init (&a_value, prop_spec->value_type);
-			g_object_get_property (G_OBJECT (a), prop_spec->name, &a_value);
-
-			g_value_init (&b_value, prop_spec->value_type);
-			g_object_get_property (G_OBJECT (b), prop_spec->name, &b_value);
-
-			different = !!g_param_values_cmp (prop_spec, &a_value, &b_value);
+			different = !NM_SETTING_GET_CLASS (a)->compare_property (a, b, prop_spec, flags);
 			if (different) {
-				if (!g_param_value_defaults (prop_spec, &a_value))
+				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;
-				if (!g_param_value_defaults (prop_spec, &b_value))
+
+				g_value_reset (&value);
+				g_object_get_property (G_OBJECT (b), prop_spec->name, &value);
+				if (!g_param_value_defaults (prop_spec, &value))
 					r |= b_result;
-			}
 
-			g_value_unset (&a_value);
-			g_value_unset (&b_value);
+				g_value_unset (&value);
+			}
 		} else
 			r = a_result;  /* only in A */
 
@@ -582,7 +801,7 @@ nm_setting_enumerate_values (NMSetting *setting,
 	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];
-		GValue value = { 0 };
+		GValue value = G_VALUE_INIT;
 
 		g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (prop_spec));
 		g_object_get_property (G_OBJECT (setting), prop_spec->name, &value);
@@ -604,46 +823,68 @@ nm_setting_enumerate_values (NMSetting *setting,
 void
 nm_setting_clear_secrets (NMSetting *setting)
 {
+	_nm_setting_clear_secrets (setting);
+}
+
+gboolean
+_nm_setting_clear_secrets (NMSetting *setting)
+{
 	GParamSpec **property_specs;
 	guint n_property_specs;
 	guint i;
+	gboolean changed = FALSE;
 
-	g_return_if_fail (NM_IS_SETTING (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];
-		GValue value = { 0 };
 
 		if (prop_spec->flags & NM_SETTING_PARAM_SECRET) {
+			GValue value = G_VALUE_INIT;
+
 			g_value_init (&value, prop_spec->value_type);
-			g_param_value_set_default (prop_spec, &value);
-			g_object_set_property (G_OBJECT (setting), prop_spec->name, &value);
+			g_object_get_property (G_OBJECT (setting), prop_spec->name, &value);
+			if (!g_param_value_defaults (prop_spec, &value)) {
+				g_param_value_set_default (prop_spec, &value);
+				g_object_set_property (G_OBJECT (setting), prop_spec->name, &value);
+				changed = TRUE;
+			}
 			g_value_unset (&value);
 		}
 	}
 
 	g_free (property_specs);
+
+	return changed;
 }
 
-static void
+static gboolean
 clear_secrets_with_flags (NMSetting *setting,
 	                      GParamSpec *pspec,
 	                      NMSettingClearSecretsWithFlagsFn func,
 	                      gpointer user_data)
 {
-	GValue value = { 0 };
 	NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE;
+	gboolean changed = FALSE;
 
 	/* Clear the secret if the user function says to do so */
 	nm_setting_get_secret_flags (setting, pspec->name, &flags, NULL);
 	if (func (setting, pspec->name, flags, user_data) == TRUE) {
+		GValue value = G_VALUE_INIT;
+
 		g_value_init (&value, pspec->value_type);
-		g_param_value_set_default (pspec, &value);
-		g_object_set_property (G_OBJECT (setting), pspec->name, &value);
+		g_object_get_property (G_OBJECT (setting), pspec->name, &value);
+		if (!g_param_value_defaults (pspec, &value)) {
+			g_param_value_set_default (pspec, &value);
+			g_object_set_property (G_OBJECT (setting), pspec->name, &value);
+			changed = TRUE;
+		}
 		g_value_unset (&value);
 	}
+
+	return changed;
 }
 
 /**
@@ -660,25 +901,35 @@ nm_setting_clear_secrets_with_flags (NMSetting *setting,
                                      NMSettingClearSecretsWithFlagsFn func,
                                      gpointer user_data)
 {
+	_nm_setting_clear_secrets_with_flags (setting, func, user_data);
+}
+
+gboolean
+_nm_setting_clear_secrets_with_flags (NMSetting *setting,
+                                      NMSettingClearSecretsWithFlagsFn func,
+                                      gpointer user_data)
+{
 	GParamSpec **property_specs;
 	guint n_property_specs;
 	guint i;
+	gboolean changed = FALSE;
 
-	g_return_if_fail (setting);
-	g_return_if_fail (NM_IS_SETTING (setting));
-	g_return_if_fail (func != NULL);
+	g_return_val_if_fail (setting, FALSE);
+	g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
+	g_return_val_if_fail (func != NULL, FALSE);
 
 	property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_property_specs);
 	for (i = 0; i < n_property_specs; i++) {
 		if (property_specs[i]->flags & NM_SETTING_PARAM_SECRET) {
-			NM_SETTING_GET_CLASS (setting)->clear_secrets_with_flags (setting,
-			                                                          property_specs[i],
-			                                                          func,
-			                                                          user_data);
+			changed |= NM_SETTING_GET_CLASS (setting)->clear_secrets_with_flags (setting,
+			                                                                     property_specs[i],
+			                                                                     func,
+			                                                                     user_data);
 		}
 	}
 
 	g_free (property_specs);
+	return changed;
 }
 
 /**
@@ -708,12 +959,11 @@ nm_setting_need_secrets (NMSetting *setting)
 	return secrets;
 }
 
-static gboolean
+static int
 update_one_secret (NMSetting *setting, const char *key, GValue *value, GError **error)
 {
 	GParamSpec *prop_spec;
-	GValue transformed_value = { 0 };
-	gboolean success = FALSE;
+	GValue transformed_value = G_VALUE_INIT;
 
 	prop_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (setting), key);
 	if (!prop_spec) {
@@ -721,27 +971,40 @@ update_one_secret (NMSetting *setting, const char *key, GValue *value, GError **
 		             NM_SETTING_ERROR,
 		             NM_SETTING_ERROR_PROPERTY_NOT_FOUND,
 		             "%s", key);
-		return FALSE;
+		return NM_SETTING_UPDATE_SECRET_ERROR;
 	}
 
 	/* Silently ignore non-secrets */
 	if (!(prop_spec->flags & NM_SETTING_PARAM_SECRET))
-		return TRUE;
+		return NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED;
 
 	if (g_value_type_compatible (G_VALUE_TYPE (value), G_PARAM_SPEC_VALUE_TYPE (prop_spec))) {
+		if (G_VALUE_HOLDS_STRING (value) && G_IS_PARAM_SPEC_STRING (prop_spec)) {
+			/* String is expected to be a common case. Handle it specially and check whether
+			 * the value is already set. Otherwise, we just reset the property and
+			 * assume the value got modified. */
+			char *v;
+
+			g_object_get (G_OBJECT (setting), prop_spec->name, &v, NULL);
+			if (g_strcmp0 (v, g_value_get_string (value)) == 0) {
+				g_free (v);
+				return NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED;
+			}
+			g_free (v);
+		}
 		g_object_set_property (G_OBJECT (setting), prop_spec->name, value);
-		success = TRUE;
-	} else if (g_value_transform (value, &transformed_value)) {
+		return NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED;
+	}
+	if (g_value_transform (value, &transformed_value)) {
 		g_object_set_property (G_OBJECT (setting), prop_spec->name, &transformed_value);
 		g_value_unset (&transformed_value);
-		success = TRUE;
-	} else {
-		g_set_error (error,
-		             NM_SETTING_ERROR,
-		             NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH,
-		             "%s", key);
+		return NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED;
 	}
-	return success;
+	g_set_error (error,
+	             NM_SETTING_ERROR,
+	             NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH,
+	             "%s", key);
+	return NM_SETTING_UPDATE_SECRET_ERROR;
 }
 
 /**
@@ -760,29 +1023,41 @@ update_one_secret (NMSetting *setting, const char *key, GValue *value, GError **
 gboolean
 nm_setting_update_secrets (NMSetting *setting, GHashTable *secrets, GError **error)
 {
+	return _nm_setting_update_secrets (setting, secrets, error) != NM_SETTING_UPDATE_SECRET_ERROR;
+}
+
+NMSettingUpdateSecretResult
+_nm_setting_update_secrets (NMSetting *setting, GHashTable *secrets, GError **error)
+{
 	GHashTableIter iter;
 	gpointer key, data;
 	GError *tmp_error = NULL;
+	NMSettingUpdateSecretResult result = NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED;
 
-	g_return_val_if_fail (setting != NULL, FALSE);
-	g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
-	g_return_val_if_fail (secrets != NULL, FALSE);
+	g_return_val_if_fail (NM_IS_SETTING (setting), NM_SETTING_UPDATE_SECRET_ERROR);
+	g_return_val_if_fail (secrets != NULL, NM_SETTING_UPDATE_SECRET_ERROR);
 	if (error)
-		g_return_val_if_fail (*error == NULL, FALSE);
+		g_return_val_if_fail (*error == NULL, NM_SETTING_UPDATE_SECRET_ERROR);
 
 	g_hash_table_iter_init (&iter, secrets);
 	while (g_hash_table_iter_next (&iter, &key, &data)) {
+		int success;
 		const char *secret_key = (const char *) key;
 		GValue *secret_value = (GValue *) data;
 
-		NM_SETTING_GET_CLASS (setting)->update_one_secret (setting, secret_key, secret_value, &tmp_error);
-		if (tmp_error) {
+		success = NM_SETTING_GET_CLASS (setting)->update_one_secret (setting, secret_key, secret_value, &tmp_error);
+		g_assert (!((success == NM_SETTING_UPDATE_SECRET_ERROR) ^ (!!tmp_error)));
+
+		if (success == NM_SETTING_UPDATE_SECRET_ERROR) {
 			g_propagate_error (error, tmp_error);
-			return FALSE;
+			return NM_SETTING_UPDATE_SECRET_ERROR;
 		}
+
+		if (success == NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED)
+			result = NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED;
 	}
 
-	return TRUE;
+	return result;
 }
 
 static gboolean
@@ -851,7 +1126,6 @@ nm_setting_get_secret_flags (NMSetting *setting,
                              NMSettingSecretFlags *out_flags,
                              GError **error)
 {
-	g_return_val_if_fail (setting != NULL, FALSE);
 	g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
 	g_return_val_if_fail (secret_name != NULL, FALSE);
 
@@ -883,7 +1157,7 @@ set_secret_flags (NMSetting *setting,
  * @flags: the #NMSettingSecretFlags for the secret
  * @error: location to store error, or %NULL
  *
- * For a given secret, retrieves the #NMSettingSecretFlags describing how to
+ * For a given secret, stores the #NMSettingSecretFlags describing how to
  * handle that secret.
  *
  * Returns: %TRUE on success (if the given secret name was a valid property of
@@ -895,7 +1169,6 @@ nm_setting_set_secret_flags (NMSetting *setting,
                              NMSettingSecretFlags flags,
                              GError **error)
 {
-	g_return_val_if_fail (setting != NULL, FALSE);
 	g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
 	g_return_val_if_fail (secret_name != NULL, FALSE);
 	g_return_val_if_fail (flags <= NM_SETTING_SECRET_FLAGS_ALL, FALSE);
@@ -934,11 +1207,13 @@ nm_setting_to_string (NMSetting *setting)
 
 	for (i = 0; i < n_property_specs; i++) {
 		GParamSpec *prop_spec = property_specs[i];
-		GValue value = { 0 };
+		GValue value = G_VALUE_INIT;
 		char *value_str;
-		gboolean is_serializable;
 		gboolean is_default;
 
+		if (strcmp (prop_spec->name, NM_SETTING_NAME) == 0)
+			continue;
+
 		g_value_init (&value, prop_spec->value_type);
 		g_object_get_property (G_OBJECT (setting), prop_spec->name, &value);
 
@@ -946,22 +1221,14 @@ nm_setting_to_string (NMSetting *setting)
 		g_string_append_printf (string, "\t%s : %s", prop_spec->name, value_str);
 		g_free (value_str);
 
-		is_serializable = prop_spec->flags & NM_SETTING_PARAM_SERIALIZE;
 		is_default = g_param_value_defaults (prop_spec, &value);
-
 		g_value_unset (&value);
 
-		if (is_serializable || is_default) {
-			g_string_append (string, " (");
-
-			if (is_serializable)
-				g_string_append_c (string, 's');
-			if (is_default)
-				g_string_append_c (string, 'd');
-
-			g_string_append_c (string, ')');
-		}
-
+		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');
 	}
 
@@ -1001,48 +1268,34 @@ nm_setting_init (NMSetting *setting)
 
 static GObject*
 constructor (GType type,
-		   guint n_construct_params,
-		   GObjectConstructParam *construct_params)
+             guint n_construct_params,
+             GObjectConstructParam *construct_params)
 {
 	GObject *object;
-	NMSettingPrivate *priv;
 
 	object = G_OBJECT_CLASS (nm_setting_parent_class)->constructor (type,
-													    n_construct_params,
-													    construct_params);
-	if (!object)
-		return NULL;
-
-	priv = NM_SETTING_GET_PRIVATE (object);
-	if (!priv->name) {
-		g_warning ("Setting name is not set.");
-		g_object_unref (object);
-		object = NULL;
-	}
+	                                                                n_construct_params,
+	                                                                construct_params);
 
+	_ensure_setting_info (object, NM_SETTING_GET_PRIVATE (object));
 	return object;
 }
 
 static void
-finalize (GObject *object)
-{
-	NMSettingPrivate *priv = NM_SETTING_GET_PRIVATE (object);
-
-	g_free (priv->name);
-
-	G_OBJECT_CLASS (nm_setting_parent_class)->finalize (object);
-}
-
-static void
 set_property (GObject *object, guint prop_id,
-		    const GValue *value, GParamSpec *pspec)
+              const GValue *value, GParamSpec *pspec)
 {
 	NMSettingPrivate *priv = NM_SETTING_GET_PRIVATE (object);
 
 	switch (prop_id) {
 	case PROP_NAME:
-		g_free (priv->name);
-		priv->name = g_value_dup_string (value);
+		/* The setter for NAME is deprecated and should not be used anymore.
+		 * Keep the setter for NAME to remain backward compatible.
+		 * Only assert that the caller does not try to set the name to a different value
+		 * then the registered name, which would be extra wrong.
+		 **/
+		_ensure_setting_info (object, priv);
+		g_return_if_fail (!g_strcmp0 (priv->info->name, g_value_get_string (value)));
 		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -1052,7 +1305,7 @@ set_property (GObject *object, guint prop_id,
 
 static void
 get_property (GObject *object, guint prop_id,
-		    GValue *value, GParamSpec *pspec)
+              GValue *value, GParamSpec *pspec)
 {
 	NMSetting *setting = NM_SETTING (object);
 
@@ -1077,7 +1330,6 @@ nm_setting_class_init (NMSettingClass *setting_class)
 	object_class->constructor  = constructor;
 	object_class->set_property = set_property;
 	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;
@@ -1092,7 +1344,7 @@ nm_setting_class_init (NMSettingClass *setting_class)
 	 *
 	 * 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 'wireless' or 'wired'.
+	 * example "ppp" or "wireless" or "wired".
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_NAME,
diff --git a/libnm-util/nm-setting.h b/libnm-util/nm-setting.h
index b717b65a..51e7de48 100644
--- a/libnm-util/nm-setting.h
+++ b/libnm-util/nm-setting.h
@@ -29,6 +29,8 @@
 #include <glib.h>
 #include <glib-object.h>
 
+#include <nm-version.h>
+
 G_BEGIN_DECLS
 
 #define NM_TYPE_SETTING            (nm_setting_get_type ())
@@ -64,7 +66,7 @@ typedef enum
 GQuark nm_setting_error_quark (void);
 
 
-/* The property of the #NMSetting should be serialized */
+/* DEPRECATED AND UNUSED */
 #define NM_SETTING_PARAM_SERIALIZE    (1 << (0 + G_PARAM_USER_SHIFT))
 
 /* The property of the #NMSetting is required for the setting to be valid */
@@ -78,6 +80,9 @@ GQuark nm_setting_error_quark (void);
  */
 #define NM_SETTING_PARAM_FUZZY_IGNORE (1 << (3 + G_PARAM_USER_SHIFT))
 
+/* Note: all non-glib GParamFlags bits are reserved by NetworkManager */
+
+
 #define NM_SETTING_NAME "name"
 
 /**
@@ -134,6 +139,8 @@ typedef enum {
 	NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS = 0x00000004,
 	NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS = 0x00000008,
 	NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS = 0x00000010
+
+	/* 0x80000000 is used for a private flag */
 } NMSettingCompareFlags;
 
 
@@ -172,7 +179,7 @@ typedef struct {
 
 	GPtrArray  *(*need_secrets)      (NMSetting  *setting);
 
-	gboolean    (*update_one_secret) (NMSetting  *setting,
+	int         (*update_one_secret) (NMSetting  *setting,
 	                                  const char *key,
 	                                  GValue     *value,
 	                                  GError    **error);
@@ -195,7 +202,7 @@ typedef struct {
 	                                  const GParamSpec *prop_spec,
 	                                  NMSettingCompareFlags flags);
 
-	void        (*clear_secrets_with_flags) (NMSetting *setting,
+	gboolean    (*clear_secrets_with_flags) (NMSetting *setting,
 	                                         GParamSpec *pspec,
 	                                         NMSettingClearSecretsWithFlagsFn func,
 	                                         gpointer user_data);
diff --git a/libnm-util/nm-utils-enum-types.c b/libnm-util/nm-utils-enum-types.c
index 7df362be..9b3eb4f4 100644
--- a/libnm-util/nm-utils-enum-types.c
+++ b/libnm-util/nm-utils-enum-types.c
@@ -11,9 +11,12 @@
 #include "nm-setting-adsl.h" 
 #include "nm-setting-bluetooth.h" 
 #include "nm-setting-bond.h" 
+#include "nm-setting-team.h" 
+#include "nm-setting-team-port.h" 
 #include "nm-setting-bridge.h" 
 #include "nm-setting-bridge-port.h" 
 #include "nm-setting-connection.h" 
+#include "nm-setting-dcb.h" 
 #include "nm-setting-infiniband.h" 
 #include "nm-setting-ip4-config.h" 
 #include "nm-setting-vlan.h" 
@@ -21,6 +24,7 @@
 #include "nm-setting-ppp.h" 
 #include "nm-setting-pppoe.h" 
 #include "nm-setting-serial.h" 
+#include "nm-setting-generic.h" 
 #include "nm-setting-gsm.h" 
 #include "nm-setting-cdma.h" 
 #include "nm-setting-olpc-mesh.h" 
@@ -282,6 +286,46 @@ nm_setting_bond_error_get_type (void)
   return g_define_type_id__volatile;
 }
 GType
+nm_setting_team_error_get_type (void)
+{
+  static volatile gsize g_define_type_id__volatile = 0;
+
+  if (g_once_init_enter (&g_define_type_id__volatile))
+    {
+      static const GEnumValue values[] = {
+        { NM_SETTING_TEAM_ERROR_UNKNOWN, "NM_SETTING_TEAM_ERROR_UNKNOWN", "UnknownError" },
+        { NM_SETTING_TEAM_ERROR_INVALID_PROPERTY, "NM_SETTING_TEAM_ERROR_INVALID_PROPERTY", "InvalidProperty" },
+        { NM_SETTING_TEAM_ERROR_MISSING_PROPERTY, "NM_SETTING_TEAM_ERROR_MISSING_PROPERTY", "MissingProperty" },
+        { 0, NULL, NULL }
+      };
+      GType g_define_type_id =
+        g_enum_register_static (g_intern_static_string ("NMSettingTeamError"), values);
+      g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+    }
+
+  return g_define_type_id__volatile;
+}
+GType
+nm_setting_team_port_error_get_type (void)
+{
+  static volatile gsize g_define_type_id__volatile = 0;
+
+  if (g_once_init_enter (&g_define_type_id__volatile))
+    {
+      static const GEnumValue values[] = {
+        { NM_SETTING_TEAM_PORT_ERROR_UNKNOWN, "NM_SETTING_TEAM_PORT_ERROR_UNKNOWN", "UnknownError" },
+        { NM_SETTING_TEAM_PORT_ERROR_INVALID_PROPERTY, "NM_SETTING_TEAM_PORT_ERROR_INVALID_PROPERTY", "InvalidProperty" },
+        { NM_SETTING_TEAM_PORT_ERROR_MISSING_PROPERTY, "NM_SETTING_TEAM_PORT_ERROR_MISSING_PROPERTY", "MissingProperty" },
+        { 0, NULL, NULL }
+      };
+      GType g_define_type_id =
+        g_enum_register_static (g_intern_static_string ("NMSettingTeamPortError"), values);
+      g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+    }
+
+  return g_define_type_id__volatile;
+}
+GType
 nm_setting_bridge_error_get_type (void)
 {
   static volatile gsize g_define_type_id__volatile = 0;
@@ -344,6 +388,47 @@ nm_setting_connection_error_get_type (void)
   return g_define_type_id__volatile;
 }
 GType
+nm_setting_dcb_error_get_type (void)
+{
+  static volatile gsize g_define_type_id__volatile = 0;
+
+  if (g_once_init_enter (&g_define_type_id__volatile))
+    {
+      static const GEnumValue values[] = {
+        { NM_SETTING_DCB_ERROR_UNKNOWN, "NM_SETTING_DCB_ERROR_UNKNOWN", "UnknownError" },
+        { NM_SETTING_DCB_ERROR_INVALID_PROPERTY, "NM_SETTING_DCB_ERROR_INVALID_PROPERTY", "InvalidProperty" },
+        { NM_SETTING_DCB_ERROR_MISSING_PROPERTY, "NM_SETTING_DCB_ERROR_MISSING_PROPERTY", "MissingProperty" },
+        { 0, NULL, NULL }
+      };
+      GType g_define_type_id =
+        g_enum_register_static (g_intern_static_string ("NMSettingDcbError"), values);
+      g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+    }
+
+  return g_define_type_id__volatile;
+}
+GType
+nm_setting_dcb_flags_get_type (void)
+{
+  static volatile gsize g_define_type_id__volatile = 0;
+
+  if (g_once_init_enter (&g_define_type_id__volatile))
+    {
+      static const GEnumValue values[] = {
+        { NM_SETTING_DCB_FLAG_NONE, "NM_SETTING_DCB_FLAG_NONE", "none" },
+        { NM_SETTING_DCB_FLAG_ENABLE, "NM_SETTING_DCB_FLAG_ENABLE", "enable" },
+        { NM_SETTING_DCB_FLAG_ADVERTISE, "NM_SETTING_DCB_FLAG_ADVERTISE", "advertise" },
+        { NM_SETTING_DCB_FLAG_WILLING, "NM_SETTING_DCB_FLAG_WILLING", "willing" },
+        { 0, NULL, NULL }
+      };
+      GType g_define_type_id =
+        g_enum_register_static (g_intern_static_string ("NMSettingDcbFlags"), values);
+      g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+    }
+
+  return g_define_type_id__volatile;
+}
+GType
 nm_setting_infiniband_error_get_type (void)
 {
   static volatile gsize g_define_type_id__volatile = 0;
@@ -550,6 +635,26 @@ nm_setting_serial_error_get_type (void)
   return g_define_type_id__volatile;
 }
 GType
+nm_setting_generic_error_get_type (void)
+{
+  static volatile gsize g_define_type_id__volatile = 0;
+
+  if (g_once_init_enter (&g_define_type_id__volatile))
+    {
+      static const GEnumValue values[] = {
+        { NM_SETTING_GENERIC_ERROR_UNKNOWN, "NM_SETTING_GENERIC_ERROR_UNKNOWN", "UnknownError" },
+        { NM_SETTING_GENERIC_ERROR_INVALID_PROPERTY, "NM_SETTING_GENERIC_ERROR_INVALID_PROPERTY", "InvalidProperty" },
+        { NM_SETTING_GENERIC_ERROR_MISSING_PROPERTY, "NM_SETTING_GENERIC_ERROR_MISSING_PROPERTY", "MissingProperty" },
+        { 0, NULL, NULL }
+      };
+      GType g_define_type_id =
+        g_enum_register_static (g_intern_static_string ("NMSettingGenericError"), values);
+      g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+    }
+
+  return g_define_type_id__volatile;
+}
+GType
 nm_setting_gsm_error_get_type (void)
 {
   static volatile gsize g_define_type_id__volatile = 0;
diff --git a/libnm-util/nm-utils-enum-types.h b/libnm-util/nm-utils-enum-types.h
index 44737b92..9b14a5d3 100644
--- a/libnm-util/nm-utils-enum-types.h
+++ b/libnm-util/nm-utils-enum-types.h
@@ -33,12 +33,20 @@ GType nm_setting_bluetooth_error_get_type (void) G_GNUC_CONST;
 #define NM_TYPE_SETTING_BLUETOOTH_ERROR (nm_setting_bluetooth_error_get_type ())
 GType nm_setting_bond_error_get_type (void) G_GNUC_CONST;
 #define NM_TYPE_SETTING_BOND_ERROR (nm_setting_bond_error_get_type ())
+GType nm_setting_team_error_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_SETTING_TEAM_ERROR (nm_setting_team_error_get_type ())
+GType nm_setting_team_port_error_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_SETTING_TEAM_PORT_ERROR (nm_setting_team_port_error_get_type ())
 GType nm_setting_bridge_error_get_type (void) G_GNUC_CONST;
 #define NM_TYPE_SETTING_BRIDGE_ERROR (nm_setting_bridge_error_get_type ())
 GType nm_setting_bridge_port_error_get_type (void) G_GNUC_CONST;
 #define NM_TYPE_SETTING_BRIDGE_PORT_ERROR (nm_setting_bridge_port_error_get_type ())
 GType nm_setting_connection_error_get_type (void) G_GNUC_CONST;
 #define NM_TYPE_SETTING_CONNECTION_ERROR (nm_setting_connection_error_get_type ())
+GType nm_setting_dcb_error_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_SETTING_DCB_ERROR (nm_setting_dcb_error_get_type ())
+GType nm_setting_dcb_flags_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_SETTING_DCB_FLAGS (nm_setting_dcb_flags_get_type ())
 GType nm_setting_infiniband_error_get_type (void) G_GNUC_CONST;
 #define NM_TYPE_SETTING_INFINIBAND_ERROR (nm_setting_infiniband_error_get_type ())
 GType nm_setting_ip4_config_error_get_type (void) G_GNUC_CONST;
@@ -59,6 +67,8 @@ GType nm_setting_pppoe_error_get_type (void) G_GNUC_CONST;
 #define NM_TYPE_SETTING_PPPOE_ERROR (nm_setting_pppoe_error_get_type ())
 GType nm_setting_serial_error_get_type (void) G_GNUC_CONST;
 #define NM_TYPE_SETTING_SERIAL_ERROR (nm_setting_serial_error_get_type ())
+GType nm_setting_generic_error_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_SETTING_GENERIC_ERROR (nm_setting_generic_error_get_type ())
 GType nm_setting_gsm_error_get_type (void) G_GNUC_CONST;
 #define NM_TYPE_SETTING_GSM_ERROR (nm_setting_gsm_error_get_type ())
 GType nm_setting_gsm_network_type_get_type (void) G_GNUC_CONST;
diff --git a/libnm-util/nm-utils-private.h b/libnm-util/nm-utils-private.h
index fa1e3a01..9d73a939 100644
--- a/libnm-util/nm-utils-private.h
+++ b/libnm-util/nm-utils-private.h
@@ -26,12 +26,45 @@
 #ifndef __NM_UTILS_PRIVATE_H__
 #define __NM_UTILS_PRIVATE_H__
 
+#include "nm-setting-private.h"
+
 gboolean    _nm_utils_string_in_list   (const char *str,
                                         const char **valid_strings);
 
 gboolean    _nm_utils_string_slist_validate (GSList *list,
                                              const char **valid_values);
 
-void        _nm_utils_register_value_transformations (void);
+gboolean    _nm_utils_gvalue_array_validate (GValueArray *elements,
+                                             guint n_expected, ...);
+
+void        _nm_value_transforms_register (void);
+
+/***********************************************************/
+
+typedef struct NMUtilsPrivateData {
+	const char * (*nm_setting_ip4_config_get_address_label)      (NMSettingIP4Config *setting,
+	                                                              guint32             i);
+	gboolean     (*nm_setting_ip4_config_add_address_with_label) (NMSettingIP4Config *setting,
+	                                                              NMIP4Address       *address,
+	                                                              const char         *label);
+} NMUtilsPrivateData;
+
+const NMUtilsPrivateData *nm_utils_get_private (void);
+
+/**
+ * NM_UTILS_PRIVATE_CALL:
+ * @call: a call to a private libnm-util function
+ *
+ * Used to call private libnm-util functions. Eg, if there was a
+ * private function called nm_foo_get_bar(), you could call it like:
+ *
+ *   bar = NM_UTILS_PRIVATE_CALL (nm_foo_get_bar (foo, x, y, z));
+ *
+ * This macro only exists inside the NetworkManager source tree and
+ * is not part of the public API.
+ *
+ * Since: 0.9.10
+ */
+#define NM_UTILS_PRIVATE_CALL(call) (nm_utils_get_private ()->call)
 
 #endif
diff --git a/libnm-util/nm-utils.c b/libnm-util/nm-utils.c
index ef5b9781..0176d9c3 100644
--- a/libnm-util/nm-utils.c
+++ b/libnm-util/nm-utils.c
@@ -21,30 +21,22 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2005 - 2012 Red Hat, Inc.
+ * (C) Copyright 2005 - 2013 Red Hat, Inc.
  */
 
 #include "config.h"
+
 #include <string.h>
-#include <stdio.h>
 #include <stdlib.h>
-#include <errno.h>
-#include <arpa/inet.h>
 #include <netinet/ether.h>
 #include <linux/if_infiniband.h>
-
-#include <glib.h>
-#include <glib-object.h>
-#include <glib/gi18n.h>
-#include <dbus/dbus-glib.h>
 #include <uuid/uuid.h>
 
 #include "nm-utils.h"
 #include "nm-utils-private.h"
-#include "NetworkManager.h"
+#include "nm-glib-compat.h"
 #include "nm-dbus-glib-types.h"
-#include "nm-setting-ip4-config.h"
-#include "nm-setting-ip6-config.h"
+#include "nm-setting-private.h"
 #include "crypto.h"
 
 /**
@@ -52,7 +44,7 @@
  * @short_description: Utility functions
  * @include: nm-utils.h
  *
- * A collection of utility functions for working SSIDs, IP addresses, WiFi
+ * A collection of utility functions for working SSIDs, IP addresses, Wi-Fi
  * access points and devices, among other things.
  */
 
@@ -239,7 +231,7 @@ nm_utils_init (GError **error)
 		if (!crypto_init (error))
 			return FALSE;
 
-		_nm_utils_register_value_transformations ();
+		_nm_value_transforms_register ();
 	}
 	return TRUE;
 }
@@ -267,7 +259,7 @@ nm_utils_deinit (void)
  * nm_utils_ssid_to_utf8:
  * @ssid: a byte array containing the SSID data
  *
- * WiFi SSIDs are byte arrays, they are _not_ strings.  Thus, an SSID may
+ * Wi-Fi SSIDs are byte arrays, they are _not_ strings.  Thus, an SSID may
  * contain embedded NULLs and other unprintable characters.  Often it is
  * useful to print the SSID out for debugging purposes, but that should be the
  * _only_ use of this function.  Do not use this function for any persistent
@@ -425,7 +417,7 @@ nm_utils_same_ssid (const GByteArray * ssid1,
 
 	if (ssid1 == ssid2)
 		return TRUE;
-	if ((ssid1 && !ssid2) || (!ssid1 && ssid2))
+	if (!ssid1 || !ssid2)
 		return FALSE;
 
 	ssid1_len = ssid1->len;
@@ -470,7 +462,7 @@ value_dup (gpointer key, gpointer val, gpointer user_data)
  * nm_utils_gvalue_hash_dup:
  * @hash: a #GHashTable mapping string:GValue
  *
- * Utility function to duplicate a hash table of GValues.
+ * Utility function to duplicate a hash table of #GValues.
  *
  * Returns: (transfer container) (element-type utf8 GObject.Value): a newly allocated duplicated #GHashTable, caller must free the
  * returned hash with g_hash_table_unref() or g_hash_table_destroy()
@@ -497,17 +489,13 @@ nm_utils_gvalue_hash_dup (GHashTable *hash)
  * @elem_destroy_fn: user function called for each element in @list
  *
  * Utility function to free a #GSList.
+ *
+ * Deprecated: use g_slist_free_full().
  **/
 void
 nm_utils_slist_free (GSList *list, GDestroyNotify elem_destroy_fn)
 {
-	if (!list)
-		return;
-
-	if (elem_destroy_fn)
-		g_slist_foreach (list, (GFunc) elem_destroy_fn, NULL);
-
-	g_slist_free (list);
+	g_slist_free_full (list, elem_destroy_fn);
 }
 
 gboolean
@@ -535,624 +523,28 @@ _nm_utils_string_slist_validate (GSList *list, const char **valid_values)
 	return TRUE;
 }
 
-static void
-_nm_utils_convert_op_to_string (const GValue *src_value, GValue *dest_value)
-{
-	g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_OBJECT_PATH));
-
-	g_value_set_string (dest_value, (const char *) g_value_get_boxed (src_value));
-}
-
-static void
-_nm_utils_convert_strv_to_slist (const GValue *src_value, GValue *dest_value)
-{
-	char **str;
-	GSList *list = NULL;
-	guint i = 0;
-
-	g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), G_TYPE_STRV));
-
-	str = (char **) g_value_get_boxed (src_value);
-
-	while (str && str[i])
-		list = g_slist_prepend (list, g_strdup (str[i++]));
-
-	g_value_take_boxed (dest_value, g_slist_reverse (list));
-}
-
-static void
-_nm_utils_convert_strv_to_ptrarray (const GValue *src_value, GValue *dest_value)
-{
-	char **str;
-	GPtrArray *array = NULL;
-	guint i = 0;
-
-	g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), G_TYPE_STRV));
-
-	str = (char **) g_value_get_boxed (src_value);
-
-	array = g_ptr_array_sized_new (3);
-	while (str && str[i])
-		g_ptr_array_add (array, g_strdup (str[i++]));
-
-	g_value_take_boxed (dest_value, array);
-}
-
-static void
-_nm_utils_convert_strv_to_string (const GValue *src_value, GValue *dest_value)
-{
-	GSList *strings;
-	GString *printable;
-	GSList *iter;
-
-	g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_LIST_OF_STRING));
-
-	strings = (GSList *) g_value_get_boxed (src_value);
-
-	printable = g_string_new ("[");
-	for (iter = strings; iter; iter = g_slist_next (iter)) {
-		if (iter != strings)
-			g_string_append (printable, ", '");
-		else
-			g_string_append_c (printable, '\'');
-		g_string_append (printable, iter->data);
-		g_string_append_c (printable, '\'');
-	}
-	g_string_append_c (printable, ']');
-
-	g_value_take_string (dest_value, printable->str);
-	g_string_free (printable, FALSE);
-}
-
-static void
-_string_array_to_string (const GPtrArray *strings, GValue *dest_value)
+gboolean
+_nm_utils_gvalue_array_validate (GValueArray *elements, guint n_expected, ...)
 {
-	GString *printable;
+	va_list args;
+	GValue *tmp;
 	int i;
+	gboolean valid = FALSE;
 
-	printable = g_string_new ("[");
-	for (i = 0; strings && i < strings->len; i++) {
-		if (i > 0)
-			g_string_append (printable, ", '");
-		else
-			g_string_append_c (printable, '\'');
-		g_string_append (printable, g_ptr_array_index (strings, i));
-		g_string_append_c (printable, '\'');
-	}
-	g_string_append_c (printable, ']');
-
-	g_value_take_string (dest_value, printable->str);
-	g_string_free (printable, FALSE);
-}
-
-static void
-_nm_utils_convert_string_array_to_string (const GValue *src_value, GValue *dest_value)
-{
-	const GPtrArray *strings;
-
-	g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_ARRAY_OF_STRING));
-
-	strings = (const GPtrArray *) g_value_get_boxed (src_value);
-	_string_array_to_string (strings, dest_value);
-}
-
-static void
-_nm_utils_convert_op_array_to_string (const GValue *src_value, GValue *dest_value)
-{
-	const GPtrArray *strings;
-
-	g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH));
-
-	strings = (const GPtrArray *) g_value_get_boxed (src_value);
-	_string_array_to_string (strings, dest_value);
-}
-
-static void
-_nm_utils_convert_uint_array_to_string (const GValue *src_value, GValue *dest_value)
-{
-	GArray *array;
-	GString *printable;
-	guint i = 0;
-
-	g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_UINT_ARRAY));
-
-	array = (GArray *) g_value_get_boxed (src_value);
-
-	printable = g_string_new ("[");
-	while (array && (i < array->len)) {
-		char buf[INET_ADDRSTRLEN + 1];
-		struct in_addr addr;
-
-		if (i > 0)
-			g_string_append (printable, ", ");
-
-		memset (buf, 0, sizeof (buf));
-		addr.s_addr = g_array_index (array, guint32, i++);
-		if (!inet_ntop (AF_INET, &addr, buf, INET_ADDRSTRLEN))
-			g_warning ("%s: error converting IP4 address 0x%X",
-			           __func__, ntohl (addr.s_addr));
-		g_string_append_printf (printable, "%u (%s)", addr.s_addr, buf);
-	}
-	g_string_append_c (printable, ']');
-
-	g_value_take_string (dest_value, printable->str);
-	g_string_free (printable, FALSE);
-}
-
-static void
-_nm_utils_convert_ip4_addr_route_struct_array_to_string (const GValue *src_value, GValue *dest_value)
-{
-	GPtrArray *ptr_array;
-	GString *printable;
-	guint i = 0;
-
-	g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT));
-
-	ptr_array = (GPtrArray *) g_value_get_boxed (src_value);
-
-	printable = g_string_new ("[");
-	while (ptr_array && (i < ptr_array->len)) {
-		GArray *array;
-		char buf[INET_ADDRSTRLEN + 1];
-		struct in_addr addr;
-		gboolean is_addr; /* array contains address x route */
-
-		if (i > 0)
-			g_string_append (printable, ", ");
-
-		g_string_append (printable, "{ ");
-		array = (GArray *) g_ptr_array_index (ptr_array, i++);
-		if (array->len < 2) {
-			g_string_append (printable, "invalid");
-			continue;
-		}
-		is_addr = (array->len < 4);
-
-		memset (buf, 0, sizeof (buf));
-		addr.s_addr = g_array_index (array, guint32, 0);
-		if (!inet_ntop (AF_INET, &addr, buf, INET_ADDRSTRLEN))
-			g_warning ("%s: error converting IP4 address 0x%X",
-			           __func__, ntohl (addr.s_addr));
-		if (is_addr)
-			g_string_append_printf (printable, "ip = %s", buf);
-		else
-			g_string_append_printf (printable, "dst = %s", buf);
-		g_string_append (printable, ", ");
-
-		memset (buf, 0, sizeof (buf));
-		g_string_append_printf (printable, "px = %u",
-		                        g_array_index (array, guint32, 1));
-
-		if (array->len > 2) {
-			g_string_append (printable, ", ");
-
-			memset (buf, 0, sizeof (buf));
-			addr.s_addr = g_array_index (array, guint32, 2);
-			if (!inet_ntop (AF_INET, &addr, buf, INET_ADDRSTRLEN))
-				g_warning ("%s: error converting IP4 address 0x%X",
-				           __func__, ntohl (addr.s_addr));
-			if (is_addr)
-				g_string_append_printf (printable, "gw = %s", buf);
-			else
-				g_string_append_printf (printable, "nh = %s", buf);
-		}
-
-		if (array->len > 3) {
-			g_string_append (printable, ", ");
-
-			memset (buf, 0, sizeof (buf));
-			g_string_append_printf (printable, "mt = %u",
-			                        g_array_index (array, guint32, 3));
-		}
-
-		g_string_append (printable, " }");
-	}
-	g_string_append_c (printable, ']');
-
-	g_value_take_string (dest_value, printable->str);
-	g_string_free (printable, FALSE);
-}
-
-static void
-convert_one_gvalue_hash_entry (gpointer key, gpointer value, gpointer user_data)
-{
-	GString *printable = (GString *) user_data;
-	char *value_as_string;
-
-	value_as_string = g_strdup_value_contents ((GValue *) value);
-	g_string_append_printf (printable, " { '%s': %s },", (const char *) key, value_as_string);
-	g_free (value_as_string);
-}
-
-static void
-_nm_utils_convert_gvalue_hash_to_string (const GValue *src_value, GValue *dest_value)
-{
-	GHashTable *hash;
-	GString *printable;
-
-	g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_MAP_OF_VARIANT));
-
-	hash = (GHashTable *) g_value_get_boxed (src_value);
-
-	printable = g_string_new ("[");
-	g_hash_table_foreach (hash, convert_one_gvalue_hash_entry, printable);
-	g_string_append (printable, " ]");
-
-	g_value_take_string (dest_value, printable->str);
-	g_string_free (printable, FALSE);
-}
-
-static void
-convert_one_string_hash_entry (gpointer key, gpointer value, gpointer user_data)
-{
-	GString *printable = (GString *) user_data;
-
-	g_string_append_printf (printable, " { '%s': %s },", (const char *) key, (const char *) value);
-}
-
-static void
-_nm_utils_convert_string_hash_to_string (const GValue *src_value, GValue *dest_value)
-{
-	GHashTable *hash;
-	GString *printable;
-
-	g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_MAP_OF_STRING));
-
-	hash = (GHashTable *) g_value_get_boxed (src_value);
-
-	printable = g_string_new ("[");
-	if (hash)
-		g_hash_table_foreach (hash, convert_one_string_hash_entry, printable);
-	g_string_append (printable, " ]");
-
-	g_value_take_string (dest_value, printable->str);
-	g_string_free (printable, FALSE);
-}
-
-static void
-_nm_utils_convert_byte_array_to_string (const GValue *src_value, GValue *dest_value)
-{
-	GArray *array;
-	GString *printable;
-	guint i = 0;
-
-	g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_UCHAR_ARRAY));
-
-	array = (GArray *) g_value_get_boxed (src_value);
-
-	printable = g_string_new ("[");
-	if (array) {
-		while (i < MIN (array->len, 35)) {
-			if (i > 0)
-				g_string_append_c (printable, ' ');
-			g_string_append_printf (printable, "0x%02X",
-			                        g_array_index (array, unsigned char, i++));
-		}
-		if (i < array->len)
-			g_string_append (printable, " ... ");
-	}
-	g_string_append_c (printable, ']');
-
-	g_value_take_string (dest_value, printable->str);
-	g_string_free (printable, FALSE);
-}
-
-static gboolean
-_nm_utils_inet6_ntop (struct in6_addr *addr, char *buf)
-{
-	if (!inet_ntop (AF_INET6, addr, buf, INET6_ADDRSTRLEN)) {
-		int i;
-		GString *ip6_str = g_string_new (NULL);
-		g_string_append_printf (ip6_str, "%02X", addr->s6_addr[0]);
-		for (i = 1; i < 16; i++)
-			g_string_append_printf (ip6_str, " %02X", addr->s6_addr[i]);
-		g_warning ("%s: error converting IP6 address %s",
-		           __func__, ip6_str->str);
-		g_string_free (ip6_str, TRUE);
+	if (n_expected != elements->n_values)
 		return FALSE;
-	}
-	return TRUE;
-}
-
-static void
-_nm_utils_convert_ip6_dns_array_to_string (const GValue *src_value, GValue *dest_value)
-{
-	GPtrArray *ptr_array;
-	GString *printable;
-	guint i = 0;
-
-	g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UCHAR));
-
-	ptr_array = (GPtrArray *) g_value_get_boxed (src_value);
-
-	printable = g_string_new ("[");
-	while (ptr_array && (i < ptr_array->len)) {
-		GByteArray *bytearray;
-		char buf[INET6_ADDRSTRLEN];
-		struct in6_addr *addr;
-
-		if (i > 0)
-			g_string_append (printable, ", ");
-
-		bytearray = (GByteArray *) g_ptr_array_index (ptr_array, i++);
-		if (bytearray->len != 16) {
-			g_string_append (printable, "invalid");
-			continue;
-		}
-		addr = (struct in6_addr *) bytearray->data;
-		memset (buf, 0, sizeof (buf));
-		_nm_utils_inet6_ntop (addr, buf);
-		g_string_append_printf (printable, "%s", buf);
-	}
-	g_string_append_c (printable, ']');
-
-	g_value_take_string (dest_value, printable->str);
-	g_string_free (printable, FALSE);
-}
-
-static void
-_nm_utils_convert_ip6_addr_struct_array_to_string (const GValue *src_value, GValue *dest_value)
-{
-	GPtrArray *ptr_array;
-	GString *printable;
-	guint i = 0;
-
-	g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS));
-
-	ptr_array = (GPtrArray *) g_value_get_boxed (src_value);
-
-	printable = g_string_new ("[");
-	while (ptr_array && (i < ptr_array->len)) {
-		GValueArray *elements;
-		GValue *tmp;
-		GByteArray *ba_addr;
-		char buf[INET6_ADDRSTRLEN];
-		struct in6_addr *addr;
-		guint32 prefix;
-
-		if (i > 0)
-			g_string_append (printable, ", ");
-
-		g_string_append (printable, "{ ");
-		elements = (GValueArray *) g_ptr_array_index (ptr_array, i++);
-		if (   (elements->n_values != 3)
-		    || (G_VALUE_TYPE (g_value_array_get_nth (elements, 0)) != DBUS_TYPE_G_UCHAR_ARRAY)
-		    || (G_VALUE_TYPE (g_value_array_get_nth (elements, 1)) != G_TYPE_UINT)
-		    || (G_VALUE_TYPE (g_value_array_get_nth (elements, 2)) != DBUS_TYPE_G_UCHAR_ARRAY)) {
-			g_string_append (printable, "invalid }");
-			continue;
-		}
-
-		/* IPv6 address */
-		tmp = g_value_array_get_nth (elements, 0);
-		ba_addr = g_value_get_boxed (tmp);
-		if (ba_addr->len != 16) {
-			g_string_append (printable, "invalid }");
-			continue;
-		}
-		addr = (struct in6_addr *) ba_addr->data;
-		memset (buf, 0, sizeof (buf));
-		_nm_utils_inet6_ntop (addr, buf);
-		g_string_append_printf (printable, "ip = %s", buf);
-		g_string_append (printable, ", ");
-
-		/* Prefix */
-		tmp = g_value_array_get_nth (elements, 1);
-		prefix = g_value_get_uint (tmp);
-		if (prefix > 128) {
-			g_string_append (printable, "invalid }");
-			continue;
-		}
-		g_string_append_printf (printable, "px = %u", prefix);
-		g_string_append (printable, ", ");
-
-		/* IPv6 Gateway */
-		tmp = g_value_array_get_nth (elements, 2);
-		ba_addr = g_value_get_boxed (tmp);
-		if (ba_addr->len != 16) {
-			g_string_append (printable, "invalid }");
-			continue;
-		}
-		addr = (struct in6_addr *) ba_addr->data;
-		memset (buf, 0, sizeof (buf));
-		_nm_utils_inet6_ntop (addr, buf);
-		g_string_append_printf (printable, "gw = %s", buf);
-		g_string_append (printable, " }");
-	}
-	g_string_append_c (printable, ']');
-
-	g_value_take_string (dest_value, printable->str);
-	g_string_free (printable, FALSE);
-}
-
-static void
-_nm_utils_convert_ip6_route_struct_array_to_string (const GValue *src_value, GValue *dest_value)
-{
-	GPtrArray *ptr_array;
-	GString *printable;
-	guint i = 0;
-
-	g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_ARRAY_OF_IP6_ROUTE));
-
-	ptr_array = (GPtrArray *) g_value_get_boxed (src_value);
-
-	printable = g_string_new ("[");
-	while (ptr_array && (i < ptr_array->len)) {
-		GValueArray *elements;
-		GValue *tmp;
-		GByteArray *ba_addr;
-		char buf[INET6_ADDRSTRLEN];
-		struct in6_addr *addr;
-		guint32 prefix, metric;
-
-		if (i > 0)
-			g_string_append (printable, ", ");
-
-		g_string_append (printable, "{ ");
-		elements = (GValueArray *) g_ptr_array_index (ptr_array, i++);
-		if (   (elements->n_values != 4)
-		    || (G_VALUE_TYPE (g_value_array_get_nth (elements, 0)) != DBUS_TYPE_G_UCHAR_ARRAY)
-		    || (G_VALUE_TYPE (g_value_array_get_nth (elements, 1)) != G_TYPE_UINT)
-		    || (G_VALUE_TYPE (g_value_array_get_nth (elements, 2)) != DBUS_TYPE_G_UCHAR_ARRAY)
-		    || (G_VALUE_TYPE (g_value_array_get_nth (elements, 3)) != G_TYPE_UINT)) {
-			g_string_append (printable, "invalid");
-			continue;
-		}
-
-		/* Destination address */
-		tmp = g_value_array_get_nth (elements, 0);
-		ba_addr = g_value_get_boxed (tmp);
-		if (ba_addr->len != 16) {
-			g_string_append (printable, "invalid");
-			continue;
-		}
-		addr = (struct in6_addr *) ba_addr->data;
-		memset (buf, 0, sizeof (buf));
-		_nm_utils_inet6_ntop (addr, buf);
-		g_string_append_printf (printable, "dst = %s", buf);
-		g_string_append (printable, ", ");
-
-		/* Prefix */
-		tmp = g_value_array_get_nth (elements, 1);
-		prefix = g_value_get_uint (tmp);
-		if (prefix > 128) {
-			g_string_append (printable, "invalid");
-			continue;
-		}
-		g_string_append_printf (printable, "px = %u", prefix);
-		g_string_append (printable, ", ");
-
-		/* Next hop addresses */
-		tmp = g_value_array_get_nth (elements, 2);
-		ba_addr = g_value_get_boxed (tmp);
-		if (ba_addr->len != 16) {
-			g_string_append (printable, "invalid");
-			continue;
-		}
-		addr = (struct in6_addr *) ba_addr->data;
-		memset (buf, 0, sizeof (buf));
-		_nm_utils_inet6_ntop (addr, buf);
-		g_string_append_printf (printable, "nh = %s", buf);
-		g_string_append (printable, ", ");
-
-		/* Metric */
-		tmp = g_value_array_get_nth (elements, 3);
-		metric = g_value_get_uint (tmp);
-		g_string_append_printf (printable, "mt = %u", metric);
-
-		g_string_append (printable, " }");
-	}
-	g_string_append_c (printable, ']');
 
-	g_value_take_string (dest_value, printable->str);
-	g_string_free (printable, FALSE);
-}
-
-#define OLD_DBUS_TYPE_G_IP6_ADDRESS (dbus_g_type_get_struct ("GValueArray", DBUS_TYPE_G_UCHAR_ARRAY, G_TYPE_UINT, G_TYPE_INVALID))
-#define OLD_DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS (dbus_g_type_get_collection ("GPtrArray", OLD_DBUS_TYPE_G_IP6_ADDRESS))
-
-static void
-_nm_utils_convert_old_ip6_addr_array (const GValue *src_value, GValue *dst_value)
-{
-	GPtrArray *src_outer_array;
-	GPtrArray *dst_outer_array;
-	guint i;
-
-	g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), OLD_DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS));
-
-	src_outer_array = (GPtrArray *) g_value_get_boxed (src_value);
-	dst_outer_array = g_ptr_array_new ();
-
-	for (i = 0; src_outer_array && (i < src_outer_array->len); i++) {
-		GValueArray *src_addr_array;
-		GValueArray *dst_addr_array;
-		GValue element = {0, };
-		GValue *src_addr, *src_prefix;
-		GByteArray *ba;
-
-		src_addr_array = (GValueArray *) g_ptr_array_index (src_outer_array, i);
-
-		if (   (src_addr_array->n_values != 2)
-		    || (G_VALUE_TYPE (g_value_array_get_nth (src_addr_array, 0)) != DBUS_TYPE_G_UCHAR_ARRAY)
-		    || (G_VALUE_TYPE (g_value_array_get_nth (src_addr_array, 1)) != G_TYPE_UINT)) {
-			g_warning ("%s: invalid old IPv6 address type", __func__);
-			return;
-		}
-
-		dst_addr_array = g_value_array_new (3);
-
-		src_addr = g_value_array_get_nth (src_addr_array, 0);
-		g_value_array_append (dst_addr_array, src_addr);
-		src_prefix = g_value_array_get_nth (src_addr_array, 1);
-		g_value_array_append (dst_addr_array, src_prefix);
-
-		/* Blank Gateway */
-		g_value_init (&element, DBUS_TYPE_G_UCHAR_ARRAY);
-		ba = g_byte_array_new ();
-		g_byte_array_append (ba, (guint8 *) "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16);
-		g_value_take_boxed (&element, ba);
-		g_value_array_append (dst_addr_array, &element);
-		g_value_unset (&element);
-
-		g_ptr_array_add (dst_outer_array, dst_addr_array);
+	va_start (args, n_expected);
+	for (i = 0; i < n_expected; i++) {
+		tmp = g_value_array_get_nth (elements, i);
+		if (G_VALUE_TYPE (tmp) != va_arg (args, GType))
+			goto done;
 	}
+	valid = TRUE;
 
-	g_value_take_boxed (dst_value, dst_outer_array);
-}
-
-void
-_nm_utils_register_value_transformations (void)
-{
-	static gboolean registered = FALSE;
-
-	if (G_UNLIKELY (!registered)) {
-		g_value_register_transform_func (DBUS_TYPE_G_OBJECT_PATH,
-		                                 G_TYPE_STRING,
-		                                 _nm_utils_convert_op_to_string);
-		g_value_register_transform_func (G_TYPE_STRV, 
-		                                 DBUS_TYPE_G_LIST_OF_STRING,
-		                                 _nm_utils_convert_strv_to_slist);
-		g_value_register_transform_func (G_TYPE_STRV,
-		                                 DBUS_TYPE_G_ARRAY_OF_STRING,
-		                                 _nm_utils_convert_strv_to_ptrarray);
-		g_value_register_transform_func (DBUS_TYPE_G_LIST_OF_STRING,
-		                                 G_TYPE_STRING, 
-		                                 _nm_utils_convert_strv_to_string);
-		g_value_register_transform_func (DBUS_TYPE_G_ARRAY_OF_STRING,
-		                                 G_TYPE_STRING,
-		                                 _nm_utils_convert_string_array_to_string);
-		g_value_register_transform_func (DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH,
-		                                 G_TYPE_STRING,
-		                                 _nm_utils_convert_op_array_to_string);
-		g_value_register_transform_func (DBUS_TYPE_G_UINT_ARRAY,
-		                                 G_TYPE_STRING, 
-		                                 _nm_utils_convert_uint_array_to_string);
-		g_value_register_transform_func (DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT,
-		                                 G_TYPE_STRING, 
-		                                 _nm_utils_convert_ip4_addr_route_struct_array_to_string);
-		g_value_register_transform_func (DBUS_TYPE_G_MAP_OF_VARIANT,
-		                                 G_TYPE_STRING, 
-		                                 _nm_utils_convert_gvalue_hash_to_string);
-		g_value_register_transform_func (DBUS_TYPE_G_MAP_OF_STRING,
-		                                 G_TYPE_STRING, 
-		                                 _nm_utils_convert_string_hash_to_string);
-		g_value_register_transform_func (DBUS_TYPE_G_UCHAR_ARRAY,
-		                                 G_TYPE_STRING,
-		                                 _nm_utils_convert_byte_array_to_string);
-		g_value_register_transform_func (DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UCHAR,
-		                                 G_TYPE_STRING, 
-		                                 _nm_utils_convert_ip6_dns_array_to_string);
-		g_value_register_transform_func (DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS,
-		                                 G_TYPE_STRING, 
-		                                 _nm_utils_convert_ip6_addr_struct_array_to_string);
-		g_value_register_transform_func (DBUS_TYPE_G_ARRAY_OF_IP6_ROUTE,
-		                                 G_TYPE_STRING, 
-		                                 _nm_utils_convert_ip6_route_struct_array_to_string);
-		g_value_register_transform_func (OLD_DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS,
-		                                 DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS,
-		                                 _nm_utils_convert_old_ip6_addr_array);
-		registered = TRUE;
-	}
+done:
+	va_end (args);
+	return valid;
 }
 
 static gboolean
@@ -1206,7 +598,7 @@ device_supports_ap_ciphers (guint32 dev_caps,
  * nm_utils_ap_mode_security_valid:
  * @type: the security type to check device capabilties against,
  * e.g. #NMU_SEC_STATIC_WEP
- * @wifi_caps: bitfield of the capabilities of the specific WiFi device, e.g.
+ * @wifi_caps: bitfield of the capabilities of the specific Wi-Fi device, e.g.
  * #NM_WIFI_DEVICE_CAP_CIPHER_WEP40
  *
  * Given a set of device capabilities, and a desired security type to check
@@ -1244,7 +636,7 @@ nm_utils_ap_mode_security_valid (NMUtilsSecurityType type,
  * nm_utils_security_valid:
  * @type: the security type to check AP flags and device capabilties against,
  * e.g. #NMU_SEC_STATIC_WEP
- * @wifi_caps: bitfield of the capabilities of the specific WiFi device, e.g.
+ * @wifi_caps: bitfield of the capabilities of the specific Wi-Fi device, e.g.
  * #NM_WIFI_DEVICE_CAP_CIPHER_WEP40
  * @have_ap: whether the @ap_flags, @ap_wpa, and @ap_rsn arguments are valid
  * @adhoc: whether the capabilities being tested are from an Ad-Hoc AP (IBSS)
@@ -1333,6 +725,7 @@ nm_utils_security_valid (NMUtilsSecurityType type,
 			/* Ad-Hoc WPA APs won't necessarily have the PSK flag set, and
 			 * they don't have any pairwise ciphers. */
 			if (adhoc) {
+				/* coverity[dead_error_line] */
 				if (   (ap_wpa & NM_802_11_AP_SEC_GROUP_TKIP)
 				    && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_TKIP))
 					return TRUE;
@@ -1361,6 +754,7 @@ nm_utils_security_valid (NMUtilsSecurityType type,
 			/* Ad-Hoc WPA APs won't necessarily have the PSK flag set, and
 			 * they don't have any pairwise ciphers, nor any RSA flags yet. */
 			if (adhoc) {
+				/* coverity[dead_error_line] */
 				if (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_TKIP)
 					return TRUE;
 				if (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP)
@@ -1492,11 +886,11 @@ nm_utils_wpa_psk_valid (const char *psk)
 
 /**
  * nm_utils_ip4_addresses_from_gvalue:
- * @value: gvalue containing a GPtrArray of GArrays of guint32s
+ * @value: #GValue containing a #GPtrArray of #GArrays of #guint32s
  *
- * Utility function to convert a #GPtrArray of #GArrays of guint32s representing
+ * Utility function to convert a #GPtrArray of #GArrays of #guint32s representing
  * a list of NetworkManager IPv4 addresses (which is a tuple of address, gateway,
- * and prefix) into a GSList of #NMIP4Address objects.  The specific format of
+ * and prefix) into a #GSList of #NMIP4Address objects.  The specific format of
  * this serialization is not guaranteed to be stable and the #GArray may be
  * extended in the future.
  *
@@ -1537,7 +931,7 @@ nm_utils_ip4_addresses_from_gvalue (const GValue *value)
  * g_value_unset().
  *
  * Utility function to convert a #GSList of #NMIP4Address objects into a
- * GPtrArray of GArrays of guint32s representing a list of NetworkManager IPv4
+ * #GPtrArray of #GArrays of #guint32s representing a list of NetworkManager IPv4
  * addresses (which is a tuple of address, gateway, and prefix).   The specific
  * format of this serialization is not guaranteed to be stable and may be
  * extended in the future.
@@ -1574,11 +968,11 @@ nm_utils_ip4_addresses_to_gvalue (GSList *list, GValue *value)
 
 /**
  * nm_utils_ip4_routes_from_gvalue:
- * @value: gvalue containing a GPtrArray of GArrays of guint32s
+ * @value: #GValue containing a #GPtrArray of #GArrays of #guint32s
  *
- * Utility function to convert a GPtrArray of GArrays of guint32s representing
+ * Utility function to convert a #GPtrArray of #GArrays of #guint32s representing
  * a list of NetworkManager IPv4 routes (which is a tuple of route, next hop,
- * prefix, and metric) into a GSList of #NMIP4Route objects.  The specific
+ * prefix, and metric) into a #GSList of #NMIP4Route objects.  The specific
  * format of this serialization is not guaranteed to be stable and may be
  * extended in the future.
  *
@@ -1600,7 +994,7 @@ nm_utils_ip4_routes_from_gvalue (const GValue *value)
 			g_warning ("Ignoring invalid IP4 route");
 			continue;
 		}
-		
+
 		route = nm_ip4_route_new ();
 		nm_ip4_route_set_dest (route, g_array_index (array, guint32, 0));
 		nm_ip4_route_set_prefix (route, g_array_index (array, guint32, 1));
@@ -1620,7 +1014,7 @@ nm_utils_ip4_routes_from_gvalue (const GValue *value)
  * g_value_unset().
  *
  * Utility function to convert a #GSList of #NMIP4Route objects into a
- * GPtrArray of GArrays of guint32s representing a list of NetworkManager IPv4
+ * #GPtrArray of #GArrays of #guint32s representing a list of NetworkManager IPv4
  * routes (which is a tuple of route, next hop, prefix, and metric).   The
  * specific format of this serialization is not guaranteed to be stable and may
  * be extended in the future.
@@ -1731,11 +1125,11 @@ nm_utils_ip4_get_default_prefix (guint32 ip)
 
 /**
  * nm_utils_ip6_addresses_from_gvalue:
- * @value: gvalue containing a GPtrArray of GValueArrays of (GArray of guchars) and guint32
+ * @value: gvalue containing a GPtrArray of GValueArrays of (GArray of guchars) and #guint32
  *
- * Utility function to convert a #GPtrArray of #GValueArrays of (#GArray of guchars) and guint32
+ * Utility function to convert a #GPtrArray of #GValueArrays of (#GArray of guchars) and #guint32
  * representing a list of NetworkManager IPv6 addresses (which is a tuple of address,
- * prefix, and gateway), into a GSList of #NMIP6Address objects.  The specific format of
+ * prefix, and gateway), into a #GSList of #NMIP6Address objects.  The specific format of
  * this serialization is not guaranteed to be stable and the #GValueArray may be
  * extended in the future.
  *
@@ -1763,15 +1157,9 @@ nm_utils_ip6_addresses_from_gvalue (const GValue *value)
 			continue;
 		}
 
-		if (   (G_VALUE_TYPE (g_value_array_get_nth (elements, 0)) != DBUS_TYPE_G_UCHAR_ARRAY)
-		    || (G_VALUE_TYPE (g_value_array_get_nth (elements, 1)) != G_TYPE_UINT)) {
-			g_warning ("%s: ignoring invalid IP6 address structure", __func__);
-			continue;
-		}
-
-		/* Check optional 3rd element (gateway) */
-		if (   elements->n_values == 3
-		    && (G_VALUE_TYPE (g_value_array_get_nth (elements, 2)) != DBUS_TYPE_G_UCHAR_ARRAY)) {
+		/* Third element (gateway) is optional */
+		if (   !_nm_utils_gvalue_array_validate (elements, 2, DBUS_TYPE_G_UCHAR_ARRAY, G_TYPE_UINT)
+		    && !_nm_utils_gvalue_array_validate (elements, 3, DBUS_TYPE_G_UCHAR_ARRAY, G_TYPE_UINT, DBUS_TYPE_G_UCHAR_ARRAY)) {
 			g_warning ("%s: ignoring invalid IP6 address structure", __func__);
 			continue;
 		}
@@ -1822,7 +1210,7 @@ nm_utils_ip6_addresses_from_gvalue (const GValue *value)
  * g_value_unset().
  *
  * Utility function to convert a #GSList of #NMIP6Address objects into a
- * GPtrArray of GValueArrays representing a list of NetworkManager IPv6 addresses
+ * #GPtrArray of #GValueArrays representing a list of NetworkManager IPv6 addresses
  * (which is a tuple of address, prefix, and gateway). The specific format of
  * this serialization is not guaranteed to be stable and may be extended in the
  * future.
@@ -1838,7 +1226,7 @@ nm_utils_ip6_addresses_to_gvalue (GSList *list, GValue *value)
 	for (iter = list; iter; iter = iter->next) {
 		NMIP6Address *addr = (NMIP6Address *) iter->data;
 		GValueArray *array;
-		GValue element = {0, };
+		GValue element = G_VALUE_INIT;
 		GByteArray *ba;
 
 		array = g_value_array_new (3);
@@ -1873,13 +1261,13 @@ nm_utils_ip6_addresses_to_gvalue (GSList *list, GValue *value)
 
 /**
  * nm_utils_ip6_routes_from_gvalue:
- * @value: gvalue containing a GPtrArray of GValueArrays of (GArray or guchars), guint32,
- * (GArray of guchars), and guint32
+ * @value: #GValue containing a #GPtrArray of #GValueArrays of (#GArray of #guchars), #guint32,
+ * (#GArray of #guchars), and #guint32
  *
- * Utility function GPtrArray of GValueArrays of (GArray or guchars), guint32,
- * (GArray of guchars), and guint32 representing a list of NetworkManager IPv6
+ * Utility function #GPtrArray of #GValueArrays of (#GArray of #guchars), #guint32,
+ * (#GArray of #guchars), and #guint32 representing a list of NetworkManager IPv6
  * routes (which is a tuple of destination, prefix, next hop, and metric)
- * into a GSList of #NMIP6Route objects.  The specific format of this serialization
+ * into a #GSList of #NMIP6Route objects.  The specific format of this serialization
  * is not guaranteed to be stable and may be extended in the future.
  *
  * Returns: (transfer full) (element-type NetworkManager.IP6Route): a newly allocated #GSList of #NMIP6Route objects
@@ -1898,11 +1286,11 @@ nm_utils_ip6_routes_from_gvalue (const GValue *value)
 		guint prefix, metric;
 		NMIP6Route *route;
 
-		if (   (route_values->n_values != 4)
-		    || (G_VALUE_TYPE (g_value_array_get_nth (route_values, 0)) != DBUS_TYPE_G_UCHAR_ARRAY)
-			|| (G_VALUE_TYPE (g_value_array_get_nth (route_values, 1)) != G_TYPE_UINT)
-		    || (G_VALUE_TYPE (g_value_array_get_nth (route_values, 2)) != DBUS_TYPE_G_UCHAR_ARRAY)
-			|| (G_VALUE_TYPE (g_value_array_get_nth (route_values, 3)) != G_TYPE_UINT)) {
+		if (!_nm_utils_gvalue_array_validate (route_values, 4,
+		                                      DBUS_TYPE_G_UCHAR_ARRAY,
+		                                      G_TYPE_UINT,
+		                                      DBUS_TYPE_G_UCHAR_ARRAY,
+		                                      G_TYPE_UINT)) {
 			g_warning ("Ignoring invalid IP6 route");
 			continue;
 		}
@@ -1943,8 +1331,8 @@ nm_utils_ip6_routes_from_gvalue (const GValue *value)
  * which should be unset by the caller (when no longer needed) with
  * g_value_unset().
  *
- * Utility function to convert a #GSList of #NMIP6Route objects into a GPtrArray of
- * GValueArrays of (GArray or guchars), guint32, (GArray of guchars), and guint32
+ * Utility function to convert a #GSList of #NMIP6Route objects into a #GPtrArray of
+ * #GValueArrays of (#GArray of #guchars), #guint32, (#GArray of #guchars), and #guint32
  * representing a list of NetworkManager IPv6 routes (which is a tuple of destination,
  * prefix, next hop, and metric).  The specific format of this serialization is not 
  * guaranteed to be stable and may be extended in the future.
@@ -1962,7 +1350,7 @@ nm_utils_ip6_routes_to_gvalue (GSList *list, GValue *value)
 		GValueArray *array;
 		const struct in6_addr *addr;
 		GByteArray *ba;
-		GValue element = {0, };
+		GValue element = G_VALUE_INIT;
 
 		array = g_value_array_new (4);
 
@@ -2003,7 +1391,7 @@ nm_utils_ip6_routes_to_gvalue (GSList *list, GValue *value)
  * @value: a #GValue
  *
  * Converts a #GValue containing a #GPtrArray of IP6 DNS, represented as
- * #GByteArray<!-- -->s into a #GSList of #in6_addr<!-- -->s.
+ * #GByteArrays into a #GSList of <literal><type>struct in6_addr</type></literal>s.
  *
  * Returns: a #GSList of IP6 addresses.
  */
@@ -2040,10 +1428,11 @@ nm_utils_ip6_dns_from_gvalue (const GValue *value)
  * addresses, which should be unset by the caller (when no longer needed) with
  * g_value_unset().
  *
- * Utility function to convert a #GSList of 'struct in6_addr' structs into a
- * GPtrArray of GByteArrays representing each server's IPv6 addresses in
- * network byte order.  The specific format of this serialization is not
- * guaranteed to be stable and may be extended in the future.
+ * Utility function to convert a #GSList of <literal><type>struct
+ * in6_addr</type></literal> structs into a #GPtrArray of #GByteArrays
+ * representing each server's IPv6 addresses in network byte order.
+ * The specific format of this serialization is not guaranteed to be
+ * stable and may be extended in the future.
  */
 void
 nm_utils_ip6_dns_to_gvalue (GSList *list, GValue *value)
@@ -2127,7 +1516,8 @@ out:
 }
 
 static char *
-make_key (const char *salt,
+make_key (const char *cipher,
+          const char *salt,
           const gsize salt_len,
           const char *password,
           gsize *out_len,
@@ -2141,14 +1531,12 @@ make_key (const char *salt,
 	g_return_val_if_fail (password != NULL, NULL);
 	g_return_val_if_fail (out_len != NULL, NULL);
 
+	if (!strcmp (cipher, "DES-EDE3-CBC"))
+		digest_len = 24;
+	else if (!strcmp (cipher, "AES-128-CBC"))
+		digest_len = 16;
+
 	key = g_malloc0 (digest_len + 1);
-	if (!key) {
-		g_set_error (error,
-		             NM_CRYPTO_ERROR,
-		             NM_CRYPTO_ERR_OUT_OF_MEMORY,
-		             _("Not enough memory to make encryption key."));
-		return NULL;
-	}
 
 	if (!crypto_md5_hash (salt, salt_len, password, strlen (password), key, digest_len, error)) {
 		*out_len = 0;
@@ -2161,46 +1549,9 @@ make_key (const char *salt,
 	return key;
 }
 
-/*
- * utils_bin2hexstr
- *
- * Convert a byte-array into a hexadecimal string.
- *
- * Code originally by Alex Larsson <alexl@redhat.com> and
- *  copyright Red Hat, Inc. under terms of the LGPL.
- *
- */
-static char *
-utils_bin2hexstr (const char *bytes, int len, int final_len)
-{
-	static char hex_digits[] = "0123456789abcdef";
-	char *result;
-	int i;
-	gsize buflen = (len * 2) + 1;
-
-	g_return_val_if_fail (bytes != NULL, NULL);
-	g_return_val_if_fail (len > 0, NULL);
-	g_return_val_if_fail (len < 4096, NULL);   /* Arbitrary limit */
-	if (final_len > -1)
-		g_return_val_if_fail (final_len < buflen, NULL);
-
-	result = g_malloc0 (buflen);
-	for (i = 0; i < len; i++)
-	{
-		result[2*i] = hex_digits[(bytes[i] >> 4) & 0xf];
-		result[2*i+1] = hex_digits[bytes[i] & 0xf];
-	}
-	/* Cut converted key off at the correct length for this cipher type */
-	if (final_len > -1)
-		result[final_len] = '\0';
-	else
-		result[buflen - 1] = '\0';
-
-	return result;
-}
-
 /**
- * nm_utils_rsa_key_encrypt:
+ * nm_utils_rsa_key_encrypt_helper:
+ * @cipher: cipher to use for encryption ("DES-EDE3-CBC" or "AES-128-CBC")
  * @data: RSA private key data to be encrypted
  * @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
@@ -2214,13 +1565,15 @@ utils_bin2hexstr (const char *bytes, int len, int final_len)
  * 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 GByteArray *data,
-                          const char *in_password,
-                          char **out_password,
-                          GError **error)
-{
-	char salt[8];
+static GByteArray *
+nm_utils_rsa_key_encrypt_helper (const char *cipher,
+                                 const GByteArray *data,
+                                 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;
@@ -2229,6 +1582,7 @@ nm_utils_rsa_key_encrypt (const GByteArray *data,
 	const char *p;
 	GByteArray *ret = NULL;
 
+	g_return_val_if_fail (!g_strcmp0 (cipher, CIPHER_DES_EDE3_CBC) || !g_strcmp0 (cipher, CIPHER_AES_CBC), NULL);
 	g_return_val_if_fail (data != NULL, NULL);
 	g_return_val_if_fail (data->len > 0, NULL);
 	if (out_password)
@@ -2238,52 +1592,36 @@ nm_utils_rsa_key_encrypt (const GByteArray *data,
 	if (!in_password) {
 		if (!crypto_randomize (pw_buf, sizeof (pw_buf), error))
 			return NULL;
-		in_password = tmp_password = utils_bin2hexstr ((const char *) pw_buf, sizeof (pw_buf), -1);
+		in_password = tmp_password = nm_utils_bin2hexstr ((const char *) pw_buf, sizeof (pw_buf), -1);
 	}
 
-	if (!crypto_randomize (salt, sizeof (salt), error))
+	if (g_strcmp0 (cipher, CIPHER_AES_CBC) == 0)
+		salt_len = 16;
+	else
+		salt_len = 8;
+
+	if (!crypto_randomize (salt, salt_len, error))
 		goto out;
 
-	key = make_key (&salt[0], sizeof (salt), in_password, &key_len, error);
+	key = make_key (cipher, &salt[0], salt_len, in_password, &key_len, error);
 	if (!key)
 		goto out;
 
-	enc = crypto_encrypt (CIPHER_DES_EDE3_CBC, data, salt, sizeof (salt), key, key_len, &enc_len, error);
+	enc = crypto_encrypt (cipher, data, salt, salt_len, key, key_len, &enc_len, error);
 	if (!enc)
 		goto out;
 
 	pem = g_string_sized_new (enc_len * 2 + 100);
-	if (!pem) {
-		g_set_error_literal (error, NM_CRYPTO_ERROR,
-		                     NM_CRYPTO_ERR_OUT_OF_MEMORY,
-		                     _("Could not allocate memory for PEM file creation."));
-		goto out;
-	}
-
 	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 = utils_bin2hexstr ((const char *) salt, sizeof (salt), 16);
-	if (!tmp) {
-		g_set_error (error, NM_CRYPTO_ERROR,
-		             NM_CRYPTO_ERR_OUT_OF_MEMORY,
-		             _("Could not allocate memory for writing IV to PEM file."));
-		goto out;
-	}
-
-	g_string_append_printf (pem, "DEK-Info: DES-EDE3-CBC,%s\n\n", tmp);
+	tmp = nm_utils_bin2hexstr ((const char *) salt, salt_len, salt_len * 2);
+	g_string_append_printf (pem, "DEK-Info: %s,%s\n\n", cipher, tmp);
 	g_free (tmp);
 
 	/* Convert the encrypted key to a base64 string */
 	p = tmp = g_base64_encode ((const guchar *) enc, enc_len);
-	if (!tmp) {
-		g_set_error (error, NM_CRYPTO_ERROR,
-		             NM_CRYPTO_ERR_OUT_OF_MEMORY,
-		             _("Could not allocate memory for writing encrypted key to PEM file."));
-		goto out;
-	}
-
 	left = strlen (tmp);
 	while (left > 0) {
 		g_string_append_len (pem, p, (left < 64) ? left : 64);
@@ -2296,12 +1634,6 @@ nm_utils_rsa_key_encrypt (const GByteArray *data,
 	g_string_append (pem, "-----END RSA PRIVATE KEY-----\n");
 
 	ret = g_byte_array_sized_new (pem->len);
-	if (!ret) {
-		g_set_error (error, NM_CRYPTO_ERROR,
-		             NM_CRYPTO_ERR_OUT_OF_MEMORY,
-		             _("Could not allocate memory for PEM file data."));
-		goto out;
-	}
 	g_byte_array_append (ret, (const unsigned char *) pem->str, pem->len);
 	if (tmp_password && out_password)
 		*out_password = g_strdup (tmp_password);
@@ -2327,6 +1659,65 @@ out:
 }
 
 /**
+ * nm_utils_rsa_key_encrypt:
+ * @data: RSA private key data to be encrypted
+ * @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 GByteArray *data,
+                          const char *in_password,
+                          char **out_password,
+                          GError **error)
+{
+
+
+	return nm_utils_rsa_key_encrypt_helper (CIPHER_DES_EDE3_CBC,
+	                                        data,
+	                                        in_password,
+	                                        out_password,
+	                                        error);
+}
+
+/**
+ * nm_utils_rsa_key_encrypt_aes:
+ * @data: RSA private key data to be encrypted
+ * @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 AES 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_aes (const GByteArray *data,
+                              const char *in_password,
+                              char **out_password,
+                              GError **error)
+{
+
+	return nm_utils_rsa_key_encrypt_helper (CIPHER_AES_CBC,
+	                                        data,
+	                                        in_password,
+	                                        out_password,
+	                                        error);
+}
+
+/**
  * nm_utils_file_is_pkcs12:
  * @filename: name of the file to test
  *
@@ -2419,7 +1810,7 @@ static struct cf_pair bg_table[] = {
  * nm_utils_wifi_freq_to_channel:
  * @freq: frequency
  *
- * Utility function to translate a WiFi frequency to its corresponding channel.
+ * Utility function to translate a Wi-Fi frequency to its corresponding channel.
  *
  * Returns: the channel represented by the frequency or 0
  **/
@@ -2446,7 +1837,7 @@ nm_utils_wifi_freq_to_channel (guint32 freq)
  * @channel: channel
  * @band: frequency band for wireless ("a" or "bg")
  *
- * Utility function to translate a WiFi channel to its corresponding frequency.
+ * Utility function to translate a Wi-Fi channel to its corresponding frequency.
  *
  * Returns: the frequency represented by the channel of the band,
  *          or -1 when the freq is invalid, or 0 when the band
@@ -2476,7 +1867,7 @@ nm_utils_wifi_channel_to_freq (guint32 channel, const char *band)
  * @direction: whether going downward (0 or less) or upward (1 or more)
  * @band: frequency band for wireless ("a" or "bg")
  *
- * Utility function to find out next/previous WiFi channel for a channel.
+ * Utility function to find out next/previous Wi-Fi channel for a channel.
  *
  * Returns: the next channel in the specified direction or 0
  **/
@@ -2523,7 +1914,7 @@ nm_utils_wifi_find_next_channel (guint32 channel, int direction, char *band)
  * @channel: channel
  * @band: frequency band for wireless ("a" or "bg")
  *
- * Utility function to verify WiFi channel validity.
+ * Utility function to verify Wi-Fi channel validity.
  *
  * Returns: %TRUE or %FALSE
  **/
@@ -2555,7 +1946,7 @@ nm_utils_wifi_is_channel_valid (guint32 channel, const char *band)
  *
  * Returns the length in octets of a hardware address of type @type.
  *
- * Return value: the length
+ * Return value: the positive length, or -1 if the type is unknown/unsupported.
  */
 int
 nm_utils_hwaddr_len (int type)
@@ -2565,18 +1956,25 @@ nm_utils_hwaddr_len (int type)
 	else if (type == ARPHRD_INFINIBAND)
 		return INFINIBAND_ALEN;
 	else
-		g_return_val_if_reached (-1);
+		return -1;
 }
 
 /**
  * nm_utils_hwaddr_type:
  * @len: the length of hardware address in bytes
  *
- * Returns the type (either %ARPHRD_ETHER or %ARPHRD_INFINIBAND) of the raw
- * address given its length.
+ * Returns the type (either %ARPHRD_ETHER or %ARPHRD_INFINIBAND) of
+ * the raw address given its length.
+ *
+ * Return value: the type, either %ARPHRD_ETHER or %ARPHRD_INFINIBAND.
+ * If the length is unexpected, return -1 (unsupported type/length).
  *
- * Return value: the type, either %ARPHRD_ETHER or %ARPHRD_INFINIBAND, or -1 if
- * the address length was not recognized
+ * Deprecated: This could not be extended to cover other types, since
+ * there is not a one-to-one mapping between types and lengths. This
+ * was mostly only used to get a type to pass to
+ * nm_utils_hwaddr_ntoa() or nm_utils_hwaddr_aton() when you only had
+ * a length; but you can just use nm_utils_hwaddr_ntoa_len() or
+ * nm_utils_hwaddr_aton_len() now instead.
  */
 int
 nm_utils_hwaddr_type (int len)
@@ -2586,7 +1984,7 @@ nm_utils_hwaddr_type (int len)
 	else if (len == INFINIBAND_ALEN)
 		return ARPHRD_INFINIBAND;
 	else
-		g_return_val_if_reached (-1);
+		return -1;
 }
 
 #define HEXVAL(c) ((c) <= '9' ? (c) - '0' : ((c) & 0x4F) - 'A' + 10)
@@ -2601,16 +1999,110 @@ nm_utils_hwaddr_type (int len)
  * nm_utils_hwaddr_atoba() if you'd rather have the result in a
  * #GByteArray.
  *
+ * See also nm_utils_hwaddr_aton_len(), which takes an output length
+ * instead of a type.
+ *
  * Return value: @buffer, or %NULL if @asc couldn't be parsed
  */
 guint8 *
 nm_utils_hwaddr_aton (const char *asc, int type, gpointer buffer)
 {
+	int len = nm_utils_hwaddr_len (type);
+
+	if (len <= 0) {
+		g_return_val_if_reached (NULL);
+		return NULL;
+	}
+	return nm_utils_hwaddr_aton_len (asc, buffer, len);
+}
+
+/**
+ * nm_utils_hwaddr_atoba:
+ * @asc: the ASCII representation of a hardware address
+ * @type: the type of address; either %ARPHRD_ETHER or %ARPHRD_INFINIBAND
+ *
+ * Parses @asc and converts it to binary form in a #GByteArray. See
+ * nm_utils_hwaddr_aton() if you don't want a #GByteArray.
+ *
+ * Return value: (transfer full): a new #GByteArray, or %NULL if @asc couldn't
+ * be parsed
+ */
+GByteArray *
+nm_utils_hwaddr_atoba (const char *asc, int type)
+{
+	GByteArray *ba;
+	int len = nm_utils_hwaddr_len (type);
+
+	if (len <= 0) {
+		g_return_val_if_reached (NULL);
+		return NULL;
+	}
+
+	ba = g_byte_array_sized_new (len);
+	g_byte_array_set_size (ba, len);
+	if (!nm_utils_hwaddr_aton_len (asc, ba->data, len)) {
+		g_byte_array_unref (ba);
+		return NULL;
+	}
+
+	return ba;
+}
+
+/**
+ * nm_utils_hwaddr_ntoa:
+ * @addr: a binary hardware address
+ * @type: the type of address; either %ARPHRD_ETHER or %ARPHRD_INFINIBAND
+ *
+ * Converts @addr to textual form.
+ *
+ * See also nm_utils_hwaddr_ntoa_len(), which takes a length instead of
+ * a type.
+ *
+ * Return value: (transfer full): the textual form of @addr
+ */
+char *
+nm_utils_hwaddr_ntoa (gconstpointer addr, int type)
+{
+	int len = nm_utils_hwaddr_len (type);
+
+	if (len <= 0) {
+		g_return_val_if_reached (NULL);
+		return NULL;
+	}
+
+	return nm_utils_hwaddr_ntoa_len (addr, len);
+}
+
+/**
+ * nm_utils_hwaddr_aton_len:
+ * @asc: the ASCII representation of a hardware address
+ * @buffer: buffer to store the result into
+ * @length: the expected length in bytes of the result and
+ * the size of the buffer in bytes.
+ *
+ * Parses @asc and converts it to binary form in @buffer.
+ * Bytes in @asc can be sepatared by colons (:), or hyphens (-), but not mixed.
+ *
+ * Return value: @buffer, or %NULL if @asc couldn't be parsed
+ *   or would be shorter or longer than @length.
+ *
+ * Since: 0.9.10
+ */
+guint8 *
+nm_utils_hwaddr_aton_len (const char *asc, gpointer buffer, gsize length)
+{
 	const char *in = asc;
 	guint8 *out = (guint8 *)buffer;
-	int left = nm_utils_hwaddr_len (type);
+	char delimiter = '\0';
 
-	while (left && *in) {
+	if (!asc) {
+		g_return_val_if_reached (NULL);
+		return NULL;
+	}
+	g_return_val_if_fail (buffer, NULL);
+	g_return_val_if_fail (length, NULL);
+
+	while (length && *in) {
 		guint8 d1 = in[0], d2 = in[1];
 
 		if (!g_ascii_isxdigit (d1))
@@ -2626,71 +2118,199 @@ nm_utils_hwaddr_aton (const char *asc, int type, gpointer buffer)
 			in += 1;
 		}
 
-		left--;
+		length--;
 		if (*in) {
-			if (*in != ':')
-				return NULL;
+			if (delimiter == '\0') {
+				if (*in == ':' || *in == '-')
+					delimiter = *in;
+				else
+					return NULL;
+			} else {
+				if (*in != delimiter)
+					return NULL;
+			}
 			in++;
 		}
 	}
 
-	if (left == 0 && !*in)
+	if (length == 0 && !*in)
 		return buffer;
 	else
 		return NULL;
 }
 
 /**
- * nm_utils_hwaddr_atoba:
- * @asc: the ASCII representation of a hardware address
- * @type: the type of address; either %ARPHRD_ETHER or %ARPHRD_INFINIBAND
+ * nm_utils_hwaddr_ntoa_len:
+ * @addr: a binary hardware address
+ * @length: the length of @addr
  *
- * Parses @asc and converts it to binary form in a #GByteArray. See
- * nm_utils_hwaddr_aton() if you don't want a #GByteArray.
+ * Converts @addr to textual form.
  *
- * Return value: (transfer full): a new #GByteArray, or %NULL if @asc couldn't
- * be parsed
+ * Return value: (transfer full): the textual form of @addr
+ *
+ * Since: 0.9.10
  */
-GByteArray *
-nm_utils_hwaddr_atoba (const char *asc, int type)
+char *
+nm_utils_hwaddr_ntoa_len (gconstpointer addr, gsize length)
 {
-	GByteArray *ba;
-	int len = nm_utils_hwaddr_len (type);
+	const guint8 *in = addr;
+	char *out, *result;
+	const char *LOOKUP = "0123456789ABCDEF";
 
-	ba = g_byte_array_sized_new (len);
-	ba->len = len;
-	if (!nm_utils_hwaddr_aton (asc, type, ba->data)) {
-		g_byte_array_unref (ba);
-		return NULL;
+	g_return_val_if_fail (addr != NULL, g_strdup (""));
+	g_return_val_if_fail (length != 0, g_strdup (""));
+
+	result = out = g_malloc (length * 3);
+	for (;;) {
+		guint8 v = *in++;
+
+		*out++ = LOOKUP[v >> 4];
+		*out++ = LOOKUP[v & 0x0F];
+		if (--length == 0) {
+			*out = 0;
+			return result;
+		}
+		*out++ = ':';
 	}
+}
 
-	return ba;
+/**
+ * nm_utils_hwaddr_valid:
+ * @asc: the ASCII representation of a hardware address
+ *
+ * Parses @asc to see if it is a valid hardware address of some type.
+ *
+ * Return value: %TRUE if @asc appears to be a valid hardware address
+ *   of some type, %FALSE if not.
+ *
+ * Since: 0.9.10
+ */
+gboolean
+nm_utils_hwaddr_valid (const char *asc)
+{
+	guint8 buf[NM_UTILS_HWADDR_LEN_MAX];
+	gsize in_len, out_len;
+
+	if (!asc || !*asc)
+		return FALSE;
+	in_len = strlen (asc);
+	if ((in_len + 1) % 3 != 0)
+		return FALSE;
+	out_len = (in_len + 1) / 3;
+	if (out_len > NM_UTILS_HWADDR_LEN_MAX)
+		return FALSE;
+	return nm_utils_hwaddr_aton_len (asc, buf, out_len) != NULL;
 }
 
 /**
- * nm_utils_hwaddr_ntoa:
- * @addr: a binary hardware address
- * @type: the type of address; either %ARPHRD_ETHER or %ARPHRD_INFINIBAND
+ * nm_utils_bin2hexstr:
+ * @bytes: an array of bytes
+ * @len: the length of the @bytes array
+ * @final_len: an index where to cut off the returned string, or -1
  *
- * Converts @addr to textual form.
+ * Converts a byte-array @bytes into a hexadecimal string.
+ * If @final_len is greater than -1, the returned string is terminated at
+ * that index (returned_string[final_len] == '\0'),
  *
- * Return value: (transfer full): the textual form of @addr
+ * Return value: (transfer full): the textual form of @bytes
+ *
+ * Since: 0.9.10
+ */
+/*
+ * Code originally by Alex Larsson <alexl@redhat.com> and
+ *  copyright Red Hat, Inc. under terms of the LGPL.
  */
 char *
-nm_utils_hwaddr_ntoa (gconstpointer addr, int type)
+nm_utils_bin2hexstr (const char *bytes, int len, int final_len)
 {
-	const guint8 *in = addr;
-	GString *out = g_string_new (NULL);
-	int left = nm_utils_hwaddr_len (type);
+	static char hex_digits[] = "0123456789abcdef";
+	char *result;
+	int i;
+	gsize buflen = (len * 2) + 1;
+
+	g_return_val_if_fail (bytes != NULL, NULL);
+	g_return_val_if_fail (len > 0, NULL);
+	g_return_val_if_fail (len < 4096, NULL);   /* Arbitrary limit */
+	if (final_len > -1)
+		g_return_val_if_fail (final_len < buflen, NULL);
 
-	while (left--) {
-		if (out->len)
-			g_string_append_c (out, ':');
-		g_string_append_printf (out, "%02X", *in++);
+	result = g_malloc0 (buflen);
+	for (i = 0; i < len; i++)
+	{
+		result[2*i] = hex_digits[(bytes[i] >> 4) & 0xf];
+		result[2*i+1] = hex_digits[bytes[i] & 0xf];
 	}
+	/* Cut converted key off at the correct length for this cipher type */
+	if (final_len > -1)
+		result[final_len] = '\0';
+	else
+		result[buflen - 1] = '\0';
+
+	return result;
+}
+
+/* From hostap, Copyright (c) 2002-2005, Jouni Malinen <jkmaline@cc.hut.fi> */
+/**
+ * nm_utils_hex2byte:
+ * @hex: a string representing a hex byte
+ *
+ * Converts a hex string (2 characters) into its byte representation.
+ *
+ * Return value: a byte, or -1 if @hex doesn't represent a hex byte
+ *
+ * Since: 0.9.10
+ */
+int
+nm_utils_hex2byte (const char *hex)
+{
+	int a, b;
+	a = g_ascii_xdigit_value (*hex++);
+	if (a < 0)
+		return -1;
+	b = g_ascii_xdigit_value (*hex++);
+	if (b < 0)
+		return -1;
+	return (a << 4) | b;
+}
+
+/**
+ * nm_utils_hexstr2bin:
+ * @hex: an hex string
+ * @len: the length of the @hex string (it has to be even)
+ *
+ * Converts a hexadecimal string @hex into a byte-array. The returned array
+ * length is @len/2.
+ *
+ * Return value: (transfer full): a array of bytes, or %NULL on error
+ *
+ * Since: 0.9.10
+ */
+char *
+nm_utils_hexstr2bin (const char *hex, size_t len)
+{
+	size_t       i;
+	int          a;
+	const char * ipos = hex;
+	char *       buf = NULL;
+	char *       opos;
+
+	/* Length must be a multiple of 2 */
+	if ((len % 2) != 0)
+		return NULL;
 
-	return g_string_free (out, FALSE);
+	opos = buf = g_malloc0 ((len / 2) + 1);
+	for (i = 0; i < len; i += 2) {
+		a = nm_utils_hex2byte (ipos);
+		if (a < 0) {
+			g_free (buf);
+			return NULL;
+		}
+		*opos++ = a;
+		ipos += 2;
+	}
+	return buf;
 }
+/* End from hostap */
 
 /**
  * nm_utils_iface_valid_name:
@@ -2759,3 +2379,161 @@ nm_utils_is_uuid (const char *str)
 
 	return FALSE;
 }
+
+static char _nm_utils_inet_ntop_buffer[NM_UTILS_INET_ADDRSTRLEN];
+
+/**
+ * nm_utils_inet4_ntop: (skip)
+ * @inaddr: the address that should be converted to string.
+ * @dst: the destination buffer, it must contain at least %INET_ADDRSTRLEN
+ *  or %NM_UTILS_INET_ADDRSTRLEN characters. If set to %NULL, it will return
+ *  a pointer to an internal, static buffer (shared with nm_utils_inet6_ntop()).
+ *  Beware, that the internal buffer will be overwritten with ever new call
+ *  of nm_utils_inet4_ntop() or nm_utils_inet6_ntop() that does not provied it's
+ *  own @dst buffer. Also, using the internal buffer is not thread safe. When
+ *  in doubt, pass your own @dst buffer to avoid these issues.
+ *
+ * Wrapper for inet_ntop.
+ *
+ * Returns: the input buffer @dst, or a pointer to an
+ *  internal, static buffer. This function cannot fail.
+ *
+ * Since: 0.9.10
+ **/
+const char *
+nm_utils_inet4_ntop (in_addr_t inaddr, char *dst)
+{
+	return inet_ntop (AF_INET, &inaddr, dst ? dst : _nm_utils_inet_ntop_buffer,
+	                  INET_ADDRSTRLEN);
+}
+
+/**
+ * nm_utils_inet6_ntop: (skip)
+ * @in6addr: the address that should be converted to string.
+ * @dst: the destination buffer, it must contain at least %INET6_ADDRSTRLEN
+ *  or %NM_UTILS_INET_ADDRSTRLEN characters. If set to %NULL, it will return
+ *  a pointer to an internal, static buffer (shared with nm_utils_inet4_ntop()).
+ *  Beware, that the internal buffer will be overwritten with ever new call
+ *  of nm_utils_inet4_ntop() or nm_utils_inet6_ntop() that does not provied it's
+ *  own @dst buffer. Also, using the internal buffer is not thread safe. When
+ *  in doubt, pass your own @dst buffer to avoid these issues.
+ *
+ * Wrapper for inet_ntop.
+ *
+ * Returns: the input buffer @dst, or a pointer to an
+ *  internal, static buffer. %NULL is not allowed as @in6addr,
+ *  otherwise, this function cannot fail.
+ *
+ * Since: 0.9.10
+ **/
+const char *
+nm_utils_inet6_ntop (const struct in6_addr *in6addr, char *dst)
+{
+	g_return_val_if_fail (in6addr, NULL);
+	return inet_ntop (AF_INET6, in6addr, dst ? dst : _nm_utils_inet_ntop_buffer,
+	                  INET6_ADDRSTRLEN);
+}
+
+/**
+ * nm_utils_check_virtual_device_compatibility:
+ * @virtual_type: a virtual connection type
+ * @other_type: a connection type to test against @virtual_type
+ *
+ * Determines if a connection of type @virtual_type can (in the
+ * general case) work with connections of type @other_type.
+ *
+ * If @virtual_type is %NM_TYPE_SETTING_VLAN, then this checks if
+ * @other_type is a valid type for the parent of a VLAN.
+ *
+ * If @virtual_type is a "master" type (eg, %NM_TYPE_SETTING_BRIDGE),
+ * then this checks if @other_type is a valid type for a slave of that
+ * master.
+ *
+ * Note that even if this returns %TRUE it is not guaranteed that
+ * <emphasis>every</emphasis> connection of type @other_type is
+ * compatible with @virtual_type; it may depend on the exact
+ * configuration of the two connections, or on the capabilities of an
+ * underlying device driver.
+ *
+ * Returns: %TRUE or %FALSE
+ *
+ * Since: 0.9.10
+ */
+gboolean
+nm_utils_check_virtual_device_compatibility (GType virtual_type, GType other_type)
+{
+	g_return_val_if_fail (_nm_setting_type_is_base_type (virtual_type), FALSE);
+	g_return_val_if_fail (_nm_setting_type_is_base_type (other_type), FALSE);
+
+	if (virtual_type == NM_TYPE_SETTING_BOND) {
+		return (   other_type == NM_TYPE_SETTING_INFINIBAND
+		        || other_type == NM_TYPE_SETTING_WIRED
+		        || other_type == NM_TYPE_SETTING_BRIDGE
+		        || other_type == NM_TYPE_SETTING_BOND
+		        || other_type == NM_TYPE_SETTING_TEAM
+		        || other_type == NM_TYPE_SETTING_VLAN);
+	} else if (virtual_type == NM_TYPE_SETTING_BRIDGE) {
+		return (   other_type == NM_TYPE_SETTING_WIRED
+		        || other_type == NM_TYPE_SETTING_BOND
+		        || other_type == NM_TYPE_SETTING_TEAM
+		        || other_type == NM_TYPE_SETTING_VLAN);
+	} else if (virtual_type == NM_TYPE_SETTING_TEAM) {
+		return (   other_type == NM_TYPE_SETTING_WIRED
+		        || other_type == NM_TYPE_SETTING_BRIDGE
+		        || other_type == NM_TYPE_SETTING_BOND
+		        || other_type == NM_TYPE_SETTING_TEAM
+		        || other_type == NM_TYPE_SETTING_VLAN);
+	} else if (virtual_type == NM_TYPE_SETTING_VLAN) {
+		return (   other_type == NM_TYPE_SETTING_WIRED
+		        || other_type == NM_TYPE_SETTING_WIRELESS
+		        || other_type == NM_TYPE_SETTING_BRIDGE
+		        || other_type == NM_TYPE_SETTING_BOND
+		        || other_type == NM_TYPE_SETTING_TEAM
+		        || other_type == NM_TYPE_SETTING_VLAN);
+	} else {
+		g_warn_if_reached ();
+		return FALSE;
+	}
+}
+
+/***********************************************************/
+
+/* Unused prototype to make the compiler happy */
+const NMUtilsPrivateData *nm_util_get_private (void);
+
+static const NMUtilsPrivateData data = {
+	.nm_setting_ip4_config_get_address_label = nm_setting_ip4_config_get_address_label,
+	.nm_setting_ip4_config_add_address_with_label = nm_setting_ip4_config_add_address_with_label,
+};
+
+/**
+ * nm_utils_get_private:
+ *
+ * Entry point for NetworkManager-internal API.  You should not use this
+ * function for any reason.
+ *
+ * Returns: Who knows? It's a mystery.
+ *
+ * Since: 0.9.10
+ */
+const NMUtilsPrivateData *
+nm_utils_get_private (void)
+{
+	return &data;
+}
+
+/**
+ * nm_util_get_private:
+ *
+ * You should not use this function for any reason.
+ *
+ * Returns: Who knows? It's a mystery.
+ *
+ * Since: 0.9.10
+ */
+const NMUtilsPrivateData *
+nm_util_get_private (void)
+{
+	/* Compat function to preserve ABI */
+	return nm_utils_get_private ();
+}
diff --git a/libnm-util/nm-utils.h b/libnm-util/nm-utils.h
index 60010f45..bb8786a1 100644
--- a/libnm-util/nm-utils.h
+++ b/libnm-util/nm-utils.h
@@ -20,7 +20,7 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2005 - 2012 Red Hat, Inc.
+ * (C) Copyright 2005 - 2013 Red Hat, Inc.
  */
 
 #ifndef NM_UTILS_H
@@ -47,6 +47,7 @@ char *      nm_utils_ssid_to_utf8  (const GByteArray *ssid);
 
 GHashTable *nm_utils_gvalue_hash_dup  (GHashTable *hash);
 
+NM_DEPRECATED_IN_0_9_10
 void        nm_utils_slist_free    (GSList *list, GDestroyNotify elem_destroy_fn);
 
 /**
@@ -119,6 +120,10 @@ GByteArray *nm_utils_rsa_key_encrypt (const GByteArray *data,
                                       const char *in_password,
                                       char **out_password,
                                       GError **error);
+GByteArray *nm_utils_rsa_key_encrypt_aes (const GByteArray *data,
+                                          const char *in_password,
+                                          char **out_password,
+                                          GError **error);
 gboolean nm_utils_file_is_pkcs12 (const char *filename);
 
 guint32 nm_utils_wifi_freq_to_channel (guint32 freq);
@@ -136,15 +141,46 @@ gboolean nm_utils_wifi_is_channel_valid (guint32 channel, const char *band);
 #define NM_UTILS_HWADDR_LEN_MAX 20 /* INFINIBAND_ALEN */
 
 int         nm_utils_hwaddr_len   (int type) G_GNUC_PURE;
+NM_DEPRECATED_IN_0_9_10
 int         nm_utils_hwaddr_type  (int len) G_GNUC_PURE;
 char       *nm_utils_hwaddr_ntoa  (gconstpointer addr, int type);
 GByteArray *nm_utils_hwaddr_atoba (const char *asc, int type);
 guint8     *nm_utils_hwaddr_aton  (const char *asc, int type, gpointer buffer);
 
+NM_AVAILABLE_IN_0_9_10
+char       *nm_utils_hwaddr_ntoa_len  (gconstpointer addr, gsize length);
+NM_AVAILABLE_IN_0_9_10
+guint8     *nm_utils_hwaddr_aton_len  (const char *asc, gpointer buffer, gsize length);
+
+NM_AVAILABLE_IN_0_9_10
+gboolean    nm_utils_hwaddr_valid (const char *asc);
+
+NM_AVAILABLE_IN_0_9_10
+char *nm_utils_bin2hexstr (const char *bytes, int len, int final_len);
+NM_AVAILABLE_IN_0_9_10
+int   nm_utils_hex2byte   (const char *hex);
+NM_AVAILABLE_IN_0_9_10
+char *nm_utils_hexstr2bin (const char *hex, size_t len);
+
 gboolean    nm_utils_iface_valid_name(const char *name);
 
 gboolean nm_utils_is_uuid (const char *str);
 
+/**
+ * NM_UTILS_INET_ADDRSTRLEN:
+ *
+ * Defines the minimal length for a char buffer that is suitable as @dst argument
+ * for both nm_utils_inet4_ntop() and nm_utils_inet6_ntop().
+ **/
+#define NM_UTILS_INET_ADDRSTRLEN     INET6_ADDRSTRLEN
+NM_AVAILABLE_IN_0_9_10
+const char *nm_utils_inet4_ntop (in_addr_t inaddr, char *dst);
+NM_AVAILABLE_IN_0_9_10
+const char *nm_utils_inet6_ntop (const struct in6_addr *in6addr, char *dst);
+
+NM_AVAILABLE_IN_0_9_10
+gboolean nm_utils_check_virtual_device_compatibility (GType virtual_type, GType other_type);
+
 G_END_DECLS
 
 #endif /* NM_UTILS_H */
diff --git a/libnm-util/nm-value-transforms.c b/libnm-util/nm-value-transforms.c
new file mode 100644
index 00000000..f92596dc
--- /dev/null
+++ b/libnm-util/nm-value-transforms.c
@@ -0,0 +1,594 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+
+/* NetworkManager -- Network link manager
+ *
+ * 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 2005 - 2014 Red Hat, Inc.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include "nm-utils.h"
+#include "nm-utils-private.h"
+#include "nm-dbus-glib-types.h"
+#include "nm-glib-compat.h"
+
+static void
+_nm_utils_convert_op_to_string (const GValue *src_value, GValue *dest_value)
+{
+	g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_OBJECT_PATH));
+
+	g_value_set_string (dest_value, (const char *) g_value_get_boxed (src_value));
+}
+
+static void
+_nm_utils_convert_strv_to_slist (const GValue *src_value, GValue *dest_value)
+{
+	char **str;
+	GSList *list = NULL;
+	guint i = 0;
+
+	g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), G_TYPE_STRV));
+
+	str = (char **) g_value_get_boxed (src_value);
+
+	while (str && str[i])
+		list = g_slist_prepend (list, g_strdup (str[i++]));
+
+	g_value_take_boxed (dest_value, g_slist_reverse (list));
+}
+
+static void
+_nm_utils_convert_slist_to_strv (const GValue *src_value, GValue *dest_value)
+{
+	GSList *slist;
+	char **strv;
+	int len, i = 0;
+
+	slist = g_value_get_boxed (src_value);
+	len = g_slist_length (slist);
+
+	strv = g_new (char *, len + 1);
+	for (i = 0; slist; slist = slist->next, i++)
+		strv[i] = g_strdup (slist->data);
+	strv[i] = NULL;
+
+	g_value_take_boxed (dest_value, strv);
+}
+
+static void
+_nm_utils_convert_strv_to_ptrarray (const GValue *src_value, GValue *dest_value)
+{
+	char **str;
+	GPtrArray *array = NULL;
+	guint i = 0;
+
+	g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), G_TYPE_STRV));
+
+	str = (char **) g_value_get_boxed (src_value);
+
+	array = g_ptr_array_sized_new (3);
+	while (str && str[i])
+		g_ptr_array_add (array, g_strdup (str[i++]));
+
+	g_value_take_boxed (dest_value, array);
+}
+
+static void
+_nm_utils_convert_string_list_to_string (const GValue *src_value, GValue *dest_value)
+{
+	GSList *strings;
+	GString *printable;
+	GSList *iter;
+
+	g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_LIST_OF_STRING));
+
+	strings = (GSList *) g_value_get_boxed (src_value);
+
+	printable = g_string_new (NULL);
+	for (iter = strings; iter; iter = iter->next) {
+		if (iter != strings)
+			g_string_append_c (printable, ',');
+		g_string_append (printable, iter->data ? iter->data : "(null)");
+	}
+
+	g_value_take_string (dest_value, g_string_free (printable, FALSE));
+}
+
+static void
+_string_array_to_string (const GPtrArray *strings, GValue *dest_value)
+{
+	GString *printable;
+	int i;
+
+	printable = g_string_new (NULL);
+	for (i = 0; strings && i < strings->len; i++) {
+		if (i > 0)
+			g_string_append_c (printable, ',');
+		g_string_append (printable, strings->pdata[i]);
+	}
+
+	g_value_take_string (dest_value, g_string_free (printable, FALSE));
+}
+
+static void
+_nm_utils_convert_string_array_to_string (const GValue *src_value, GValue *dest_value)
+{
+	const GPtrArray *strings;
+
+	g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_ARRAY_OF_STRING));
+
+	strings = (const GPtrArray *) g_value_get_boxed (src_value);
+	_string_array_to_string (strings, dest_value);
+}
+
+static void
+_nm_utils_convert_op_array_to_string (const GValue *src_value, GValue *dest_value)
+{
+	const GPtrArray *strings;
+
+	g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH));
+
+	strings = (const GPtrArray *) g_value_get_boxed (src_value);
+	_string_array_to_string (strings, dest_value);
+}
+
+static void
+_nm_utils_convert_uint_array_to_string (const GValue *src_value, GValue *dest_value)
+{
+	GArray *array;
+	GString *printable;
+	guint i = 0;
+
+	g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_UINT_ARRAY));
+
+	array = (GArray *) g_value_get_boxed (src_value);
+
+	printable = g_string_new (NULL);
+	while (array && (i < array->len)) {
+		guint32 addr;
+
+		if (i > 0)
+			g_string_append (printable, ", ");
+
+		addr = g_array_index (array, guint32, i++);
+		g_string_append (printable, nm_utils_inet4_ntop (addr, NULL));
+	}
+
+	g_value_take_string (dest_value, g_string_free (printable, FALSE));
+}
+
+static void
+_nm_utils_convert_ip4_addr_route_struct_array_to_string (const GValue *src_value, GValue *dest_value)
+{
+	GPtrArray *ptr_array;
+	GString *printable;
+	guint i = 0;
+	char buf[INET_ADDRSTRLEN];
+
+	g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT));
+
+	ptr_array = (GPtrArray *) g_value_get_boxed (src_value);
+
+	printable = g_string_new (NULL);
+	while (ptr_array && (i < ptr_array->len)) {
+		GArray *array;
+		gboolean is_addr; /* array contains address x route */
+
+		if (i > 0)
+			g_string_append (printable, "; ");
+
+		g_string_append (printable, "{ ");
+		array = (GArray *) g_ptr_array_index (ptr_array, i++);
+		if (array->len < 2) {
+			g_string_append (printable, "invalid");
+			continue;
+		}
+		is_addr = (array->len < 4);
+
+		nm_utils_inet4_ntop (g_array_index (array, guint32, 0), buf);
+		if (is_addr)
+			g_string_append_printf (printable, "ip = %s", buf);
+		else
+			g_string_append_printf (printable, "dst = %s", buf);
+
+		g_string_append_printf (printable, "/%u",
+		                        g_array_index (array, guint32, 1));
+
+		if (array->len > 2) {
+			nm_utils_inet4_ntop (g_array_index (array, guint32, 2), buf);
+			if (is_addr)
+				g_string_append_printf (printable, ", gw = %s", buf);
+			else
+				g_string_append_printf (printable, ", nh = %s", buf);
+		}
+
+		if (array->len > 3) {
+			g_string_append_printf (printable, ", mt = %u",
+			                        g_array_index (array, guint32, 3));
+		}
+
+		g_string_append (printable, " }");
+	}
+
+	g_value_take_string (dest_value, g_string_free (printable, FALSE));
+}
+
+static void
+convert_one_gvalue_hash_entry (gpointer key, gpointer value, gpointer user_data)
+{
+	GString *printable = (GString *) user_data;
+	char *value_as_string;
+
+	value_as_string = g_strdup_value_contents ((GValue *) value);
+	g_string_append_printf (printable, " { '%s': %s },", (const char *) key, value_as_string);
+	g_free (value_as_string);
+}
+
+static void
+_nm_utils_convert_gvalue_hash_to_string (const GValue *src_value, GValue *dest_value)
+{
+	GHashTable *hash;
+	GString *printable;
+
+	g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_MAP_OF_VARIANT));
+
+	hash = (GHashTable *) g_value_get_boxed (src_value);
+
+	printable = g_string_new ("[");
+	g_hash_table_foreach (hash, convert_one_gvalue_hash_entry, printable);
+	g_string_append (printable, " ]");
+
+	g_value_take_string (dest_value, printable->str);
+	g_string_free (printable, FALSE);
+}
+
+static void
+convert_one_string_hash_entry (gpointer key, gpointer value, gpointer user_data)
+{
+	GString *printable = (GString *) user_data;
+
+	if (printable->len)
+		g_string_append_c (printable, ',');
+	g_string_append_printf (printable, "%s=%s", (const char *) key, (const char *) value);
+}
+
+static void
+_nm_utils_convert_string_hash_to_string (const GValue *src_value, GValue *dest_value)
+{
+	GHashTable *hash;
+	GString *printable;
+
+	g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_MAP_OF_STRING));
+
+	hash = (GHashTable *) g_value_get_boxed (src_value);
+
+	printable = g_string_new (NULL);
+	if (hash)
+		g_hash_table_foreach (hash, convert_one_string_hash_entry, printable);
+
+	g_value_take_string (dest_value, g_string_free (printable, FALSE));
+}
+
+static void
+_nm_utils_convert_byte_array_to_string (const GValue *src_value, GValue *dest_value)
+{
+	GArray *array;
+	GString *printable;
+	guint i = 0;
+
+	g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_UCHAR_ARRAY));
+
+	array = (GArray *) g_value_get_boxed (src_value);
+
+	printable = g_string_new ("[");
+	if (array) {
+		while (i < MIN (array->len, 35)) {
+			if (i > 0)
+				g_string_append_c (printable, ' ');
+			g_string_append_printf (printable, "0x%02X",
+			                        g_array_index (array, unsigned char, i++));
+		}
+		if (i < array->len)
+			g_string_append (printable, " ... ");
+	}
+	g_string_append_c (printable, ']');
+
+	g_value_take_string (dest_value, g_string_free (printable, FALSE));
+}
+
+static void
+_nm_utils_convert_ip6_dns_array_to_string (const GValue *src_value, GValue *dest_value)
+{
+	GPtrArray *ptr_array;
+	GString *printable;
+	guint i = 0;
+
+	g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UCHAR));
+
+	ptr_array = (GPtrArray *) g_value_get_boxed (src_value);
+
+	printable = g_string_new (NULL);
+	while (ptr_array && (i < ptr_array->len)) {
+		GByteArray *bytearray;
+		struct in6_addr *addr;
+
+		if (i > 0)
+			g_string_append (printable, ", ");
+
+		bytearray = (GByteArray *) g_ptr_array_index (ptr_array, i++);
+		if (bytearray->len != 16) {
+			g_string_append (printable, "invalid");
+			continue;
+		}
+		addr = (struct in6_addr *) bytearray->data;
+		g_string_append (printable, nm_utils_inet6_ntop (addr, NULL));
+	}
+
+	g_value_take_string (dest_value, g_string_free (printable, FALSE));
+}
+
+static void
+_nm_utils_convert_ip6_addr_struct_array_to_string (const GValue *src_value, GValue *dest_value)
+{
+	GPtrArray *ptr_array;
+	GString *printable;
+	guint i = 0;
+
+	g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS));
+
+	ptr_array = (GPtrArray *) g_value_get_boxed (src_value);
+
+	printable = g_string_new (NULL);
+	while (ptr_array && (i < ptr_array->len)) {
+		GValueArray *elements;
+		GValue *tmp;
+		GByteArray *ba_addr;
+		struct in6_addr *addr;
+		guint32 prefix;
+
+		if (i > 0)
+			g_string_append (printable, "; ");
+
+		g_string_append (printable, "{ ");
+		elements = (GValueArray *) g_ptr_array_index (ptr_array, i++);
+		if (!_nm_utils_gvalue_array_validate (elements, 3,
+		                                      DBUS_TYPE_G_UCHAR_ARRAY,
+		                                      G_TYPE_UINT,
+		                                      DBUS_TYPE_G_UCHAR_ARRAY)) {
+			g_string_append (printable, "invalid }");
+			continue;
+		}
+
+		/* IPv6 address */
+		tmp = g_value_array_get_nth (elements, 0);
+		ba_addr = g_value_get_boxed (tmp);
+		if (ba_addr->len != 16) {
+			g_string_append (printable, "invalid }");
+			continue;
+		}
+		addr = (struct in6_addr *) ba_addr->data;
+		g_string_append_printf (printable, "ip = %s", nm_utils_inet6_ntop (addr, NULL));
+
+		/* Prefix */
+		tmp = g_value_array_get_nth (elements, 1);
+		prefix = g_value_get_uint (tmp);
+		if (prefix > 128) {
+			g_string_append (printable, "/invalid }");
+			continue;
+		}
+		g_string_append_printf (printable, "/%u", prefix);
+		g_string_append (printable, ", ");
+
+		/* IPv6 Gateway */
+		tmp = g_value_array_get_nth (elements, 2);
+		ba_addr = g_value_get_boxed (tmp);
+		if (ba_addr->len != 16) {
+			g_string_append (printable, "invalid }");
+			continue;
+		}
+		addr = (struct in6_addr *) ba_addr->data;
+		g_string_append_printf (printable, "gw = %s", nm_utils_inet6_ntop (addr, NULL));
+		g_string_append (printable, " }");
+	}
+
+	g_value_take_string (dest_value, g_string_free (printable, FALSE));
+}
+
+static void
+_nm_utils_convert_ip6_route_struct_array_to_string (const GValue *src_value, GValue *dest_value)
+{
+	GPtrArray *ptr_array;
+	GString *printable;
+	guint i = 0;
+
+	g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), DBUS_TYPE_G_ARRAY_OF_IP6_ROUTE));
+
+	ptr_array = (GPtrArray *) g_value_get_boxed (src_value);
+
+	printable = g_string_new (NULL);
+	while (ptr_array && (i < ptr_array->len)) {
+		GValueArray *elements;
+		GValue *tmp;
+		GByteArray *ba_addr;
+		struct in6_addr *addr;
+		guint32 prefix, metric;
+
+		if (i > 0)
+			g_string_append (printable, "; ");
+
+		g_string_append (printable, "{ ");
+		elements = (GValueArray *) g_ptr_array_index (ptr_array, i++);
+		if (!_nm_utils_gvalue_array_validate (elements, 4,
+		                                      DBUS_TYPE_G_UCHAR_ARRAY,
+		                                      G_TYPE_UINT,
+		                                      DBUS_TYPE_G_UCHAR_ARRAY,
+		                                      G_TYPE_UINT)) {
+			g_string_append (printable, "invalid");
+			continue;
+		}
+
+		/* Destination address */
+		tmp = g_value_array_get_nth (elements, 0);
+		ba_addr = g_value_get_boxed (tmp);
+		if (ba_addr->len != 16) {
+			g_string_append (printable, "invalid");
+			continue;
+		}
+		addr = (struct in6_addr *) ba_addr->data;
+		g_string_append_printf (printable, "dst = %s", nm_utils_inet6_ntop (addr, NULL));
+
+		/* Prefix */
+		tmp = g_value_array_get_nth (elements, 1);
+		prefix = g_value_get_uint (tmp);
+		if (prefix > 128) {
+			g_string_append (printable, "/invalid");
+			continue;
+		}
+		g_string_append_printf (printable, "/%u", prefix);
+		g_string_append (printable, ", ");
+
+		/* Next hop addresses */
+		tmp = g_value_array_get_nth (elements, 2);
+		ba_addr = g_value_get_boxed (tmp);
+		if (ba_addr->len != 16) {
+			g_string_append (printable, "invalid");
+			continue;
+		}
+		addr = (struct in6_addr *) ba_addr->data;
+		g_string_append_printf (printable, "nh = %s", nm_utils_inet6_ntop (addr, NULL));
+		g_string_append (printable, ", ");
+
+		/* Metric */
+		tmp = g_value_array_get_nth (elements, 3);
+		metric = g_value_get_uint (tmp);
+		g_string_append_printf (printable, "mt = %u", metric);
+
+		g_string_append (printable, " }");
+	}
+
+	g_value_take_string (dest_value, g_string_free (printable, FALSE));
+}
+
+#define OLD_DBUS_TYPE_G_IP6_ADDRESS (dbus_g_type_get_struct ("GValueArray", DBUS_TYPE_G_UCHAR_ARRAY, G_TYPE_UINT, G_TYPE_INVALID))
+#define OLD_DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS (dbus_g_type_get_collection ("GPtrArray", OLD_DBUS_TYPE_G_IP6_ADDRESS))
+
+static void
+_nm_utils_convert_old_ip6_addr_array (const GValue *src_value, GValue *dst_value)
+{
+	GPtrArray *src_outer_array;
+	GPtrArray *dst_outer_array;
+	guint i;
+
+	g_return_if_fail (g_type_is_a (G_VALUE_TYPE (src_value), OLD_DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS));
+
+	src_outer_array = (GPtrArray *) g_value_get_boxed (src_value);
+	dst_outer_array = g_ptr_array_new ();
+
+	for (i = 0; src_outer_array && (i < src_outer_array->len); i++) {
+		GValueArray *src_addr_array;
+		GValueArray *dst_addr_array;
+		GValue element = G_VALUE_INIT;
+		GValue *src_addr, *src_prefix;
+		GByteArray *ba;
+
+		src_addr_array = (GValueArray *) g_ptr_array_index (src_outer_array, i);
+		if (!_nm_utils_gvalue_array_validate (src_addr_array, 2, DBUS_TYPE_G_UCHAR_ARRAY, G_TYPE_UINT)) {
+			g_warning ("%s: invalid old IPv6 address type", __func__);
+			return;
+		}
+
+		dst_addr_array = g_value_array_new (3);
+
+		src_addr = g_value_array_get_nth (src_addr_array, 0);
+		g_value_array_append (dst_addr_array, src_addr);
+		src_prefix = g_value_array_get_nth (src_addr_array, 1);
+		g_value_array_append (dst_addr_array, src_prefix);
+
+		/* Blank Gateway */
+		g_value_init (&element, DBUS_TYPE_G_UCHAR_ARRAY);
+		ba = g_byte_array_new ();
+		g_byte_array_append (ba, (guint8 *) "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16);
+		g_value_take_boxed (&element, ba);
+		g_value_array_append (dst_addr_array, &element);
+		g_value_unset (&element);
+
+		g_ptr_array_add (dst_outer_array, dst_addr_array);
+	}
+
+	g_value_take_boxed (dst_value, dst_outer_array);
+}
+
+void
+_nm_value_transforms_register (void)
+{
+	static gboolean registered = FALSE;
+
+	if (G_UNLIKELY (!registered)) {
+		g_value_register_transform_func (DBUS_TYPE_G_OBJECT_PATH,
+		                                 G_TYPE_STRING,
+		                                 _nm_utils_convert_op_to_string);
+		g_value_register_transform_func (G_TYPE_STRV, 
+		                                 DBUS_TYPE_G_LIST_OF_STRING,
+		                                 _nm_utils_convert_strv_to_slist);
+		g_value_register_transform_func (DBUS_TYPE_G_LIST_OF_STRING,
+		                                 G_TYPE_STRV,
+		                                 _nm_utils_convert_slist_to_strv);
+		g_value_register_transform_func (G_TYPE_STRV,
+		                                 DBUS_TYPE_G_ARRAY_OF_STRING,
+		                                 _nm_utils_convert_strv_to_ptrarray);
+		g_value_register_transform_func (DBUS_TYPE_G_LIST_OF_STRING,
+		                                 G_TYPE_STRING, 
+		                                 _nm_utils_convert_string_list_to_string);
+		g_value_register_transform_func (DBUS_TYPE_G_ARRAY_OF_STRING,
+		                                 G_TYPE_STRING,
+		                                 _nm_utils_convert_string_array_to_string);
+		g_value_register_transform_func (DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH,
+		                                 G_TYPE_STRING,
+		                                 _nm_utils_convert_op_array_to_string);
+		g_value_register_transform_func (DBUS_TYPE_G_UINT_ARRAY,
+		                                 G_TYPE_STRING, 
+		                                 _nm_utils_convert_uint_array_to_string);
+		g_value_register_transform_func (DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT,
+		                                 G_TYPE_STRING, 
+		                                 _nm_utils_convert_ip4_addr_route_struct_array_to_string);
+		g_value_register_transform_func (DBUS_TYPE_G_MAP_OF_VARIANT,
+		                                 G_TYPE_STRING, 
+		                                 _nm_utils_convert_gvalue_hash_to_string);
+		g_value_register_transform_func (DBUS_TYPE_G_MAP_OF_STRING,
+		                                 G_TYPE_STRING, 
+		                                 _nm_utils_convert_string_hash_to_string);
+		g_value_register_transform_func (DBUS_TYPE_G_UCHAR_ARRAY,
+		                                 G_TYPE_STRING,
+		                                 _nm_utils_convert_byte_array_to_string);
+		g_value_register_transform_func (DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UCHAR,
+		                                 G_TYPE_STRING, 
+		                                 _nm_utils_convert_ip6_dns_array_to_string);
+		g_value_register_transform_func (DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS,
+		                                 G_TYPE_STRING, 
+		                                 _nm_utils_convert_ip6_addr_struct_array_to_string);
+		g_value_register_transform_func (DBUS_TYPE_G_ARRAY_OF_IP6_ROUTE,
+		                                 G_TYPE_STRING, 
+		                                 _nm_utils_convert_ip6_route_struct_array_to_string);
+		g_value_register_transform_func (OLD_DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS,
+		                                 DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS,
+		                                 _nm_utils_convert_old_ip6_addr_array);
+		registered = TRUE;
+	}
+}
diff --git a/libnm-util/tests/Makefile.am b/libnm-util/tests/Makefile.am
index d49ef8c8..6d3d225e 100644
--- a/libnm-util/tests/Makefile.am
+++ b/libnm-util/tests/Makefile.am
@@ -7,15 +7,18 @@ AM_CPPFLAGS = \
 	-I$(top_builddir)/include \
 	-I$(top_srcdir)/libnm-util \
 	-I$(top_builddir)/libnm-util \
+	-DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \
 	$(GLIB_CFLAGS) \
-	$(DBUS_CFLAGS)
+	$(DBUS_CFLAGS) \
+	-DTEST_CERT_DIR=\"$(top_srcdir)/libnm-util/tests/certs/\"
 
 noinst_PROGRAMS = \
 	test-settings-defaults \
 	test-crypto \
 	test-secrets \
 	test-general \
-	test-setting-8021x
+	test-setting-8021x \
+	test-setting-dcb
 
 test_settings_defaults_SOURCES = \
 	test-settings-defaults.c
@@ -36,10 +39,6 @@ test_crypto_LDADD = \
 test_secrets_SOURCES = \
 	test-secrets.c
 
-test_secrets_CPPFLAGS = \
-	-DTEST_CERT_DIR=\"$(top_srcdir)/libnm-util/tests/certs/\" \
-	$(AM_CPPFLAGS)
-
 test_secrets_LDADD = \
 	$(top_builddir)/libnm-util/libnm-util.la \
 	$(GLIB_LIBS) \
@@ -61,11 +60,15 @@ test_setting_8021x_LDADD = \
 	$(GLIB_LIBS) \
 	$(DBUS_LIBS)
 
-check-local: test-settings-defaults test-crypto test-secrets
-	$(abs_builddir)/test-settings-defaults
-	$(abs_builddir)/test-secrets
-	$(abs_builddir)/test-general
+test_setting_dcb_SOURCES = \
+	test-setting-dcb.c
 
+test_setting_dcb_LDADD = \
+	$(top_builddir)/libnm-util/libnm-util.la \
+	$(GLIB_LIBS) \
+	$(DBUS_LIBS)
+
+check-local: test-crypto test-setting-8021x
 # Private key and CA certificate in the same file (PEM)
 	$(abs_builddir)/test-setting-8021x $(srcdir)/certs/test_key_and_cert.pem "test"
 
@@ -122,4 +125,9 @@ check-local: test-settings-defaults test-crypto test-secrets
 		$(srcdir)/certs/pkcs8-enc-key.pem \
 		"1234567890"
 
+# Private key with AES cipher
+	$(abs_builddir)/test-crypto --key $(srcdir)/certs/test-aes-key.pem "test-aes-password"
+
+TESTS = test-settings-defaults test-secrets test-general test-setting-dcb
+
 endif
diff --git a/libnm-util/tests/Makefile.in b/libnm-util/tests/Makefile.in
index 662c3161..de57f25a 100644
--- a/libnm-util/tests/Makefile.in
+++ b/libnm-util/tests/Makefile.in
@@ -81,12 +81,17 @@ host_triplet = @host@
 @ENABLE_TESTS_TRUE@noinst_PROGRAMS = test-settings-defaults$(EXEEXT) \
 @ENABLE_TESTS_TRUE@	test-crypto$(EXEEXT) test-secrets$(EXEEXT) \
 @ENABLE_TESTS_TRUE@	test-general$(EXEEXT) \
-@ENABLE_TESTS_TRUE@	test-setting-8021x$(EXEEXT)
+@ENABLE_TESTS_TRUE@	test-setting-8021x$(EXEEXT) \
+@ENABLE_TESTS_TRUE@	test-setting-dcb$(EXEEXT)
+@ENABLE_TESTS_TRUE@TESTS = test-settings-defaults$(EXEEXT) \
+@ENABLE_TESTS_TRUE@	test-secrets$(EXEEXT) test-general$(EXEEXT) \
+@ENABLE_TESTS_TRUE@	test-setting-dcb$(EXEEXT)
 subdir = libnm-util/tests
 DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
 	$(top_srcdir)/build-aux/depcomp
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_lib_readline.m4 \
+	$(top_srcdir)/m4/compiler_warnings.m4 \
 	$(top_srcdir)/m4/gettext.m4 \
 	$(top_srcdir)/m4/gnome-code-coverage.m4 \
 	$(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \
@@ -123,8 +128,7 @@ test_general_OBJECTS = $(am_test_general_OBJECTS)
 @ENABLE_TESTS_TRUE@	$(top_builddir)/libnm-util/libnm-util.la \
 @ENABLE_TESTS_TRUE@	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
 am__test_secrets_SOURCES_DIST = test-secrets.c
-@ENABLE_TESTS_TRUE@am_test_secrets_OBJECTS =  \
-@ENABLE_TESTS_TRUE@	test_secrets-test-secrets.$(OBJEXT)
+@ENABLE_TESTS_TRUE@am_test_secrets_OBJECTS = test-secrets.$(OBJEXT)
 test_secrets_OBJECTS = $(am_test_secrets_OBJECTS)
 @ENABLE_TESTS_TRUE@test_secrets_DEPENDENCIES =  \
 @ENABLE_TESTS_TRUE@	$(top_builddir)/libnm-util/libnm-util.la \
@@ -136,6 +140,13 @@ test_setting_8021x_OBJECTS = $(am_test_setting_8021x_OBJECTS)
 @ENABLE_TESTS_TRUE@test_setting_8021x_DEPENDENCIES =  \
 @ENABLE_TESTS_TRUE@	$(top_builddir)/libnm-util/libnm-util.la \
 @ENABLE_TESTS_TRUE@	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+am__test_setting_dcb_SOURCES_DIST = test-setting-dcb.c
+@ENABLE_TESTS_TRUE@am_test_setting_dcb_OBJECTS =  \
+@ENABLE_TESTS_TRUE@	test-setting-dcb.$(OBJEXT)
+test_setting_dcb_OBJECTS = $(am_test_setting_dcb_OBJECTS)
+@ENABLE_TESTS_TRUE@test_setting_dcb_DEPENDENCIES =  \
+@ENABLE_TESTS_TRUE@	$(top_builddir)/libnm-util/libnm-util.la \
+@ENABLE_TESTS_TRUE@	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
 am__test_settings_defaults_SOURCES_DIST = test-settings-defaults.c
 @ENABLE_TESTS_TRUE@am_test_settings_defaults_OBJECTS =  \
 @ENABLE_TESTS_TRUE@	test-settings-defaults.$(OBJEXT)
@@ -179,11 +190,12 @@ am__v_CCLD_0 = @echo "  CCLD    " $@;
 am__v_CCLD_1 = 
 SOURCES = $(test_crypto_SOURCES) $(test_general_SOURCES) \
 	$(test_secrets_SOURCES) $(test_setting_8021x_SOURCES) \
-	$(test_settings_defaults_SOURCES)
+	$(test_setting_dcb_SOURCES) $(test_settings_defaults_SOURCES)
 DIST_SOURCES = $(am__test_crypto_SOURCES_DIST) \
 	$(am__test_general_SOURCES_DIST) \
 	$(am__test_secrets_SOURCES_DIST) \
 	$(am__test_setting_8021x_SOURCES_DIST) \
+	$(am__test_setting_dcb_SOURCES_DIST) \
 	$(am__test_settings_defaults_SOURCES_DIST)
 RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
 	ctags-recursive dvi-recursive html-recursive info-recursive \
@@ -225,6 +237,28 @@ am__define_uniq_tagged_files = \
   done | $(am__uniquify_input)`
 ETAGS = etags
 CTAGS = ctags
+am__tty_colors_dummy = \
+  mgn= red= grn= lgn= blu= brg= std=; \
+  am__color_tests=no
+am__tty_colors = { \
+  $(am__tty_colors_dummy); \
+  if test "X$(AM_COLOR_TESTS)" = Xno; then \
+    am__color_tests=no; \
+  elif test "X$(AM_COLOR_TESTS)" = Xalways; then \
+    am__color_tests=yes; \
+  elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \
+    am__color_tests=yes; \
+  fi; \
+  if test $$am__color_tests = yes; then \
+    red=''; \
+    grn=''; \
+    lgn=''; \
+    blu=''; \
+    mgn=''; \
+    brg=''; \
+    std=''; \
+  fi; \
+}
 DIST_SUBDIRS = certs
 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
 am__relativize = \
@@ -277,12 +311,15 @@ CXXFLAGS = @CXXFLAGS@
 CYGPATH_W = @CYGPATH_W@
 DATADIRNAME = @DATADIRNAME@
 DBUS_CFLAGS = @DBUS_CFLAGS@
+DBUS_GLIB_100_CFLAGS = @DBUS_GLIB_100_CFLAGS@
+DBUS_GLIB_100_LIBS = @DBUS_GLIB_100_LIBS@
 DBUS_LIBS = @DBUS_LIBS@
 DBUS_SYS_DIR = @DBUS_SYS_DIR@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
 DHCLIENT_PATH = @DHCLIENT_PATH@
 DHCPCD_PATH = @DHCPCD_PATH@
+DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@
 DLLTOOL = @DLLTOOL@
 DNSMASQ_PATH = @DNSMASQ_PATH@
 DSYMUTIL = @DSYMUTIL@
@@ -307,7 +344,6 @@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
 GNUTLS_LIBS = @GNUTLS_LIBS@
 GREP = @GREP@
 GTKDOC_CHECK = @GTKDOC_CHECK@
-GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@
 GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@
 GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@
 GTKDOC_MKPDF = @GTKDOC_MKPDF@
@@ -352,12 +388,16 @@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
 LIBICONV = @LIBICONV@
 LIBINTL = @LIBINTL@
 LIBM = @LIBM@
+LIBNDP_CFLAGS = @LIBNDP_CFLAGS@
+LIBNDP_LIBS = @LIBNDP_LIBS@
 LIBNL_CFLAGS = @LIBNL_CFLAGS@
 LIBNL_LIBS = @LIBNL_LIBS@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
 LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@
 LIBSOUP_LIBS = @LIBSOUP_LIBS@
+LIBTEAMDCTL_CFLAGS = @LIBTEAMDCTL_CFLAGS@
+LIBTEAMDCTL_LIBS = @LIBTEAMDCTL_LIBS@
 LIBTOOL = @LIBTOOL@
 LIPO = @LIPO@
 LN_S = @LN_S@
@@ -374,6 +414,8 @@ MOC = @MOC@
 MSGFMT = @MSGFMT@
 MSGFMT_015 = @MSGFMT_015@
 MSGMERGE = @MSGMERGE@
+NEWT_CFLAGS = @NEWT_CFLAGS@
+NEWT_LIBS = @NEWT_LIBS@
 NM = @NM@
 NMEDIT = @NMEDIT@
 NM_MAJOR_VERSION = @NM_MAJOR_VERSION@
@@ -401,11 +443,16 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
 POLKIT_CFLAGS = @POLKIT_CFLAGS@
 POLKIT_LIBS = @POLKIT_LIBS@
 POSUB = @POSUB@
+PPPD_PATH = @PPPD_PATH@
 PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@
+PPPOE_PATH = @PPPOE_PATH@
 QT_CFLAGS = @QT_CFLAGS@
 QT_LIBS = @QT_LIBS@
 RANLIB = @RANLIB@
+READLINE_LIBS = @READLINE_LIBS@
 SED = @SED@
+SELINUX_CFLAGS = @SELINUX_CFLAGS@
+SELINUX_LIBS = @SELINUX_LIBS@
 SET_MAKE = @SET_MAKE@
 SHELL = @SHELL@
 STRIP = @STRIP@
@@ -420,6 +467,7 @@ UDEV_BASE_DIR = @UDEV_BASE_DIR@
 USE_NLS = @USE_NLS@
 UUID_CFLAGS = @UUID_CFLAGS@
 UUID_LIBS = @UUID_LIBS@
+VALGRIND_RULES = @VALGRIND_RULES@
 VAPIGEN = @VAPIGEN@
 VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@
 VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@
@@ -482,6 +530,7 @@ psdir = @psdir@
 sbindir = @sbindir@
 sharedstatedir = @sharedstatedir@
 srcdir = @srcdir@
+subdirs = @subdirs@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 target_alias = @target_alias@
@@ -492,14 +541,17 @@ with_dhclient = @with_dhclient@
 with_dhcpcd = @with_dhcpcd@
 with_netconfig = @with_netconfig@
 with_resolvconf = @with_resolvconf@
+with_valgrind = @with_valgrind@
 @ENABLE_TESTS_TRUE@SUBDIRS = certs
 @ENABLE_TESTS_TRUE@AM_CPPFLAGS = \
 @ENABLE_TESTS_TRUE@	-I$(top_srcdir)/include \
 @ENABLE_TESTS_TRUE@	-I$(top_builddir)/include \
 @ENABLE_TESTS_TRUE@	-I$(top_srcdir)/libnm-util \
 @ENABLE_TESTS_TRUE@	-I$(top_builddir)/libnm-util \
+@ENABLE_TESTS_TRUE@	-DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \
 @ENABLE_TESTS_TRUE@	$(GLIB_CFLAGS) \
-@ENABLE_TESTS_TRUE@	$(DBUS_CFLAGS)
+@ENABLE_TESTS_TRUE@	$(DBUS_CFLAGS) \
+@ENABLE_TESTS_TRUE@	-DTEST_CERT_DIR=\"$(top_srcdir)/libnm-util/tests/certs/\"
 
 @ENABLE_TESTS_TRUE@test_settings_defaults_SOURCES = \
 @ENABLE_TESTS_TRUE@	test-settings-defaults.c
@@ -520,10 +572,6 @@ with_resolvconf = @with_resolvconf@
 @ENABLE_TESTS_TRUE@test_secrets_SOURCES = \
 @ENABLE_TESTS_TRUE@	test-secrets.c
 
-@ENABLE_TESTS_TRUE@test_secrets_CPPFLAGS = \
-@ENABLE_TESTS_TRUE@	-DTEST_CERT_DIR=\"$(top_srcdir)/libnm-util/tests/certs/\" \
-@ENABLE_TESTS_TRUE@	$(AM_CPPFLAGS)
-
 @ENABLE_TESTS_TRUE@test_secrets_LDADD = \
 @ENABLE_TESTS_TRUE@	$(top_builddir)/libnm-util/libnm-util.la \
 @ENABLE_TESTS_TRUE@	$(GLIB_LIBS) \
@@ -545,6 +593,14 @@ with_resolvconf = @with_resolvconf@
 @ENABLE_TESTS_TRUE@	$(GLIB_LIBS) \
 @ENABLE_TESTS_TRUE@	$(DBUS_LIBS)
 
+@ENABLE_TESTS_TRUE@test_setting_dcb_SOURCES = \
+@ENABLE_TESTS_TRUE@	test-setting-dcb.c
+
+@ENABLE_TESTS_TRUE@test_setting_dcb_LDADD = \
+@ENABLE_TESTS_TRUE@	$(top_builddir)/libnm-util/libnm-util.la \
+@ENABLE_TESTS_TRUE@	$(GLIB_LIBS) \
+@ENABLE_TESTS_TRUE@	$(DBUS_LIBS)
+
 all: all-recursive
 
 .SUFFIXES:
@@ -605,6 +661,10 @@ test-setting-8021x$(EXEEXT): $(test_setting_8021x_OBJECTS) $(test_setting_8021x_
 	@rm -f test-setting-8021x$(EXEEXT)
 	$(AM_V_CCLD)$(LINK) $(test_setting_8021x_OBJECTS) $(test_setting_8021x_LDADD) $(LIBS)
 
+test-setting-dcb$(EXEEXT): $(test_setting_dcb_OBJECTS) $(test_setting_dcb_DEPENDENCIES) $(EXTRA_test_setting_dcb_DEPENDENCIES) 
+	@rm -f test-setting-dcb$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(test_setting_dcb_OBJECTS) $(test_setting_dcb_LDADD) $(LIBS)
+
 test-settings-defaults$(EXEEXT): $(test_settings_defaults_OBJECTS) $(test_settings_defaults_DEPENDENCIES) $(EXTRA_test_settings_defaults_DEPENDENCIES) 
 	@rm -f test-settings-defaults$(EXEEXT)
 	$(AM_V_CCLD)$(LINK) $(test_settings_defaults_OBJECTS) $(test_settings_defaults_LDADD) $(LIBS)
@@ -617,9 +677,10 @@ distclean-compile:
 
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-crypto.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-general.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-secrets.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-setting-8021x.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-setting-dcb.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-settings-defaults.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_secrets-test-secrets.Po@am__quote@
 
 .c.o:
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@@ -642,20 +703,6 @@ distclean-compile:
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
 
-test_secrets-test-secrets.o: test-secrets.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_secrets_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_secrets-test-secrets.o -MD -MP -MF $(DEPDIR)/test_secrets-test-secrets.Tpo -c -o test_secrets-test-secrets.o `test -f 'test-secrets.c' || echo '$(srcdir)/'`test-secrets.c
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_secrets-test-secrets.Tpo $(DEPDIR)/test_secrets-test-secrets.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='test-secrets.c' object='test_secrets-test-secrets.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_secrets_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_secrets-test-secrets.o `test -f 'test-secrets.c' || echo '$(srcdir)/'`test-secrets.c
-
-test_secrets-test-secrets.obj: test-secrets.c
-@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_secrets_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_secrets-test-secrets.obj -MD -MP -MF $(DEPDIR)/test_secrets-test-secrets.Tpo -c -o test_secrets-test-secrets.obj `if test -f 'test-secrets.c'; then $(CYGPATH_W) 'test-secrets.c'; else $(CYGPATH_W) '$(srcdir)/test-secrets.c'; fi`
-@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/test_secrets-test-secrets.Tpo $(DEPDIR)/test_secrets-test-secrets.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='test-secrets.c' object='test_secrets-test-secrets.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_secrets_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_secrets-test-secrets.obj `if test -f 'test-secrets.c'; then $(CYGPATH_W) 'test-secrets.c'; else $(CYGPATH_W) '$(srcdir)/test-secrets.c'; fi`
-
 mostlyclean-libtool:
 	-rm -f *.lo
 
@@ -761,6 +808,99 @@ cscopelist-am: $(am__tagged_files)
 distclean-tags:
 	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
 
+check-TESTS: $(TESTS)
+	@failed=0; all=0; xfail=0; xpass=0; skip=0; \
+	srcdir=$(srcdir); export srcdir; \
+	list=' $(TESTS) '; \
+	$(am__tty_colors); \
+	if test -n "$$list"; then \
+	  for tst in $$list; do \
+	    if test -f ./$$tst; then dir=./; \
+	    elif test -f $$tst; then dir=; \
+	    else dir="$(srcdir)/"; fi; \
+	    if $(TESTS_ENVIRONMENT) $${dir}$$tst $(AM_TESTS_FD_REDIRECT); then \
+	      all=`expr $$all + 1`; \
+	      case " $(XFAIL_TESTS) " in \
+	      *[\ \	]$$tst[\ \	]*) \
+		xpass=`expr $$xpass + 1`; \
+		failed=`expr $$failed + 1`; \
+		col=$$red; res=XPASS; \
+	      ;; \
+	      *) \
+		col=$$grn; res=PASS; \
+	      ;; \
+	      esac; \
+	    elif test $$? -ne 77; then \
+	      all=`expr $$all + 1`; \
+	      case " $(XFAIL_TESTS) " in \
+	      *[\ \	]$$tst[\ \	]*) \
+		xfail=`expr $$xfail + 1`; \
+		col=$$lgn; res=XFAIL; \
+	      ;; \
+	      *) \
+		failed=`expr $$failed + 1`; \
+		col=$$red; res=FAIL; \
+	      ;; \
+	      esac; \
+	    else \
+	      skip=`expr $$skip + 1`; \
+	      col=$$blu; res=SKIP; \
+	    fi; \
+	    echo "$${col}$$res$${std}: $$tst"; \
+	  done; \
+	  if test "$$all" -eq 1; then \
+	    tests="test"; \
+	    All=""; \
+	  else \
+	    tests="tests"; \
+	    All="All "; \
+	  fi; \
+	  if test "$$failed" -eq 0; then \
+	    if test "$$xfail" -eq 0; then \
+	      banner="$$All$$all $$tests passed"; \
+	    else \
+	      if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \
+	      banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \
+	    fi; \
+	  else \
+	    if test "$$xpass" -eq 0; then \
+	      banner="$$failed of $$all $$tests failed"; \
+	    else \
+	      if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \
+	      banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \
+	    fi; \
+	  fi; \
+	  dashes="$$banner"; \
+	  skipped=""; \
+	  if test "$$skip" -ne 0; then \
+	    if test "$$skip" -eq 1; then \
+	      skipped="($$skip test was not run)"; \
+	    else \
+	      skipped="($$skip tests were not run)"; \
+	    fi; \
+	    test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
+	      dashes="$$skipped"; \
+	  fi; \
+	  report=""; \
+	  if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
+	    report="Please report to $(PACKAGE_BUGREPORT)"; \
+	    test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
+	      dashes="$$report"; \
+	  fi; \
+	  dashes=`echo "$$dashes" | sed s/./=/g`; \
+	  if test "$$failed" -eq 0; then \
+	    col="$$grn"; \
+	  else \
+	    col="$$red"; \
+	  fi; \
+	  echo "$${col}$$dashes$${std}"; \
+	  echo "$${col}$$banner$${std}"; \
+	  test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \
+	  test -z "$$report" || echo "$${col}$$report$${std}"; \
+	  echo "$${col}$$dashes$${std}"; \
+	  test "$$failed" -eq 0; \
+	else :; fi
+
 distdir: $(DISTFILES)
 	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
 	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
@@ -818,7 +958,7 @@ distdir: $(DISTFILES)
 	done
 @ENABLE_TESTS_FALSE@check-local:
 check-am: all-am
-	$(MAKE) $(AM_MAKEFLAGS) check-local
+	$(MAKE) $(AM_MAKEFLAGS) check-TESTS check-local
 check: check-recursive
 all-am: Makefile $(PROGRAMS)
 installdirs: installdirs-recursive
@@ -927,26 +1067,22 @@ uninstall-am:
 .MAKE: $(am__recursive_targets) check-am install-am install-strip
 
 .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \
-	check-am check-local clean clean-generic clean-libtool \
-	clean-noinstPROGRAMS cscopelist-am ctags ctags-am distclean \
-	distclean-compile distclean-generic distclean-libtool \
-	distclean-tags distdir dvi dvi-am html html-am info info-am \
-	install install-am install-data install-data-am install-dvi \
-	install-dvi-am install-exec install-exec-am install-html \
-	install-html-am install-info install-info-am install-man \
-	install-pdf install-pdf-am install-ps install-ps-am \
-	install-strip installcheck installcheck-am installdirs \
-	installdirs-am maintainer-clean maintainer-clean-generic \
-	mostlyclean mostlyclean-compile mostlyclean-generic \
-	mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
-	uninstall-am
-
-
-@ENABLE_TESTS_TRUE@check-local: test-settings-defaults test-crypto test-secrets
-@ENABLE_TESTS_TRUE@	$(abs_builddir)/test-settings-defaults
-@ENABLE_TESTS_TRUE@	$(abs_builddir)/test-secrets
-@ENABLE_TESTS_TRUE@	$(abs_builddir)/test-general
-
+	check-TESTS check-am check-local clean clean-generic \
+	clean-libtool clean-noinstPROGRAMS cscopelist-am ctags \
+	ctags-am distclean distclean-compile distclean-generic \
+	distclean-libtool distclean-tags distdir dvi dvi-am html \
+	html-am info info-am install install-am install-data \
+	install-data-am install-dvi install-dvi-am install-exec \
+	install-exec-am install-html install-html-am install-info \
+	install-info-am install-man install-pdf install-pdf-am \
+	install-ps install-ps-am install-strip installcheck \
+	installcheck-am installdirs installdirs-am maintainer-clean \
+	maintainer-clean-generic mostlyclean mostlyclean-compile \
+	mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+	tags tags-am uninstall uninstall-am
+
+
+@ENABLE_TESTS_TRUE@check-local: test-crypto test-setting-8021x
 # Private key and CA certificate in the same file (PEM)
 @ENABLE_TESTS_TRUE@	$(abs_builddir)/test-setting-8021x $(srcdir)/certs/test_key_and_cert.pem "test"
 
@@ -1003,6 +1139,9 @@ uninstall-am:
 @ENABLE_TESTS_TRUE@		$(srcdir)/certs/pkcs8-enc-key.pem \
 @ENABLE_TESTS_TRUE@		"1234567890"
 
+# Private key with AES cipher
+@ENABLE_TESTS_TRUE@	$(abs_builddir)/test-crypto --key $(srcdir)/certs/test-aes-key.pem "test-aes-password"
+
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
 # Otherwise a system limit (for SysV at least) may be exceeded.
 .NOEXPORT:
diff --git a/libnm-util/tests/certs/Makefile.am b/libnm-util/tests/certs/Makefile.am
index e0f00a47..30992517 100644
--- a/libnm-util/tests/certs/Makefile.am
+++ b/libnm-util/tests/certs/Makefile.am
@@ -20,5 +20,6 @@ EXTRA_DIST = \
 	test-key-only-decrypted.der \
 	pkcs8-enc-key.pem \
 	pkcs8-noenc-key.pem \
-	pkcs8-decrypted.der
+	pkcs8-decrypted.der \
+	test-aes-key.pem
 
diff --git a/libnm-util/tests/certs/Makefile.in b/libnm-util/tests/certs/Makefile.in
index e570aafd..218cb48d 100644
--- a/libnm-util/tests/certs/Makefile.in
+++ b/libnm-util/tests/certs/Makefile.in
@@ -89,7 +89,8 @@ host_triplet = @host@
 subdir = libnm-util/tests/certs
 DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_lib_readline.m4 \
+	$(top_srcdir)/m4/compiler_warnings.m4 \
 	$(top_srcdir)/m4/gettext.m4 \
 	$(top_srcdir)/m4/gnome-code-coverage.m4 \
 	$(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \
@@ -153,12 +154,15 @@ CXXFLAGS = @CXXFLAGS@
 CYGPATH_W = @CYGPATH_W@
 DATADIRNAME = @DATADIRNAME@
 DBUS_CFLAGS = @DBUS_CFLAGS@
+DBUS_GLIB_100_CFLAGS = @DBUS_GLIB_100_CFLAGS@
+DBUS_GLIB_100_LIBS = @DBUS_GLIB_100_LIBS@
 DBUS_LIBS = @DBUS_LIBS@
 DBUS_SYS_DIR = @DBUS_SYS_DIR@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
 DHCLIENT_PATH = @DHCLIENT_PATH@
 DHCPCD_PATH = @DHCPCD_PATH@
+DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@
 DLLTOOL = @DLLTOOL@
 DNSMASQ_PATH = @DNSMASQ_PATH@
 DSYMUTIL = @DSYMUTIL@
@@ -183,7 +187,6 @@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
 GNUTLS_LIBS = @GNUTLS_LIBS@
 GREP = @GREP@
 GTKDOC_CHECK = @GTKDOC_CHECK@
-GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@
 GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@
 GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@
 GTKDOC_MKPDF = @GTKDOC_MKPDF@
@@ -228,12 +231,16 @@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
 LIBICONV = @LIBICONV@
 LIBINTL = @LIBINTL@
 LIBM = @LIBM@
+LIBNDP_CFLAGS = @LIBNDP_CFLAGS@
+LIBNDP_LIBS = @LIBNDP_LIBS@
 LIBNL_CFLAGS = @LIBNL_CFLAGS@
 LIBNL_LIBS = @LIBNL_LIBS@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
 LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@
 LIBSOUP_LIBS = @LIBSOUP_LIBS@
+LIBTEAMDCTL_CFLAGS = @LIBTEAMDCTL_CFLAGS@
+LIBTEAMDCTL_LIBS = @LIBTEAMDCTL_LIBS@
 LIBTOOL = @LIBTOOL@
 LIPO = @LIPO@
 LN_S = @LN_S@
@@ -250,6 +257,8 @@ MOC = @MOC@
 MSGFMT = @MSGFMT@
 MSGFMT_015 = @MSGFMT_015@
 MSGMERGE = @MSGMERGE@
+NEWT_CFLAGS = @NEWT_CFLAGS@
+NEWT_LIBS = @NEWT_LIBS@
 NM = @NM@
 NMEDIT = @NMEDIT@
 NM_MAJOR_VERSION = @NM_MAJOR_VERSION@
@@ -277,11 +286,16 @@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
 POLKIT_CFLAGS = @POLKIT_CFLAGS@
 POLKIT_LIBS = @POLKIT_LIBS@
 POSUB = @POSUB@
+PPPD_PATH = @PPPD_PATH@
 PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@
+PPPOE_PATH = @PPPOE_PATH@
 QT_CFLAGS = @QT_CFLAGS@
 QT_LIBS = @QT_LIBS@
 RANLIB = @RANLIB@
+READLINE_LIBS = @READLINE_LIBS@
 SED = @SED@
+SELINUX_CFLAGS = @SELINUX_CFLAGS@
+SELINUX_LIBS = @SELINUX_LIBS@
 SET_MAKE = @SET_MAKE@
 SHELL = @SHELL@
 STRIP = @STRIP@
@@ -296,6 +310,7 @@ UDEV_BASE_DIR = @UDEV_BASE_DIR@
 USE_NLS = @USE_NLS@
 UUID_CFLAGS = @UUID_CFLAGS@
 UUID_LIBS = @UUID_LIBS@
+VALGRIND_RULES = @VALGRIND_RULES@
 VAPIGEN = @VAPIGEN@
 VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@
 VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@
@@ -358,6 +373,7 @@ psdir = @psdir@
 sbindir = @sbindir@
 sharedstatedir = @sharedstatedir@
 srcdir = @srcdir@
+subdirs = @subdirs@
 sysconfdir = @sysconfdir@
 systemdsystemunitdir = @systemdsystemunitdir@
 target_alias = @target_alias@
@@ -368,6 +384,7 @@ with_dhclient = @with_dhclient@
 with_dhcpcd = @with_dhcpcd@
 with_netconfig = @with_netconfig@
 with_resolvconf = @with_resolvconf@
+with_valgrind = @with_valgrind@
 EXTRA_DIST = \
 	test_ca_cert.pem \
 	test_ca_cert.der \
@@ -381,7 +398,8 @@ EXTRA_DIST = \
 	test-key-only-decrypted.der \
 	pkcs8-enc-key.pem \
 	pkcs8-noenc-key.pem \
-	pkcs8-decrypted.der
+	pkcs8-decrypted.der \
+	test-aes-key.pem
 
 all: all-am
 
diff --git a/libnm-util/tests/certs/test-aes-key.pem b/libnm-util/tests/certs/test-aes-key.pem
new file mode 100644
index 00000000..aab8f463
--- /dev/null
+++ b/libnm-util/tests/certs/test-aes-key.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-CBC,800391B7DD72364B4C2562E0B6AEA000
+
+E9dgNCIATOr4CN5c8o6B+8wdqq/I1BLmPmW2qT7YZepoF7E+RUb8ZLjo1VO2XsJw
+Ir4EzuH7837zBD9dP5CjlY8cWfR63gZpEWRY5Jub8kzvqiL4UZ0Qr8IHOZxAkKEz
+EL1Pn7e+tYt4kA372LPZHWO3vRCgmL1iSJj2/k3avPWAx7NUie4bzGI+00WNv699
+ClKzsJbWB1eiQvYgOr4aVV26oWfa896JkBoGhgZQ6ckqFpsdAos8m46iOSVZrwgq
+Y2/d1CvfQod+87c8LRatwAjf+d6YAJJaeMyxjCGuAY6/JyDsorUkM2OlvbTt6WOA
+gSPWO8I+Ov6THb4IuPhpIJ30Sl88tc6MlIByW49EWu2G1jPw3L8iqRzZ50Z85dyz
+N9yFP91wEwi5F0Zed4iEpg3NVfklEe/VYqCldc5f9fZ84G5V98ZlAdNSqwd/UNBU
+iPTflGqVpp1u+J2isOk+Agpj1MCxh2q0RNuvY9KHzOYBScirfbG4DKNbQgS/5Zw7
+3g9YL5Wbo7BczHLiXf/2adu6T8wI1LKRjkeLV9dK1Vw3ZaGy3mB9oFhCgjh9BNHw
+wC78CVcUErjtOXdQagiCQn5k5EGeAB97QFROoAFjAmGvq3xCi4EHd9Sk6fcMm7Oi
+1fuVR5EXUubF4Llq06lFzQp01s2F73noH49bs3qwdf0n8nrL2XhKB0XCOV/I3K5c
+Y3W+YSl361QGjZ/NUcFLIIy+Uro90MmUBNk6af+wGHRJeflpVnK0ATX1PtpNHziz
+jiMiIZicjgfVLxl1a5zTl6KUmGWKlZb533adQ0s6q9Qmi5Vk5L5W/GdMjcFtZbM6
+GU7EOkwihMLb3DVsNbm7vb8tUXqe/e5RmXtij8Yb+2a6/M9yaOHa0VjHzdiKHecr
+eEYaKQDj7NCWLslNnRRh9GmgXcu2pqBhqRM3HAt3cEaHKKWHTcoWcz11pFwMHNtn
+bU9GjGRVc3lCGhVNRiloO0zrKHmcBpDVLw2+ycXXpj/RaBW2fy0xRLKolyla+jEr
+zdLzVI61O50ZMycOtPmE7DVZpkokn32hGer1eCOFnsN1lywi4cWLvU0jbQC+CJyw
+T9vS8zB3WgOl8rC1AHsfQ4KYajlKleQm89deurQymnt/Qx49SiQA+TpwG9Xvx2TP
+3Vc1NwZfM9ZZ1+6xit/rTuS3LhnmhEnGnV5ZyvAdmkCcV2iHjOnLnQWWQn24MHU3
+8Y9D4AdpI5V7Igwr3vH2NZMiw1W2Yc5EJuPAT8nIs5sgOYhXB/QLPJvulvOQhuNC
+NPwJ6A505JrVNfHuEaoGUyA+mPeWuLwQo8y8cM6ZdFMG3RrwFNzuYTrc1Z/9GsmA
+C0UfHf5dL0r7oWZ1SbpSvsmHYqc8sIypq0ohuLEbpegS/hWP8b2/XDRTjfTiJOrM
+4LsUH9PMOJSxDlwS+7e3FdcGfgXfsMgB3aOjQvNpKEolOuv4A5LVFeMrrwtw4Xo1
+EuhstZwyarUTJenDUXzkakhA+8Yw/g2a7RsnANVTkeBuv2PbqFL4zdlsWvcpkz41
+ESxx1siSeU1E9beOII0zSi8vUD0IAevRHaWSlfU2po600IzX1FN97pa4DJV2ycgn
+-----END RSA PRIVATE KEY-----
diff --git a/libnm-util/tests/test-crypto.c b/libnm-util/tests/test-crypto.c
index 57e39fca..c11b6392 100644
--- a/libnm-util/tests/test-crypto.c
+++ b/libnm-util/tests/test-crypto.c
@@ -28,10 +28,11 @@
 #include <stdio.h>
 #include <string.h>
 
-#include "nm-test-helpers.h"
 #include "crypto.h"
 #include "nm-utils.h"
 
+#include "nm-test-utils.h"
+
 #if 0
 static const char *pem_rsa_key_begin = "-----BEGIN RSA PRIVATE KEY-----";
 static const char *pem_rsa_key_end = "-----END RSA PRIVATE KEY-----";
@@ -69,10 +70,6 @@ dump_key_to_pem (const char *key, gsize key_len, int key_type)
 	}
 
 	str = g_string_new (NULL);
-	if (!str) {
-		g_warning ("Couldn't allocate buffer to write out key.");
-		goto out;
-	}
 
 	g_string_append (str, start_tag);
 	g_string_append_c (str, '\n');
@@ -122,10 +119,8 @@ file_to_byte_array (const char *filename)
 
 	if (g_file_get_contents (filename, &contents, &length, NULL)) {
 		array = g_byte_array_sized_new (length);
-		if (array) {
-			g_byte_array_append (array, (guint8 *) contents, length);
-			g_assert (array->len == length);
-		}
+		g_byte_array_append (array, (guint8 *) contents, length);
+		g_assert (array->len == length);
 		g_free (contents);
 	}
 	return array;
@@ -261,6 +256,28 @@ test_load_pkcs8 (const char *path,
 	}
 }
 
+static gboolean
+is_cipher_aes (const char *path)
+{
+	char *contents;
+	gsize length = 0;
+	const char *cipher;
+	gboolean is_aes = FALSE;
+
+	if (!g_file_get_contents (path, &contents, &length, NULL))
+		return FALSE;
+
+	cipher = strstr (contents, "DEK-Info: ");
+	if (cipher) {
+		cipher += strlen ("DEK-Info: ");
+		if (g_str_has_prefix (cipher, "AES-128-CBC"))
+			is_aes = TRUE;
+	}
+
+	g_free (contents);
+        return is_aes;
+}
+
 static void
 test_encrypt_private_key (const char *path,
                           const char *password,
@@ -280,7 +297,10 @@ test_encrypt_private_key (const char *path,
 	        path, NM_CRYPTO_KEY_TYPE_RSA, key_type);
 
 	/* Now re-encrypt the private key */
-	encrypted = nm_utils_rsa_key_encrypt (array, password, NULL, &error);
+	if (is_cipher_aes (path))
+		encrypted = nm_utils_rsa_key_encrypt_aes (array, password, NULL, &error);
+	else
+		encrypted = nm_utils_rsa_key_encrypt (array, password, NULL, &error);
 	ASSERT (encrypted != NULL, desc,
 	        "couldn't re-encrypt private key file '%s': %d %s",
 	        path, error->code, error->message);
diff --git a/libnm-util/tests/test-general.c b/libnm-util/tests/test-general.c
index 20a99472..97625605 100644
--- a/libnm-util/tests/test-general.c
+++ b/libnm-util/tests/test-general.c
@@ -25,9 +25,9 @@
 #include <netinet/ether.h>
 #include <linux/if_infiniband.h>
 
-#include "nm-test-helpers.h"
 #include <nm-utils.h>
 
+#include "nm-setting-private.h"
 #include "nm-setting-connection.h"
 #include "nm-setting-vpn.h"
 #include "nm-setting-gsm.h"
@@ -38,8 +38,14 @@
 #include "nm-setting-ip4-config.h"
 #include "nm-setting-pppoe.h"
 #include "nm-setting-serial.h"
+#include "nm-setting-vlan.h"
+#include "nm-setting-bond.h"
+#include "nm-utils.h"
+#include "nm-utils-private.h"
 #include "nm-dbus-glib-types.h"
 
+#include "nm-test-utils.h"
+
 static void
 vpn_check_func (const char *key, const char *value, gpointer user_data)
 {
@@ -116,22 +122,56 @@ test_setting_vpn_items (void)
 	nm_setting_vpn_remove_secret (s_vpn, "foobar4");
 
 	/* Try to add some blank values and make sure they are rejected */
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*key != NULL*");
 	nm_setting_vpn_add_data_item (s_vpn, NULL, NULL);
+	g_test_assert_expected_messages ();
+
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*strlen (key) > 0*");
 	nm_setting_vpn_add_data_item (s_vpn, "", "");
+	g_test_assert_expected_messages ();
+
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*item != NULL*");
 	nm_setting_vpn_add_data_item (s_vpn, "foobar1", NULL);
+	g_test_assert_expected_messages ();
+
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*strlen (item) > 0*");
 	nm_setting_vpn_add_data_item (s_vpn, "foobar1", "");
+	g_test_assert_expected_messages ();
+
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*key != NULL*");
 	nm_setting_vpn_add_data_item (s_vpn, NULL, "blahblah1");
+	g_test_assert_expected_messages ();
+
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*strlen (key) > 0*");
 	nm_setting_vpn_add_data_item (s_vpn, "", "blahblah1");
+	g_test_assert_expected_messages ();
 
 	nm_setting_vpn_foreach_data_item (s_vpn, vpn_check_empty_func, "vpn-data-empty");
 
 	/* Try to add some blank secrets and make sure they are rejected */
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*key != NULL*");
 	nm_setting_vpn_add_secret (s_vpn, NULL, NULL);
+	g_test_assert_expected_messages ();
+
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*strlen (key) > 0*");
 	nm_setting_vpn_add_secret (s_vpn, "", "");
+	g_test_assert_expected_messages ();
+
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*secret != NULL*");
 	nm_setting_vpn_add_secret (s_vpn, "foobar1", NULL);
+	g_test_assert_expected_messages ();
+
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*strlen (secret) > 0*");
 	nm_setting_vpn_add_secret (s_vpn, "foobar1", "");
+	g_test_assert_expected_messages ();
+
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*key != NULL*");
 	nm_setting_vpn_add_secret (s_vpn, NULL, "blahblah1");
+	g_test_assert_expected_messages ();
+
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*strlen (key) > 0*");
 	nm_setting_vpn_add_secret (s_vpn, "", "blahblah1");
+	g_test_assert_expected_messages ();
 
 	nm_setting_vpn_foreach_secret (s_vpn, vpn_check_empty_func, "vpn-secrets-empty");
 
@@ -144,7 +184,7 @@ test_setting_vpn_update_secrets (void)
 	NMConnection *connection;
 	NMSettingVPN *s_vpn;
 	GHashTable *settings, *vpn, *secrets;
-	GValue val = { 0 };
+	GValue val = G_VALUE_INIT;
 	gboolean success;
 	GError *error = NULL;
 	const char *tmp;
@@ -194,6 +234,7 @@ test_setting_vpn_update_secrets (void)
 	ASSERT (strcmp (tmp, val2) == 0,
 	        "vpn-update-secrets", "unexpected key #2 value");
 
+	g_hash_table_destroy (settings);
 	g_object_unref (connection);
 }
 
@@ -266,6 +307,156 @@ test_setting_vpn_modify_during_foreach (void)
 	g_object_unref (s_vpn);
 }
 
+static void
+test_setting_ip4_config_labels (void)
+{
+	NMSettingIP4Config *s_ip4;
+	NMIP4Address *addr;
+	const char *label;
+	GPtrArray *addrs;
+	GSList *labels;
+	GError *error = NULL;
+
+	s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
+	g_object_set (G_OBJECT (s_ip4),
+	              NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL,
+	              NULL);
+
+	/* addr 1 */
+	addr = nm_ip4_address_new ();
+	nm_ip4_address_set_address (addr, 0x01010101);
+	nm_ip4_address_set_prefix (addr, 24);
+
+	nm_setting_ip4_config_add_address (s_ip4, addr);
+	nm_ip4_address_unref (addr);
+	nm_setting_verify (NM_SETTING (s_ip4), NULL, &error);
+	g_assert_no_error (error);
+
+	label = NM_UTILS_PRIVATE_CALL (nm_setting_ip4_config_get_address_label (s_ip4, 0));
+	g_assert_cmpstr (label, ==, NULL);
+
+	/* addr 2 */
+	addr = nm_ip4_address_new ();
+	nm_ip4_address_set_address (addr, 0x02020202);
+	nm_ip4_address_set_prefix (addr, 24);
+
+	NM_UTILS_PRIVATE_CALL (nm_setting_ip4_config_add_address_with_label (s_ip4, addr, "eth0:1"));
+	nm_ip4_address_unref (addr);
+	nm_setting_verify (NM_SETTING (s_ip4), NULL, &error);
+	g_assert_no_error (error);
+
+	label = NM_UTILS_PRIVATE_CALL (nm_setting_ip4_config_get_address_label (s_ip4, 1));
+	g_assert_cmpstr (label, ==, "eth0:1");
+
+	/* addr 3 */
+	addr = nm_ip4_address_new ();
+	nm_ip4_address_set_address (addr, 0x03030303);
+	nm_ip4_address_set_prefix (addr, 24);
+
+	NM_UTILS_PRIVATE_CALL (nm_setting_ip4_config_add_address_with_label (s_ip4, addr, NULL));
+	nm_ip4_address_unref (addr);
+	nm_setting_verify (NM_SETTING (s_ip4), NULL, &error);
+	g_assert_no_error (error);
+
+	label = NM_UTILS_PRIVATE_CALL (nm_setting_ip4_config_get_address_label (s_ip4, 2));
+	g_assert_cmpstr (label, ==, NULL);
+
+	/* Remove addr 1 and re-verify remaining addresses */
+	nm_setting_ip4_config_remove_address (s_ip4, 0);
+	nm_setting_verify (NM_SETTING (s_ip4), NULL, &error);
+	g_assert_no_error (error);
+
+	addr = nm_setting_ip4_config_get_address (s_ip4, 0);
+	g_assert_cmpint (nm_ip4_address_get_address (addr), ==, 0x02020202);
+	label = NM_UTILS_PRIVATE_CALL (nm_setting_ip4_config_get_address_label (s_ip4, 0));
+	g_assert_cmpstr (label, ==, "eth0:1");
+
+	addr = nm_setting_ip4_config_get_address (s_ip4, 1);
+	g_assert_cmpint (nm_ip4_address_get_address (addr), ==, 0x03030303);
+	label = NM_UTILS_PRIVATE_CALL (nm_setting_ip4_config_get_address_label (s_ip4, 1));
+	g_assert_cmpstr (label, ==, NULL);
+
+
+	/* Test explicit property assignment */
+	g_object_get (G_OBJECT (s_ip4),
+	              NM_SETTING_IP4_CONFIG_ADDRESSES, &addrs,
+	              "address-labels", &labels,
+	              NULL);
+
+	nm_setting_ip4_config_clear_addresses (s_ip4);
+	g_assert_cmpint (nm_setting_ip4_config_get_num_addresses (s_ip4), ==, 0);
+
+	/* Setting addrs but not labels will result in empty labels */
+	g_object_set (G_OBJECT (s_ip4),
+	              NM_SETTING_IP4_CONFIG_ADDRESSES, addrs,
+	              NULL);
+	g_boxed_free (DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT, addrs);
+	nm_setting_verify (NM_SETTING (s_ip4), NULL, &error);
+	g_assert_no_error (error);
+	g_assert_cmpint (nm_setting_ip4_config_get_num_addresses (s_ip4), ==, 2);
+
+	addr = nm_setting_ip4_config_get_address (s_ip4, 0);
+	g_assert_cmpint (nm_ip4_address_get_address (addr), ==, 0x02020202);
+	label = NM_UTILS_PRIVATE_CALL (nm_setting_ip4_config_get_address_label (s_ip4, 0));
+	g_assert_cmpstr (label, ==, NULL);
+
+	addr = nm_setting_ip4_config_get_address (s_ip4, 1);
+	g_assert_cmpint (nm_ip4_address_get_address (addr), ==, 0x03030303);
+	label = NM_UTILS_PRIVATE_CALL (nm_setting_ip4_config_get_address_label (s_ip4, 1));
+	g_assert_cmpstr (label, ==, NULL);
+
+	/* Setting labels now will leave addresses untouched */
+	g_object_set (G_OBJECT (s_ip4),
+	              "address-labels", labels,
+	              NULL);
+	g_boxed_free (DBUS_TYPE_G_LIST_OF_STRING, labels);
+	nm_setting_verify (NM_SETTING (s_ip4), NULL, &error);
+	g_assert_no_error (error);
+	g_assert_cmpint (nm_setting_ip4_config_get_num_addresses (s_ip4), ==, 2);
+
+	addr = nm_setting_ip4_config_get_address (s_ip4, 0);
+	g_assert_cmpint (nm_ip4_address_get_address (addr), ==, 0x02020202);
+	label = NM_UTILS_PRIVATE_CALL (nm_setting_ip4_config_get_address_label (s_ip4, 0));
+	g_assert_cmpstr (label, ==, "eth0:1");
+
+	addr = nm_setting_ip4_config_get_address (s_ip4, 1);
+	g_assert_cmpint (nm_ip4_address_get_address (addr), ==, 0x03030303);
+	label = NM_UTILS_PRIVATE_CALL (nm_setting_ip4_config_get_address_label (s_ip4, 1));
+	g_assert_cmpstr (label, ==, NULL);
+
+	/* Setting labels to a value that's too short or too long will result in
+	 * the setting not verifying.
+	 */
+	labels = g_slist_append (NULL, "eth0:2");
+	g_object_set (G_OBJECT (s_ip4),
+	              "address-labels", labels,
+	              NULL);
+
+	nm_setting_verify (NM_SETTING (s_ip4), NULL, &error);
+	g_assert_error (error, NM_SETTING_IP4_CONFIG_ERROR, NM_SETTING_IP4_CONFIG_ERROR_INVALID_PROPERTY);
+	g_assert (g_str_has_prefix (error->message, "ipv4.address-labels:"));
+	g_clear_error (&error);
+
+	labels = g_slist_append (labels, "eth0:3");
+	g_object_set (G_OBJECT (s_ip4),
+	              "address-labels", labels,
+	              NULL);
+	nm_setting_verify (NM_SETTING (s_ip4), NULL, &error);
+	g_assert_no_error (error);
+
+	labels = g_slist_append (labels, "eth0:4");
+	g_object_set (G_OBJECT (s_ip4),
+	              "address-labels", labels,
+	              NULL);
+	nm_setting_verify (NM_SETTING (s_ip4), NULL, &error);
+	g_assert_error (error, NM_SETTING_IP4_CONFIG_ERROR, NM_SETTING_IP4_CONFIG_ERROR_INVALID_PROPERTY);
+	g_assert (g_str_has_prefix (error->message, "ipv4.address-labels:"));
+	g_clear_error (&error);
+
+
+	g_object_unref (s_ip4);
+}
+
 #define OLD_DBUS_TYPE_G_IP6_ADDRESS (dbus_g_type_get_struct ("GValueArray", DBUS_TYPE_G_UCHAR_ARRAY, G_TYPE_UINT, G_TYPE_INVALID))
 #define OLD_DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS (dbus_g_type_get_collection ("GPtrArray", OLD_DBUS_TYPE_G_IP6_ADDRESS))
 
@@ -279,7 +470,7 @@ test_setting_ip6_config_old_address_array (void)
 	NMSettingIP6Config *s_ip6;
 	GPtrArray *addresses, *read_addresses;
 	GValueArray *array, *read_array;
-	GValue element = {0, }, written_value = {0, }, read_value = {0, };
+	GValue element = G_VALUE_INIT, written_value = G_VALUE_INIT, read_value = G_VALUE_INIT;
 	GByteArray *ba;
 	const guint8 addr[16] = { 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11,
 	                          0x11, 0x22, 0x33, 0x44, 0x66, 0x77, 0x88, 0x99 };
@@ -462,6 +653,7 @@ test_setting_gsm_without_number (void)
 	g_object_set (s_gsm, NM_SETTING_GSM_NUMBER, "", NULL);
 	success = nm_setting_verify (NM_SETTING (s_gsm), NULL, &error);
 	g_assert_error (error, NM_SETTING_GSM_ERROR, NM_SETTING_GSM_ERROR_INVALID_PROPERTY);
+	g_error_free (error);
 }
 
 static NMSettingWirelessSecurity *
@@ -582,6 +774,262 @@ test_connection_to_hash_setting_name (void)
 }
 
 static void
+test_setting_new_from_hash (void)
+{
+	NMSettingWirelessSecurity *s_wsec;
+	GHashTable *hash;
+
+	s_wsec = make_test_wsec_setting ("setting-to-hash-all");
+	hash = nm_setting_to_hash (NM_SETTING (s_wsec), NM_SETTING_HASH_FLAG_ALL);
+	g_object_unref (s_wsec);
+
+	s_wsec = (NMSettingWirelessSecurity *) nm_setting_new_from_hash (NM_TYPE_SETTING_WIRELESS_SECURITY, hash);
+	g_hash_table_destroy (hash);
+
+	g_assert (s_wsec);
+	g_assert_cmpstr (nm_setting_wireless_security_get_key_mgmt (s_wsec), ==, "wpa-psk");
+	g_assert_cmpstr (nm_setting_wireless_security_get_leap_username (s_wsec), ==, "foobarbaz");
+	g_assert_cmpstr (nm_setting_wireless_security_get_psk (s_wsec), ==, "random psk");
+	g_object_unref (s_wsec);
+}
+
+static NMConnection *
+new_test_connection (void)
+{
+	NMConnection *connection;
+	NMSetting *setting;
+	char *uuid;
+	guint64 timestamp = time (NULL);
+
+	connection = nm_connection_new ();
+
+	setting = nm_setting_connection_new ();
+	uuid = nm_utils_uuid_generate ();
+	g_object_set (G_OBJECT (setting),
+	              NM_SETTING_CONNECTION_ID, "foobar",
+	              NM_SETTING_CONNECTION_UUID, uuid,
+	              NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME,
+	              NM_SETTING_CONNECTION_TIMESTAMP, timestamp,
+	              NULL);
+	g_free (uuid);
+	nm_connection_add_setting (connection, setting);
+
+	setting = nm_setting_wired_new ();
+	g_object_set (G_OBJECT (setting),
+	              NM_SETTING_WIRED_MTU, 1592,
+	              NULL);
+	nm_connection_add_setting (connection, setting);
+
+	setting = nm_setting_ip4_config_new ();
+	g_object_set (G_OBJECT (setting),
+	              NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO,
+	              NM_SETTING_IP4_CONFIG_DHCP_HOSTNAME, "eyeofthetiger",
+	              NULL);
+	nm_connection_add_setting (connection, setting);
+
+	return connection;
+}
+
+static GValue *
+string_to_gvalue (const char *str)
+{
+	GValue *val;
+
+	val = g_slice_new0 (GValue);
+	g_value_init (val, G_TYPE_STRING);
+	g_value_set_string (val, str);
+	return val;
+}
+
+static void
+destroy_gvalue (gpointer data)
+{
+	g_value_unset ((GValue *) data);
+	g_slice_free (GValue, data);
+}
+
+static GHashTable *
+new_connection_hash (char **out_uuid,
+                     const char **out_expected_id,
+                     const char **out_expected_ip6_method)
+{
+	GHashTable *hash;
+	GHashTable *setting;
+
+	hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_hash_table_destroy);
+
+	*out_uuid = nm_utils_uuid_generate ();
+	*out_expected_id = "My happy connection";
+	*out_expected_ip6_method = NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL;
+
+	/* Connection setting */
+	setting = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, destroy_gvalue);
+	g_hash_table_insert (setting,
+	                     g_strdup (NM_SETTING_NAME),
+	                     string_to_gvalue (NM_SETTING_CONNECTION_SETTING_NAME));
+	g_hash_table_insert (setting,
+	                     g_strdup (NM_SETTING_CONNECTION_ID),
+	                     string_to_gvalue (*out_expected_id));
+	g_hash_table_insert (setting,
+	                     g_strdup (NM_SETTING_CONNECTION_UUID),
+	                     string_to_gvalue (*out_uuid));
+	g_hash_table_insert (setting,
+	                     g_strdup (NM_SETTING_CONNECTION_TYPE),
+	                     string_to_gvalue (NM_SETTING_WIRED_SETTING_NAME));
+	g_hash_table_insert (hash, g_strdup (NM_SETTING_CONNECTION_SETTING_NAME), setting);
+
+	/* Wired setting */
+	setting = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, destroy_gvalue);
+	g_hash_table_insert (hash, g_strdup (NM_SETTING_WIRED_SETTING_NAME), setting);
+
+	/* IP6 */
+	setting = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, destroy_gvalue);
+	g_hash_table_insert (setting,
+	                     g_strdup (NM_SETTING_IP6_CONFIG_METHOD),
+	                     string_to_gvalue (*out_expected_ip6_method));
+	g_hash_table_insert (hash, g_strdup (NM_SETTING_IP6_CONFIG_SETTING_NAME), setting);
+
+	return hash;
+}
+
+static void
+test_connection_replace_settings ()
+{
+	NMConnection *connection;
+	GHashTable *new_settings;
+	GError *error = NULL;
+	gboolean success;
+	NMSettingConnection *s_con;
+	NMSettingIP6Config *s_ip6;
+	char *uuid = NULL;
+	const char *expected_id = NULL, *expected_method = NULL;
+
+	connection = new_test_connection ();
+
+	new_settings = new_connection_hash (&uuid, &expected_id, &expected_method);
+	g_assert (new_settings);
+
+	/* Replace settings and test */
+	success = nm_connection_replace_settings (connection, new_settings, &error);
+	g_assert_no_error (error);
+	g_assert (success);
+
+	s_con = nm_connection_get_setting_connection (connection);
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, expected_id);
+	g_assert_cmpstr (nm_setting_connection_get_uuid (s_con), ==, uuid);
+
+	g_assert (nm_connection_get_setting_wired (connection));
+	g_assert (!nm_connection_get_setting_ip4_config (connection));
+
+	s_ip6 = nm_connection_get_setting_ip6_config (connection);
+	g_assert (s_ip6);
+	g_assert_cmpstr (nm_setting_ip6_config_get_method (s_ip6), ==, expected_method);
+
+	g_free (uuid);
+	g_hash_table_destroy (new_settings);
+	g_object_unref (connection);
+}
+
+static void
+test_connection_replace_settings_from_connection ()
+{
+	NMConnection *connection, *replacement;
+	GError *error = NULL;
+	gboolean success;
+	NMSettingConnection *s_con;
+	NMSetting *setting;
+	GByteArray *ssid;
+	char *uuid = NULL;
+	const char *expected_id = "Awesome connection";
+
+	connection = new_test_connection ();
+	g_assert (connection);
+
+	replacement = nm_connection_new ();
+	g_assert (replacement);
+
+	/* New connection setting */
+	setting = nm_setting_connection_new ();
+	g_assert (setting);
+
+	uuid = nm_utils_uuid_generate ();
+	g_object_set (setting,
+	              NM_SETTING_CONNECTION_ID, expected_id,
+	              NM_SETTING_CONNECTION_UUID, uuid,
+	              NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME,
+	              NULL);
+	nm_connection_add_setting (replacement, setting);
+
+	/* New wifi setting */
+	setting = nm_setting_wireless_new ();
+	g_assert (setting);
+
+	ssid = g_byte_array_new ();
+	g_byte_array_append (ssid, (const guint8 *) "1234567", 7);
+	g_object_set (setting,
+	              NM_SETTING_WIRELESS_SSID, ssid,
+	              NM_SETTING_WIRELESS_MODE, "infrastructure",
+	              NULL);
+	g_byte_array_free (ssid, TRUE);
+	nm_connection_add_setting (replacement, setting);
+
+	/* Replace settings and test */
+	success = nm_connection_replace_settings_from_connection (connection, replacement, &error);
+	g_assert_no_error (error);
+	g_assert (success);
+
+	s_con = nm_connection_get_setting_connection (connection);
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, expected_id);
+	g_assert_cmpstr (nm_setting_connection_get_uuid (s_con), ==, uuid);
+
+	g_assert (!nm_connection_get_setting_wired (connection));
+	g_assert (!nm_connection_get_setting_ip6_config (connection));
+	g_assert (nm_connection_get_setting_wireless (connection));
+
+	g_free (uuid);
+	g_object_unref (replacement);
+	g_object_unref (connection);
+}
+
+static void
+test_connection_new_from_hash ()
+{
+	NMConnection *connection;
+	GHashTable *new_settings;
+	GError *error = NULL;
+	NMSettingConnection *s_con;
+	NMSettingIP6Config *s_ip6;
+	char *uuid = NULL;
+	const char *expected_id = NULL, *expected_method = NULL;
+
+	new_settings = new_connection_hash (&uuid, &expected_id, &expected_method);
+	g_assert (new_settings);
+
+	/* Replace settings and test */
+	connection = nm_connection_new_from_hash (new_settings, &error);
+	g_assert_no_error (error);
+	g_assert (connection);
+
+	s_con = nm_connection_get_setting_connection (connection);
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, expected_id);
+	g_assert_cmpstr (nm_setting_connection_get_uuid (s_con), ==, uuid);
+
+	g_assert (nm_connection_get_setting_wired (connection));
+	g_assert (!nm_connection_get_setting_ip4_config (connection));
+
+	s_ip6 = nm_connection_get_setting_ip6_config (connection);
+	g_assert (s_ip6);
+	g_assert_cmpstr (nm_setting_ip6_config_get_method (s_ip6), ==, expected_method);
+
+	g_free (uuid);
+	g_hash_table_destroy (new_settings);
+	g_object_unref (connection);
+}
+
+static void
 check_permission (NMSettingConnection *s_con,
                   guint32 idx,
                   const char *expected_uname,
@@ -618,37 +1066,55 @@ test_setting_connection_permissions_helpers (void)
 	s_con = NM_SETTING_CONNECTION (nm_setting_connection_new ());
 
 	/* Ensure a bad [type] is rejected */
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*strcmp (ptype, \"user\") == 0*");
 	success = nm_setting_connection_add_permission (s_con, "foobar", "blah", NULL);
+	g_test_assert_expected_messages ();
 	ASSERT (success == FALSE,
 	        "setting-connection-permissions-helpers", "unexpected success adding bad permission type #1");
 
 	/* Ensure a bad [type] is rejected */
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*ptype*");
 	success = nm_setting_connection_add_permission (s_con, NULL, "blah", NULL);
+	g_test_assert_expected_messages ();
 	ASSERT (success == FALSE,
 	        "setting-connection-permissions-helpers", "unexpected success adding bad permission type #2");
 
 	/* Ensure a bad [item] is rejected */
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*uname*");
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*p != NULL*");
 	success = nm_setting_connection_add_permission (s_con, "user", NULL, NULL);
+	g_test_assert_expected_messages ();
 	ASSERT (success == FALSE,
 	        "setting-connection-permissions-helpers", "unexpected success adding bad permission item #1");
 
 	/* Ensure a bad [item] is rejected */
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*uname[0] != '\\0'*");
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*p != NULL*");
 	success = nm_setting_connection_add_permission (s_con, "user", "", NULL);
+	g_test_assert_expected_messages ();
 	ASSERT (success == FALSE,
 	        "setting-connection-permissions-helpers", "unexpected success adding bad permission item #2");
 
 	/* Ensure an [item] with ':' is rejected */
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*strchr (uname, ':')*");
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*p != NULL*");
 	success = nm_setting_connection_add_permission (s_con, "user", "ad:asdf", NULL);
+	g_test_assert_expected_messages ();
 	ASSERT (success == FALSE,
 	        "setting-connection-permissions-helpers", "unexpected success adding bad permission item #3");
 
 	/* Ensure a non-UTF-8 [item] is rejected */
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*g_utf8_validate (uname, -1, NULL)*");
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*p != NULL*");
 	success = nm_setting_connection_add_permission (s_con, "user", buf, NULL);
+	g_test_assert_expected_messages ();
 	ASSERT (success == FALSE,
 	        "setting-connection-permissions-helpers", "unexpected success adding bad permission item #4");
 
 	/* Ensure a non-NULL [detail] is rejected */
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*detail == NULL*");
 	success = nm_setting_connection_add_permission (s_con, "user", "dafasdf", "asdf");
+	g_test_assert_expected_messages ();
 	ASSERT (success == FALSE,
 	        "setting-connection-permissions-helpers", "unexpected success adding bad detail");
 
@@ -670,6 +1136,7 @@ test_setting_connection_permissions_helpers (void)
 	        "setting-connection-permissions-helpers", "unexpected failure getting number of permissions in list");
 	ASSERT (strcmp (list->data, expected_perm) == 0,
 	        "setting-connection-permissions-helpers", "unexpected permission property data");
+	g_slist_free_full (list, g_free);
 
 	/* Now remove that permission and ensure we have 0 permissions */
 	nm_setting_connection_remove_permission (s_con, 0);
@@ -723,42 +1190,58 @@ test_setting_connection_permissions_property (void)
 	s_con = NM_SETTING_CONNECTION (nm_setting_connection_new ());
 
 	/* Ensure a bad [type] is rejected */
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*strncmp (str, PERM_USER_PREFIX, strlen (PERM_USER_PREFIX)) == 0*");
 	add_permission_property (s_con, "foobar", "blah", -1, NULL);
+	g_test_assert_expected_messages ();
 	ASSERT (nm_setting_connection_get_num_permissions (s_con) == 0,
 	        "setting-connection-permissions-property", "unexpected success adding bad permission type #1");
 
 	/* Ensure a bad [type] is rejected */
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*strncmp (str, PERM_USER_PREFIX, strlen (PERM_USER_PREFIX)) == 0*");
 	add_permission_property (s_con, NULL, "blah", -1, NULL);
+	g_test_assert_expected_messages ();
 	ASSERT (nm_setting_connection_get_num_permissions (s_con) == 0,
 	        "setting-connection-permissions-property", "unexpected success adding bad permission type #2");
 
 	/* Ensure a bad [item] is rejected */
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*last_colon > str*");
 	add_permission_property (s_con, "user", NULL, -1, NULL);
+	g_test_assert_expected_messages ();
 	ASSERT (nm_setting_connection_get_num_permissions (s_con) == 0,
 	        "setting-connection-permissions-property", "unexpected success adding bad permission item #1");
 
 	/* Ensure a bad [item] is rejected */
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*last_colon > str*");
 	add_permission_property (s_con, "user", "", -1, NULL);
+	g_test_assert_expected_messages ();
 	ASSERT (nm_setting_connection_get_num_permissions (s_con) == 0,
 	        "setting-connection-permissions-property", "unexpected success adding bad permission item #2");
 
 	/* Ensure an [item] with ':' in the middle is rejected */
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*str[i] != ':'*");
 	add_permission_property (s_con, "user", "ad:asdf", -1, NULL);
+	g_test_assert_expected_messages ();
 	ASSERT (nm_setting_connection_get_num_permissions (s_con) == 0,
 	        "setting-connection-permissions-property", "unexpected success adding bad permission item #3");
 
 	/* Ensure an [item] with ':' at the end is rejected */
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*str[i] != ':'*");
 	add_permission_property (s_con, "user", "adasdfaf:", -1, NULL);
+	g_test_assert_expected_messages ();
 	ASSERT (nm_setting_connection_get_num_permissions (s_con) == 0,
 	        "setting-connection-permissions-property", "unexpected success adding bad permission item #4");
 
 	/* Ensure a non-UTF-8 [item] is rejected */
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*g_utf8_validate (str, -1, NULL)*");
 	add_permission_property (s_con, "user", buf, (int) sizeof (buf), NULL);
+	g_test_assert_expected_messages ();
 	ASSERT (nm_setting_connection_get_num_permissions (s_con) == 0,
 	        "setting-connection-permissions-property", "unexpected success adding bad permission item #5");
 
 	/* Ensure a non-NULL [detail] is rejected */
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*(last_colon + 1) == '\\0'*");
 	add_permission_property (s_con, "user", "dafasdf", -1, "asdf");
+	g_test_assert_expected_messages ();
 	ASSERT (nm_setting_connection_get_num_permissions (s_con) == 0,
 	        "setting-connection-permissions-property", "unexpected success adding bad detail");
 
@@ -777,41 +1260,76 @@ test_setting_connection_permissions_property (void)
 	g_object_unref (s_con);
 }
 
-static NMConnection *
-new_test_connection (void)
+static void
+test_connection_compare_same (void)
 {
-	NMConnection *connection;
-	NMSetting *setting;
-	char *uuid;
-	guint64 timestamp = time (NULL);
+	NMConnection *a, *b;
 
-	connection = nm_connection_new ();
+	a = new_test_connection ();
+	b = nm_connection_duplicate (a);
+	g_assert (nm_connection_compare (a, b, NM_SETTING_COMPARE_FLAG_EXACT));
+	g_object_unref (a);
+	g_object_unref (b);
+}
 
-	setting = nm_setting_connection_new ();
-	uuid = nm_utils_uuid_generate ();
-	g_object_set (G_OBJECT (setting),
-	              NM_SETTING_CONNECTION_ID, "foobar",
-	              NM_SETTING_CONNECTION_UUID, uuid,
-	              NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME,
-	              NM_SETTING_CONNECTION_TIMESTAMP, timestamp,
-	              NULL);
-	g_free (uuid);
-	nm_connection_add_setting (connection, setting);
+static void
+test_connection_compare_key_only_in_a (void)
+{
+	NMConnection *a, *b;
+	NMSettingConnection *s_con;
 
-	setting = nm_setting_wired_new ();
-	g_object_set (G_OBJECT (setting),
-	              NM_SETTING_WIRED_MTU, 1592,
-	              NULL);
-	nm_connection_add_setting (connection, setting);
+	a = new_test_connection ();
+	b = nm_connection_duplicate (a);
+	s_con = (NMSettingConnection *) nm_connection_get_setting (b, NM_TYPE_SETTING_CONNECTION);
+	g_assert (s_con);
+	g_object_set (s_con, NM_SETTING_CONNECTION_TIMESTAMP, (guint64) 0, NULL);
 
-	setting = nm_setting_ip4_config_new ();
-	g_object_set (G_OBJECT (setting),
-	              NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO,
-	              NM_SETTING_IP4_CONFIG_DHCP_HOSTNAME, "eyeofthetiger",
-	              NULL);
-	nm_connection_add_setting (connection, setting);
+	g_assert (!nm_connection_compare (a, b, NM_SETTING_COMPARE_FLAG_EXACT));
+	g_object_unref (a);
+	g_object_unref (b);
+}
 
-	return connection;
+static void
+test_connection_compare_setting_only_in_a (void)
+{
+	NMConnection *a, *b;
+
+	a = new_test_connection ();
+	b = nm_connection_duplicate (a);
+	nm_connection_remove_setting (b, NM_TYPE_SETTING_IP4_CONFIG);
+	g_assert (!nm_connection_compare (a, b, NM_SETTING_COMPARE_FLAG_EXACT));
+	g_object_unref (a);
+	g_object_unref (b);
+}
+
+static void
+test_connection_compare_key_only_in_b (void)
+{
+	NMConnection *a, *b;
+	NMSettingConnection *s_con;
+
+	a = new_test_connection ();
+	b = nm_connection_duplicate (a);
+	s_con = (NMSettingConnection *) nm_connection_get_setting (b, NM_TYPE_SETTING_CONNECTION);
+	g_assert (s_con);
+	g_object_set (s_con, NM_SETTING_CONNECTION_TIMESTAMP, (guint64) 0, NULL);
+
+	g_assert (!nm_connection_compare (a, b, NM_SETTING_COMPARE_FLAG_EXACT));
+	g_object_unref (a);
+	g_object_unref (b);
+}
+
+static void
+test_connection_compare_setting_only_in_b (void)
+{
+	NMConnection *a, *b;
+
+	a = new_test_connection ();
+	b = nm_connection_duplicate (a);
+	nm_connection_remove_setting (a, NM_TYPE_SETTING_IP4_CONFIG);
+	g_assert (!nm_connection_compare (a, b, NM_SETTING_COMPARE_FLAG_EXACT));
+	g_object_unref (a);
+	g_object_unref (b);
 }
 
 typedef struct {
@@ -864,17 +1382,19 @@ test_connection_diff_a_only (void)
 	gboolean same;
 	const DiffSetting settings[] = {
 		{ NM_SETTING_CONNECTION_SETTING_NAME, {
-			{ NM_SETTING_CONNECTION_ID,          NM_SETTING_DIFF_RESULT_IN_A },
-			{ NM_SETTING_CONNECTION_UUID,        NM_SETTING_DIFF_RESULT_IN_A },
-			{ NM_SETTING_CONNECTION_TYPE,        NM_SETTING_DIFF_RESULT_IN_A },
-			{ NM_SETTING_CONNECTION_TIMESTAMP,   NM_SETTING_DIFF_RESULT_IN_A },
-			{ NM_SETTING_CONNECTION_AUTOCONNECT, 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 },
-			{ NM_SETTING_CONNECTION_MASTER,      NM_SETTING_DIFF_RESULT_IN_A },
-			{ NM_SETTING_CONNECTION_SLAVE_TYPE,  NM_SETTING_DIFF_RESULT_IN_A },
-			{ NM_SETTING_CONNECTION_SECONDARIES, NM_SETTING_DIFF_RESULT_IN_A },
+			{ NM_SETTING_CONNECTION_ID,                   NM_SETTING_DIFF_RESULT_IN_A },
+			{ NM_SETTING_CONNECTION_UUID,                 NM_SETTING_DIFF_RESULT_IN_A },
+			{ NM_SETTING_CONNECTION_INTERFACE_NAME,       NM_SETTING_DIFF_RESULT_IN_A },
+			{ NM_SETTING_CONNECTION_TYPE,                 NM_SETTING_DIFF_RESULT_IN_A },
+			{ NM_SETTING_CONNECTION_TIMESTAMP,            NM_SETTING_DIFF_RESULT_IN_A },
+			{ NM_SETTING_CONNECTION_AUTOCONNECT,          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 },
+			{ NM_SETTING_CONNECTION_MASTER,               NM_SETTING_DIFF_RESULT_IN_A },
+			{ NM_SETTING_CONNECTION_SLAVE_TYPE,           NM_SETTING_DIFF_RESULT_IN_A },
+			{ NM_SETTING_CONNECTION_SECONDARIES,          NM_SETTING_DIFF_RESULT_IN_A },
+			{ NM_SETTING_CONNECTION_GATEWAY_PING_TIMEOUT, NM_SETTING_DIFF_RESULT_IN_A },
 			{ NULL, NM_SETTING_DIFF_RESULT_UNKNOWN }
 		} },
 		{ NM_SETTING_WIRED_SETTING_NAME, {
@@ -896,6 +1416,7 @@ test_connection_diff_a_only (void)
 			{ NM_SETTING_IP4_CONFIG_DNS,                NM_SETTING_DIFF_RESULT_IN_A },
 			{ NM_SETTING_IP4_CONFIG_DNS_SEARCH,         NM_SETTING_DIFF_RESULT_IN_A },
 			{ NM_SETTING_IP4_CONFIG_ADDRESSES,          NM_SETTING_DIFF_RESULT_IN_A },
+			{ "address-labels",                         NM_SETTING_DIFF_RESULT_IN_A },
 			{ NM_SETTING_IP4_CONFIG_ROUTES,             NM_SETTING_DIFF_RESULT_IN_A },
 			{ NM_SETTING_IP4_CONFIG_IGNORE_AUTO_ROUTES, NM_SETTING_DIFF_RESULT_IN_A },
 			{ NM_SETTING_IP4_CONFIG_IGNORE_AUTO_DNS,    NM_SETTING_DIFF_RESULT_IN_A },
@@ -917,6 +1438,7 @@ test_connection_diff_a_only (void)
 
 	ensure_diffs (out_diffs, settings, ARRAY_LEN (settings));
 
+	g_hash_table_destroy (out_diffs);
 	g_object_unref (connection);
 }
 
@@ -966,6 +1488,7 @@ test_connection_diff_different (void)
 
 	ensure_diffs (out_diffs, settings, ARRAY_LEN (settings));
 
+	g_hash_table_destroy (out_diffs);
 	g_object_unref (a);
 	g_object_unref (b);
 }
@@ -1013,6 +1536,66 @@ test_connection_diff_no_secrets (void)
 
 	ensure_diffs (out_diffs, settings, ARRAY_LEN (settings));
 
+	g_hash_table_destroy (out_diffs);
+	g_object_unref (a);
+	g_object_unref (b);
+}
+
+static void
+test_connection_diff_inferrable (void)
+{
+	NMConnection *a, *b;
+	GHashTable *out_diffs = NULL;
+	gboolean same;
+	NMSettingConnection *s_con;
+	NMSettingWired *s_wired;
+	NMSettingIP4Config *s_ip4;
+	char *uuid;
+	const DiffSetting settings[] = {
+		{ NM_SETTING_CONNECTION_SETTING_NAME, {
+			{ NM_SETTING_CONNECTION_INTERFACE_NAME, NM_SETTING_DIFF_RESULT_IN_A },
+			{ NULL, NM_SETTING_DIFF_RESULT_UNKNOWN },
+		} },
+	};
+
+	a = new_test_connection ();
+	b = nm_connection_duplicate (a);
+
+	/* Change the UUID, wired MTU, and set ignore-auto-dns */
+	s_con = nm_connection_get_setting_connection (a);
+	g_assert (s_con);
+	uuid = nm_utils_uuid_generate ();
+	g_object_set (G_OBJECT (s_con),
+	              NM_SETTING_CONNECTION_UUID, uuid,
+	              NM_SETTING_CONNECTION_ID, "really neat connection",
+	              NULL);
+	g_free (uuid);
+
+	s_wired = nm_connection_get_setting_wired (a);
+	g_assert (s_wired);
+	g_object_set (G_OBJECT (s_wired), NM_SETTING_WIRED_MTU, 300, NULL);
+
+	s_ip4 = nm_connection_get_setting_ip4_config (a);
+	g_assert (s_ip4);
+	g_object_set (G_OBJECT (s_ip4), NM_SETTING_IP4_CONFIG_IGNORE_AUTO_DNS, TRUE, NULL);
+
+	/* Make sure the diff returns no results as secrets are ignored */
+	same = nm_connection_diff (a, b, NM_SETTING_COMPARE_FLAG_INFERRABLE, &out_diffs);
+	g_assert (same == TRUE);
+	g_assert (out_diffs == NULL);
+
+	/* And change a INFERRABLE property to ensure that it shows up in the diff results */
+	g_object_set (G_OBJECT (s_con), NM_SETTING_CONNECTION_INTERFACE_NAME, "usb0", NULL);
+
+	/* Make sure the diff returns no results as secrets are ignored */
+	same = nm_connection_diff (a, b, NM_SETTING_COMPARE_FLAG_INFERRABLE, &out_diffs);
+	g_assert (same == FALSE);
+	g_assert (out_diffs != NULL);
+	g_assert (g_hash_table_size (out_diffs) > 0);
+
+	ensure_diffs (out_diffs, settings, ARRAY_LEN (settings));
+
+	g_hash_table_destroy (out_diffs);
 	g_object_unref (a);
 	g_object_unref (b);
 }
@@ -1363,6 +1946,12 @@ test_hwaddr_aton_malformed (void)
 }
 
 static void
+test_connection_changed_cb (NMConnection *connection, gboolean *data)
+{
+	*data = TRUE;
+}
+
+static void
 test_ip4_prefix_to_netmask (void)
 {
 	int i;
@@ -1422,6 +2011,456 @@ test_ip4_netmask_to_prefix (void)
 	g_rand_free (rand);
 }
 
+#define ASSERT_CHANGED(statement) \
+{ \
+	changed = FALSE; \
+	statement; \
+	g_assert (changed); \
+}
+
+#define ASSERT_UNCHANGED(statement) \
+{ \
+	changed = FALSE; \
+	statement; \
+	g_assert (!changed); \
+}
+
+static void
+test_connection_changed_signal (void)
+{
+	NMConnection *connection;
+	gboolean changed = FALSE;
+
+	connection = new_test_connection ();
+	g_signal_connect (connection,
+	                  NM_CONNECTION_CHANGED,
+	                  (GCallback) test_connection_changed_cb,
+	                  &changed);
+
+	/* Add new setting */
+	ASSERT_CHANGED (nm_connection_add_setting (connection, nm_setting_vlan_new ()));
+
+	/* Remove existing setting */
+	ASSERT_CHANGED (nm_connection_remove_setting (connection, NM_TYPE_SETTING_VLAN));
+
+	/* Remove non-existing setting */
+	ASSERT_UNCHANGED (nm_connection_remove_setting (connection, NM_TYPE_SETTING_VLAN));
+
+	g_object_unref (connection);
+}
+
+static void
+test_setting_connection_changed_signal (void)
+{
+	NMConnection *connection;
+	gboolean changed = FALSE;
+	NMSettingConnection *s_con;
+	char *uuid;
+
+	connection = nm_connection_new ();
+	g_signal_connect (connection,
+	                  NM_CONNECTION_CHANGED,
+	                  (GCallback) test_connection_changed_cb,
+	                  &changed);
+
+	s_con = (NMSettingConnection *) nm_setting_connection_new ();
+	nm_connection_add_setting (connection, NM_SETTING (s_con));
+
+	ASSERT_CHANGED (g_object_set (s_con, NM_SETTING_CONNECTION_ID, "adfadfasdfaf", NULL));
+
+	ASSERT_CHANGED (nm_setting_connection_add_permission (s_con, "user", "billsmith", NULL));
+	ASSERT_CHANGED (nm_setting_connection_remove_permission (s_con, 0));
+
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*iter != NULL*");
+	ASSERT_UNCHANGED (nm_setting_connection_remove_permission (s_con, 1));
+	g_test_assert_expected_messages ();
+
+	uuid = nm_utils_uuid_generate ();
+	ASSERT_CHANGED (nm_setting_connection_add_secondary (s_con, uuid));
+	ASSERT_CHANGED (nm_setting_connection_remove_secondary (s_con, 0));
+
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*elt != NULL*");
+	ASSERT_UNCHANGED (nm_setting_connection_remove_secondary (s_con, 1));
+	g_test_assert_expected_messages ();
+
+	g_object_unref (connection);
+}
+
+static void
+test_setting_bond_changed_signal (void)
+{
+	NMConnection *connection;
+	gboolean changed = FALSE;
+	NMSettingBond *s_bond;
+
+	connection = nm_connection_new ();
+	g_signal_connect (connection,
+	                  NM_CONNECTION_CHANGED,
+	                  (GCallback) test_connection_changed_cb,
+	                  &changed);
+
+	s_bond = (NMSettingBond *) nm_setting_bond_new ();
+	nm_connection_add_setting (connection, NM_SETTING (s_bond));
+
+	ASSERT_CHANGED (nm_setting_bond_add_option (s_bond, NM_SETTING_BOND_OPTION_DOWNDELAY, "10"));
+	ASSERT_CHANGED (nm_setting_bond_remove_option (s_bond, NM_SETTING_BOND_OPTION_DOWNDELAY));
+	ASSERT_UNCHANGED (nm_setting_bond_remove_option (s_bond, NM_SETTING_BOND_OPTION_UPDELAY));
+
+	g_object_unref (connection);
+}
+
+static void
+test_setting_ip4_changed_signal (void)
+{
+	NMConnection *connection;
+	gboolean changed = FALSE;
+	NMSettingIP4Config *s_ip4;
+	NMIP4Address *addr;
+	NMIP4Route *route;
+
+	connection = nm_connection_new ();
+	g_signal_connect (connection,
+	                  NM_CONNECTION_CHANGED,
+	                  (GCallback) test_connection_changed_cb,
+	                  &changed);
+
+	s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
+	nm_connection_add_setting (connection, NM_SETTING (s_ip4));
+
+	ASSERT_CHANGED (nm_setting_ip4_config_add_dns (s_ip4, 0x1122));
+	ASSERT_CHANGED (nm_setting_ip4_config_remove_dns (s_ip4, 0));
+
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*i <= priv->dns->len*");
+	ASSERT_UNCHANGED (nm_setting_ip4_config_remove_dns (s_ip4, 1));
+	g_test_assert_expected_messages ();
+
+	nm_setting_ip4_config_add_dns (s_ip4, 0x3344);
+	ASSERT_CHANGED (nm_setting_ip4_config_clear_dns (s_ip4));
+
+	ASSERT_CHANGED (nm_setting_ip4_config_add_dns_search (s_ip4, "foobar.com"));
+	ASSERT_CHANGED (nm_setting_ip4_config_remove_dns_search (s_ip4, 0));
+
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*elt != NULL*");
+	ASSERT_UNCHANGED (nm_setting_ip4_config_remove_dns_search (s_ip4, 1));
+	g_test_assert_expected_messages ();
+
+	ASSERT_CHANGED (nm_setting_ip4_config_add_dns_search (s_ip4, "foobar.com"));
+	ASSERT_CHANGED (nm_setting_ip4_config_clear_dns_searches (s_ip4));
+
+	addr = nm_ip4_address_new ();
+	nm_ip4_address_set_address (addr, 0x2233);
+	nm_ip4_address_set_prefix (addr, 24);
+	ASSERT_CHANGED (nm_setting_ip4_config_add_address (s_ip4, addr));
+	ASSERT_CHANGED (nm_setting_ip4_config_remove_address (s_ip4, 0));
+
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*addr != NULL && label != NULL*");
+	ASSERT_UNCHANGED (nm_setting_ip4_config_remove_address (s_ip4, 1));
+	g_test_assert_expected_messages ();
+
+	nm_setting_ip4_config_add_address (s_ip4, addr);
+	ASSERT_CHANGED (nm_setting_ip4_config_clear_addresses (s_ip4));
+
+	route = nm_ip4_route_new ();
+	nm_ip4_route_set_dest (route, 0x2233);
+	nm_ip4_route_set_prefix (route, 24);
+
+	ASSERT_CHANGED (nm_setting_ip4_config_add_route (s_ip4, route));
+	ASSERT_CHANGED (nm_setting_ip4_config_remove_route (s_ip4, 0));
+
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*elt != NULL*");
+	ASSERT_UNCHANGED (nm_setting_ip4_config_remove_route (s_ip4, 1));
+	g_test_assert_expected_messages ();
+
+	nm_setting_ip4_config_add_route (s_ip4, route);
+	ASSERT_CHANGED (nm_setting_ip4_config_clear_routes (s_ip4));
+
+	nm_ip4_address_unref (addr);
+	nm_ip4_route_unref (route);
+	g_object_unref (connection);
+}
+
+static void
+test_setting_ip6_changed_signal (void)
+{
+	NMConnection *connection;
+	gboolean changed = FALSE;
+	NMSettingIP6Config *s_ip6;
+	NMIP6Address *addr;
+	NMIP6Route *route;
+	const struct in6_addr t = { { { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 } } };
+
+	connection = nm_connection_new ();
+	g_signal_connect (connection,
+	                  NM_CONNECTION_CHANGED,
+	                  (GCallback) test_connection_changed_cb,
+	                  &changed);
+
+	s_ip6 = (NMSettingIP6Config *) nm_setting_ip6_config_new ();
+	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
+
+	ASSERT_CHANGED (nm_setting_ip6_config_add_dns (s_ip6, &t));
+	ASSERT_CHANGED (nm_setting_ip6_config_remove_dns (s_ip6, 0));
+
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*elt != NULL*");
+	ASSERT_UNCHANGED (nm_setting_ip6_config_remove_dns (s_ip6, 1));
+	g_test_assert_expected_messages ();
+
+	nm_setting_ip6_config_add_dns (s_ip6, &t);
+	ASSERT_CHANGED (nm_setting_ip6_config_clear_dns (s_ip6));
+
+	ASSERT_CHANGED (nm_setting_ip6_config_add_dns_search (s_ip6, "foobar.com"));
+	ASSERT_CHANGED (nm_setting_ip6_config_remove_dns_search (s_ip6, 0));
+
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*elt != NULL*");
+	ASSERT_UNCHANGED (nm_setting_ip6_config_remove_dns_search (s_ip6, 1));
+	g_test_assert_expected_messages ();
+
+	nm_setting_ip6_config_add_dns_search (s_ip6, "foobar.com");
+	ASSERT_CHANGED (nm_setting_ip6_config_clear_dns_searches (s_ip6));
+
+	addr = nm_ip6_address_new ();
+	nm_ip6_address_set_address (addr, &t);
+	nm_ip6_address_set_prefix (addr, 64);
+
+	ASSERT_CHANGED (nm_setting_ip6_config_add_address (s_ip6, addr));
+	ASSERT_CHANGED (nm_setting_ip6_config_remove_address (s_ip6, 0));
+
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*elt != NULL*");
+	ASSERT_UNCHANGED (nm_setting_ip6_config_remove_address (s_ip6, 1));
+	g_test_assert_expected_messages ();
+
+	nm_setting_ip6_config_add_address (s_ip6, addr);
+	ASSERT_CHANGED (nm_setting_ip6_config_clear_addresses (s_ip6));
+
+	route = nm_ip6_route_new ();
+	nm_ip6_route_set_dest (route, &t);
+	nm_ip6_route_set_prefix (route, 128);
+
+	ASSERT_CHANGED (nm_setting_ip6_config_add_route (s_ip6, route));
+	ASSERT_CHANGED (nm_setting_ip6_config_remove_route (s_ip6, 0));
+
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*elt != NULL*");
+	ASSERT_UNCHANGED (nm_setting_ip6_config_remove_route (s_ip6, 1));
+	g_test_assert_expected_messages ();
+
+	nm_setting_ip6_config_add_route (s_ip6, route);
+	ASSERT_CHANGED (nm_setting_ip6_config_clear_routes (s_ip6));
+
+	nm_ip6_address_unref (addr);
+	nm_ip6_route_unref (route);
+	g_object_unref (connection);
+}
+
+static void
+test_setting_vlan_changed_signal (void)
+{
+	NMConnection *connection;
+	gboolean changed = FALSE;
+	NMSettingVlan *s_vlan;
+
+	connection = nm_connection_new ();
+	g_signal_connect (connection,
+	                  NM_CONNECTION_CHANGED,
+	                  (GCallback) test_connection_changed_cb,
+	                  &changed);
+
+	s_vlan = (NMSettingVlan *) nm_setting_vlan_new ();
+	nm_connection_add_setting (connection, NM_SETTING (s_vlan));
+
+	ASSERT_CHANGED (nm_setting_vlan_add_priority (s_vlan, NM_VLAN_INGRESS_MAP, 1, 3));
+	ASSERT_CHANGED (nm_setting_vlan_remove_priority (s_vlan, NM_VLAN_INGRESS_MAP, 0));
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*idx < g_slist_length (list)*");
+	ASSERT_UNCHANGED (nm_setting_vlan_remove_priority (s_vlan, NM_VLAN_INGRESS_MAP, 1));
+	g_test_assert_expected_messages ();
+	ASSERT_CHANGED (nm_setting_vlan_add_priority_str (s_vlan, NM_VLAN_INGRESS_MAP, "1:3"));
+	ASSERT_CHANGED (nm_setting_vlan_clear_priorities (s_vlan, NM_VLAN_INGRESS_MAP));
+
+	ASSERT_CHANGED (nm_setting_vlan_add_priority (s_vlan, NM_VLAN_EGRESS_MAP, 1, 3));
+	ASSERT_CHANGED (nm_setting_vlan_remove_priority (s_vlan, NM_VLAN_EGRESS_MAP, 0));
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*idx < g_slist_length (list)*");
+	ASSERT_UNCHANGED (nm_setting_vlan_remove_priority (s_vlan, NM_VLAN_EGRESS_MAP, 1));
+	g_test_assert_expected_messages ();
+	ASSERT_CHANGED (nm_setting_vlan_add_priority_str (s_vlan, NM_VLAN_EGRESS_MAP, "1:3"));
+	ASSERT_CHANGED (nm_setting_vlan_clear_priorities (s_vlan, NM_VLAN_EGRESS_MAP));
+
+	g_object_unref (connection);
+}
+
+static void
+test_setting_vpn_changed_signal (void)
+{
+	NMConnection *connection;
+	gboolean changed = FALSE;
+	NMSettingVPN *s_vpn;
+
+	connection = nm_connection_new ();
+	g_signal_connect (connection,
+	                  NM_CONNECTION_CHANGED,
+	                  (GCallback) test_connection_changed_cb,
+	                  &changed);
+
+	s_vpn = (NMSettingVPN *) nm_setting_vpn_new ();
+	nm_connection_add_setting (connection, NM_SETTING (s_vpn));
+
+	ASSERT_CHANGED (nm_setting_vpn_add_data_item (s_vpn, "foobar", "baz"));
+	ASSERT_CHANGED (nm_setting_vpn_remove_data_item (s_vpn, "foobar"));
+	ASSERT_UNCHANGED (nm_setting_vpn_remove_data_item (s_vpn, "not added"));
+
+	ASSERT_CHANGED (nm_setting_vpn_add_secret (s_vpn, "foobar", "baz"));
+	ASSERT_CHANGED (nm_setting_vpn_remove_secret (s_vpn, "foobar"));
+	ASSERT_UNCHANGED (nm_setting_vpn_remove_secret (s_vpn, "not added"));
+
+	g_object_unref (connection);
+}
+
+static void
+test_setting_wired_changed_signal (void)
+{
+	NMConnection *connection;
+	gboolean changed = FALSE;
+	NMSettingWired *s_wired;
+
+	connection = nm_connection_new ();
+	g_signal_connect (connection,
+	                  NM_CONNECTION_CHANGED,
+	                  (GCallback) test_connection_changed_cb,
+	                  &changed);
+
+	s_wired = (NMSettingWired *) nm_setting_wired_new ();
+	nm_connection_add_setting (connection, NM_SETTING (s_wired));
+
+	ASSERT_CHANGED (nm_setting_wired_add_s390_option (s_wired, "portno", "1"));
+	ASSERT_CHANGED (nm_setting_wired_remove_s390_option (s_wired, "portno"));
+	ASSERT_UNCHANGED (nm_setting_wired_remove_s390_option (s_wired, "layer2"));
+
+	g_object_unref (connection);
+}
+
+static void
+test_setting_wireless_changed_signal (void)
+{
+	NMConnection *connection;
+	gboolean changed = FALSE;
+	NMSettingWireless *s_wifi;
+
+	connection = nm_connection_new ();
+	g_signal_connect (connection,
+	                  NM_CONNECTION_CHANGED,
+	                  (GCallback) test_connection_changed_cb,
+	                  &changed);
+
+	s_wifi = (NMSettingWireless *) nm_setting_wireless_new ();
+	nm_connection_add_setting (connection, NM_SETTING (s_wifi));
+
+	ASSERT_CHANGED (nm_setting_wireless_add_seen_bssid (s_wifi, "00:11:22:33:44:55"));
+
+	g_object_unref (connection);
+}
+
+static void
+test_setting_wireless_security_changed_signal (void)
+{
+	NMConnection *connection;
+	gboolean changed = FALSE;
+	NMSettingWirelessSecurity *s_wsec;
+
+	connection = nm_connection_new ();
+	g_signal_connect (connection,
+	                  NM_CONNECTION_CHANGED,
+	                  (GCallback) test_connection_changed_cb,
+	                  &changed);
+
+	s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
+	nm_connection_add_setting (connection, NM_SETTING (s_wsec));
+
+	/* Protos */
+	ASSERT_CHANGED (nm_setting_wireless_security_add_proto (s_wsec, "wpa"));
+	ASSERT_CHANGED (nm_setting_wireless_security_remove_proto (s_wsec, 0));
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*elt != NULL*");
+	ASSERT_UNCHANGED (nm_setting_wireless_security_remove_proto (s_wsec, 1));
+	g_test_assert_expected_messages ();
+
+	nm_setting_wireless_security_add_proto (s_wsec, "wep");
+	ASSERT_CHANGED (nm_setting_wireless_security_clear_protos (s_wsec));
+
+	/* Pairwise ciphers */
+	ASSERT_CHANGED (nm_setting_wireless_security_add_pairwise (s_wsec, "tkip"));
+	ASSERT_CHANGED (nm_setting_wireless_security_remove_pairwise (s_wsec, 0));
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*elt != NULL*");
+	ASSERT_UNCHANGED (nm_setting_wireless_security_remove_pairwise (s_wsec, 1));
+	g_test_assert_expected_messages ();
+
+	nm_setting_wireless_security_add_pairwise (s_wsec, "tkip");
+	ASSERT_CHANGED (nm_setting_wireless_security_clear_pairwise (s_wsec));
+
+	/* Group ciphers */
+	ASSERT_CHANGED (nm_setting_wireless_security_add_group (s_wsec, "ccmp"));
+	ASSERT_CHANGED (nm_setting_wireless_security_remove_group (s_wsec, 0));
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*elt != NULL*");
+	ASSERT_UNCHANGED (nm_setting_wireless_security_remove_group (s_wsec, 1));
+	g_test_assert_expected_messages ();
+
+	nm_setting_wireless_security_add_group (s_wsec, "tkip");
+	ASSERT_CHANGED (nm_setting_wireless_security_clear_groups (s_wsec));
+
+	/* WEP key secret flags */
+	ASSERT_CHANGED (g_assert (nm_setting_set_secret_flags (NM_SETTING (s_wsec), "wep-key0", NM_SETTING_SECRET_FLAG_AGENT_OWNED, NULL)));
+	ASSERT_CHANGED (g_assert (nm_setting_set_secret_flags (NM_SETTING (s_wsec), "wep-key1", NM_SETTING_SECRET_FLAG_AGENT_OWNED, NULL)));
+	ASSERT_CHANGED (g_assert (nm_setting_set_secret_flags (NM_SETTING (s_wsec), "wep-key2", NM_SETTING_SECRET_FLAG_AGENT_OWNED, NULL)));
+	ASSERT_CHANGED (g_assert (nm_setting_set_secret_flags (NM_SETTING (s_wsec), "wep-key3", NM_SETTING_SECRET_FLAG_AGENT_OWNED, NULL)));
+
+	g_object_unref (connection);
+}
+
+static void
+test_setting_802_1x_changed_signal (void)
+{
+	NMConnection *connection;
+	gboolean changed = FALSE;
+	NMSetting8021x *s_8021x;
+
+	connection = nm_connection_new ();
+	g_signal_connect (connection,
+	                  NM_CONNECTION_CHANGED,
+	                  (GCallback) test_connection_changed_cb,
+	                  &changed);
+
+	s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
+	nm_connection_add_setting (connection, NM_SETTING (s_8021x));
+
+	/* EAP methods */
+	ASSERT_CHANGED (nm_setting_802_1x_add_eap_method (s_8021x, "tls"));
+	ASSERT_CHANGED (nm_setting_802_1x_remove_eap_method (s_8021x, 0));
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*elt != NULL*");
+	ASSERT_UNCHANGED (nm_setting_802_1x_remove_eap_method (s_8021x, 1));
+	g_test_assert_expected_messages ();
+
+	nm_setting_802_1x_add_eap_method (s_8021x, "ttls");
+	ASSERT_CHANGED (nm_setting_802_1x_clear_eap_methods (s_8021x));
+
+	/* alternate subject matches */
+	ASSERT_CHANGED (nm_setting_802_1x_add_altsubject_match (s_8021x, "EMAIL:server@example.com"));
+	ASSERT_CHANGED (nm_setting_802_1x_remove_altsubject_match (s_8021x, 0));
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*elt != NULL*");
+	ASSERT_UNCHANGED (nm_setting_802_1x_remove_altsubject_match (s_8021x, 1));
+	g_test_assert_expected_messages ();
+
+	nm_setting_802_1x_add_altsubject_match (s_8021x, "EMAIL:server@example.com");
+	ASSERT_CHANGED (nm_setting_802_1x_clear_altsubject_matches (s_8021x));
+
+	/* phase2 alternate subject matches */
+	ASSERT_CHANGED (nm_setting_802_1x_add_phase2_altsubject_match (s_8021x, "EMAIL:server@example.com"));
+	ASSERT_CHANGED (nm_setting_802_1x_remove_phase2_altsubject_match (s_8021x, 0));
+	g_test_expect_message ("libnm-util", G_LOG_LEVEL_CRITICAL, "*elt != NULL*");
+	ASSERT_UNCHANGED (nm_setting_802_1x_remove_phase2_altsubject_match (s_8021x, 1));
+	g_test_assert_expected_messages ();
+
+	nm_setting_802_1x_add_phase2_altsubject_match (s_8021x, "EMAIL:server@example.com");
+	ASSERT_CHANGED (nm_setting_802_1x_clear_phase2_altsubject_matches (s_8021x));
+
+	g_object_unref (connection);
+}
+
 static void
 test_setting_old_uuid (void)
 {
@@ -1445,20 +2484,19 @@ test_setting_old_uuid (void)
 	g_assert (success == TRUE);
 }
 
+NMTST_DEFINE ();
+
 int main (int argc, char **argv)
 {
-	GError *error = NULL;
 	char *base;
 
-	g_type_init ();
-
-	if (!nm_utils_init (&error))
-		FAIL ("nm-utils-init", "failed to initialize libnm-util: %s", error->message);
+	nmtst_init (&argc, &argv, TRUE);
 
 	/* The tests */
 	test_setting_vpn_items ();
 	test_setting_vpn_update_secrets ();
 	test_setting_vpn_modify_during_foreach ();
+	test_setting_ip4_config_labels ();
 	test_setting_ip6_config_old_address_array ();
 	test_setting_gsm_apn_spaces ();
 	test_setting_gsm_apn_bad_chars ();
@@ -1479,12 +2517,25 @@ int main (int argc, char **argv)
 	test_setting_old_uuid ();
 
 	test_connection_to_hash_setting_name ();
+	test_setting_new_from_hash ();
+	test_connection_replace_settings ();
+	test_connection_replace_settings_from_connection ();
+	test_connection_new_from_hash ();
+
 	test_setting_connection_permissions_helpers ();
 	test_setting_connection_permissions_property ();
+
+	test_connection_compare_same ();
+	test_connection_compare_key_only_in_a ();
+	test_connection_compare_setting_only_in_a ();
+	test_connection_compare_key_only_in_b ();
+	test_connection_compare_setting_only_in_b ();
+
 	test_connection_diff_a_only ();
 	test_connection_diff_same ();
 	test_connection_diff_different ();
 	test_connection_diff_no_secrets ();
+	test_connection_diff_inferrable ();
 	test_connection_good_base_types ();
 	test_connection_bad_base_types ();
 
@@ -1495,6 +2546,18 @@ int main (int argc, char **argv)
 	test_ip4_prefix_to_netmask ();
 	test_ip4_netmask_to_prefix ();
 
+	test_connection_changed_signal ();
+	test_setting_connection_changed_signal ();
+	test_setting_bond_changed_signal ();
+	test_setting_ip4_changed_signal ();
+	test_setting_ip6_changed_signal ();
+	test_setting_vlan_changed_signal ();
+	test_setting_vpn_changed_signal ();
+	test_setting_wired_changed_signal ();
+	test_setting_wireless_changed_signal ();
+	test_setting_wireless_security_changed_signal ();
+	test_setting_802_1x_changed_signal ();
+
 	base = g_path_get_basename (argv[0]);
 	fprintf (stdout, "%s: SUCCESS\n", base);
 	g_free (base);
diff --git a/libnm-util/tests/test-secrets.c b/libnm-util/tests/test-secrets.c
index 0e859abc..73fc9224 100644
--- a/libnm-util/tests/test-secrets.c
+++ b/libnm-util/tests/test-secrets.c
@@ -22,7 +22,6 @@
 #include <glib.h>
 #include <string.h>
 
-#include "nm-test-helpers.h"
 #include <nm-utils.h>
 
 #include "nm-setting-connection.h"
@@ -37,6 +36,7 @@
 #include "nm-setting-pppoe.h"
 #include "nm-setting-vpn.h"
 
+#include "nm-test-utils.h"
 
 #define TEST_NEED_SECRETS_EAP_TLS_CA_CERT TEST_CERT_DIR "/test_ca_cert.pem"
 #define TEST_NEED_SECRETS_EAP_TLS_CLIENT_CERT TEST_CERT_DIR "/test_key_and_cert.pem"
@@ -67,14 +67,9 @@ make_tls_connection (const char *detail, NMSetting8021xCKScheme scheme)
 	GError *error = NULL;
 
 	connection = nm_connection_new ();
-	ASSERT (connection != NULL,
-	        detail, "failed to allocate new connection");
 
 	/* Connection setting */
 	s_con = (NMSettingConnection *) nm_setting_connection_new ();
-	ASSERT (s_con != NULL,
-	        detail, "failed to allocate new %s setting",
-	        NM_SETTING_CONNECTION_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_con));
 
 	uuid = nm_utils_uuid_generate ();
@@ -88,16 +83,10 @@ make_tls_connection (const char *detail, NMSetting8021xCKScheme scheme)
 
 	/* Wired setting */
 	s_wired = (NMSettingWired *) nm_setting_wired_new ();
-	ASSERT (s_wired != NULL,
-	        detail, "failed to allocate new %s setting",
-	        NM_SETTING_WIRED_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_wired));
 
 	/* Wireless security setting */
 	s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
-	ASSERT (s_8021x != NULL,
-	        detail, "failed to allocate new %s setting",
-	        NM_SETTING_802_1X_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_8021x));
 
 	g_object_set (s_8021x, NM_SETTING_802_1X_IDENTITY, "Bill Smith", NULL);
@@ -134,9 +123,6 @@ make_tls_connection (const char *detail, NMSetting8021xCKScheme scheme)
 
 	/* IP4 setting */
 	s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
-	ASSERT (s_ip4 != NULL,
-			detail, "failed to allocate new %s setting",
-			NM_SETTING_IP4_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip4));
 
 	g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL);
@@ -247,14 +233,9 @@ make_tls_phase2_connection (const char *detail, NMSetting8021xCKScheme scheme)
 	GError *error = NULL;
 
 	connection = nm_connection_new ();
-	ASSERT (connection != NULL,
-	        detail, "failed to allocate new connection");
 
 	/* Connection setting */
 	s_con = (NMSettingConnection *) nm_setting_connection_new ();
-	ASSERT (s_con != NULL,
-	        detail, "failed to allocate new %s setting",
-	        NM_SETTING_CONNECTION_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_con));
 
 	uuid = nm_utils_uuid_generate ();
@@ -268,16 +249,10 @@ make_tls_phase2_connection (const char *detail, NMSetting8021xCKScheme scheme)
 
 	/* Wired setting */
 	s_wired = (NMSettingWired *) nm_setting_wired_new ();
-	ASSERT (s_wired != NULL,
-	        detail, "failed to allocate new %s setting",
-	        NM_SETTING_WIRED_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_wired));
 
 	/* Wireless security setting */
 	s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
-	ASSERT (s_8021x != NULL,
-	        detail, "failed to allocate new %s setting",
-	        NM_SETTING_802_1X_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_8021x));
 
 	g_object_set (s_8021x, NM_SETTING_802_1X_ANONYMOUS_IDENTITY, "blahblah", NULL);
@@ -316,9 +291,6 @@ make_tls_phase2_connection (const char *detail, NMSetting8021xCKScheme scheme)
 
 	/* IP4 setting */
 	s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
-	ASSERT (s_ip4 != NULL,
-			detail, "failed to allocate new %s setting",
-			NM_SETTING_IP4_CONFIG_SETTING_NAME);
 	nm_connection_add_setting (connection, NM_SETTING (s_ip4));
 
 	g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL);
@@ -454,7 +426,6 @@ wifi_connection_new (void)
 	g_byte_array_append (ssid, &tmpssid[0], sizeof (tmpssid));
 	g_object_set (s_wifi,
 	              NM_SETTING_WIRELESS_SSID, ssid,
-	              NM_SETTING_WIRELESS_SEC, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
 	              NULL);
 	g_byte_array_free (ssid, TRUE);
 	nm_connection_add_setting (connection, NM_SETTING (s_wifi));
@@ -512,6 +483,8 @@ test_update_secrets_wifi_single_setting (void)
 	const char *wepkey = "11111111111111111111111111";
 	const char *tmp;
 
+	/* Test update with a hashed setting of 802-11-wireless secrets */
+
 	connection = wifi_connection_new ();
 
 	/* Build up the secrets hash */
@@ -546,6 +519,10 @@ test_update_secrets_wifi_full_hash (void)
 	const char *wepkey = "11111111111111111111111111";
 	const char *tmp;
 
+	/* Test update with a hashed connection containing only 802-11-wireless
+	 * setting and secrets.
+	 */
+
 	connection = wifi_connection_new ();
 
 	/* Build up the secrets hash */
@@ -580,6 +557,10 @@ test_update_secrets_wifi_bad_setting_name (void)
 	gboolean success;
 	const char *wepkey = "11111111111111111111111111";
 
+	/* Test that passing an invalid setting name to
+	 * nm_connection_update_secrets() fails with the correct error.
+	 */
+
 	connection = wifi_connection_new ();
 
 	/* Build up the secrets hash */
@@ -607,6 +588,10 @@ test_update_secrets_whole_connection (void)
 	gboolean success;
 	const char *wepkey = "11111111111111111111111111";
 
+	/* Test calling nm_connection_update_secrets() with an entire hashed
+	 * connection including non-secrets.
+	 */
+
 	connection = wifi_connection_new ();
 
 	/* Build up the secrets hash */
@@ -634,6 +619,8 @@ test_update_secrets_whole_connection_empty_hash (void)
 	GError *error = NULL;
 	gboolean success;
 
+	/* Test that updating secrets with an empty hash returns success */
+
 	connection = wifi_connection_new ();
 	secrets = g_hash_table_new (g_str_hash, g_str_equal);
 	success = nm_connection_update_secrets (connection, NULL, secrets, &error);
@@ -651,6 +638,10 @@ test_update_secrets_whole_connection_bad_setting (void)
 	gboolean success;
 	const char *wepkey = "11111111111111111111111111";
 
+	/* Test that sending a hashed connection containing an invalid setting
+	 * name fails with the right error.
+	 */
+
 	connection = wifi_connection_new ();
 
 	/* Build up the secrets hash */
@@ -674,12 +665,67 @@ test_update_secrets_whole_connection_bad_setting (void)
 	g_object_unref (connection);
 }
 
+static void
+test_update_secrets_whole_connection_empty_base_setting (void)
+{
+	NMConnection *connection;
+	GHashTable *secrets;
+	GError *error = NULL;
+	gboolean success;
+
+	/* Test that a hashed connection which does not have any hashed secrets
+	 * for the requested setting returns success.
+	 */
+
+	connection = wifi_connection_new ();
+	secrets = nm_connection_to_hash (connection, NM_SETTING_HASH_FLAG_ONLY_SECRETS);
+	g_assert_cmpint (g_hash_table_size (secrets), ==, 1);
+	g_assert (g_hash_table_lookup (secrets, NM_SETTING_WIRELESS_SETTING_NAME));
+
+	success = nm_connection_update_secrets (connection,
+	                                        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
+	                                        secrets,
+	                                        &error);
+	g_assert_no_error (error);
+	g_assert (success);
+
+	g_hash_table_destroy (secrets);
+	g_object_unref (connection);
+}
+
+static void
+test_update_secrets_null_setting_name_with_setting_hash (void)
+{
+	NMConnection *connection;
+	GHashTable *secrets;
+	GError *error = NULL;
+	gboolean success;
+	const char *wepkey = "11111111111111111111111111";
+
+	/* Ensure that a NULL setting name and only a hashed setting fails */
+
+	connection = wifi_connection_new ();
+
+	secrets = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, value_destroy);
+	g_hash_table_insert (secrets, NM_SETTING_WIRELESS_SECURITY_WEP_KEY0, string_to_gvalue (wepkey));
+	g_hash_table_insert (secrets, NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE, uint_to_gvalue (NM_WEP_KEY_TYPE_KEY));
+
+	success = nm_connection_update_secrets (connection, NULL, secrets, &error);
+	g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_SETTING_NOT_FOUND);
+	g_assert (!success);
+
+	g_hash_table_destroy (secrets);
+	g_object_unref (connection);
+}
+
 int main (int argc, char **argv)
 {
 	GError *error = NULL;
 	char *base;
 
+#if !GLIB_CHECK_VERSION (2, 35, 0)
 	g_type_init ();
+#endif
 
 	if (!nm_utils_init (&error))
 		FAIL ("nm-utils-init", "failed to initialize libnm-util: %s", error->message);
@@ -697,6 +743,8 @@ int main (int argc, char **argv)
 	test_update_secrets_whole_connection ();
 	test_update_secrets_whole_connection_empty_hash ();
 	test_update_secrets_whole_connection_bad_setting ();
+	test_update_secrets_whole_connection_empty_base_setting ();
+	test_update_secrets_null_setting_name_with_setting_hash ();
 
 	base = g_path_get_basename (argv[0]);
 	fprintf (stdout, "%s: SUCCESS\n", base);
diff --git a/libnm-util/tests/test-setting-8021x.c b/libnm-util/tests/test-setting-8021x.c
index bdfc8e03..62889c61 100644
--- a/libnm-util/tests/test-setting-8021x.c
+++ b/libnm-util/tests/test-setting-8021x.c
@@ -22,12 +22,13 @@
 #include <glib.h>
 #include <string.h>
 
-#include "nm-test-helpers.h"
 #include <nm-utils.h>
 
 #include "nm-setting-connection.h"
 #include "nm-setting-8021x.h"
 
+#include "nm-test-utils.h"
+
 static void
 compare_blob_data (const char *test,
                    const char *key_path,
@@ -411,7 +412,9 @@ int main (int argc, char **argv)
 	if (argc < 3)
 		FAIL ("init", "need at least two arguments: <path> <password>");
 
+#if !GLIB_CHECK_VERSION (2, 35, 0)
 	g_type_init ();
+#endif
 
 	if (!nm_utils_init (&error))
 		FAIL ("nm-utils-init", "failed to initialize libnm-util: %s", error->message);
diff --git a/libnm-util/tests/test-setting-dcb.c b/libnm-util/tests/test-setting-dcb.c
new file mode 100644
index 00000000..de07f2c2
--- /dev/null
+++ b/libnm-util/tests/test-setting-dcb.c
@@ -0,0 +1,328 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2013 Red Hat, Inc.
+ *
+ */
+
+#include <glib.h>
+#include <string.h>
+#include <nm-utils.h>
+#include <nm-glib-compat.h>
+#include "nm-setting-dcb.h"
+
+#define DCB_FLAGS_ALL (NM_SETTING_DCB_FLAG_ENABLE | \
+                       NM_SETTING_DCB_FLAG_ADVERTISE | \
+                       NM_SETTING_DCB_FLAG_WILLING)
+
+static void
+test_dcb_flags_valid (void)
+{
+	NMSettingDcb *s_dcb;
+	GError *error = NULL;
+	gboolean success;
+	guint i;
+
+	s_dcb = (NMSettingDcb *) nm_setting_dcb_new ();
+	g_assert (s_dcb);
+
+	g_assert_cmpint (nm_setting_dcb_get_app_fcoe_flags (s_dcb), ==, 0);
+	g_assert_cmpint (nm_setting_dcb_get_app_iscsi_flags (s_dcb), ==, 0);
+	g_assert_cmpint (nm_setting_dcb_get_app_fip_flags (s_dcb), ==, 0);
+	g_assert_cmpint (nm_setting_dcb_get_priority_flow_control_flags (s_dcb), ==, 0);
+	g_assert_cmpint (nm_setting_dcb_get_priority_group_flags (s_dcb), ==, 0);
+
+	g_object_set (G_OBJECT (s_dcb),
+	              NM_SETTING_DCB_APP_FCOE_FLAGS, DCB_FLAGS_ALL,
+	              NM_SETTING_DCB_APP_ISCSI_FLAGS, DCB_FLAGS_ALL,
+	              NM_SETTING_DCB_APP_FIP_FLAGS, DCB_FLAGS_ALL,
+	              NM_SETTING_DCB_PRIORITY_FLOW_CONTROL_FLAGS, DCB_FLAGS_ALL,
+	              NM_SETTING_DCB_PRIORITY_GROUP_FLAGS, DCB_FLAGS_ALL,
+	              NULL);
+	/* Priority Group Bandwidth must total 100% */
+	for (i = 0; i < 7; i++)
+		nm_setting_dcb_set_priority_group_bandwidth (s_dcb, i, 12);
+	nm_setting_dcb_set_priority_group_bandwidth (s_dcb, 7, 16);
+
+	success = nm_setting_verify (NM_SETTING (s_dcb), NULL, &error);
+	g_assert_no_error (error);
+	g_assert (success);
+
+	g_assert_cmpint (nm_setting_dcb_get_app_fcoe_flags (s_dcb), ==, DCB_FLAGS_ALL);
+	g_assert_cmpint (nm_setting_dcb_get_app_iscsi_flags (s_dcb), ==, DCB_FLAGS_ALL);
+	g_assert_cmpint (nm_setting_dcb_get_app_fip_flags (s_dcb), ==, DCB_FLAGS_ALL);
+	g_assert_cmpint (nm_setting_dcb_get_priority_flow_control_flags (s_dcb), ==, DCB_FLAGS_ALL);
+	g_assert_cmpint (nm_setting_dcb_get_priority_group_flags (s_dcb), ==, DCB_FLAGS_ALL);
+}
+
+#define TEST_FLAG(p, f, v) \
+{ \
+	/* GObject property min/max should ensure the property does not get set to \
+	 * the invalid value, so we ensure the value we just tried to set is 0 and \
+	 * that verify is successful since the property never got set. \
+	 */ \
+	g_object_set (G_OBJECT (s_dcb), p, v, NULL); \
+	g_assert_cmpint (f (s_dcb), ==, 0); \
+	success = nm_setting_verify (NM_SETTING (s_dcb), NULL, &error); \
+	g_assert_no_error (error); \
+	g_assert (success); \
+}
+
+static void
+test_dcb_flags_invalid (void)
+{
+	NMSettingDcb *s_dcb;
+	GError *error = NULL;
+	gboolean success;
+
+	s_dcb = (NMSettingDcb *) nm_setting_dcb_new ();
+	g_assert (s_dcb);
+
+	g_test_expect_message ("GLib-GObject", G_LOG_LEVEL_WARNING, "*invalid or out of range*");
+	TEST_FLAG (NM_SETTING_DCB_APP_FCOE_FLAGS, nm_setting_dcb_get_app_fcoe_flags, 0x332523);
+	g_test_assert_expected_messages ();
+
+	g_test_expect_message ("GLib-GObject", G_LOG_LEVEL_WARNING, "*invalid or out of range*");
+	TEST_FLAG (NM_SETTING_DCB_APP_ISCSI_FLAGS, nm_setting_dcb_get_app_iscsi_flags, 0xFF);
+	g_test_assert_expected_messages ();
+
+	g_test_expect_message ("GLib-GObject", G_LOG_LEVEL_WARNING, "*invalid or out of range*");
+	TEST_FLAG (NM_SETTING_DCB_APP_FIP_FLAGS, nm_setting_dcb_get_app_fip_flags, 0x1111);
+	g_test_assert_expected_messages ();
+
+	g_test_expect_message ("GLib-GObject", G_LOG_LEVEL_WARNING, "*invalid or out of range*");
+	TEST_FLAG (NM_SETTING_DCB_PRIORITY_FLOW_CONTROL_FLAGS, nm_setting_dcb_get_priority_flow_control_flags, G_MAXUINT32);
+	g_test_assert_expected_messages ();
+
+	g_test_expect_message ("GLib-GObject", G_LOG_LEVEL_WARNING, "*invalid or out of range*");
+	TEST_FLAG (NM_SETTING_DCB_PRIORITY_GROUP_FLAGS, nm_setting_dcb_get_priority_group_flags,
+	           (NM_SETTING_DCB_FLAG_ENABLE | NM_SETTING_DCB_FLAG_ADVERTISE | NM_SETTING_DCB_FLAG_WILLING) + 1);
+	g_test_assert_expected_messages ();
+}
+
+#define TEST_APP_PRIORITY(lcprop, ucprop, v) \
+{ \
+	g_object_set (G_OBJECT (s_dcb), NM_SETTING_DCB_APP_##ucprop##_FLAGS, NM_SETTING_DCB_FLAG_NONE, NULL); \
+ \
+	g_object_set (G_OBJECT (s_dcb), NM_SETTING_DCB_APP_##ucprop##_PRIORITY, v, NULL); \
+	g_assert_cmpint (nm_setting_dcb_get_app_##lcprop##_priority (s_dcb), ==, v); \
+ \
+	/* Assert that the setting is invalid while the app is disabled unless v is default */ \
+	success = nm_setting_verify (NM_SETTING (s_dcb), NULL, &error); \
+	if (v >= 0) { \
+		g_assert_error (error, NM_SETTING_DCB_ERROR, NM_SETTING_DCB_ERROR_INVALID_PROPERTY); \
+		g_assert (success == FALSE); \
+	} else { \
+		g_assert_no_error (error); \
+		g_assert (success); \
+	} \
+	g_clear_error (&error); \
+ \
+	/* Set the enable flag and re-verify, this time it should be valid */ \
+	g_object_set (G_OBJECT (s_dcb), NM_SETTING_DCB_APP_##ucprop##_FLAGS, NM_SETTING_DCB_FLAG_ENABLE, NULL); \
+	success = nm_setting_verify (NM_SETTING (s_dcb), NULL, &error); \
+	g_assert_no_error (error); \
+	g_assert (success); \
+ \
+	g_object_set (G_OBJECT (s_dcb), NM_SETTING_DCB_APP_##ucprop##_PRIORITY, 0, NULL); \
+}
+
+static void
+test_dcb_app_priorities (void)
+{
+	NMSettingDcb *s_dcb;
+	GError *error = NULL;
+	gboolean success;
+
+	s_dcb = (NMSettingDcb *) nm_setting_dcb_new ();
+	g_assert (s_dcb);
+
+	/* Defaults */
+	g_assert_cmpint (nm_setting_dcb_get_app_fcoe_priority (s_dcb), ==, -1);
+	g_assert_cmpint (nm_setting_dcb_get_app_iscsi_priority (s_dcb), ==, -1);
+	g_assert_cmpint (nm_setting_dcb_get_app_fip_priority (s_dcb), ==, -1);
+
+	TEST_APP_PRIORITY (fcoe, FCOE, 6);
+	TEST_APP_PRIORITY (iscsi, ISCSI, 5);
+	TEST_APP_PRIORITY (fip, FIP, 4);
+
+	TEST_APP_PRIORITY (fcoe, FCOE, -1);
+	TEST_APP_PRIORITY (iscsi, ISCSI, -1);
+	TEST_APP_PRIORITY (fip, FIP, -1);
+}
+
+#define TEST_PRIORITY_VALID(fn, id, val, flagsprop, verify) \
+{ \
+	/* Assert that setting the value gets the same value back out */ \
+	nm_setting_dcb_set_priority_##fn (s_dcb, id, val); \
+	g_assert_cmpint (nm_setting_dcb_get_priority_##fn (s_dcb, id), ==, val); \
+ \
+	if (verify) { \
+		if (val != 0) { \
+			/* Assert that verify fails because the flags do not include 'enabled' \
+			 * and a value has been set. \
+			 */ \
+			success = nm_setting_verify (NM_SETTING (s_dcb), NULL, &error); \
+			g_assert_error (error, NM_SETTING_DCB_ERROR, NM_SETTING_DCB_ERROR_INVALID_PROPERTY); \
+			g_assert (success == FALSE); \
+			g_clear_error (&error); \
+		} \
+ \
+		/* Assert that adding the 'enabled' flag verifies the setting */ \
+		g_object_set (G_OBJECT (s_dcb), NM_SETTING_DCB_PRIORITY_##flagsprop##_FLAGS, NM_SETTING_DCB_FLAG_ENABLE, NULL); \
+		success = nm_setting_verify (NM_SETTING (s_dcb), NULL, &error); \
+		g_assert_no_error (error); \
+		g_assert (success); \
+	} \
+ \
+	/* Reset everything */ \
+	g_object_set (G_OBJECT (s_dcb), NM_SETTING_DCB_PRIORITY_##flagsprop##_FLAGS, NM_SETTING_DCB_FLAG_NONE, NULL); \
+	nm_setting_dcb_set_priority_##fn (s_dcb, id, 0); \
+}
+
+/* If Priority Groups are enabled, PG bandwidth must equal 100% */
+#define SET_VALID_PRIORITY_GROUP_BANDWIDTH \
+{ \
+	guint x; \
+	for (x = 0; x < 7; x++) \
+		nm_setting_dcb_set_priority_group_bandwidth (s_dcb, x, 12); \
+	nm_setting_dcb_set_priority_group_bandwidth (s_dcb, 7, 16); \
+}
+
+static void
+test_dcb_priorities_valid (void)
+{
+	NMSettingDcb *s_dcb;
+	GError *error = NULL;
+	gboolean success;
+	guint i;
+
+	s_dcb = (NMSettingDcb *) nm_setting_dcb_new ();
+	g_assert (s_dcb);
+
+	for (i = 0; i < 8; i++)
+		TEST_PRIORITY_VALID (flow_control, i, TRUE, FLOW_CONTROL, TRUE);
+
+	SET_VALID_PRIORITY_GROUP_BANDWIDTH
+	for (i = 0; i < 8; i++) {
+		TEST_PRIORITY_VALID (group_id, i, i, GROUP, TRUE);
+		TEST_PRIORITY_VALID (group_id, i, 7 - i, GROUP, TRUE);
+	}
+
+	/* Clear PG bandwidth from earlier tests */
+	for (i = 0; i < 8; i++)
+		nm_setting_dcb_set_priority_group_bandwidth (s_dcb, i, 0);
+
+	/* Priority Group Bandwidth must add up to 100% if enabled, which requires
+	 * some dancing for verifying individual values here.
+	 */
+	for (i = 0; i < 8; i++) {
+		guint other = 7 - (i % 8);
+
+		/* Set another priority group to the remaining bandwidth */
+		nm_setting_dcb_set_priority_group_bandwidth (s_dcb, other, 100 - i);
+		TEST_PRIORITY_VALID (group_bandwidth, i, i, GROUP, TRUE);
+
+		/* Set another priority group to the remaining bandwidth */
+		nm_setting_dcb_set_priority_group_bandwidth (s_dcb, other, 100 - (7 - i));
+		TEST_PRIORITY_VALID (group_bandwidth, i, 7 - i, GROUP, TRUE);
+
+		/* Clear remaining bandwidth */
+		nm_setting_dcb_set_priority_group_bandwidth (s_dcb, other, 0);
+	}
+
+	SET_VALID_PRIORITY_GROUP_BANDWIDTH
+	for (i = 0; i < 8; i++) {
+		TEST_PRIORITY_VALID (bandwidth, i, i, GROUP, TRUE);
+		TEST_PRIORITY_VALID (bandwidth, i, 7 - i, GROUP, TRUE);
+	}
+
+	SET_VALID_PRIORITY_GROUP_BANDWIDTH
+	for (i = 0; i < 8; i++)
+		TEST_PRIORITY_VALID (strict_bandwidth, i, TRUE, GROUP, TRUE);
+
+	SET_VALID_PRIORITY_GROUP_BANDWIDTH
+	for (i = 0; i < 8; i++) {
+		TEST_PRIORITY_VALID (traffic_class, i, i, GROUP, TRUE);
+		TEST_PRIORITY_VALID (traffic_class, i, 7 - i, GROUP, TRUE);
+	}
+}
+
+static void
+test_dcb_bandwidth_sums (void)
+{
+	NMSettingDcb *s_dcb;
+	GError *error = NULL;
+	gboolean success;
+
+	s_dcb = (NMSettingDcb *) nm_setting_dcb_new ();
+	g_assert (s_dcb);
+
+	/* Assert that setting the value gets the same value back out */
+	nm_setting_dcb_set_priority_group_bandwidth (s_dcb, 0, 9);
+	nm_setting_dcb_set_priority_group_bandwidth (s_dcb, 1, 10);
+	nm_setting_dcb_set_priority_group_bandwidth (s_dcb, 2, 11);
+	nm_setting_dcb_set_priority_group_bandwidth (s_dcb, 3, 12);
+	nm_setting_dcb_set_priority_group_bandwidth (s_dcb, 4, 13);
+	nm_setting_dcb_set_priority_group_bandwidth (s_dcb, 5, 14);
+	nm_setting_dcb_set_priority_group_bandwidth (s_dcb, 6, 15);
+	nm_setting_dcb_set_priority_group_bandwidth (s_dcb, 7, 16);
+
+	/* Assert verify success when sums total 100% */
+	g_object_set (G_OBJECT (s_dcb), NM_SETTING_DCB_PRIORITY_GROUP_FLAGS, NM_SETTING_DCB_FLAG_ENABLE, NULL);
+	success = nm_setting_verify (NM_SETTING (s_dcb), NULL, &error);
+	g_assert_no_error (error);
+	g_assert (success);
+
+	/* Assert verify fails when sums do not total 100% */
+	nm_setting_dcb_set_priority_group_bandwidth (s_dcb, 4, 20);
+	success = nm_setting_verify (NM_SETTING (s_dcb), NULL, &error);
+	g_assert_error (error, NM_SETTING_DCB_ERROR, NM_SETTING_DCB_ERROR_INVALID_PROPERTY);
+	g_assert (success == FALSE);
+	g_clear_error (&error);
+}
+
+#define TPATH "/libnm-util/settings/dcb/"
+
+int main (int argc, char **argv)
+{
+	GError *error = NULL;
+	gboolean success;
+
+	g_test_init (&argc, &argv, NULL);
+
+#if !GLIB_CHECK_VERSION (2, 35, 0)
+	g_type_init ();
+#endif
+
+	success = nm_utils_init (&error);
+	g_assert_no_error (error);
+	g_assert (success);
+
+#if !GLIB_CHECK_VERSION(2,34,0)
+	g_log_set_always_fatal (G_LOG_LEVEL_CRITICAL);
+#endif
+
+	g_test_add_func (TPATH "flags-valid", test_dcb_flags_valid);
+	g_test_add_func (TPATH "flags-invalid", test_dcb_flags_invalid);
+	g_test_add_func (TPATH "app-priorities", test_dcb_app_priorities);
+	g_test_add_func (TPATH "priorities", test_dcb_priorities_valid);
+	g_test_add_func (TPATH "bandwidth-sums", test_dcb_bandwidth_sums);
+
+	return g_test_run ();
+}
+
diff --git a/libnm-util/tests/test-settings-defaults.c b/libnm-util/tests/test-settings-defaults.c
index b77ddfef..15412fed 100644
--- a/libnm-util/tests/test-settings-defaults.c
+++ b/libnm-util/tests/test-settings-defaults.c
@@ -22,7 +22,6 @@
 #include <glib.h>
 #include <string.h>
 
-#include "nm-test-helpers.h"
 #include <nm-utils.h>
 
 #include "nm-setting-8021x.h"
@@ -39,6 +38,7 @@
 #include "nm-setting-wireless.h"
 #include "nm-setting-wireless-security.h"
 
+#include "nm-test-utils.h"
 
 static void
 test_defaults (GType type, const char *name)
@@ -57,8 +57,8 @@ test_defaults (GType type, const char *name)
 
 	for (i = 0; i < n_property_specs; i++) {
 		GParamSpec *prop_spec = property_specs[i];
-		GValue value = { 0, };
-		GValue defvalue = { 0, };
+		GValue value = G_VALUE_INIT;
+		GValue defvalue = G_VALUE_INIT;
 		char *actual, *expected;
 		gboolean ok = FALSE;
 
@@ -104,7 +104,9 @@ int main (int argc, char **argv)
 	GError *error = NULL;
 	char *base;
 
+#if !GLIB_CHECK_VERSION (2, 35, 0)
 	g_type_init ();
+#endif
 
 	if (!nm_utils_init (&error))
 		FAIL ("nm-utils-init", "failed to initialize libnm-util: %s", error->message);