summary refs log tree commit diff
path: root/libnm-core
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2016-01-20 16:26:51 +0100
committerMichael Biebl <biebl@debian.org>2016-01-20 16:26:51 +0100
commit494f296a3baab08522617b24b1f126d8f9a17502 (patch)
treec8ef32fb0dd1c4ff35a0b38e787abb58692de0cd /libnm-core
parent54f6333410ffd570e62717d9e77c5c987175e397 (diff)
Imported Upstream version 1.1.90 upstream/1.1.90
Diffstat (limited to 'libnm-core')
-rw-r--r--libnm-core/Makefile.am12
-rw-r--r--libnm-core/Makefile.in158
-rw-r--r--libnm-core/Makefile.libnm-core20
-rw-r--r--libnm-core/crypto.c3
-rw-r--r--libnm-core/crypto.h2
-rw-r--r--libnm-core/crypto_gnutls.c118
-rw-r--r--libnm-core/crypto_nss.c4
-rw-r--r--libnm-core/nm-connection.c116
-rw-r--r--libnm-core/nm-connection.h9
-rw-r--r--libnm-core/nm-core-enum-types.c165
-rw-r--r--libnm-core/nm-core-enum-types.h14
-rw-r--r--libnm-core/nm-core-internal.h130
-rw-r--r--libnm-core/nm-core-types-internal.h30
-rw-r--r--libnm-core/nm-core-types.h4
-rw-r--r--libnm-core/nm-dbus-interface.h67
-rw-r--r--libnm-core/nm-dbus-utils.c294
-rw-r--r--libnm-core/nm-errors.c3
-rw-r--r--libnm-core/nm-keyfile-internal.h3
-rw-r--r--libnm-core/nm-keyfile-reader.c41
-rw-r--r--libnm-core/nm-keyfile-utils.c4
-rw-r--r--libnm-core/nm-keyfile-writer.c36
-rw-r--r--libnm-core/nm-property-compare.c7
-rw-r--r--libnm-core/nm-property-compare.h2
-rw-r--r--libnm-core/nm-setting-8021x.c5
-rw-r--r--libnm-core/nm-setting-8021x.h3
-rw-r--r--libnm-core/nm-setting-adsl.c11
-rw-r--r--libnm-core/nm-setting-bluetooth.c1
-rw-r--r--libnm-core/nm-setting-bond.c1
-rw-r--r--libnm-core/nm-setting-bridge-port.c1
-rw-r--r--libnm-core/nm-setting-bridge.c52
-rw-r--r--libnm-core/nm-setting-bridge.h5
-rw-r--r--libnm-core/nm-setting-cdma.c11
-rw-r--r--libnm-core/nm-setting-connection.c77
-rw-r--r--libnm-core/nm-setting-connection.h21
-rw-r--r--libnm-core/nm-setting-dcb.c1
-rw-r--r--libnm-core/nm-setting-gsm.c185
-rw-r--r--libnm-core/nm-setting-gsm.h44
-rw-r--r--libnm-core/nm-setting-infiniband.c1
-rw-r--r--libnm-core/nm-setting-ip-config.c381
-rw-r--r--libnm-core/nm-setting-ip-config.h46
-rw-r--r--libnm-core/nm-setting-ip-tunnel.c767
-rw-r--r--libnm-core/nm-setting-ip-tunnel.h98
-rw-r--r--libnm-core/nm-setting-ip4-config.c131
-rw-r--r--libnm-core/nm-setting-ip4-config.h6
-rw-r--r--libnm-core/nm-setting-ip6-config.c93
-rw-r--r--libnm-core/nm-setting-ip6-config.h23
-rw-r--r--libnm-core/nm-setting-macvlan.c350
-rw-r--r--libnm-core/nm-setting-macvlan.h94
-rw-r--r--libnm-core/nm-setting-olpc-mesh.c9
-rw-r--r--libnm-core/nm-setting-ppp.c2
-rw-r--r--libnm-core/nm-setting-pppoe.c1
-rw-r--r--libnm-core/nm-setting-private.h21
-rw-r--r--libnm-core/nm-setting-serial.c2
-rw-r--r--libnm-core/nm-setting-team-port.c1
-rw-r--r--libnm-core/nm-setting-team.c1
-rw-r--r--libnm-core/nm-setting-tun.c409
-rw-r--r--libnm-core/nm-setting-tun.h94
-rw-r--r--libnm-core/nm-setting-vlan.c260
-rw-r--r--libnm-core/nm-setting-vlan.h11
-rw-r--r--libnm-core/nm-setting-vpn.c45
-rw-r--r--libnm-core/nm-setting-vpn.h3
-rw-r--r--libnm-core/nm-setting-vxlan.c843
-rw-r--r--libnm-core/nm-setting-vxlan.h109
-rw-r--r--libnm-core/nm-setting-wimax.c15
-rw-r--r--libnm-core/nm-setting-wimax.h4
-rw-r--r--libnm-core/nm-setting-wired.c15
-rw-r--r--libnm-core/nm-setting-wired.h4
-rw-r--r--libnm-core/nm-setting-wireless-security.c59
-rw-r--r--libnm-core/nm-setting-wireless.c102
-rw-r--r--libnm-core/nm-setting-wireless.h7
-rw-r--r--libnm-core/nm-setting.c73
-rw-r--r--libnm-core/nm-setting.h29
-rw-r--r--libnm-core/nm-utils-private.h5
-rw-r--r--libnm-core/nm-utils.c470
-rw-r--r--libnm-core/nm-utils.h22
-rw-r--r--libnm-core/nm-version.h14
-rw-r--r--libnm-core/nm-vpn-editor-plugin.c287
-rw-r--r--libnm-core/nm-vpn-editor-plugin.h152
-rw-r--r--libnm-core/nm-vpn-plugin-info.c1030
-rw-r--r--libnm-core/nm-vpn-plugin-info.h114
-rw-r--r--libnm-core/tests/Makefile.am8
-rw-r--r--libnm-core/tests/Makefile.in35
-rw-r--r--libnm-core/tests/nm-core-tests-enum-types.c2
-rw-r--r--libnm-core/tests/test-compare.c3
-rw-r--r--libnm-core/tests/test-crypto.c3
-rw-r--r--libnm-core/tests/test-general.c461
-rw-r--r--libnm-core/tests/test-secrets.c2
-rw-r--r--libnm-core/tests/test-setting-8021x.c2
-rw-r--r--libnm-core/tests/test-setting-dcb.c18
-rw-r--r--libnm-core/tests/test-settings-defaults.c2
90 files changed, 7872 insertions, 527 deletions
diff --git a/libnm-core/Makefile.am b/libnm-core/Makefile.am
index d76a48da..527a1c24 100644
--- a/libnm-core/Makefile.am
+++ b/libnm-core/Makefile.am
@@ -3,11 +3,13 @@ include $(GLIB_MAKEFILE)
 SUBDIRS = . tests
 
 AM_CPPFLAGS = \
-	-I${top_srcdir}/include \
-	-I${top_builddir}/include \
+	-I${top_srcdir}/shared \
+	-I${top_builddir}/shared \
 	-DG_LOG_DOMAIN=\""libnm"\" \
 	-DLOCALEDIR=\"$(datadir)/locale\" \
-	-DNETWORKMANAGER_COMPILATION \
+	-DNMCONFDIR=\"$(nmconfdir)\" \
+	-DNMLIBDIR=\"$(nmlibdir)\" \
+	-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_LIB \
 	-DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \
 	$(GLIB_CFLAGS)
 
@@ -34,9 +36,9 @@ libnm_core_la_LIBADD =			\
 	$(UUID_LIBS)
 
 if WITH_GNUTLS
-AM_CPPFLAGS += $(LIBGCRYPT_CFLAGS) $(GNUTLS_CFLAGS)
+AM_CPPFLAGS += $(GNUTLS_CFLAGS)
 libnm_core_la_SOURCES += crypto_gnutls.c
-libnm_core_la_LIBADD += $(LIBGCRYPT_LIBS) $(GNUTLS_LIBS)
+libnm_core_la_LIBADD += $(GNUTLS_LIBS)
 endif
 
 if WITH_NSS
diff --git a/libnm-core/Makefile.in b/libnm-core/Makefile.in
index f4b6bcd0..7ca647e2 100644
--- a/libnm-core/Makefile.in
+++ b/libnm-core/Makefile.in
@@ -93,9 +93,9 @@ PRE_UNINSTALL = :
 POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
-@WITH_GNUTLS_TRUE@am__append_1 = $(LIBGCRYPT_CFLAGS) $(GNUTLS_CFLAGS)
+@WITH_GNUTLS_TRUE@am__append_1 = $(GNUTLS_CFLAGS)
 @WITH_GNUTLS_TRUE@am__append_2 = crypto_gnutls.c
-@WITH_GNUTLS_TRUE@am__append_3 = $(LIBGCRYPT_LIBS) $(GNUTLS_LIBS)
+@WITH_GNUTLS_TRUE@am__append_3 = $(GNUTLS_LIBS)
 @WITH_NSS_TRUE@am__append_4 = $(NSS_CFLAGS)
 @WITH_NSS_TRUE@am__append_5 = crypto_nss.c
 @WITH_NSS_TRUE@am__append_6 = $(NSS_LIBS)
@@ -124,14 +124,14 @@ CONFIG_CLEAN_FILES =
 CONFIG_CLEAN_VPATH_FILES =
 LTLIBRARIES = $(noinst_LTLIBRARIES)
 am__DEPENDENCIES_1 =
-@WITH_GNUTLS_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) \
-@WITH_GNUTLS_TRUE@	$(am__DEPENDENCIES_1)
+@WITH_GNUTLS_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
 @WITH_NSS_TRUE@am__DEPENDENCIES_3 = $(am__DEPENDENCIES_1)
 libnm_core_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
 	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) \
 	$(am__DEPENDENCIES_3)
 am__libnm_core_la_SOURCES_DIST = $(core_build)/nm-core-enum-types.c \
-	$(core)/crypto.c $(core)/nm-connection.c $(core)/nm-errors.c \
+	$(core)/crypto.c $(core)/nm-connection.c \
+	$(core)/nm-dbus-utils.c $(core)/nm-errors.c \
 	$(core)/nm-keyfile-reader.c $(core)/nm-keyfile-utils.c \
 	$(core)/nm-keyfile-writer.c $(core)/nm-property-compare.c \
 	$(core)/nm-setting-8021x.c $(core)/nm-setting-adsl.c \
@@ -140,37 +140,42 @@ am__libnm_core_la_SOURCES_DIST = $(core_build)/nm-core-enum-types.c \
 	$(core)/nm-setting-cdma.c $(core)/nm-setting-connection.c \
 	$(core)/nm-setting-dcb.c $(core)/nm-setting-generic.c \
 	$(core)/nm-setting-gsm.c $(core)/nm-setting-infiniband.c \
-	$(core)/nm-setting-ip-config.c $(core)/nm-setting-ip4-config.c \
-	$(core)/nm-setting-ip6-config.c $(core)/nm-setting-olpc-mesh.c \
-	$(core)/nm-setting-ppp.c $(core)/nm-setting-pppoe.c \
-	$(core)/nm-setting-serial.c $(core)/nm-setting-team-port.c \
-	$(core)/nm-setting-team.c $(core)/nm-setting-vlan.c \
-	$(core)/nm-setting-vpn.c $(core)/nm-setting-wimax.c \
-	$(core)/nm-setting-wired.c \
+	$(core)/nm-setting-ip-config.c $(core)/nm-setting-ip-tunnel.c \
+	$(core)/nm-setting-ip4-config.c \
+	$(core)/nm-setting-ip6-config.c $(core)/nm-setting-macvlan.c \
+	$(core)/nm-setting-olpc-mesh.c $(core)/nm-setting-ppp.c \
+	$(core)/nm-setting-pppoe.c $(core)/nm-setting-serial.c \
+	$(core)/nm-setting-team-port.c $(core)/nm-setting-team.c \
+	$(core)/nm-setting-tun.c $(core)/nm-setting-vlan.c \
+	$(core)/nm-setting-vpn.c $(core)/nm-setting-vxlan.c \
+	$(core)/nm-setting-wimax.c $(core)/nm-setting-wired.c \
 	$(core)/nm-setting-wireless-security.c \
 	$(core)/nm-setting-wireless.c $(core)/nm-setting.c \
 	$(core)/nm-simple-connection.c $(core)/nm-utils.c \
+	$(core)/nm-vpn-editor-plugin.c $(core)/nm-vpn-plugin-info.c \
 	$(core)/crypto.h $(core)/nm-connection-private.h \
-	$(core)/nm-core-internal.h $(core)/nm-keyfile-internal.h \
-	$(core)/nm-keyfile-utils.h $(core)/nm-property-compare.h \
-	$(core)/nm-setting-private.h $(core)/nm-utils-private.h \
-	crypto_gnutls.c crypto_nss.c
+	$(core)/nm-core-internal.h $(core)/nm-core-types-internal.h \
+	$(core)/nm-keyfile-internal.h $(core)/nm-keyfile-utils.h \
+	$(core)/nm-property-compare.h $(core)/nm-setting-private.h \
+	$(core)/nm-utils-private.h crypto_gnutls.c crypto_nss.c
 am__objects_1 = nm-core-enum-types.lo crypto.lo nm-connection.lo \
-	nm-errors.lo nm-keyfile-reader.lo nm-keyfile-utils.lo \
-	nm-keyfile-writer.lo nm-property-compare.lo \
-	nm-setting-8021x.lo nm-setting-adsl.lo nm-setting-bluetooth.lo \
-	nm-setting-bond.lo nm-setting-bridge-port.lo \
-	nm-setting-bridge.lo nm-setting-cdma.lo \
-	nm-setting-connection.lo nm-setting-dcb.lo \
+	nm-dbus-utils.lo nm-errors.lo nm-keyfile-reader.lo \
+	nm-keyfile-utils.lo nm-keyfile-writer.lo \
+	nm-property-compare.lo nm-setting-8021x.lo nm-setting-adsl.lo \
+	nm-setting-bluetooth.lo nm-setting-bond.lo \
+	nm-setting-bridge-port.lo nm-setting-bridge.lo \
+	nm-setting-cdma.lo nm-setting-connection.lo nm-setting-dcb.lo \
 	nm-setting-generic.lo nm-setting-gsm.lo \
 	nm-setting-infiniband.lo nm-setting-ip-config.lo \
-	nm-setting-ip4-config.lo nm-setting-ip6-config.lo \
+	nm-setting-ip-tunnel.lo nm-setting-ip4-config.lo \
+	nm-setting-ip6-config.lo nm-setting-macvlan.lo \
 	nm-setting-olpc-mesh.lo nm-setting-ppp.lo nm-setting-pppoe.lo \
 	nm-setting-serial.lo nm-setting-team-port.lo \
-	nm-setting-team.lo nm-setting-vlan.lo nm-setting-vpn.lo \
-	nm-setting-wimax.lo nm-setting-wired.lo \
-	nm-setting-wireless-security.lo nm-setting-wireless.lo \
-	nm-setting.lo nm-simple-connection.lo nm-utils.lo
+	nm-setting-team.lo nm-setting-tun.lo nm-setting-vlan.lo \
+	nm-setting-vpn.lo nm-setting-vxlan.lo nm-setting-wimax.lo \
+	nm-setting-wired.lo nm-setting-wireless-security.lo \
+	nm-setting-wireless.lo nm-setting.lo nm-simple-connection.lo \
+	nm-utils.lo nm-vpn-editor-plugin.lo nm-vpn-plugin-info.lo
 am__objects_2 =
 @WITH_GNUTLS_TRUE@am__objects_3 = crypto_gnutls.lo
 @WITH_NSS_TRUE@am__objects_4 = crypto_nss.lo
@@ -330,7 +335,6 @@ BLUEZ5_LIBS = @BLUEZ5_LIBS@
 CC = @CC@
 CCDEPMODE = @CCDEPMODE@
 CFLAGS = @CFLAGS@
-CKDB_PATH = @CKDB_PATH@
 CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@
 CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@
 CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@
@@ -342,8 +346,6 @@ CXXDEPMODE = @CXXDEPMODE@
 CXXFLAGS = @CXXFLAGS@
 CYGPATH_W = @CYGPATH_W@
 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@
@@ -353,6 +355,7 @@ DHCPCD_PATH = @DHCPCD_PATH@
 DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@
 DLLTOOL = @DLLTOOL@
 DNSMASQ_PATH = @DNSMASQ_PATH@
+DNSSEC_TRIGGER_SCRIPT = @DNSSEC_TRIGGER_SCRIPT@
 DSYMUTIL = @DSYMUTIL@
 DUMPBIN = @DUMPBIN@
 ECHO_C = @ECHO_C@
@@ -407,16 +410,13 @@ INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@
 INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@
 INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@
 IPTABLES_PATH = @IPTABLES_PATH@
-IWMX_SDK_CFLAGS = @IWMX_SDK_CFLAGS@
-IWMX_SDK_LIBS = @IWMX_SDK_LIBS@
 KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@
 LCOV = @LCOV@
 LD = @LD@
 LDFLAGS = @LDFLAGS@
+LIBAUDIT_CFLAGS = @LIBAUDIT_CFLAGS@
+LIBAUDIT_LIBS = @LIBAUDIT_LIBS@
 LIBDL = @LIBDL@
-LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
-LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
-LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
 LIBICONV = @LIBICONV@
 LIBINTL = @LIBINTL@
 LIBM = @LIBM@
@@ -453,6 +453,8 @@ NEWT_LIBS = @NEWT_LIBS@
 NM = @NM@
 NMEDIT = @NMEDIT@
 NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@
+NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@
+NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@
 NM_MAJOR_VERSION = @NM_MAJOR_VERSION@
 NM_MICRO_VERSION = @NM_MICRO_VERSION@
 NM_MINOR_VERSION = @NM_MINOR_VERSION@
@@ -481,7 +483,6 @@ 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@
@@ -496,6 +497,8 @@ SYSTEMD_200_CFLAGS = @SYSTEMD_200_CFLAGS@
 SYSTEMD_200_LIBS = @SYSTEMD_200_LIBS@
 SYSTEMD_INHIBIT_CFLAGS = @SYSTEMD_INHIBIT_CFLAGS@
 SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@
+SYSTEMD_JOURNAL_CFLAGS = @SYSTEMD_JOURNAL_CFLAGS@
+SYSTEMD_JOURNAL_LIBS = @SYSTEMD_JOURNAL_LIBS@
 SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@
 SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@
 SYSTEM_CA_PATH = @SYSTEM_CA_PATH@
@@ -556,6 +559,7 @@ mkdir_p = @mkdir_p@
 nmbinary = @nmbinary@
 nmconfdir = @nmconfdir@
 nmdatadir = @nmdatadir@
+nmlibdir = @nmlibdir@
 nmrundir = @nmrundir@
 nmstatedir = @nmstatedir@
 oldincludedir = @oldincludedir@
@@ -563,6 +567,7 @@ pdfdir = @pdfdir@
 prefix = @prefix@
 program_transform_name = @program_transform_name@
 psdir = @psdir@
+runstatedir = @runstatedir@
 sbindir = @sbindir@
 sharedstatedir = @sharedstatedir@
 srcdir = @srcdir@
@@ -579,16 +584,17 @@ with_netconfig = @with_netconfig@
 with_resolvconf = @with_resolvconf@
 with_valgrind = @with_valgrind@
 SUBDIRS = . tests
-AM_CPPFLAGS = -I${top_srcdir}/include -I${top_builddir}/include \
+AM_CPPFLAGS = -I${top_srcdir}/shared -I${top_builddir}/shared \
 	-DG_LOG_DOMAIN=\""libnm"\" -DLOCALEDIR=\"$(datadir)/locale\" \
-	-DNETWORKMANAGER_COMPILATION \
+	-DNMCONFDIR=\"$(nmconfdir)\" -DNMLIBDIR=\"$(nmlibdir)\" \
+	-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_LIB \
 	-DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE $(GLIB_CFLAGS) \
 	$(am__append_1) $(am__append_4)
 noinst_LTLIBRARIES = libnm-core.la
 core = $(top_srcdir)/libnm-core
 core_build = $(top_builddir)/libnm-core
 libnm_core_headers = \
-	$(top_builddir)/include/nm-version-macros.h \
+	$(top_builddir)/shared/nm-version-macros.h \
 	$(core_build)/nm-core-enum-types.h	\
 	$(core)/nm-connection.h			\
 	$(core)/nm-core-types.h			\
@@ -607,16 +613,20 @@ libnm_core_headers = \
 	$(core)/nm-setting-gsm.h		\
 	$(core)/nm-setting-infiniband.h		\
 	$(core)/nm-setting-ip-config.h		\
+	$(core)/nm-setting-ip-tunnel.h		\
 	$(core)/nm-setting-ip4-config.h		\
 	$(core)/nm-setting-ip6-config.h		\
+	$(core)/nm-setting-macvlan.h		\
 	$(core)/nm-setting-olpc-mesh.h		\
 	$(core)/nm-setting-ppp.h		\
 	$(core)/nm-setting-pppoe.h		\
 	$(core)/nm-setting-serial.h		\
 	$(core)/nm-setting-team-port.h		\
 	$(core)/nm-setting-team.h		\
+	$(core)/nm-setting-tun.h		\
 	$(core)/nm-setting-vlan.h		\
 	$(core)/nm-setting-vpn.h		\
+	$(core)/nm-setting-vxlan.h		\
 	$(core)/nm-setting-wimax.h		\
 	$(core)/nm-setting-wired.h		\
 	$(core)/nm-setting-wireless-security.h	\
@@ -625,12 +635,15 @@ libnm_core_headers = \
 	$(core)/nm-simple-connection.h		\
 	$(core)/nm-utils.h			\
 	$(core)/nm-version.h \
-	$(core)/nm-vpn-dbus-interface.h
+	$(core)/nm-vpn-dbus-interface.h     \
+	$(core)/nm-vpn-editor-plugin.h \
+	$(core)/nm-vpn-plugin-info.h
 
 libnm_core_private_headers = \
 	$(core)/crypto.h			\
 	$(core)/nm-connection-private.h		\
 	$(core)/nm-core-internal.h		\
+	$(core)/nm-core-types-internal.h    \
 	$(core)/nm-keyfile-internal.h       \
 	$(core)/nm-keyfile-utils.h          \
 	$(core)/nm-property-compare.h		\
@@ -641,6 +654,7 @@ libnm_core_sources = \
 	$(core_build)/nm-core-enum-types.c	\
 	$(core)/crypto.c			\
 	$(core)/nm-connection.c			\
+	$(core)/nm-dbus-utils.c			\
 	$(core)/nm-errors.c			\
 	$(core)/nm-keyfile-reader.c         \
 	$(core)/nm-keyfile-utils.c          \
@@ -659,23 +673,29 @@ libnm_core_sources = \
 	$(core)/nm-setting-gsm.c		\
 	$(core)/nm-setting-infiniband.c		\
 	$(core)/nm-setting-ip-config.c		\
+	$(core)/nm-setting-ip-tunnel.c		\
 	$(core)/nm-setting-ip4-config.c		\
 	$(core)/nm-setting-ip6-config.c		\
+	$(core)/nm-setting-macvlan.c		\
 	$(core)/nm-setting-olpc-mesh.c		\
 	$(core)/nm-setting-ppp.c		\
 	$(core)/nm-setting-pppoe.c		\
 	$(core)/nm-setting-serial.c		\
 	$(core)/nm-setting-team-port.c		\
 	$(core)/nm-setting-team.c		\
+	$(core)/nm-setting-tun.c		\
 	$(core)/nm-setting-vlan.c		\
 	$(core)/nm-setting-vpn.c		\
+	$(core)/nm-setting-vxlan.c		\
 	$(core)/nm-setting-wimax.c		\
 	$(core)/nm-setting-wired.c		\
 	$(core)/nm-setting-wireless-security.c	\
 	$(core)/nm-setting-wireless.c		\
 	$(core)/nm-setting.c			\
 	$(core)/nm-simple-connection.c		\
-	$(core)/nm-utils.c
+	$(core)/nm-utils.c                  \
+	$(core)/nm-vpn-editor-plugin.c \
+	$(core)/nm-vpn-plugin-info.c
 
 
 # header/source defines are in Makefile.libnm-core, so they can be shared
@@ -753,6 +773,7 @@ distclean-compile:
 @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-core-enum-types.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-dbus-utils.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-errors.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-keyfile-reader.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-keyfile-utils.Plo@am__quote@
@@ -771,16 +792,20 @@ distclean-compile:
 @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-ip-config.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-ip-tunnel.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-macvlan.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-tun.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-vxlan.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@
@@ -788,6 +813,8 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-simple-connection.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-utils.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-vpn-editor-plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-vpn-plugin-info.Plo@am__quote@
 
 .c.o:
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@@ -831,6 +858,13 @@ nm-connection.lo: $(core)/nm-connection.c
 @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) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-connection.lo `test -f '$(core)/nm-connection.c' || echo '$(srcdir)/'`$(core)/nm-connection.c
 
+nm-dbus-utils.lo: $(core)/nm-dbus-utils.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-dbus-utils.lo -MD -MP -MF $(DEPDIR)/nm-dbus-utils.Tpo -c -o nm-dbus-utils.lo `test -f '$(core)/nm-dbus-utils.c' || echo '$(srcdir)/'`$(core)/nm-dbus-utils.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/nm-dbus-utils.Tpo $(DEPDIR)/nm-dbus-utils.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$(core)/nm-dbus-utils.c' object='nm-dbus-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) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-dbus-utils.lo `test -f '$(core)/nm-dbus-utils.c' || echo '$(srcdir)/'`$(core)/nm-dbus-utils.c
+
 nm-errors.lo: $(core)/nm-errors.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-errors.lo -MD -MP -MF $(DEPDIR)/nm-errors.Tpo -c -o nm-errors.lo `test -f '$(core)/nm-errors.c' || echo '$(srcdir)/'`$(core)/nm-errors.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/nm-errors.Tpo $(DEPDIR)/nm-errors.Plo
@@ -957,6 +991,13 @@ nm-setting-ip-config.lo: $(core)/nm-setting-ip-config.c
 @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) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-setting-ip-config.lo `test -f '$(core)/nm-setting-ip-config.c' || echo '$(srcdir)/'`$(core)/nm-setting-ip-config.c
 
+nm-setting-ip-tunnel.lo: $(core)/nm-setting-ip-tunnel.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-setting-ip-tunnel.lo -MD -MP -MF $(DEPDIR)/nm-setting-ip-tunnel.Tpo -c -o nm-setting-ip-tunnel.lo `test -f '$(core)/nm-setting-ip-tunnel.c' || echo '$(srcdir)/'`$(core)/nm-setting-ip-tunnel.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/nm-setting-ip-tunnel.Tpo $(DEPDIR)/nm-setting-ip-tunnel.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$(core)/nm-setting-ip-tunnel.c' object='nm-setting-ip-tunnel.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) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-setting-ip-tunnel.lo `test -f '$(core)/nm-setting-ip-tunnel.c' || echo '$(srcdir)/'`$(core)/nm-setting-ip-tunnel.c
+
 nm-setting-ip4-config.lo: $(core)/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) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-setting-ip4-config.lo -MD -MP -MF $(DEPDIR)/nm-setting-ip4-config.Tpo -c -o nm-setting-ip4-config.lo `test -f '$(core)/nm-setting-ip4-config.c' || echo '$(srcdir)/'`$(core)/nm-setting-ip4-config.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/nm-setting-ip4-config.Tpo $(DEPDIR)/nm-setting-ip4-config.Plo
@@ -971,6 +1012,13 @@ nm-setting-ip6-config.lo: $(core)/nm-setting-ip6-config.c
 @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) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-setting-ip6-config.lo `test -f '$(core)/nm-setting-ip6-config.c' || echo '$(srcdir)/'`$(core)/nm-setting-ip6-config.c
 
+nm-setting-macvlan.lo: $(core)/nm-setting-macvlan.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-setting-macvlan.lo -MD -MP -MF $(DEPDIR)/nm-setting-macvlan.Tpo -c -o nm-setting-macvlan.lo `test -f '$(core)/nm-setting-macvlan.c' || echo '$(srcdir)/'`$(core)/nm-setting-macvlan.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/nm-setting-macvlan.Tpo $(DEPDIR)/nm-setting-macvlan.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$(core)/nm-setting-macvlan.c' object='nm-setting-macvlan.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) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-setting-macvlan.lo `test -f '$(core)/nm-setting-macvlan.c' || echo '$(srcdir)/'`$(core)/nm-setting-macvlan.c
+
 nm-setting-olpc-mesh.lo: $(core)/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) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-setting-olpc-mesh.lo -MD -MP -MF $(DEPDIR)/nm-setting-olpc-mesh.Tpo -c -o nm-setting-olpc-mesh.lo `test -f '$(core)/nm-setting-olpc-mesh.c' || echo '$(srcdir)/'`$(core)/nm-setting-olpc-mesh.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/nm-setting-olpc-mesh.Tpo $(DEPDIR)/nm-setting-olpc-mesh.Plo
@@ -1013,6 +1061,13 @@ nm-setting-team.lo: $(core)/nm-setting-team.c
 @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) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-setting-team.lo `test -f '$(core)/nm-setting-team.c' || echo '$(srcdir)/'`$(core)/nm-setting-team.c
 
+nm-setting-tun.lo: $(core)/nm-setting-tun.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-setting-tun.lo -MD -MP -MF $(DEPDIR)/nm-setting-tun.Tpo -c -o nm-setting-tun.lo `test -f '$(core)/nm-setting-tun.c' || echo '$(srcdir)/'`$(core)/nm-setting-tun.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/nm-setting-tun.Tpo $(DEPDIR)/nm-setting-tun.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$(core)/nm-setting-tun.c' object='nm-setting-tun.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) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-setting-tun.lo `test -f '$(core)/nm-setting-tun.c' || echo '$(srcdir)/'`$(core)/nm-setting-tun.c
+
 nm-setting-vlan.lo: $(core)/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) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-setting-vlan.lo -MD -MP -MF $(DEPDIR)/nm-setting-vlan.Tpo -c -o nm-setting-vlan.lo `test -f '$(core)/nm-setting-vlan.c' || echo '$(srcdir)/'`$(core)/nm-setting-vlan.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/nm-setting-vlan.Tpo $(DEPDIR)/nm-setting-vlan.Plo
@@ -1027,6 +1082,13 @@ nm-setting-vpn.lo: $(core)/nm-setting-vpn.c
 @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) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-setting-vpn.lo `test -f '$(core)/nm-setting-vpn.c' || echo '$(srcdir)/'`$(core)/nm-setting-vpn.c
 
+nm-setting-vxlan.lo: $(core)/nm-setting-vxlan.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-setting-vxlan.lo -MD -MP -MF $(DEPDIR)/nm-setting-vxlan.Tpo -c -o nm-setting-vxlan.lo `test -f '$(core)/nm-setting-vxlan.c' || echo '$(srcdir)/'`$(core)/nm-setting-vxlan.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/nm-setting-vxlan.Tpo $(DEPDIR)/nm-setting-vxlan.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$(core)/nm-setting-vxlan.c' object='nm-setting-vxlan.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) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-setting-vxlan.lo `test -f '$(core)/nm-setting-vxlan.c' || echo '$(srcdir)/'`$(core)/nm-setting-vxlan.c
+
 nm-setting-wimax.lo: $(core)/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) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-setting-wimax.lo -MD -MP -MF $(DEPDIR)/nm-setting-wimax.Tpo -c -o nm-setting-wimax.lo `test -f '$(core)/nm-setting-wimax.c' || echo '$(srcdir)/'`$(core)/nm-setting-wimax.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/nm-setting-wimax.Tpo $(DEPDIR)/nm-setting-wimax.Plo
@@ -1076,6 +1138,20 @@ nm-utils.lo: $(core)/nm-utils.c
 @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) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-utils.lo `test -f '$(core)/nm-utils.c' || echo '$(srcdir)/'`$(core)/nm-utils.c
 
+nm-vpn-editor-plugin.lo: $(core)/nm-vpn-editor-plugin.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-vpn-editor-plugin.lo -MD -MP -MF $(DEPDIR)/nm-vpn-editor-plugin.Tpo -c -o nm-vpn-editor-plugin.lo `test -f '$(core)/nm-vpn-editor-plugin.c' || echo '$(srcdir)/'`$(core)/nm-vpn-editor-plugin.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/nm-vpn-editor-plugin.Tpo $(DEPDIR)/nm-vpn-editor-plugin.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$(core)/nm-vpn-editor-plugin.c' object='nm-vpn-editor-plugin.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) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-vpn-editor-plugin.lo `test -f '$(core)/nm-vpn-editor-plugin.c' || echo '$(srcdir)/'`$(core)/nm-vpn-editor-plugin.c
+
+nm-vpn-plugin-info.lo: $(core)/nm-vpn-plugin-info.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-vpn-plugin-info.lo -MD -MP -MF $(DEPDIR)/nm-vpn-plugin-info.Tpo -c -o nm-vpn-plugin-info.lo `test -f '$(core)/nm-vpn-plugin-info.c' || echo '$(srcdir)/'`$(core)/nm-vpn-plugin-info.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/nm-vpn-plugin-info.Tpo $(DEPDIR)/nm-vpn-plugin-info.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$(core)/nm-vpn-plugin-info.c' object='nm-vpn-plugin-info.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) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-vpn-plugin-info.lo `test -f '$(core)/nm-vpn-plugin-info.c' || echo '$(srcdir)/'`$(core)/nm-vpn-plugin-info.c
+
 mostlyclean-libtool:
 	-rm -f *.lo
 
diff --git a/libnm-core/Makefile.libnm-core b/libnm-core/Makefile.libnm-core
index 0b606f32..fe8cc8a6 100644
--- a/libnm-core/Makefile.libnm-core
+++ b/libnm-core/Makefile.libnm-core
@@ -6,7 +6,7 @@ core = $(top_srcdir)/libnm-core
 core_build = $(top_builddir)/libnm-core
 
 libnm_core_headers =				\
-	$(top_builddir)/include/nm-version-macros.h \
+	$(top_builddir)/shared/nm-version-macros.h \
 	$(core_build)/nm-core-enum-types.h	\
 	$(core)/nm-connection.h			\
 	$(core)/nm-core-types.h			\
@@ -25,16 +25,20 @@ libnm_core_headers =				\
 	$(core)/nm-setting-gsm.h		\
 	$(core)/nm-setting-infiniband.h		\
 	$(core)/nm-setting-ip-config.h		\
+	$(core)/nm-setting-ip-tunnel.h		\
 	$(core)/nm-setting-ip4-config.h		\
 	$(core)/nm-setting-ip6-config.h		\
+	$(core)/nm-setting-macvlan.h		\
 	$(core)/nm-setting-olpc-mesh.h		\
 	$(core)/nm-setting-ppp.h		\
 	$(core)/nm-setting-pppoe.h		\
 	$(core)/nm-setting-serial.h		\
 	$(core)/nm-setting-team-port.h		\
 	$(core)/nm-setting-team.h		\
+	$(core)/nm-setting-tun.h		\
 	$(core)/nm-setting-vlan.h		\
 	$(core)/nm-setting-vpn.h		\
+	$(core)/nm-setting-vxlan.h		\
 	$(core)/nm-setting-wimax.h		\
 	$(core)/nm-setting-wired.h		\
 	$(core)/nm-setting-wireless-security.h	\
@@ -43,12 +47,15 @@ libnm_core_headers =				\
 	$(core)/nm-simple-connection.h		\
 	$(core)/nm-utils.h			\
 	$(core)/nm-version.h \
-	$(core)/nm-vpn-dbus-interface.h
+	$(core)/nm-vpn-dbus-interface.h     \
+	$(core)/nm-vpn-editor-plugin.h \
+	$(core)/nm-vpn-plugin-info.h
 
 libnm_core_private_headers =			\
 	$(core)/crypto.h			\
 	$(core)/nm-connection-private.h		\
 	$(core)/nm-core-internal.h		\
+	$(core)/nm-core-types-internal.h    \
 	$(core)/nm-keyfile-internal.h       \
 	$(core)/nm-keyfile-utils.h          \
 	$(core)/nm-property-compare.h		\
@@ -59,6 +66,7 @@ libnm_core_sources =				\
 	$(core_build)/nm-core-enum-types.c	\
 	$(core)/crypto.c			\
 	$(core)/nm-connection.c			\
+	$(core)/nm-dbus-utils.c			\
 	$(core)/nm-errors.c			\
 	$(core)/nm-keyfile-reader.c         \
 	$(core)/nm-keyfile-utils.c          \
@@ -77,21 +85,27 @@ libnm_core_sources =				\
 	$(core)/nm-setting-gsm.c		\
 	$(core)/nm-setting-infiniband.c		\
 	$(core)/nm-setting-ip-config.c		\
+	$(core)/nm-setting-ip-tunnel.c		\
 	$(core)/nm-setting-ip4-config.c		\
 	$(core)/nm-setting-ip6-config.c		\
+	$(core)/nm-setting-macvlan.c		\
 	$(core)/nm-setting-olpc-mesh.c		\
 	$(core)/nm-setting-ppp.c		\
 	$(core)/nm-setting-pppoe.c		\
 	$(core)/nm-setting-serial.c		\
 	$(core)/nm-setting-team-port.c		\
 	$(core)/nm-setting-team.c		\
+	$(core)/nm-setting-tun.c		\
 	$(core)/nm-setting-vlan.c		\
 	$(core)/nm-setting-vpn.c		\
+	$(core)/nm-setting-vxlan.c		\
 	$(core)/nm-setting-wimax.c		\
 	$(core)/nm-setting-wired.c		\
 	$(core)/nm-setting-wireless-security.c	\
 	$(core)/nm-setting-wireless.c		\
 	$(core)/nm-setting.c			\
 	$(core)/nm-simple-connection.c		\
-	$(core)/nm-utils.c
+	$(core)/nm-utils.c                  \
+	$(core)/nm-vpn-editor-plugin.c \
+	$(core)/nm-vpn-plugin-info.c
 
diff --git a/libnm-core/crypto.c b/libnm-core/crypto.c
index 205d22c6..559ac52b 100644
--- a/libnm-core/crypto.c
+++ b/libnm-core/crypto.c
@@ -23,13 +23,12 @@
 
 #include "config.h"
 
-#include <glib.h>
 #include <string.h>
 #include <strings.h>
 #include <unistd.h>
 #include <stdlib.h>
-#include <glib/gi18n-lib.h>
 
+#include "nm-default.h"
 #include "crypto.h"
 #include "nm-errors.h"
 
diff --git a/libnm-core/crypto.h b/libnm-core/crypto.h
index 434f108d..c77ada5a 100644
--- a/libnm-core/crypto.h
+++ b/libnm-core/crypto.h
@@ -24,7 +24,7 @@
 #ifndef __CRYPTO_H__
 #define __CRYPTO_H__
 
-#include <glib.h>
+#include "nm-default.h"
 
 #define MD5_HASH_LEN 20
 #define CIPHER_DES_EDE3_CBC "DES-EDE3-CBC"
diff --git a/libnm-core/crypto_gnutls.c b/libnm-core/crypto_gnutls.c
index 96dddb90..3f90c77d 100644
--- a/libnm-core/crypto_gnutls.c
+++ b/libnm-core/crypto_gnutls.c
@@ -18,19 +18,17 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * Copyright 2007 - 2009 Red Hat, Inc.
+ * Copyright 2007 - 2015 Red Hat, Inc.
  */
 
 #include "config.h"
 
-#include <glib.h>
-#include <glib/gi18n-lib.h>
-
-#include <gcrypt.h>
 #include <gnutls/gnutls.h>
+#include <gnutls/crypto.h>
 #include <gnutls/x509.h>
 #include <gnutls/pkcs12.h>
 
+#include "nm-default.h"
 #include "crypto.h"
 #include "nm-errors.h"
 
@@ -68,8 +66,9 @@ crypto_decrypt (const char *cipher,
                 gsize *out_len,
                 GError **error)
 {
-	gcry_cipher_hd_t ctx;
-	gcry_error_t err;
+	gnutls_cipher_hd_t ctx;
+	gnutls_datum_t key_dt, iv_dt;
+	int err;
 	int cipher_mech, i;
 	char *output = NULL;
 	gboolean success = FALSE;
@@ -79,13 +78,13 @@ crypto_decrypt (const char *cipher,
 		return NULL;
 
 	if (!strcmp (cipher, CIPHER_DES_EDE3_CBC)) {
-		cipher_mech = GCRY_CIPHER_3DES;
+		cipher_mech = GNUTLS_CIPHER_3DES_CBC;
 		real_iv_len = SALT_LEN;
 	} else if (!strcmp (cipher, CIPHER_DES_CBC)) {
-		cipher_mech = GCRY_CIPHER_DES;
+		cipher_mech = GNUTLS_CIPHER_DES_CBC;
 		real_iv_len = SALT_LEN;
 	} else if (!strcmp (cipher, CIPHER_AES_CBC)) {
-		cipher_mech = GCRY_CIPHER_AES;
+		cipher_mech = GNUTLS_CIPHER_AES_128_CBC;
 		real_iv_len = 16;
 	} else {
 		g_set_error (error, NM_CRYPTO_ERROR,
@@ -105,39 +104,26 @@ crypto_decrypt (const char *cipher,
 
 	output = g_malloc0 (data_len);
 
-	err = gcry_cipher_open (&ctx, cipher_mech, GCRY_CIPHER_MODE_CBC, 0);
-	if (err) {
-		g_set_error (error, NM_CRYPTO_ERROR,
-		             NM_CRYPTO_ERROR_DECRYPTION_FAILED,
-		             _("Failed to initialize the decryption cipher context: %s / %s."),
-		             gcry_strsource (err), gcry_strerror (err));
-		goto out;
-	}
+	key_dt.data = (unsigned char *) key;
+	key_dt.size = key_len;
+	iv_dt.data = (unsigned char *) iv;
+	iv_dt.size = iv_len;
 
-	err = gcry_cipher_setkey (ctx, key, key_len);
-	if (err) {
-		g_set_error (error, NM_CRYPTO_ERROR,
-		             NM_CRYPTO_ERROR_DECRYPTION_FAILED,
-		             _("Failed to set symmetric key for decryption: %s / %s."),
-		             gcry_strsource (err), gcry_strerror (err));
-		goto out;
-	}
-
-	err = gcry_cipher_setiv (ctx, iv, iv_len);
-	if (err) {
+	err = gnutls_cipher_init (&ctx, cipher_mech, &key_dt, &iv_dt);
+	if (err < 0) {
 		g_set_error (error, NM_CRYPTO_ERROR,
 		             NM_CRYPTO_ERROR_DECRYPTION_FAILED,
-		             _("Failed to set IV for decryption: %s / %s."),
-		             gcry_strsource (err), gcry_strerror (err));
+		             _("Failed to initialize the decryption cipher context: %s (%s)"),
+		             gnutls_strerror_name (err), gnutls_strerror (err));
 		goto out;
 	}
 
-	err = gcry_cipher_decrypt (ctx, output, data_len, data, data_len);
-	if (err) {
+	err = gnutls_cipher_decrypt2 (ctx, data, data_len, output, data_len);
+	if (err < 0) {
 		g_set_error (error, NM_CRYPTO_ERROR,
 		             NM_CRYPTO_ERROR_DECRYPTION_FAILED,
-		             _("Failed to decrypt the private key: %s / %s."),
-		             gcry_strsource (err), gcry_strerror (err));
+		             _("Failed to decrypt the private key: %s (%s)"),
+		             gnutls_strerror_name (err), gnutls_strerror (err));
 		goto out;
 	}
 	pad_len = output[data_len - 1];
@@ -174,7 +160,7 @@ out:
 			output = NULL;
 		}
 	}
-	gcry_cipher_close (ctx);
+	gnutls_cipher_deinit (ctx);
 	return output;
 }
 
@@ -189,26 +175,24 @@ crypto_encrypt (const char *cipher,
                 gsize *out_len,
                 GError **error)
 {
-	gcry_cipher_hd_t ctx;
-	gcry_error_t err;
+	gnutls_cipher_hd_t ctx;
+	gnutls_datum_t key_dt, iv_dt;
+	int err;
 	int cipher_mech;
 	char *output = NULL;
 	gboolean success = FALSE;
 	gsize padded_buf_len, pad_len, output_len;
 	char *padded_buf = NULL;
 	guint32 i;
-	gsize salt_len;
 
 	if (!crypto_init (error))
 		return NULL;
 
-	if (!strcmp (cipher, CIPHER_DES_EDE3_CBC)) {
-		cipher_mech = GCRY_CIPHER_3DES;
-		salt_len = SALT_LEN;
-	} else if (!strcmp (cipher, CIPHER_AES_CBC)) {
-		cipher_mech = GCRY_CIPHER_AES;
-		salt_len = iv_len;
-	} else {
+	if (!strcmp (cipher, CIPHER_DES_EDE3_CBC))
+		cipher_mech = GNUTLS_CIPHER_3DES_CBC;
+	else if (!strcmp (cipher, CIPHER_AES_CBC))
+		cipher_mech = GNUTLS_CIPHER_AES_128_CBC;
+	else {
 		g_set_error (error, NM_CRYPTO_ERROR,
 		             NM_CRYPTO_ERROR_UNKNOWN_CIPHER,
 		             _("Private key cipher '%s' was unknown."),
@@ -229,40 +213,26 @@ crypto_encrypt (const char *cipher,
 
 	output = g_malloc0 (output_len);
 
-	err = gcry_cipher_open (&ctx, cipher_mech, GCRY_CIPHER_MODE_CBC, 0);
-	if (err) {
-		g_set_error (error, NM_CRYPTO_ERROR,
-		             NM_CRYPTO_ERROR_ENCRYPTION_FAILED,
-		             _("Failed to initialize the encryption cipher context: %s / %s."),
-		             gcry_strsource (err), gcry_strerror (err));
-		goto out;
-	}
-
-	err = gcry_cipher_setkey (ctx, key, key_len);
-	if (err) {
-		g_set_error (error, NM_CRYPTO_ERROR,
-		             NM_CRYPTO_ERROR_ENCRYPTION_FAILED,
-		             _("Failed to set symmetric key for encryption: %s / %s."),
-		             gcry_strsource (err), gcry_strerror (err));
-		goto out;
-	}
+	key_dt.data = (unsigned char *) key;
+	key_dt.size = key_len;
+	iv_dt.data = (unsigned char *) iv;
+	iv_dt.size = iv_len;
 
-	/* gcrypt only wants 8 bytes of the IV (same as the DES block length) */
-	err = gcry_cipher_setiv (ctx, iv, salt_len);
-	if (err) {
+	err = gnutls_cipher_init (&ctx, cipher_mech, &key_dt, &iv_dt);
+	if (err < 0) {
 		g_set_error (error, NM_CRYPTO_ERROR,
 		             NM_CRYPTO_ERROR_ENCRYPTION_FAILED,
-		             _("Failed to set IV for encryption: %s / %s."),
-		             gcry_strsource (err), gcry_strerror (err));
+		             _("Failed to initialize the encryption cipher context: %s (%s)"),
+		             gnutls_strerror_name (err), gnutls_strerror (err));
 		goto out;
 	}
 
-	err = gcry_cipher_encrypt (ctx, output, output_len, padded_buf, padded_buf_len);
-	if (err) {
+	err = gnutls_cipher_encrypt2 (ctx, padded_buf, padded_buf_len, output, output_len);
+	if (err < 0) {
 		g_set_error (error, NM_CRYPTO_ERROR,
 		             NM_CRYPTO_ERROR_ENCRYPTION_FAILED,
-		             _("Failed to encrypt the data: %s / %s."),
-		             gcry_strsource (err), gcry_strerror (err));
+		             _("Failed to encrypt the data: %s (%s)"),
+		             gnutls_strerror_name (err), gnutls_strerror (err));
 		goto out;
 	}
 
@@ -284,7 +254,7 @@ out:
 			output = NULL;
 		}
 	}
-	gcry_cipher_close (ctx);
+	gnutls_cipher_deinit (ctx);
 	return output;
 }
 
@@ -449,6 +419,6 @@ crypto_randomize (void *buffer, gsize buffer_len, GError **error)
 	if (!crypto_init (error))
 		return FALSE;
 
-	gcry_randomize (buffer, buffer_len, GCRY_STRONG_RANDOM);
+	gnutls_rnd (GNUTLS_RND_RANDOM, buffer, buffer_len);
 	return TRUE;
 }
diff --git a/libnm-core/crypto_nss.c b/libnm-core/crypto_nss.c
index d0c3506b..7f61ad7c 100644
--- a/libnm-core/crypto_nss.c
+++ b/libnm-core/crypto_nss.c
@@ -23,9 +23,6 @@
 
 #include "config.h"
 
-#include <glib.h>
-#include <glib/gi18n-lib.h>
-
 #include <prinit.h>
 #include <nss.h>
 #include <pk11pub.h>
@@ -36,6 +33,7 @@
 #include <ciferfam.h>
 #include <p12plcy.h>
 
+#include "nm-default.h"
 #include "crypto.h"
 #include "nm-errors.h"
 
diff --git a/libnm-core/nm-connection.c b/libnm-core/nm-connection.c
index 8f226582..5a491b40 100644
--- a/libnm-core/nm-connection.c
+++ b/libnm-core/nm-connection.c
@@ -22,15 +22,13 @@
 
 #include "config.h"
 
-#include <glib-object.h>
-#include <glib/gi18n-lib.h>
 #include <string.h>
+#include "nm-default.h"
 #include "nm-connection.h"
 #include "nm-connection-private.h"
 #include "nm-utils.h"
 #include "nm-setting-private.h"
 #include "nm-core-internal.h"
-#include "gsystem-local-alloc.h"
 
 /**
  * SECTION:nm-connection
@@ -899,6 +897,34 @@ EXIT:
 }
 
 /**
+ * nm_connection_verify_secrets:
+ * @connection: the #NMConnection to verify in
+ * @error: location to store error, or %NULL
+ *
+ * Verifies the secrets in the connection.
+ *
+ * Returns: %TRUE if the secrets are valid, %FALSE if they are not
+ *
+ * Since: 1.2
+ **/
+gboolean
+nm_connection_verify_secrets (NMConnection *connection, GError **error)
+{
+	GHashTableIter iter;
+	NMSetting *setting;
+
+	g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
+	g_return_val_if_fail (!error || !*error, FALSE);
+
+	g_hash_table_iter_init (&iter, NM_CONNECTION_GET_PRIVATE (connection)->settings);
+	while (g_hash_table_iter_next (&iter, NULL, (gpointer) &setting)) {
+		if (!nm_setting_verify_secrets (setting, connection, error))
+			return FALSE;
+	}
+	return TRUE;
+}
+
+/**
  * nm_connection_normalize:
  * @connection: the #NMConnection to normalize
  * @parameters: (allow-none) (element-type utf8 gpointer): a #GHashTable with
@@ -1520,7 +1546,8 @@ nm_connection_get_id (NMConnection *connection)
 	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);
+	if (!s_con)
+		return NULL;
 
 	return nm_setting_connection_get_id (s_con);
 }
@@ -1541,7 +1568,8 @@ nm_connection_get_connection_type (NMConnection *connection)
 	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);
+	if (!s_con)
+		return NULL;
 
 	return nm_setting_connection_get_connection_type (s_con);
 }
@@ -1566,7 +1594,11 @@ nm_connection_is_virtual (NMConnection *connection)
 	if (   !strcmp (type, NM_SETTING_BOND_SETTING_NAME)
 	    || !strcmp (type, NM_SETTING_TEAM_SETTING_NAME)
 	    || !strcmp (type, NM_SETTING_BRIDGE_SETTING_NAME)
-	    || !strcmp (type, NM_SETTING_VLAN_SETTING_NAME))
+	    || !strcmp (type, NM_SETTING_VLAN_SETTING_NAME)
+	    || !strcmp (type, NM_SETTING_TUN_SETTING_NAME)
+	    || !strcmp (type, NM_SETTING_IP_TUNNEL_SETTING_NAME)
+	    || !strcmp (type, NM_SETTING_MACVLAN_SETTING_NAME)
+	    || !strcmp (type, NM_SETTING_VXLAN_SETTING_NAME))
 		return TRUE;
 
 	if (!strcmp (type, NM_SETTING_INFINIBAND_SETTING_NAME)) {
@@ -1837,6 +1869,24 @@ nm_connection_get_setting_ip4_config (NMConnection *connection)
 }
 
 /**
+ * nm_connection_get_setting_ip_tunnel:
+ * @connection: the #NMConnection
+ *
+ * A shortcut to return any #NMSettingIPTunnel the connection might contain.
+ *
+ * Returns: (transfer none): an #NMSettingIPTunnel if the connection contains one, otherwise %NULL
+ *
+ * Since: 1.2
+ **/
+NMSettingIPTunnel *
+nm_connection_get_setting_ip_tunnel (NMConnection *connection)
+{
+	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+	return (NMSettingIPTunnel *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP_TUNNEL);
+}
+
+/**
  * nm_connection_get_setting_ip6_config:
  * @connection: the #NMConnection
  *
@@ -1858,6 +1908,24 @@ nm_connection_get_setting_ip6_config (NMConnection *connection)
 }
 
 /**
+ * nm_connection_get_setting_macvlan:
+ * @connection: the #NMConnection
+ *
+ * A shortcut to return any #NMSettingMacvlan the connection might contain.
+ *
+ * Returns: (transfer none): an #NMSettingMacvlan if the connection contains one, otherwise %NULL
+ *
+ * Since: 1.2
+ **/
+NMSettingMacvlan *
+nm_connection_get_setting_macvlan (NMConnection *connection)
+{
+	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+	return (NMSettingMacvlan *) nm_connection_get_setting (connection, NM_TYPE_SETTING_MACVLAN);
+}
+
+/**
  * nm_connection_get_setting_olpc_mesh:
  * @connection: the #NMConnection
  *
@@ -1922,6 +1990,24 @@ nm_connection_get_setting_serial (NMConnection *connection)
 }
 
 /**
+ * nm_connection_get_setting_tun:
+ * @connection: the #NMConnection
+ *
+ * A shortcut to return any #NMSettingTun the connection might contain.
+ *
+ * Returns: (transfer none): an #NMSettingTun if the connection contains one, otherwise %NULL
+ *
+ * Since: 1.2
+ **/
+NMSettingTun *
+nm_connection_get_setting_tun (NMConnection *connection)
+{
+	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+	return (NMSettingTun *) nm_connection_get_setting (connection, NM_TYPE_SETTING_TUN);
+}
+
+/**
  * nm_connection_get_setting_vpn:
  * @connection: the #NMConnection
  *
@@ -1938,6 +2024,24 @@ nm_connection_get_setting_vpn (NMConnection *connection)
 }
 
 /**
+ * nm_connection_get_setting_vxlan:
+ * @connection: the #NMConnection
+ *
+ * A shortcut to return any #NMSettingVxlan the connection might contain.
+ *
+ * Returns: (transfer none): an #NMSettingVxlan if the connection contains one, otherwise %NULL
+ *
+ * Since: 1.2
+ **/
+NMSettingVxlan *
+nm_connection_get_setting_vxlan (NMConnection *connection)
+{
+	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+	return (NMSettingVxlan *) nm_connection_get_setting (connection, NM_TYPE_SETTING_VXLAN);
+}
+
+/**
  * nm_connection_get_setting_wimax:
  * @connection: the #NMConnection
  *
diff --git a/libnm-core/nm-connection.h b/libnm-core/nm-connection.h
index c76ad607..21e30422 100644
--- a/libnm-core/nm-connection.h
+++ b/libnm-core/nm-connection.h
@@ -145,6 +145,8 @@ gboolean      nm_connection_diff          (NMConnection *a,
                                            GHashTable **out_settings);
 
 gboolean      nm_connection_verify        (NMConnection *connection, GError **error);
+NM_AVAILABLE_IN_1_2
+gboolean      nm_connection_verify_secrets (NMConnection *connection, GError **error);
 gboolean      nm_connection_normalize     (NMConnection *connection,
                                            GHashTable *parameters,
                                            gboolean *modified,
@@ -200,12 +202,17 @@ NMSettingDcb *             nm_connection_get_setting_dcb               (NMConnec
 NMSettingGeneric *         nm_connection_get_setting_generic           (NMConnection *connection);
 NMSettingGsm *             nm_connection_get_setting_gsm               (NMConnection *connection);
 NMSettingInfiniband *      nm_connection_get_setting_infiniband        (NMConnection *connection);
+NM_AVAILABLE_IN_1_2
+NMSettingIPTunnel *        nm_connection_get_setting_ip_tunnel         (NMConnection *connection);
 NMSettingIPConfig *        nm_connection_get_setting_ip4_config        (NMConnection *connection);
 NMSettingIPConfig *        nm_connection_get_setting_ip6_config        (NMConnection *connection);
+NM_AVAILABLE_IN_1_2
+NMSettingMacvlan *         nm_connection_get_setting_macvlan           (NMConnection *connection);
 NMSettingOlpcMesh *        nm_connection_get_setting_olpc_mesh         (NMConnection *connection);
 NMSettingPpp *             nm_connection_get_setting_ppp               (NMConnection *connection);
 NMSettingPppoe *           nm_connection_get_setting_pppoe             (NMConnection *connection);
 NMSettingSerial *          nm_connection_get_setting_serial            (NMConnection *connection);
+NMSettingTun *             nm_connection_get_setting_tun               (NMConnection *connection);
 NMSettingVpn *             nm_connection_get_setting_vpn               (NMConnection *connection);
 NMSettingWimax *           nm_connection_get_setting_wimax             (NMConnection *connection);
 NMSettingAdsl *            nm_connection_get_setting_adsl              (NMConnection *connection);
@@ -213,6 +220,8 @@ NMSettingWired *           nm_connection_get_setting_wired             (NMConnec
 NMSettingWireless *        nm_connection_get_setting_wireless          (NMConnection *connection);
 NMSettingWirelessSecurity *nm_connection_get_setting_wireless_security (NMConnection *connection);
 NMSettingVlan *            nm_connection_get_setting_vlan              (NMConnection *connection);
+NM_AVAILABLE_IN_1_2
+NMSettingVxlan *           nm_connection_get_setting_vxlan             (NMConnection *connection);
 
 G_END_DECLS
 
diff --git a/libnm-core/nm-core-enum-types.c b/libnm-core/nm-core-enum-types.c
index d2281653..4c580984 100644
--- a/libnm-core/nm-core-enum-types.c
+++ b/libnm-core/nm-core-enum-types.c
@@ -3,6 +3,8 @@
 
 /* Generated by glib-mkenums. Do not edit */
 
+#include "config.h"
+
 #include "nm-core-enum-types.h"
 
 #include "nm-version-macros.h" 
@@ -23,16 +25,20 @@
 #include "nm-setting-gsm.h" 
 #include "nm-setting-infiniband.h" 
 #include "nm-setting-ip-config.h" 
+#include "nm-setting-ip-tunnel.h" 
 #include "nm-setting-ip4-config.h" 
 #include "nm-setting-ip6-config.h" 
+#include "nm-setting-macvlan.h" 
 #include "nm-setting-olpc-mesh.h" 
 #include "nm-setting-ppp.h" 
 #include "nm-setting-pppoe.h" 
 #include "nm-setting-serial.h" 
 #include "nm-setting-team-port.h" 
 #include "nm-setting-team.h" 
+#include "nm-setting-tun.h" 
 #include "nm-setting-vlan.h" 
 #include "nm-setting-vpn.h" 
+#include "nm-setting-vxlan.h" 
 #include "nm-setting-wimax.h" 
 #include "nm-setting-wired.h" 
 #include "nm-setting-wireless-security.h" 
@@ -41,7 +47,9 @@
 #include "nm-simple-connection.h" 
 #include "nm-utils.h" 
 #include "nm-version.h" 
-#include "nm-vpn-dbus-interface.h"
+#include "nm-vpn-dbus-interface.h" 
+#include "nm-vpn-editor-plugin.h" 
+#include "nm-vpn-plugin-info.h"
 
 GType
 nm_connection_serialization_flags_get_type (void)
@@ -134,6 +142,10 @@ nm_device_type_get_type (void)
         { NM_DEVICE_TYPE_BRIDGE, "NM_DEVICE_TYPE_BRIDGE", "bridge" },
         { NM_DEVICE_TYPE_GENERIC, "NM_DEVICE_TYPE_GENERIC", "generic" },
         { NM_DEVICE_TYPE_TEAM, "NM_DEVICE_TYPE_TEAM", "team" },
+        { NM_DEVICE_TYPE_TUN, "NM_DEVICE_TYPE_TUN", "tun" },
+        { NM_DEVICE_TYPE_IP_TUNNEL, "NM_DEVICE_TYPE_IP_TUNNEL", "ip-tunnel" },
+        { NM_DEVICE_TYPE_MACVLAN, "NM_DEVICE_TYPE_MACVLAN", "macvlan" },
+        { NM_DEVICE_TYPE_VXLAN, "NM_DEVICE_TYPE_VXLAN", "vxlan" },
         { 0, NULL, NULL }
       };
       GType g_define_type_id =
@@ -501,6 +513,33 @@ nm_secret_agent_capabilities_get_type (void)
   return g_define_type_id__volatile;
 }
 GType
+nm_ip_tunnel_mode_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_IP_TUNNEL_MODE_UKNOWN, "NM_IP_TUNNEL_MODE_UKNOWN", "uknown" },
+        { NM_IP_TUNNEL_MODE_IPIP, "NM_IP_TUNNEL_MODE_IPIP", "ipip" },
+        { NM_IP_TUNNEL_MODE_GRE, "NM_IP_TUNNEL_MODE_GRE", "gre" },
+        { NM_IP_TUNNEL_MODE_SIT, "NM_IP_TUNNEL_MODE_SIT", "sit" },
+        { NM_IP_TUNNEL_MODE_ISATAP, "NM_IP_TUNNEL_MODE_ISATAP", "isatap" },
+        { NM_IP_TUNNEL_MODE_VTI, "NM_IP_TUNNEL_MODE_VTI", "vti" },
+        { NM_IP_TUNNEL_MODE_IP6IP6, "NM_IP_TUNNEL_MODE_IP6IP6", "ip6ip6" },
+        { NM_IP_TUNNEL_MODE_IPIP6, "NM_IP_TUNNEL_MODE_IPIP6", "ipip6" },
+        { NM_IP_TUNNEL_MODE_IP6GRE, "NM_IP_TUNNEL_MODE_IP6GRE", "ip6gre" },
+        { NM_IP_TUNNEL_MODE_VTI6, "NM_IP_TUNNEL_MODE_VTI6", "vti6" },
+        { 0, NULL, NULL }
+      };
+      GType g_define_type_id =
+        g_enum_register_static (g_intern_static_string ("NMIPTunnelMode"), values);
+      g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+    }
+
+  return g_define_type_id__volatile;
+}
+GType
 nm_agent_manager_error_get_type (void)
 {
   static volatile gsize g_define_type_id__volatile = 0;
@@ -761,6 +800,26 @@ nm_setting_connection_autoconnect_slaves_get_type (void)
   return g_define_type_id__volatile;
 }
 GType
+nm_setting_connection_lldp_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_CONNECTION_LLDP_DEFAULT, "NM_SETTING_CONNECTION_LLDP_DEFAULT", "default" },
+        { NM_SETTING_CONNECTION_LLDP_DISABLE, "NM_SETTING_CONNECTION_LLDP_DISABLE", "disable" },
+        { NM_SETTING_CONNECTION_LLDP_ENABLE_RX, "NM_SETTING_CONNECTION_LLDP_ENABLE_RX", "enable-rx" },
+        { 0, NULL, NULL }
+      };
+      GType g_define_type_id =
+        g_enum_register_static (g_intern_static_string ("NMSettingConnectionLldp"), 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;
@@ -803,6 +862,48 @@ nm_setting_ip6_config_privacy_get_type (void)
   return g_define_type_id__volatile;
 }
 GType
+nm_setting_ip6_config_addr_gen_mode_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_IP6_CONFIG_ADDR_GEN_MODE_EUI64, "NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64", "eui64" },
+        { NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY, "NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY", "stable-privacy" },
+        { 0, NULL, NULL }
+      };
+      GType g_define_type_id =
+        g_enum_register_static (g_intern_static_string ("NMSettingIP6ConfigAddrGenMode"), values);
+      g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+    }
+
+  return g_define_type_id__volatile;
+}
+GType
+nm_setting_macvlan_mode_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_MACVLAN_MODE_UNKNOWN, "NM_SETTING_MACVLAN_MODE_UNKNOWN", "unknown" },
+        { NM_SETTING_MACVLAN_MODE_VEPA, "NM_SETTING_MACVLAN_MODE_VEPA", "vepa" },
+        { NM_SETTING_MACVLAN_MODE_BRIDGE, "NM_SETTING_MACVLAN_MODE_BRIDGE", "bridge" },
+        { NM_SETTING_MACVLAN_MODE_PRIVATE, "NM_SETTING_MACVLAN_MODE_PRIVATE", "private" },
+        { NM_SETTING_MACVLAN_MODE_PASSTHRU, "NM_SETTING_MACVLAN_MODE_PASSTHRU", "passthru" },
+        { NM_SETTING_MACVLAN_MODE_SOURCE, "NM_SETTING_MACVLAN_MODE_SOURCE", "source" },
+        { 0, NULL, NULL }
+      };
+      GType g_define_type_id =
+        g_enum_register_static (g_intern_static_string ("NMSettingMacvlanMode"), values);
+      g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+    }
+
+  return g_define_type_id__volatile;
+}
+GType
 nm_setting_serial_parity_get_type (void)
 {
   static volatile gsize g_define_type_id__volatile = 0;
@@ -823,6 +924,26 @@ nm_setting_serial_parity_get_type (void)
   return g_define_type_id__volatile;
 }
 GType
+nm_setting_tun_mode_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_TUN_MODE_UNKNOWN, "NM_SETTING_TUN_MODE_UNKNOWN", "unknown" },
+        { NM_SETTING_TUN_MODE_TUN, "NM_SETTING_TUN_MODE_TUN", "tun" },
+        { NM_SETTING_TUN_MODE_TAP, "NM_SETTING_TUN_MODE_TAP", "tap" },
+        { 0, NULL, NULL }
+      };
+      GType g_define_type_id =
+        g_enum_register_static (g_intern_static_string ("NMSettingTunMode"), values);
+      g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+    }
+
+  return g_define_type_id__volatile;
+}
+GType
 nm_vlan_priority_map_get_type (void)
 {
   static volatile gsize g_define_type_id__volatile = 0;
@@ -852,6 +973,7 @@ nm_vlan_flags_get_type (void)
         { NM_VLAN_FLAG_REORDER_HEADERS, "NM_VLAN_FLAG_REORDER_HEADERS", "reorder-headers" },
         { NM_VLAN_FLAG_GVRP, "NM_VLAN_FLAG_GVRP", "gvrp" },
         { NM_VLAN_FLAG_LOOSE_BINDING, "NM_VLAN_FLAG_LOOSE_BINDING", "loose-binding" },
+        { NM_VLAN_FLAG_MVRP, "NM_VLAN_FLAG_MVRP", "mvrp" },
         { 0, NULL, NULL }
       };
       GType g_define_type_id =
@@ -955,6 +1077,26 @@ nm_setting_compare_flags_get_type (void)
   return g_define_type_id__volatile;
 }
 GType
+nm_setting_mac_randomization_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_MAC_RANDOMIZATION_DEFAULT, "NM_SETTING_MAC_RANDOMIZATION_DEFAULT", "default" },
+        { NM_SETTING_MAC_RANDOMIZATION_NEVER, "NM_SETTING_MAC_RANDOMIZATION_NEVER", "never" },
+        { NM_SETTING_MAC_RANDOMIZATION_ALWAYS, "NM_SETTING_MAC_RANDOMIZATION_ALWAYS", "always" },
+        { 0, NULL, NULL }
+      };
+      GType g_define_type_id =
+        g_enum_register_static (g_intern_static_string ("NMSettingMacRandomization"), values);
+      g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+    }
+
+  return g_define_type_id__volatile;
+}
+GType
 nm_setting_diff_result_get_type (void)
 {
   static volatile gsize g_define_type_id__volatile = 0;
@@ -1100,6 +1242,27 @@ nm_vpn_plugin_failure_get_type (void)
 
   return g_define_type_id__volatile;
 }
+GType
+nm_vpn_editor_plugin_capability_get_type (void)
+{
+  static volatile gsize g_define_type_id__volatile = 0;
+
+  if (g_once_init_enter (&g_define_type_id__volatile))
+    {
+      static const GFlagsValue values[] = {
+        { NM_VPN_EDITOR_PLUGIN_CAPABILITY_NONE, "NM_VPN_EDITOR_PLUGIN_CAPABILITY_NONE", "none" },
+        { NM_VPN_EDITOR_PLUGIN_CAPABILITY_IMPORT, "NM_VPN_EDITOR_PLUGIN_CAPABILITY_IMPORT", "import" },
+        { NM_VPN_EDITOR_PLUGIN_CAPABILITY_EXPORT, "NM_VPN_EDITOR_PLUGIN_CAPABILITY_EXPORT", "export" },
+        { NM_VPN_EDITOR_PLUGIN_CAPABILITY_IPV6, "NM_VPN_EDITOR_PLUGIN_CAPABILITY_IPV6", "ipv6" },
+        { 0, NULL, NULL }
+      };
+      GType g_define_type_id =
+        g_flags_register_static (g_intern_static_string ("NMVpnEditorPluginCapability"), values);
+      g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+    }
+
+  return g_define_type_id__volatile;
+}
 
 
 
diff --git a/libnm-core/nm-core-enum-types.h b/libnm-core/nm-core-enum-types.h
index 7e5c6df0..1c16cb21 100644
--- a/libnm-core/nm-core-enum-types.h
+++ b/libnm-core/nm-core-enum-types.h
@@ -43,6 +43,8 @@ GType nm_secret_agent_get_secrets_flags_get_type (void) G_GNUC_CONST;
 #define NM_TYPE_SECRET_AGENT_GET_SECRETS_FLAGS (nm_secret_agent_get_secrets_flags_get_type ())
 GType nm_secret_agent_capabilities_get_type (void) G_GNUC_CONST;
 #define NM_TYPE_SECRET_AGENT_CAPABILITIES (nm_secret_agent_capabilities_get_type ())
+GType nm_ip_tunnel_mode_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_IP_TUNNEL_MODE (nm_ip_tunnel_mode_get_type ())
 GType nm_agent_manager_error_get_type (void) G_GNUC_CONST;
 #define NM_TYPE_AGENT_MANAGER_ERROR (nm_agent_manager_error_get_type ())
 GType nm_connection_error_get_type (void) G_GNUC_CONST;
@@ -65,12 +67,20 @@ GType nm_setting_802_1x_ck_scheme_get_type (void) G_GNUC_CONST;
 #define NM_TYPE_SETTING_802_1X_CK_SCHEME (nm_setting_802_1x_ck_scheme_get_type ())
 GType nm_setting_connection_autoconnect_slaves_get_type (void) G_GNUC_CONST;
 #define NM_TYPE_SETTING_CONNECTION_AUTOCONNECT_SLAVES (nm_setting_connection_autoconnect_slaves_get_type ())
+GType nm_setting_connection_lldp_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_SETTING_CONNECTION_LLDP (nm_setting_connection_lldp_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_ip6_config_privacy_get_type (void) G_GNUC_CONST;
 #define NM_TYPE_SETTING_IP6_CONFIG_PRIVACY (nm_setting_ip6_config_privacy_get_type ())
+GType nm_setting_ip6_config_addr_gen_mode_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_SETTING_IP6_CONFIG_ADDR_GEN_MODE (nm_setting_ip6_config_addr_gen_mode_get_type ())
+GType nm_setting_macvlan_mode_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_SETTING_MACVLAN_MODE (nm_setting_macvlan_mode_get_type ())
 GType nm_setting_serial_parity_get_type (void) G_GNUC_CONST;
 #define NM_TYPE_SETTING_SERIAL_PARITY (nm_setting_serial_parity_get_type ())
+GType nm_setting_tun_mode_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_SETTING_TUN_MODE (nm_setting_tun_mode_get_type ())
 GType nm_vlan_priority_map_get_type (void) G_GNUC_CONST;
 #define NM_TYPE_VLAN_PRIORITY_MAP (nm_vlan_priority_map_get_type ())
 GType nm_vlan_flags_get_type (void) G_GNUC_CONST;
@@ -83,6 +93,8 @@ GType nm_setting_secret_flags_get_type (void) G_GNUC_CONST;
 #define NM_TYPE_SETTING_SECRET_FLAGS (nm_setting_secret_flags_get_type ())
 GType nm_setting_compare_flags_get_type (void) G_GNUC_CONST;
 #define NM_TYPE_SETTING_COMPARE_FLAGS (nm_setting_compare_flags_get_type ())
+GType nm_setting_mac_randomization_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_SETTING_MAC_RANDOMIZATION (nm_setting_mac_randomization_get_type ())
 GType nm_setting_diff_result_get_type (void) G_GNUC_CONST;
 #define NM_TYPE_SETTING_DIFF_RESULT (nm_setting_diff_result_get_type ())
 GType nm_utils_security_type_get_type (void) G_GNUC_CONST;
@@ -95,6 +107,8 @@ GType nm_vpn_connection_state_reason_get_type (void) G_GNUC_CONST;
 #define NM_TYPE_VPN_CONNECTION_STATE_REASON (nm_vpn_connection_state_reason_get_type ())
 GType nm_vpn_plugin_failure_get_type (void) G_GNUC_CONST;
 #define NM_TYPE_VPN_PLUGIN_FAILURE (nm_vpn_plugin_failure_get_type ())
+GType nm_vpn_editor_plugin_capability_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_VPN_EDITOR_PLUGIN_CAPABILITY (nm_vpn_editor_plugin_capability_get_type ())
 G_END_DECLS
 
 #endif /* __NM_CORE_ENUM_TYPES_H__ */
diff --git a/libnm-core/nm-core-internal.h b/libnm-core/nm-core-internal.h
index 56cb7806..3e1236b9 100644
--- a/libnm-core/nm-core-internal.h
+++ b/libnm-core/nm-core-internal.h
@@ -33,6 +33,8 @@
  * and some test programs.
  **/
 
+
+#include "nm-default.h"
 #include "nm-connection.h"
 #include "nm-core-enum-types.h"
 #include "nm-setting-8021x.h"
@@ -47,16 +49,20 @@
 #include "nm-setting-generic.h"
 #include "nm-setting-gsm.h"
 #include "nm-setting-infiniband.h"
+#include "nm-setting-ip-tunnel.h"
 #include "nm-setting-ip4-config.h"
 #include "nm-setting-ip6-config.h"
+#include "nm-setting-macvlan.h"
 #include "nm-setting-olpc-mesh.h"
 #include "nm-setting-ppp.h"
 #include "nm-setting-pppoe.h"
 #include "nm-setting-serial.h"
 #include "nm-setting-team-port.h"
 #include "nm-setting-team.h"
+#include "nm-setting-tun.h"
 #include "nm-setting-vlan.h"
 #include "nm-setting-vpn.h"
+#include "nm-setting-vxlan.h"
 #include "nm-setting-wimax.h"
 #include "nm-setting-wired.h"
 #include "nm-setting-wireless-security.h"
@@ -64,22 +70,28 @@
 #include "nm-setting.h"
 #include "nm-simple-connection.h"
 #include "nm-utils.h"
-#include "nm-version.h"
 #include "nm-vpn-dbus-interface.h"
-
-#define NM_UTILS_CLEAR_CANCELLABLE(c) \
-	if (c) { \
-		g_cancellable_cancel (c); \
-		g_clear_object (&c); \
-	}
+#include "nm-core-types-internal.h"
 
 /* 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
+#define NM_SETTING_COMPARE_FLAG_INFERRABLE ((NMSettingCompareFlags) 0x80000000)
+
+/* NM_SETTING_COMPARE_FLAG_IGNORE_REAPPLY_IMMEDIATELY: this flag is used for properties
+ * that automatically get re-applied on an active connection when the settings
+ * connection is modified. For most properties, the applied-connection is distinct
+ * from the setting-connection and changes don't propagate. Exceptions are the
+ * firewall-zone and the metered property.
+ */
+#define NM_SETTING_COMPARE_FLAG_IGNORE_REAPPLY_IMMEDIATELY ((NMSettingCompareFlags) 0x40000000)
 
+/* NM_SETTING_COMPARE_FLAG_NONE: for convenience, define a special flag NONE -- which
+ * equals to numeric zero (NM_SETTING_COMPARE_FLAG_EXACT).
+ */
+#define NM_SETTING_COMPARE_FLAG_NONE ((NMSettingCompareFlags) 0)
 
 
 #define NM_SETTING_SECRET_FLAGS_ALL \
@@ -132,12 +144,27 @@ char **     _nm_utils_slist_to_strv (GSList *slist, gboolean deep_copy);
 
 GPtrArray * _nm_utils_strv_to_ptrarray (char **strv);
 char **     _nm_utils_ptrarray_to_strv (GPtrArray *ptrarray);
+gboolean    _nm_utils_strv_equal (char **strv1, char **strv2);
+
+gboolean _nm_utils_check_file (const char *filename,
+                               gint64 check_owner,
+                               NMUtilsCheckFilePredicate check_file,
+                               gpointer user_data,
+                               struct stat *out_st,
+                               GError **error);
+
+gboolean _nm_utils_check_module_file (const char *name,
+                                      int check_owner,
+                                      NMUtilsCheckFilePredicate check_file,
+                                      gpointer user_data,
+                                      GError **error);
 
 #define NM_UTILS_UUID_TYPE_LEGACY            0
 #define NM_UTILS_UUID_TYPE_VARIANT3          1
 
 char *nm_utils_uuid_generate_from_string (const char *s, gssize slen, int uuid_type, gpointer type_args);
 
+/* arbitrarily choosen namespace UUID for _nm_utils_uuid_generate_from_strings() */
 #define NM_UTILS_UUID_NS "b425e9fb-7598-44b4-9e3b-5a2e3aaa4905"
 
 char *_nm_utils_uuid_generate_from_strings (const char *string1, ...) G_GNUC_NULL_TERMINATED;
@@ -152,12 +179,91 @@ GByteArray *nm_utils_rsa_key_encrypt (const guint8 *data,
                                       char **out_password,
                                       GError **error);
 
-/* These are public API in NM 1.2, but private on nm-1-0. */
-int nm_utils_bond_mode_string_to_int (const char *mode);
-const char *nm_utils_bond_mode_int_to_string (int mode);
-
 gint64 _nm_utils_ascii_str_to_int64 (const char *str, guint base, gint64 min, gint64 max, gint64 fallback);
 
+gulong _nm_dbus_signal_connect_data (GDBusProxy *proxy,
+                                     const char *signal_name,
+                                     const GVariantType *signature,
+                                     GCallback c_handler,
+                                     gpointer data,
+                                     GClosureNotify destroy_data,
+                                     GConnectFlags connect_flags);
+#define _nm_dbus_signal_connect(proxy, name, signature, handler, data) \
+	_nm_dbus_signal_connect_data (proxy, name, signature, handler, data, NULL, (GConnectFlags) 0)
+
+GVariant *_nm_dbus_proxy_call_finish (GDBusProxy           *proxy,
+                                      GAsyncResult         *res,
+                                      const GVariantType   *reply_type,
+                                      GError              **error);
+
+GVariant *_nm_dbus_proxy_call_sync   (GDBusProxy           *proxy,
+                                      const gchar          *method_name,
+                                      GVariant             *parameters,
+                                      const GVariantType   *reply_type,
+                                      GDBusCallFlags        flags,
+                                      gint                  timeout_msec,
+                                      GCancellable         *cancellable,
+                                      GError              **error);
+
 gboolean _nm_dbus_error_has_name (GError     *error,
                                   const char *dbus_error_name);
+
+/***********************************************************/
+
+gboolean _nm_vpn_plugin_info_check_file (const char *filename,
+                                         gboolean check_absolute,
+                                         gboolean do_validate_filename,
+                                         gint64 check_owner,
+                                         NMUtilsCheckFilePredicate check_file,
+                                         gpointer user_data,
+                                         GError **error);
+
+const char *_nm_vpn_plugin_info_get_default_dir_etc (void);
+const char *_nm_vpn_plugin_info_get_default_dir_lib (void);
+const char *_nm_vpn_plugin_info_get_default_dir_user (void);
+
+GSList *_nm_vpn_plugin_info_list_load_dir (const char *dirname,
+                                           gboolean do_validate_filename,
+                                           gint64 check_owner,
+                                           NMUtilsCheckFilePredicate check_file,
+                                           gpointer user_data);
+
+/***********************************************************/
+
+typedef struct {
+	const char *name;
+	gboolean numeric;
+	gboolean ipv6_only;
+} NMUtilsDNSOptionDesc;
+
+extern const NMUtilsDNSOptionDesc _nm_utils_dns_option_descs[];
+
+gboolean    _nm_utils_dns_option_validate (const char *option, char **out_name,
+                                           long *out_value, gboolean ipv6,
+                                           const NMUtilsDNSOptionDesc *option_descs);
+int         _nm_utils_dns_option_find_idx (GPtrArray *array, const char *option);
+
+/***********************************************************/
+
+typedef struct _NMUtilsStrStrDictKey NMUtilsStrStrDictKey;
+guint                 _nm_utils_strstrdictkey_hash   (gconstpointer a);
+gboolean              _nm_utils_strstrdictkey_equal  (gconstpointer a, gconstpointer b);
+NMUtilsStrStrDictKey *_nm_utils_strstrdictkey_create (const char *v1, const char *v2);
+
+#define _nm_utils_strstrdictkey_static(v1, v2) \
+    ( (NMUtilsStrStrDictKey *) ("\03" v1 "\0" v2 "") )
+
+/***********************************************************/
+
+gboolean _nm_setting_vlan_set_priorities (NMSettingVlan *setting,
+                                          NMVlanPriorityMap map,
+                                          const NMVlanQosMapping *qos_map,
+                                          guint n_qos_map);
+void     _nm_setting_vlan_get_priorities (NMSettingVlan *setting,
+                                          NMVlanPriorityMap map,
+                                          NMVlanQosMapping **out_qos_map,
+                                          guint *out_n_qos_map);
+
+/***********************************************************/
+
 #endif
diff --git a/libnm-core/nm-core-types-internal.h b/libnm-core/nm-core-types-internal.h
new file mode 100644
index 00000000..442a10a3
--- /dev/null
+++ b/libnm-core/nm-core-types-internal.h
@@ -0,0 +1,30 @@
+/* -*- 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.
+ *
+ * (C) Copyright 2015 Red Hat, Inc.
+ */
+
+#ifndef NM_CORE_TYPES_INTERNAL_H
+#define NM_CORE_TYPES_INTERNAL_H
+
+typedef struct {
+	guint32 from;
+	guint32 to;
+} NMVlanQosMapping;
+
+#endif /* NM_CORE_TYPES_INTERNAL_H */
diff --git a/libnm-core/nm-core-types.h b/libnm-core/nm-core-types.h
index 19388c5b..cd19923b 100644
--- a/libnm-core/nm-core-types.h
+++ b/libnm-core/nm-core-types.h
@@ -42,16 +42,20 @@ typedef struct _NMSettingGeneric          NMSettingGeneric;
 typedef struct _NMSettingGsm              NMSettingGsm;
 typedef struct _NMSettingInfiniband       NMSettingInfiniband;
 typedef struct _NMSettingIPConfig         NMSettingIPConfig;
+typedef struct _NMSettingIPTunnel         NMSettingIPTunnel;
 typedef struct _NMSettingIP4Config        NMSettingIP4Config;
 typedef struct _NMSettingIP6Config        NMSettingIP6Config;
+typedef struct _NMSettingMacvlan          NMSettingMacvlan;
 typedef struct _NMSettingOlpcMesh         NMSettingOlpcMesh;
 typedef struct _NMSettingPpp              NMSettingPpp;
 typedef struct _NMSettingPppoe            NMSettingPppoe;
 typedef struct _NMSettingSerial           NMSettingSerial;
 typedef struct _NMSettingTeam             NMSettingTeam;
 typedef struct _NMSettingTeamPort         NMSettingTeamPort;
+typedef struct _NMSettingTun              NMSettingTun;
 typedef struct _NMSettingVlan             NMSettingVlan;
 typedef struct _NMSettingVpn              NMSettingVpn;
+typedef struct _NMSettingVxlan            NMSettingVxlan;
 typedef struct _NMSettingWimax            NMSettingWimax;
 typedef struct _NMSettingWired            NMSettingWired;
 typedef struct _NMSettingWireless         NMSettingWireless;
diff --git a/libnm-core/nm-dbus-interface.h b/libnm-core/nm-dbus-interface.h
index ac20fa2e..b32aabc2 100644
--- a/libnm-core/nm-dbus-interface.h
+++ b/libnm-core/nm-dbus-interface.h
@@ -29,7 +29,7 @@
 /* This header must not include glib or libnm. */
 
 #ifndef NM_VERSION_H
-#define NM_AVAILABLE_IN_1_0_6
+#define NM_AVAILABLE_IN_1_2
 #endif
 
 /*
@@ -67,7 +67,7 @@
 #define NM_DBUS_INTERFACE_DEVICE_MACVLAN    NM_DBUS_INTERFACE_DEVICE ".Macvlan"
 #define NM_DBUS_INTERFACE_DEVICE_VXLAN      NM_DBUS_INTERFACE_DEVICE ".Vxlan"
 #define NM_DBUS_INTERFACE_DEVICE_GRE        NM_DBUS_INTERFACE_DEVICE ".Gre"
-
+#define NM_DBUS_INTERFACE_DEVICE_IP_TUNNEL  NM_DBUS_INTERFACE_DEVICE ".IPTunnel"
 
 #define NM_DBUS_INTERFACE_SETTINGS        "org.freedesktop.NetworkManager.Settings"
 #define NM_DBUS_PATH_SETTINGS             "/org/freedesktop/NetworkManager/Settings"
@@ -148,6 +148,10 @@ typedef enum {
  * @NM_DEVICE_TYPE_ADSL: ADSL modem
  * @NM_DEVICE_TYPE_BRIDGE: a bridge master interface
  * @NM_DEVICE_TYPE_TEAM: a team master interface
+ * @NM_DEVICE_TYPE_TUN: a TUN or TAP interface
+ * @NM_DEVICE_TYPE_IP_TUNNEL: a IP tunnel interface
+ * @NM_DEVICE_TYPE_MACVLAN: a MACVLAN interface
+ * @NM_DEVICE_TYPE_VXLAN: a VXLAN interface
  *
  * #NMDeviceType values indicate the type of hardware represented by
  * an #NMDevice.
@@ -171,6 +175,10 @@ typedef enum {
 	NM_DEVICE_TYPE_BRIDGE     = 13,
 	NM_DEVICE_TYPE_GENERIC    = 14,
 	NM_DEVICE_TYPE_TEAM       = 15,
+	NM_DEVICE_TYPE_TUN        = 16,
+	NM_DEVICE_TYPE_IP_TUNNEL  = 17,
+	NM_DEVICE_TYPE_MACVLAN    = 18,
+	NM_DEVICE_TYPE_VXLAN      = 19,
 } NMDeviceType;
 
 /**
@@ -553,9 +561,9 @@ typedef enum {
  *
  * (Corresponds to the NM_METERED type in nm-device.xml.)
  *
- * Since: 1.0.6
+ * Since: 1.2
  **/
-NM_AVAILABLE_IN_1_0_6
+NM_AVAILABLE_IN_1_2
 typedef enum {
 	NM_METERED_UNKNOWN    = 0,
 	NM_METERED_YES        = 1,
@@ -644,7 +652,56 @@ typedef enum /*< flags >*/ {
 } NMSecretAgentCapabilities;
 
 #ifndef NM_VERSION_H
-#undef NM_AVAILABLE_IN_1_0_6
+#undef NM_AVAILABLE_IN_1_2
 #endif
 
+#define NM_LLDP_ATTR_DESTINATION "destination"
+#define NM_LLDP_ATTR_CHASSIS_ID_TYPE "chassis-id-type"
+#define NM_LLDP_ATTR_CHASSIS_ID "chassis-id"
+#define NM_LLDP_ATTR_PORT_ID_TYPE "port-id-type"
+#define NM_LLDP_ATTR_PORT_ID "port-id"
+#define NM_LLDP_ATTR_PORT_DESCRIPTION "port-description"
+#define NM_LLDP_ATTR_SYSTEM_NAME "system-name"
+#define NM_LLDP_ATTR_SYSTEM_DESCRIPTION "system-description"
+#define NM_LLDP_ATTR_SYSTEM_CAPABILITIES "system-capabilities"
+#define NM_LLDP_ATTR_IEEE_802_1_PVID "ieee-802-1-pvid"
+#define NM_LLDP_ATTR_IEEE_802_1_PPVID "ieee-802-1-ppvid"
+#define NM_LLDP_ATTR_IEEE_802_1_PPVID_FLAGS "ieee-802-1-ppvid-flags"
+#define NM_LLDP_ATTR_IEEE_802_1_VID "ieee-802-1-pvid"
+#define NM_LLDP_ATTR_IEEE_802_1_VLAN_NAME "ieee-802-1-vlan-name"
+
+#define NM_LLDP_DEST_NEAREST_BRIDGE "nearest-bridge"
+#define NM_LLDP_DEST_NEAREST_NON_TPMR_BRIDGE "nearest-non-tpmr-bridge"
+#define NM_LLDP_DEST_NEAREST_CUSTOMER_BRIDGE "nearest-customer-bridge"
+
+/**
+ * NMIPTunnelMode:
+ * @NM_IP_TUNNEL_MODE_UNKNOWN: Unknown/unset tunnel mode
+ * @NM_IP_TUNNEL_MODE_IPIP:    IP in IP tunnel
+ * @NM_IP_TUNNEL_MODE_GRE:     GRE tunnel
+ * @NM_IP_TUNNEL_MODE_SIT:     SIT tunnel
+ * @NM_IP_TUNNEL_MODE_ISATAP:  ISATAP tunnel
+ * @NM_IP_TUNNEL_MODE_VTI:     VTI tunnel
+ * @NM_IP_TUNNEL_MODE_IP6IP6:  IPv6 in IPv6 tunnel
+ * @NM_IP_TUNNEL_MODE_IPIP6:   IPv4 in IPv6 tunnel
+ * @NM_IP_TUNNEL_MODE_IP6GRE:  IPv6 GRE tunnel
+ * @NM_IP_TUNNEL_MODE_VTI6:    IPv6 VTI tunnel
+ *
+ * The tunneling mode.
+ *
+ * Since: 1.2
+ */
+typedef enum {
+	NM_IP_TUNNEL_MODE_UKNOWN      = 0,
+	NM_IP_TUNNEL_MODE_IPIP        = 1,
+	NM_IP_TUNNEL_MODE_GRE         = 2,
+	NM_IP_TUNNEL_MODE_SIT         = 3,
+	NM_IP_TUNNEL_MODE_ISATAP      = 4,
+	NM_IP_TUNNEL_MODE_VTI         = 5,
+	NM_IP_TUNNEL_MODE_IP6IP6      = 6,
+	NM_IP_TUNNEL_MODE_IPIP6       = 7,
+	NM_IP_TUNNEL_MODE_IP6GRE      = 8,
+	NM_IP_TUNNEL_MODE_VTI6        = 9,
+} NMIPTunnelMode;
+
 #endif /* __NM_DBUS_INTERFACE_H__ */
diff --git a/libnm-core/nm-dbus-utils.c b/libnm-core/nm-dbus-utils.c
new file mode 100644
index 00000000..86272786
--- /dev/null
+++ b/libnm-core/nm-dbus-utils.c
@@ -0,0 +1,294 @@
+/* -*- 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 2015 Red Hat, Inc.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include "nm-default.h"
+#include "nm-core-internal.h"
+
+typedef struct {
+	char *signal_name;
+	const GVariantType *signature;
+} NMDBusSignalData;
+
+static void
+dbus_signal_data_free (gpointer data, GClosure *closure)
+{
+	NMDBusSignalData *sd = data;
+
+	g_free (sd->signal_name);
+	g_slice_free (NMDBusSignalData, sd);
+}
+
+static void
+dbus_signal_meta_marshal (GClosure     *closure,
+                          GValue       *return_value,
+                          guint         n_param_values,
+                          const GValue *param_values,
+                          gpointer      invocation_hint,
+                          gpointer      marshal_data)
+{
+	NMDBusSignalData *sd = marshal_data;
+	const char *signal_name;
+	GVariant *parameters, *param;
+	GValue *closure_params;
+	gsize n_params, i;
+
+	g_return_if_fail (n_param_values == 4);
+
+	signal_name = g_value_get_string (&param_values[2]);
+	parameters = g_value_get_variant (&param_values[3]);
+
+	if (strcmp (signal_name, sd->signal_name) != 0)
+		return;
+
+	if (sd->signature) {
+		if (!g_variant_is_of_type (parameters, sd->signature)) {
+			g_warning ("%p: got signal '%s' but parameters were of type '%s', not '%s'",
+			           g_value_get_object (&param_values[0]),
+			           signal_name, g_variant_get_type_string (parameters),
+			           g_variant_type_peek_string (sd->signature));
+			return;
+		}
+
+		n_params = g_variant_n_children (parameters) + 1;
+	} else
+		n_params = 1;
+
+	closure_params = g_new0 (GValue, n_params);
+	g_value_init (&closure_params[0], G_TYPE_OBJECT);
+	g_value_copy (&param_values[0], &closure_params[0]);
+
+	for (i = 1; i < n_params; i++) {
+		param = g_variant_get_child_value (parameters, i - 1);
+		if (   g_variant_is_of_type (param, G_VARIANT_TYPE ("ay"))
+		    || g_variant_is_of_type (param, G_VARIANT_TYPE ("aay"))) {
+			/* g_dbus_gvariant_to_gvalue() thinks 'ay' means "non-UTF-8 NUL-terminated string" */
+			g_value_init (&closure_params[i], G_TYPE_VARIANT);
+			g_value_set_variant (&closure_params[i], param);
+		} else
+			g_dbus_gvariant_to_gvalue (param, &closure_params[i]);
+		g_variant_unref (param);
+	}
+
+	g_cclosure_marshal_generic (closure,
+	                            NULL,
+	                            n_params,
+	                            closure_params,
+	                            invocation_hint,
+	                            NULL);
+
+	for (i = 0; i < n_params; i++)
+		g_value_unset (&closure_params[i]);
+	g_free (closure_params);
+}
+
+/**
+ * _nm_dbus_signal_connect_data:
+ * @proxy: a #GDBusProxy
+ * @signal_name: the D-Bus signal to connect to
+ * @signature: (allow-none): the signal's type signature (must be a tuple)
+ * @c_handler: the signal handler function
+ * @data: (allow-none): data to pass to @c_handler
+ * @destroy_data: (allow-none): closure destroy notify for @data
+ * @connect_flags: connection flags
+ *
+ * Connects to the D-Bus signal @signal_name on @proxy. @c_handler must be a
+ * void function whose first argument is a #GDBusProxy, followed by arguments
+ * for each element of @signature, ending with a #gpointer argument for @data.
+ *
+ * The argument types in @c_handler correspond to the types output by
+ * g_dbus_gvariant_to_gvalue(), except for 'ay' and 'aay'. In particular:
+ * - both 16-bit and 32-bit integers are passed as #gint/#guint
+ * - 'as' values are passed as #GStrv (char **)
+ * - all other array, tuple, and dict types are passed as #GVariant
+ *
+ * If @signature is %NULL, then the signal's parameters will be ignored, and
+ * @c_handler should take only the #GDBusProxy and #gpointer arguments.
+ *
+ * Returns: the signal handler ID, which can be used with
+ *   g_signal_handler_remove(). Beware that because of the way the signal is
+ *   connected, you will not be able to remove it with
+ *   g_signal_handlers_disconnect_by_func(), although
+ *   g_signal_handlers_disconnect_by_data() will work correctly.
+ */
+gulong
+_nm_dbus_signal_connect_data (GDBusProxy *proxy,
+                              const char *signal_name,
+                              const GVariantType *signature,
+                              GCallback c_handler,
+                              gpointer data,
+                              GClosureNotify destroy_data,
+                              GConnectFlags connect_flags)
+{
+	NMDBusSignalData *sd;
+	GClosure *closure;
+	gboolean swapped = !!(connect_flags & G_CONNECT_SWAPPED);
+	gboolean after = !!(connect_flags & G_CONNECT_AFTER);
+
+	g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), 0);
+	g_return_val_if_fail (signal_name != NULL, 0);
+	g_return_val_if_fail (signature == NULL || g_variant_type_is_tuple (signature), 0);
+	g_return_val_if_fail (c_handler != NULL, 0);
+
+	sd = g_slice_new (NMDBusSignalData);
+	sd->signal_name = g_strdup (signal_name);
+	sd->signature = signature;
+
+	closure = (swapped ? g_cclosure_new_swap : g_cclosure_new) (c_handler, data, destroy_data);
+	g_closure_set_marshal (closure, g_cclosure_marshal_generic);
+	g_closure_set_meta_marshal (closure, sd, dbus_signal_meta_marshal);
+	g_closure_add_finalize_notifier (closure, sd, dbus_signal_data_free);
+
+	return g_signal_connect_closure (proxy, "g-signal", closure, after);
+}
+
+/**
+ * _nm_dbus_signal_connect:
+ * @proxy: a #GDBusProxy
+ * @signal_name: the D-Bus signal to connect to
+ * @signature: the signal's type signature (must be a tuple)
+ * @c_handler: the signal handler function
+ * @data: (allow-none): data to pass to @c_handler
+ *
+ * Simplified version of _nm_dbus_signal_connect_data() with fewer arguments.
+ *
+ * Returns: the signal handler ID, as with _nm_signal_connect_data().
+ */
+
+
+static void
+typecheck_response (GVariant           **response,
+                    const GVariantType  *reply_type,
+                    GError             **error)
+{
+	if (*response && reply_type && !g_variant_is_of_type (*response, reply_type)) {
+		/* This is the same error code that g_dbus_connection_call() returns if
+		 * @reply_type doesn't match.
+		 */
+		g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
+		             _("Method returned type '%s', but expected '%s'"),
+		             g_variant_get_type_string (*response),
+		             g_variant_type_peek_string (reply_type));
+		g_clear_pointer (response, g_variant_unref);
+	}
+}
+
+/**
+ * _nm_dbus_proxy_call_finish:
+ * @proxy: A #GDBusProxy.
+ * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to
+ *   g_dbus_proxy_call().
+ * @reply_type: (allow-none): the expected type of the reply, or %NULL
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes an operation started with g_dbus_proxy_call(), as with
+ * g_dbus_proxy_call_finish(), except thatif @reply_type is non-%NULL, then it
+ * will also check that the response matches that type signature, and return
+ * an error if not.
+ *
+ * Returns: %NULL if @error is set. Otherwise a #GVariant tuple with
+ * return values. Free with g_variant_unref().
+ */
+GVariant *
+_nm_dbus_proxy_call_finish (GDBusProxy          *proxy,
+                            GAsyncResult        *res,
+                            const GVariantType  *reply_type,
+                            GError             **error)
+{
+	GVariant *ret;
+
+	ret = g_dbus_proxy_call_finish (proxy, res, error);
+	typecheck_response (&ret, reply_type, error);
+	return ret;
+}
+
+/**
+ * _nm_dbus_proxy_call_sync:
+ * @proxy: A #GDBusProxy.
+ * @method_name: Name of method to invoke.
+ * @parameters: (allow-none): A #GVariant tuple with parameters for the signal
+ *   or %NULL if not passing parameters.
+ * @reply_type: (allow-none): the expected type of the reply, or %NULL
+ * @flags: Flags from the #GDBusCallFlags enumeration.
+ * @timeout_msec: The timeout in milliseconds (with %G_MAXINT meaning
+ *   "infinite") or -1 to use the proxy default timeout.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Synchronously invokes the @method_name method on @proxy, as with
+ * g_dbus_proxy_call_sync(), except that if @reply_type is non-%NULL, then the
+ * reply to the call will be checked against it, and an error returned if it
+ * does not match.
+ *
+ * Returns: %NULL if @error is set. Otherwise a #GVariant tuple with
+ * return values. Free with g_variant_unref().
+ */
+GVariant *
+_nm_dbus_proxy_call_sync (GDBusProxy          *proxy,
+                          const gchar         *method_name,
+                          GVariant            *parameters,
+                          const GVariantType  *reply_type,
+                          GDBusCallFlags       flags,
+                          gint                 timeout_msec,
+                          GCancellable        *cancellable,
+                          GError             **error)
+{
+	GVariant *ret;
+
+	ret = g_dbus_proxy_call_sync (proxy, method_name, parameters,
+	                              flags, timeout_msec,
+	                              cancellable, error);
+	typecheck_response (&ret, reply_type, error);
+	return ret;
+}
+
+/**
+ * _nm_dbus_error_has_name:
+ * @error: (allow-none): a #GError, or %NULL
+ * @dbus_error_name: a D-Bus error name
+ *
+ * Checks if @error is set and corresponds to the D-Bus error @dbus_error_name.
+ *
+ * This should only be used for "foreign" D-Bus errors (eg, errors
+ * from BlueZ or wpa_supplicant). All NetworkManager D-Bus errors
+ * should be properly mapped by gdbus to one of the domains/codes in
+ * nm-errors.h.
+ *
+ * Returns: %TRUE or %FALSE
+ */
+gboolean
+_nm_dbus_error_has_name (GError     *error,
+                         const char *dbus_error_name)
+{
+	gboolean has_name = FALSE;
+
+	if (error && g_dbus_error_is_remote_error (error)) {
+		char *error_name;
+
+		error_name = g_dbus_error_get_remote_error (error);
+		has_name = !g_strcmp0 (error_name, dbus_error_name);
+		g_free (error_name);
+	}
+
+	return has_name;
+}
diff --git a/libnm-core/nm-errors.c b/libnm-core/nm-errors.c
index 222f2de6..4c950f69 100644
--- a/libnm-core/nm-errors.c
+++ b/libnm-core/nm-errors.c
@@ -21,10 +21,9 @@
 #include "config.h"
 
 #include <string.h>
-#include <gio/gio.h>
 
+#include "nm-default.h"
 #include "nm-errors.h"
-#include "nm-glib-compat.h"
 #include "nm-vpn-dbus-interface.h"
 #include "nm-core-internal.h"
 
diff --git a/libnm-core/nm-keyfile-internal.h b/libnm-core/nm-keyfile-internal.h
index f4bb0796..7873aa7c 100644
--- a/libnm-core/nm-keyfile-internal.h
+++ b/libnm-core/nm-keyfile-internal.h
@@ -22,13 +22,12 @@
 #ifndef __NM_KEYFILE_INTERNAL_H__
 #define __NM_KEYFILE_INTERNAL_H__
 
-#include <glib.h>
 #include <sys/types.h>
 
+#include "nm-default.h"
 #include "nm-connection.h"
 #include "nm-setting-8021x.h"
 
-
 /*********************************************************/
 
 #define NM_KEYFILE_CERT_SCHEME_PREFIX_BLOB "data:;base64,"
diff --git a/libnm-core/nm-keyfile-reader.c b/libnm-core/nm-keyfile-reader.c
index 9d8c8734..6a0584a5 100644
--- a/libnm-core/nm-keyfile-reader.c
+++ b/libnm-core/nm-keyfile-reader.c
@@ -28,16 +28,12 @@
 #include <sys/types.h>
 #include <arpa/inet.h>
 #include <string.h>
-#include <glib/gi18n-lib.h>
 
+#include "nm-default.h"
 #include "nm-core-internal.h"
 #include "nm-macros-internal.h"
-#include "gsystem-local-alloc.h"
-#include "nm-glib-compat.h"
 #include "nm-keyfile-internal.h"
 #include "nm-keyfile-utils.h"
-#include "nm-setting-private.h"
-
 
 typedef struct {
 	NMConnection *connection;
@@ -564,6 +560,28 @@ ip6_dns_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key)
 }
 
 static void
+ip6_addr_gen_mode_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key)
+{
+	NMSettingIP6ConfigAddrGenMode addr_gen_mode;
+	const char *setting_name = nm_setting_get_name (setting);
+	gs_free char *s = NULL;
+
+	s = nm_keyfile_plugin_kf_get_string (info->keyfile, setting_name, key, NULL);
+	if (s) {
+		if (!nm_utils_enum_from_str (nm_setting_ip6_config_addr_gen_mode_get_type (), s,
+		                             (int *) &addr_gen_mode, NULL)) {
+			handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN,
+			             _("invalid option '%s', use one of [%s]"),
+			             s, "eui64,stable-privacy");
+			return;
+		}
+	} else
+		addr_gen_mode = NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64;
+
+	g_object_set (G_OBJECT (setting), key, (gint) addr_gen_mode, NULL);
+}
+
+static void
 mac_address_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key, gsize enforce_length)
 {
 	const char *setting_name = nm_setting_get_name (setting);
@@ -1181,6 +1199,10 @@ static KeyParser key_parsers[] = {
 	  NM_SETTING_IP_CONFIG_DNS,
 	  FALSE,
 	  ip6_dns_parser },
+	{ NM_SETTING_IP6_CONFIG_SETTING_NAME,
+	  NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE,
+	  FALSE,
+	  ip6_addr_gen_mode_parser },
 	{ NM_SETTING_WIRED_SETTING_NAME,
 	  NM_SETTING_WIRED_MAC_ADDRESS,
 	  TRUE,
@@ -1257,8 +1279,13 @@ set_default_for_missing_key (NMSetting *setting, const char *property)
 {
 	/* Set a value different from the default value of the property's spec */
 
-	if (NM_IS_SETTING_VLAN (setting) && !strcmp (property, NM_SETTING_VLAN_FLAGS))
-		g_object_set (setting, property, 0, NULL);
+	if (NM_IS_SETTING_VLAN (setting)) {
+		if (!strcmp (property, NM_SETTING_VLAN_FLAGS))
+			g_object_set (setting, property, (NMVlanFlags) 0, NULL);
+	} else if (NM_IS_SETTING_WIRELESS (setting)) {
+		if (!strcmp (property, NM_SETTING_WIRELESS_MAC_ADDRESS_RANDOMIZATION))
+			g_object_set (setting, property, (NMSettingMacRandomization) NM_SETTING_MAC_RANDOMIZATION_NEVER, NULL);
+	}
 }
 
 static void
diff --git a/libnm-core/nm-keyfile-utils.c b/libnm-core/nm-keyfile-utils.c
index d04a3d1b..15b14a3e 100644
--- a/libnm-core/nm-keyfile-utils.c
+++ b/libnm-core/nm-keyfile-utils.c
@@ -20,18 +20,16 @@
 
 #include "config.h"
 
-#include <glib.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include "gsystem-local-alloc.h"
+#include "nm-default.h"
 #include "nm-keyfile-utils.h"
 #include "nm-keyfile-internal.h"
 #include "nm-setting-wired.h"
 #include "nm-setting-wireless.h"
 #include "nm-setting-wireless-security.h"
 
-
 typedef struct {
 	const char *setting;
 	const char *alias;
diff --git a/libnm-core/nm-keyfile-writer.c b/libnm-core/nm-keyfile-writer.c
index 1dac5c32..ba1736b9 100644
--- a/libnm-core/nm-keyfile-writer.c
+++ b/libnm-core/nm-keyfile-writer.c
@@ -28,11 +28,8 @@
 #include <errno.h>
 #include <arpa/inet.h>
 #include <string.h>
-#include <glib/gi18n-lib.h>
 
 #include "nm-core-internal.h"
-#include "gsystem-local-alloc.h"
-#include "nm-glib-compat.h"
 #include "nm-keyfile-internal.h"
 #include "nm-keyfile-utils.h"
 
@@ -106,6 +103,24 @@ dns_writer (KeyfileWriterInfo *info,
 }
 
 static void
+ip6_addr_gen_mode_writer (KeyfileWriterInfo *info,
+                          NMSetting *setting,
+                          const char *key,
+                          const GValue *value)
+{
+	NMSettingIP6ConfigAddrGenMode addr_gen_mode;
+	gs_free char *str = NULL;
+
+	addr_gen_mode = (NMSettingIP6ConfigAddrGenMode) g_value_get_int (value);
+	str = nm_utils_enum_to_str (nm_setting_ip6_config_addr_gen_mode_get_type (),
+	                            addr_gen_mode);
+	nm_keyfile_plugin_kf_set_string (info->keyfile,
+	                                 nm_setting_get_name (setting),
+	                                 key,
+	                                 str);
+}
+
+static void
 write_ip_values (GKeyFile *file,
                  const char *setting_name,
                  GPtrArray *array,
@@ -560,6 +575,9 @@ static KeyWriter key_writers[] = {
 	{ NM_SETTING_IP6_CONFIG_SETTING_NAME,
 	  NM_SETTING_IP_CONFIG_DNS,
 	  dns_writer },
+	{ NM_SETTING_IP6_CONFIG_SETTING_NAME,
+	  NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE,
+	  ip6_addr_gen_mode_writer },
 	{ NM_SETTING_WIRELESS_SETTING_NAME,
 	  NM_SETTING_WIRELESS_SSID,
 	  ssid_writer },
@@ -590,8 +608,16 @@ static KeyWriter key_writers[] = {
 static gboolean
 can_omit_default_value (NMSetting *setting, const char *property)
 {
-	if (NM_IS_SETTING_VLAN (setting) && !strcmp (property, NM_SETTING_VLAN_FLAGS))
-		return FALSE;
+	if (NM_IS_SETTING_VLAN (setting)) {
+		if (!strcmp (property, NM_SETTING_VLAN_FLAGS))
+			return FALSE;
+	} else if (NM_IS_SETTING_IP6_CONFIG (setting)) {
+		if (!strcmp (property, NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE))
+			return FALSE;
+	} else if (NM_IS_SETTING_WIRELESS (setting)) {
+		if (!strcmp (property, NM_SETTING_WIRELESS_MAC_ADDRESS_RANDOMIZATION))
+			return FALSE;
+	}
 
 	return TRUE;
 }
diff --git a/libnm-core/nm-property-compare.c b/libnm-core/nm-property-compare.c
index 5d270706..d244f745 100644
--- a/libnm-core/nm-property-compare.c
+++ b/libnm-core/nm-property-compare.c
@@ -22,13 +22,12 @@
 
 #include "config.h"
 
-#include "nm-property-compare.h"
-#include "nm-glib-compat.h"
-
 #include <string.h>
 #include <math.h>
 #include <netinet/in.h>
-#include <gio/gio.h>
+
+#include "nm-property-compare.h"
+#include "nm-default.h"
 
 static gint
 _nm_property_compare_collection (GVariant *value1, GVariant *value2)
diff --git a/libnm-core/nm-property-compare.h b/libnm-core/nm-property-compare.h
index 33016787..3f105818 100644
--- a/libnm-core/nm-property-compare.h
+++ b/libnm-core/nm-property-compare.h
@@ -23,7 +23,7 @@
 #ifndef __NM_PROPERTY_COMPARE_H__
 #define __NM_PROPERTY_COMPARE_H__
 
-#include <glib.h>
+#include "nm-default.h"
 
 int nm_property_compare (GVariant *value1, GVariant *value2);
 
diff --git a/libnm-core/nm-setting-8021x.c b/libnm-core/nm-setting-8021x.c
index d53ae43b..cd0d4e66 100644
--- a/libnm-core/nm-setting-8021x.c
+++ b/libnm-core/nm-setting-8021x.c
@@ -23,8 +23,8 @@
 #include "config.h"
 
 #include <string.h>
-#include <glib/gi18n-lib.h>
 
+#include "nm-default.h"
 #include "nm-setting-8021x.h"
 #include "nm-utils.h"
 #include "crypto.h"
@@ -32,7 +32,6 @@
 #include "nm-setting-private.h"
 #include "nm-core-enum-types.h"
 #include "nm-macros-internal.h"
-#include "gsystem-local-alloc.h"
 
 /**
  * SECTION:nm-setting-8021x
@@ -429,6 +428,8 @@ get_cert_scheme (GBytes *bytes, GError **error)
  *
  * Returns: the scheme of the blob or %NM_SETTING_802_1X_CK_SCHEME_UNKNOWN.
  * For NULL it also returns NM_SETTING_802_1X_CK_SCHEME_UNKNOWN.
+ *
+ * Since: 1.2
  **/
 NMSetting8021xCKScheme
 nm_setting_802_1x_check_cert_scheme (gconstpointer pdata, gsize length, GError **error)
diff --git a/libnm-core/nm-setting-8021x.h b/libnm-core/nm-setting-8021x.h
index 3099fbd1..da86071a 100644
--- a/libnm-core/nm-setting-8021x.h
+++ b/libnm-core/nm-setting-8021x.h
@@ -149,6 +149,9 @@ GType nm_setting_802_1x_get_type (void);
 
 NMSetting *nm_setting_802_1x_new (void);
 
+NM_AVAILABLE_IN_1_2
+NMSetting8021xCKScheme nm_setting_802_1x_check_cert_scheme (gconstpointer pdata, gsize length, GError **error);
+
 guint32           nm_setting_802_1x_get_num_eap_methods              (NMSetting8021x *setting);
 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);
diff --git a/libnm-core/nm-setting-adsl.c b/libnm-core/nm-setting-adsl.c
index 7d78f060..0cf386d8 100644
--- a/libnm-core/nm-setting-adsl.c
+++ b/libnm-core/nm-setting-adsl.c
@@ -22,7 +22,6 @@
 #include "config.h"
 
 #include <string.h>
-#include <glib/gi18n-lib.h>
 
 #include "nm-setting-adsl.h"
 #include "nm-setting-ppp.h"
@@ -227,6 +226,15 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
 	return TRUE;
 }
 
+static gboolean
+verify_secrets (NMSetting *setting, NMConnection *connection, GError **error)
+{
+	return _nm_setting_verify_secret_string (NM_SETTING_ADSL_GET_PRIVATE (setting)->password,
+	                                         NM_SETTING_ADSL_SETTING_NAME,
+	                                         NM_SETTING_ADSL_PASSWORD,
+	                                         error);
+}
+
 static GPtrArray *
 need_secrets (NMSetting *setting)
 {
@@ -350,6 +358,7 @@ nm_setting_adsl_class_init (NMSettingAdslClass *setting_class)
 	object_class->get_property = get_property;
 	object_class->finalize     = finalize;
 	parent_class->verify       = verify;
+	parent_class->verify_secrets = verify_secrets;
 	parent_class->need_secrets = need_secrets;
 
 	/* Properties */
diff --git a/libnm-core/nm-setting-bluetooth.c b/libnm-core/nm-setting-bluetooth.c
index 41a0b4c2..864a91cc 100644
--- a/libnm-core/nm-setting-bluetooth.c
+++ b/libnm-core/nm-setting-bluetooth.c
@@ -24,7 +24,6 @@
 
 #include <string.h>
 #include <net/ethernet.h>
-#include <glib/gi18n-lib.h>
 
 #include "nm-setting-bluetooth.h"
 #include "nm-setting-cdma.h"
diff --git a/libnm-core/nm-setting-bond.c b/libnm-core/nm-setting-bond.c
index 5441a090..1c377584 100644
--- a/libnm-core/nm-setting-bond.c
+++ b/libnm-core/nm-setting-bond.c
@@ -26,7 +26,6 @@
 #include <errno.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
-#include <glib/gi18n-lib.h>
 
 #include "nm-setting-bond.h"
 #include "nm-utils.h"
diff --git a/libnm-core/nm-setting-bridge-port.c b/libnm-core/nm-setting-bridge-port.c
index 763af37b..a02b8de1 100644
--- a/libnm-core/nm-setting-bridge-port.c
+++ b/libnm-core/nm-setting-bridge-port.c
@@ -24,7 +24,6 @@
 #include <string.h>
 #include <ctype.h>
 #include <stdlib.h>
-#include <glib/gi18n-lib.h>
 
 #include "nm-setting-bridge-port.h"
 #include "nm-utils.h"
diff --git a/libnm-core/nm-setting-bridge.c b/libnm-core/nm-setting-bridge.c
index d00271b7..7915e730 100644
--- a/libnm-core/nm-setting-bridge.c
+++ b/libnm-core/nm-setting-bridge.c
@@ -24,7 +24,6 @@
 #include <string.h>
 #include <ctype.h>
 #include <stdlib.h>
-#include <glib/gi18n-lib.h>
 
 #include "nm-setting-bridge.h"
 #include "nm-connection-private.h"
@@ -53,6 +52,7 @@ typedef struct {
 	guint16  hello_time;
 	guint16  max_age;
 	guint32  ageing_time;
+	gboolean multicast_snooping;
 } NMSettingBridgePrivate;
 
 enum {
@@ -64,6 +64,7 @@ enum {
 	PROP_HELLO_TIME,
 	PROP_MAX_AGE,
 	PROP_AGEING_TIME,
+	PROP_MULTICAST_SNOOPING,
 	LAST_PROP
 };
 
@@ -178,6 +179,22 @@ nm_setting_bridge_get_ageing_time (NMSettingBridge *setting)
 	return NM_SETTING_BRIDGE_GET_PRIVATE (setting)->ageing_time;
 }
 
+/**
+ * nm_setting_bridge_get_multicast_snooping:
+ * @setting: the #NMSettingBridge
+ *
+ * Returns: the #NMSettingBridge:multicast-snooping property of the setting
+ *
+ * Since: 1.2
+ **/
+gboolean
+nm_setting_bridge_get_multicast_snooping (NMSettingBridge *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_BRIDGE (setting), FALSE);
+
+	return NM_SETTING_BRIDGE_GET_PRIVATE (setting)->multicast_snooping;
+}
+
 /* IEEE 802.1D-1998 timer values */
 #define BR_MIN_HELLO_TIME    1
 #define BR_MAX_HELLO_TIME    10
@@ -309,6 +326,9 @@ set_property (GObject *object, guint prop_id,
 	case PROP_AGEING_TIME:
 		priv->ageing_time = g_value_get_uint (value);
 		break;
+	case PROP_MULTICAST_SNOOPING:
+		priv->multicast_snooping = g_value_get_boolean (value);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -344,6 +364,9 @@ get_property (GObject *object, guint prop_id,
 	case PROP_AGEING_TIME:
 		g_value_set_uint (value, priv->ageing_time);
 		break;
+	case PROP_MULTICAST_SNOOPING:
+		g_value_set_boolean (value, priv->multicast_snooping);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -533,6 +556,33 @@ nm_setting_bridge_class_init (NMSettingBridgeClass *setting_class)
 		                    NM_SETTING_PARAM_INFERRABLE |
 		                    G_PARAM_STATIC_STRINGS));
 
+	/**
+	 * NMSettingBridge:multicast-snooping:
+	 *
+	 * Controls whether IGMP snooping is enabled for this bridge.
+	 * Note that if snooping was automatically disabled due to hash collisions,
+	 * the system may refuse to enable the feature until the collisions are
+	 * resolved.
+	 *
+	 * Since: 1.2
+	 **/
+	/* ---ifcfg-rh---
+	 * property: multicast-snooping
+	 * variable: BRIDGING_OPTS: multicast_snooping=
+	 * values: 0 or 1
+	 * default: 1
+	 * description: IGMP snooping support.
+	 * ---end---
+	 */
+	g_object_class_install_property
+		(object_class, PROP_MULTICAST_SNOOPING,
+		 g_param_spec_boolean (NM_SETTING_BRIDGE_MULTICAST_SNOOPING, "", "",
+		                       TRUE,
+		                       G_PARAM_READWRITE |
+		                       G_PARAM_CONSTRUCT |
+		                       NM_SETTING_PARAM_INFERRABLE |
+		                       G_PARAM_STATIC_STRINGS));
+
 	/* ---dbus---
 	 * property: interface-name
 	 * format: string
diff --git a/libnm-core/nm-setting-bridge.h b/libnm-core/nm-setting-bridge.h
index b4fe7477..020d6db6 100644
--- a/libnm-core/nm-setting-bridge.h
+++ b/libnm-core/nm-setting-bridge.h
@@ -16,7 +16,7 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * Copyright 2011 - 2012 Red Hat, Inc.
+ * Copyright 2011 - 2015 Red Hat, Inc.
  */
 
 #ifndef __NM_SETTING_BRIDGE_H__
@@ -46,6 +46,7 @@ G_BEGIN_DECLS
 #define NM_SETTING_BRIDGE_HELLO_TIME     "hello-time"
 #define NM_SETTING_BRIDGE_MAX_AGE        "max-age"
 #define NM_SETTING_BRIDGE_AGEING_TIME    "ageing-time"
+#define NM_SETTING_BRIDGE_MULTICAST_SNOOPING "multicast-snooping"
 
 struct _NMSettingBridge {
 	NMSetting parent;
@@ -76,6 +77,8 @@ guint16      nm_setting_bridge_get_max_age        (NMSettingBridge *setting);
 
 guint32      nm_setting_bridge_get_ageing_time    (NMSettingBridge *setting);
 
+gboolean     nm_setting_bridge_get_multicast_snooping (NMSettingBridge *setting);
+
 G_END_DECLS
 
 #endif /* __NM_SETTING_BRIDGE_H__ */
diff --git a/libnm-core/nm-setting-cdma.c b/libnm-core/nm-setting-cdma.c
index 6fd2ad8b..3c01b43f 100644
--- a/libnm-core/nm-setting-cdma.c
+++ b/libnm-core/nm-setting-cdma.c
@@ -22,7 +22,6 @@
 #include "config.h"
 
 #include <string.h>
-#include <glib/gi18n-lib.h>
 
 #include "nm-setting-cdma.h"
 #include "nm-utils.h"
@@ -163,6 +162,15 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
 	return TRUE;
 }
 
+static gboolean
+verify_secrets (NMSetting *setting, NMConnection *connection, GError **error)
+{
+	return _nm_setting_verify_secret_string (NM_SETTING_CDMA_GET_PRIVATE (setting)->password,
+	                                         NM_SETTING_CDMA_SETTING_NAME,
+	                                         NM_SETTING_CDMA_PASSWORD,
+	                                         error);
+}
+
 static GPtrArray *
 need_secrets (NMSetting *setting)
 {
@@ -265,6 +273,7 @@ nm_setting_cdma_class_init (NMSettingCdmaClass *setting_class)
 	object_class->get_property = get_property;
 	object_class->finalize     = finalize;
 	parent_class->verify       = verify;
+	parent_class->verify_secrets = verify_secrets;
 	parent_class->need_secrets = need_secrets;
 
 	/* Properties */
diff --git a/libnm-core/nm-setting-connection.c b/libnm-core/nm-setting-connection.c
index 28e590df..f341a398 100644
--- a/libnm-core/nm-setting-connection.c
+++ b/libnm-core/nm-setting-connection.c
@@ -23,7 +23,6 @@
 #include "config.h"
 
 #include <string.h>
-#include <glib/gi18n-lib.h>
 
 #include "nm-utils.h"
 #include "nm-utils-private.h"
@@ -34,6 +33,7 @@
 #include "nm-setting-bridge.h"
 #include "nm-setting-team.h"
 #include "nm-setting-vlan.h"
+#include "nm-macros-internal.h"
 
 /**
  * SECTION:nm-setting-connection
@@ -77,6 +77,7 @@ typedef struct {
 	GSList *secondaries; /* secondary connections to activate with the base connection */
 	guint gateway_ping_timeout;
 	NMMetered metered;
+	NMSettingConnectionLldp lldp;
 } NMSettingConnectionPrivate;
 
 enum {
@@ -97,6 +98,7 @@ enum {
 	PROP_SECONDARIES,
 	PROP_GATEWAY_PING_TIMEOUT,
 	PROP_METERED,
+	PROP_LLDP,
 
 	LAST_PROP
 };
@@ -616,7 +618,7 @@ nm_setting_connection_is_slave_type (NMSettingConnection *setting,
  * Returns: whether slaves of the connection should be activated together
  *          with the connection.
  *
- * Since: 1.0.4
+ * Since: 1.2
  **/
 NMSettingConnectionAutoconnectSlaves
 nm_setting_connection_get_autoconnect_slaves (NMSettingConnection *setting)
@@ -625,6 +627,9 @@ nm_setting_connection_get_autoconnect_slaves (NMSettingConnection *setting)
 
 	return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->autoconnect_slaves;
 }
+NM_BACKPORT_SYMBOL (libnm_1_0_4, NMSettingConnectionAutoconnectSlaves, nm_setting_connection_get_autoconnect_slaves, (NMSettingConnection *setting), (setting));
+
+NM_BACKPORT_SYMBOL (libnm_1_0_4, GType, nm_setting_connection_autoconnect_slaves_get_type, (void), ());
 
 /**
  * nm_setting_connection_get_num_secondaries:
@@ -768,7 +773,7 @@ nm_setting_connection_get_gateway_ping_timeout (NMSettingConnection *setting)
  *
  * Returns: the #NMSettingConnection:metered property of the setting.
  *
- * Since: 1.0.6
+ * Since: 1.2
  **/
 NMMetered
 nm_setting_connection_get_metered (NMSettingConnection *setting)
@@ -779,6 +784,29 @@ nm_setting_connection_get_metered (NMSettingConnection *setting)
 	return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->metered;
 }
 
+NM_BACKPORT_SYMBOL (libnm_1_0_6, NMMetered, nm_setting_connection_get_metered, (NMSettingConnection *setting), (setting));
+
+NM_BACKPORT_SYMBOL (libnm_1_0_6, GType, nm_metered_get_type, (void), ());
+
+/**
+ * nm_setting_connection_get_lldp:
+ * @setting: the #NMSettingConnection
+ *
+ * Returns the #NMSettingConnection:lldp property of the connection.
+ *
+ * Returns: a %NMSettingConnectionLldp which indicates whether LLDP must be
+ * enabled for the connection.
+ *
+ * Since: 1.2
+ **/
+NMSettingConnectionLldp
+nm_setting_connection_get_lldp (NMSettingConnection *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), NM_SETTING_CONNECTION_LLDP_DEFAULT);
+
+	return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->lldp;
+}
+
 static void
 _set_error_missing_base_setting (GError **error, const char *type)
 {
@@ -1188,6 +1216,9 @@ set_property (GObject *object, guint prop_id,
 	case PROP_METERED:
 		priv->metered = g_value_get_enum (value);
 		break;
+	case PROP_LLDP:
+		priv->lldp = g_value_get_int (value);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -1264,6 +1295,9 @@ get_property (GObject *object, guint prop_id,
 	case PROP_METERED:
 		g_value_set_enum (value, priv->metered);
 		break;
+	case PROP_LLDP:
+		g_value_set_int (value, priv->lldp);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -1525,6 +1559,9 @@ nm_setting_connection_class_init (NMSettingConnectionClass *setting_class)
 	 * (for example "Home", "Work", "Public").  %NULL or unspecified zone means
 	 * the connection will be placed in the default zone as defined by the
 	 * firewall.
+	 *
+	 * When updating this property on a currently activated connection,
+	 * the change takes effect immediately.
 	 **/
 	/* ---ifcfg-rh---
 	 * property: zone
@@ -1541,6 +1578,7 @@ nm_setting_connection_class_init (NMSettingConnectionClass *setting_class)
 		                      G_PARAM_READWRITE |
 		                      G_PARAM_CONSTRUCT |
 		                      NM_SETTING_PARAM_FUZZY_IGNORE |
+		                      NM_SETTING_PARAM_REAPPLY_IMMEDIATELY |
 		                      G_PARAM_STATIC_STRINGS));
 
 	/**
@@ -1599,7 +1637,7 @@ nm_setting_connection_class_init (NMSettingConnectionClass *setting_class)
 	 * If -1 (default) is set, global connection.autoconnect-slaves is read to
 	 * determine the real value. If it is default as well, this fallbacks to 0.
 	 *
-	 * Since: 1.0.4
+	 * Since: 1.2
 	 **/
 	/* ---ifcfg-rh---
 	 * property: autoconnect-slaves
@@ -1669,7 +1707,10 @@ nm_setting_connection_class_init (NMSettingConnectionClass *setting_class)
 	 *
 	 * Whether the connection is metered.
 	 *
-	 * Since: 1.0.6
+	 * When updating this property on a currently activated connection,
+	 * the change takes effect immediately.
+	 *
+	 * Since: 1.2
 	 **/
 	/* ---ifcfg-rh---
 	 * property: metered
@@ -1685,5 +1726,31 @@ nm_setting_connection_class_init (NMSettingConnectionClass *setting_class)
 		                    NM_TYPE_METERED,
 		                    NM_METERED_UNKNOWN,
 		                    G_PARAM_READWRITE |
+		                    NM_SETTING_PARAM_REAPPLY_IMMEDIATELY |
 		                    G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMSettingConnection:lldp:
+	 *
+	 * Whether LLDP is enabled for the connection.
+	 *
+	 * Since: 1.2
+	 **/
+	/* ---ifcfg-rh---
+	 * property: lldp
+	 * variable: LLDP
+	 * values: boolean value or 'rx'
+	 * default: missing variable means global default
+	 * description: whether LLDP is enabled for the connection
+	 * example: LLDP=no
+	 * ---end---
+	 */
+	g_object_class_install_property
+		(object_class, PROP_LLDP,
+		 g_param_spec_int (NM_SETTING_CONNECTION_LLDP, "", "",
+		                   G_MININT32, G_MAXINT32, NM_SETTING_CONNECTION_LLDP_DEFAULT,
+		                   NM_SETTING_PARAM_FUZZY_IGNORE |
+		                   G_PARAM_READWRITE |
+		                   G_PARAM_CONSTRUCT |
+		                   G_PARAM_STATIC_STRINGS));
 }
diff --git a/libnm-core/nm-setting-connection.h b/libnm-core/nm-setting-connection.h
index 24b5f6ac..0d4966f0 100644
--- a/libnm-core/nm-setting-connection.h
+++ b/libnm-core/nm-setting-connection.h
@@ -60,6 +60,7 @@ G_BEGIN_DECLS
 #define NM_SETTING_CONNECTION_SECONDARIES    "secondaries"
 #define NM_SETTING_CONNECTION_GATEWAY_PING_TIMEOUT "gateway-ping-timeout"
 #define NM_SETTING_CONNECTION_METERED        "metered"
+#define NM_SETTING_CONNECTION_LLDP           "lldp"
 
 /* Types for property values */
 /**
@@ -73,13 +74,25 @@ G_BEGIN_DECLS
  * #NMSettingConnectionAutoconnectSlaves values indicate whether slave connections
  * should be activated when master is activated.
  */
-NM_AVAILABLE_IN_1_0_4
 typedef enum {
 	NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_DEFAULT = -1,
 	NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_NO = 0,
 	NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_YES = 1,
 } NMSettingConnectionAutoconnectSlaves;
 
+/**
+ * NMSettingConnectionLldp:
+ * @NM_SETTING_CONNECTION_LLDP_DEFAULT: default value
+ * @NM_SETTING_CONNECTION_LLDP_DISABLE: disable LLDP
+ * @NM_SETTING_CONNECTION_LLDP_ENABLE_RX: enable reception of LLDP frames
+ *
+ * #NMSettingConnectionLldp values indicate whether LLDP should be enabled.
+ */
+typedef enum {
+	NM_SETTING_CONNECTION_LLDP_DEFAULT = -1,
+	NM_SETTING_CONNECTION_LLDP_DISABLE = 0,
+	NM_SETTING_CONNECTION_LLDP_ENABLE_RX = 1,
+} NMSettingConnectionLldp;
 
 /**
  * NMSettingConnection:
@@ -133,7 +146,7 @@ const char *nm_setting_connection_get_master           (NMSettingConnection *set
 gboolean    nm_setting_connection_is_slave_type        (NMSettingConnection *setting,
                                                         const char *type);
 const char *nm_setting_connection_get_slave_type       (NMSettingConnection *setting);
-NM_AVAILABLE_IN_1_0_4
+NM_AVAILABLE_IN_1_2
 NMSettingConnectionAutoconnectSlaves nm_setting_connection_get_autoconnect_slaves (NMSettingConnection *setting);
 
 guint32     nm_setting_connection_get_num_secondaries  (NMSettingConnection *setting);
@@ -143,8 +156,10 @@ void        nm_setting_connection_remove_secondary     (NMSettingConnection *set
 gboolean    nm_setting_connection_remove_secondary_by_value (NMSettingConnection *setting, const char *sec_uuid);
 
 guint32     nm_setting_connection_get_gateway_ping_timeout (NMSettingConnection *setting);
-NM_AVAILABLE_IN_1_0_6
+NM_AVAILABLE_IN_1_2
 NMMetered   nm_setting_connection_get_metered (NMSettingConnection *setting);
+NM_AVAILABLE_IN_1_2
+NMSettingConnectionLldp nm_setting_connection_get_lldp (NMSettingConnection *setting);
 
 G_END_DECLS
 
diff --git a/libnm-core/nm-setting-dcb.c b/libnm-core/nm-setting-dcb.c
index 915cc41f..89675810 100644
--- a/libnm-core/nm-setting-dcb.c
+++ b/libnm-core/nm-setting-dcb.c
@@ -22,7 +22,6 @@
 #include "config.h"
 
 #include <string.h>
-#include <glib/gi18n-lib.h>
 
 #include "nm-setting-dcb.h"
 #include "nm-utils.h"
diff --git a/libnm-core/nm-setting-gsm.c b/libnm-core/nm-setting-gsm.c
index 36557a25..4bb5ba9f 100644
--- a/libnm-core/nm-setting-gsm.c
+++ b/libnm-core/nm-setting-gsm.c
@@ -23,7 +23,6 @@
 #include "config.h"
 
 #include <string.h>
-#include <glib/gi18n-lib.h>
 
 #include "nm-setting-gsm.h"
 #include "nm-utils.h"
@@ -51,6 +50,11 @@ typedef struct {
 	char *password;
 	NMSettingSecretFlags password_flags;
 
+	/* Restrict connection to certain devices or SIMs */
+	char *device_id;
+	char *sim_id;
+	char *sim_operator_id;
+
 	char *apn; /* NULL for dynamic */
 	char *network_id; /* for manual registration or NULL for automatic */
 
@@ -71,6 +75,9 @@ enum {
 	PROP_PIN,
 	PROP_PIN_FLAGS,
 	PROP_HOME_ONLY,
+	PROP_DEVICE_ID,
+	PROP_SIM_ID,
+	PROP_SIM_OPERATOR_ID,
 
 	LAST_PROP
 };
@@ -214,6 +221,54 @@ nm_setting_gsm_get_home_only (NMSettingGsm *setting)
 	return NM_SETTING_GSM_GET_PRIVATE (setting)->home_only;
 }
 
+/**
+ * nm_setting_gsm_get_device_id:
+ * @setting: the #NMSettingGsm
+ *
+ * Returns: the #NMSettingGsm:device-id property of the setting
+ *
+ * Since: 1.2
+ **/
+const char *
+nm_setting_gsm_get_device_id (NMSettingGsm *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_GSM (setting), NULL);
+
+	return NM_SETTING_GSM_GET_PRIVATE (setting)->device_id;
+}
+
+/**
+ * nm_setting_gsm_get_sim_id:
+ * @setting: the #NMSettingGsm
+ *
+ * Returns: the #NMSettingGsm:sim-id property of the setting
+ *
+ * Since: 1.2
+ **/
+const char *
+nm_setting_gsm_get_sim_id (NMSettingGsm *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_GSM (setting), NULL);
+
+	return NM_SETTING_GSM_GET_PRIVATE (setting)->sim_id;
+}
+
+/**
+ * nm_setting_gsm_get_sim_operator_id:
+ * @setting: the #NMSettingGsm
+ *
+ * Returns: the #NMSettingGsm:sim-operator-id property of the setting
+ *
+ * Since: 1.2
+ **/
+const char *
+nm_setting_gsm_get_sim_operator_id (NMSettingGsm *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_GSM (setting), NULL);
+
+	return NM_SETTING_GSM_GET_PRIVATE (setting)->sim_operator_id;
+}
+
 static gboolean
 verify (NMSetting *setting, NMConnection *connection, GError **error)
 {
@@ -313,9 +368,61 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
 		}
 	}
 
+	if (priv->device_id && !priv->device_id[0]) {
+		g_set_error_literal (error,
+		                     NM_CONNECTION_ERROR,
+		                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
+		                     _("property is empty"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_GSM_SETTING_NAME, NM_SETTING_GSM_DEVICE_ID);
+		return FALSE;
+	}
+
+	if (priv->sim_id && !priv->sim_id[0]) {
+		g_set_error_literal (error,
+		                     NM_CONNECTION_ERROR,
+		                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
+		                     _("property is empty"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_GSM_SETTING_NAME, NM_SETTING_GSM_SIM_ID);
+		return FALSE;
+	}
+
+	if (priv->sim_operator_id) {
+		size_t len = strlen (priv->sim_operator_id);
+		const char *p = priv->sim_operator_id;
+
+		if (len == 0 || (len != 5 && len != 6)) {
+			g_set_error_literal (error,
+			                     NM_CONNECTION_ERROR,
+			                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
+			                     _("property is empty or wrong size"));
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_GSM_SETTING_NAME, NM_SETTING_GSM_SIM_OPERATOR_ID);
+			return FALSE;
+		}
+
+		while (p && *p) {
+			if (!g_ascii_isdigit (*p++)) {
+				g_set_error_literal (error,
+				                     NM_CONNECTION_ERROR,
+				                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
+				                     _("property must contain only digits"));
+				g_prefix_error (error, "%s.%s: ", NM_SETTING_GSM_SETTING_NAME, NM_SETTING_GSM_SIM_OPERATOR_ID);
+				return FALSE;
+			}
+		}
+	}
+
 	return TRUE;
 }
 
+static gboolean
+verify_secrets (NMSetting *setting, NMConnection *connection, GError **error)
+{
+	return _nm_setting_verify_secret_string (NM_SETTING_GSM_GET_PRIVATE (setting)->password,
+	                                         NM_SETTING_GSM_SETTING_NAME,
+	                                         NM_SETTING_GSM_PASSWORD,
+	                                         error);
+}
+
 static GPtrArray *
 need_secrets (NMSetting *setting)
 {
@@ -351,6 +458,9 @@ finalize (GObject *object)
 	g_free (priv->apn);
 	g_free (priv->network_id);
 	g_free (priv->pin);
+	g_free (priv->device_id);
+	g_free (priv->sim_id);
+	g_free (priv->sim_operator_id);
 
 	G_OBJECT_CLASS (nm_setting_gsm_parent_class)->finalize (object);
 }
@@ -402,6 +512,18 @@ set_property (GObject *object, guint prop_id,
 	case PROP_HOME_ONLY:
 		priv->home_only = g_value_get_boolean (value);
 		break;
+	case PROP_DEVICE_ID:
+		g_free (priv->device_id);
+		priv->device_id = g_value_dup_string (value);
+		break;
+	case PROP_SIM_ID:
+		g_free (priv->sim_id);
+		priv->sim_id = g_value_dup_string (value);
+		break;
+	case PROP_SIM_OPERATOR_ID:
+		g_free (priv->sim_operator_id);
+		priv->sim_operator_id = g_value_dup_string (value);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -442,6 +564,15 @@ get_property (GObject *object, guint prop_id,
 	case PROP_HOME_ONLY:
 		g_value_set_boolean (value, nm_setting_gsm_get_home_only (setting));
 		break;
+	case PROP_DEVICE_ID:
+		g_value_set_string (value, nm_setting_gsm_get_device_id (setting));
+		break;
+	case PROP_SIM_ID:
+		g_value_set_string (value, nm_setting_gsm_get_sim_id (setting));
+		break;
+	case PROP_SIM_OPERATOR_ID:
+		g_value_set_string (value, nm_setting_gsm_get_sim_operator_id (setting));
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -461,6 +592,7 @@ nm_setting_gsm_class_init (NMSettingGsmClass *setting_class)
 	object_class->get_property = get_property;
 	object_class->finalize     = finalize;
 	parent_class->verify       = verify;
+	parent_class->verify_secrets = verify_secrets;
 	parent_class->need_secrets = need_secrets;
 
 	/* Properties */
@@ -597,6 +729,57 @@ nm_setting_gsm_class_init (NMSettingGsmClass *setting_class)
 		                       G_PARAM_READWRITE |
 		                       G_PARAM_STATIC_STRINGS));
 
+	/**
+	 * NMSettingGsm:device-id:
+	 *
+	 * The device unique identifier (as given by the WWAN management service)
+	 * which this connection applies to.  If given, the connection will only
+	 * apply to the specified device.
+	 *
+	 * Since: 1.2
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_DEVICE_ID,
+		 g_param_spec_string (NM_SETTING_GSM_DEVICE_ID, "", "",
+		                      NULL,
+		                      G_PARAM_READWRITE |
+		                      G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMSettingGsm:sim-id:
+	 *
+	 * The SIM card unique identifier (as given by the WWAN management service)
+	 * which this connection applies to.  If given, the connection will apply
+	 * to any device also allowed by #NMSettingGsm:device-id which contains a
+	 * SIM card matching the given identifier.
+	 *
+	 * Since: 1.2
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_SIM_ID,
+		 g_param_spec_string (NM_SETTING_GSM_SIM_ID, "", "",
+		                      NULL,
+		                      G_PARAM_READWRITE |
+		                      G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMSettingGsm:sim-operator-id:
+	 *
+	 * A MCC/MNC string like "310260" or "21601" identifying the specific
+	 * mobile network operator which this connection applies to.  If given,
+	 * the connection will apply to any device also allowed by
+	 * #NMSettingGsm:device-id and #NMSettingGsm:sim-id which contains a SIM
+	 * card provisioined by the given operator.
+	 *
+	 * Since: 1.2
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_SIM_OPERATOR_ID,
+		 g_param_spec_string (NM_SETTING_GSM_SIM_OPERATOR_ID, "", "",
+		                      NULL,
+		                      G_PARAM_READWRITE |
+		                      G_PARAM_STATIC_STRINGS));
+
 	/* Ignore incoming deprecated properties */
 	_nm_setting_class_add_dbus_only_property (parent_class, "allowed-bands",
 	                                          G_VARIANT_TYPE_UINT32,
diff --git a/libnm-core/nm-setting-gsm.h b/libnm-core/nm-setting-gsm.h
index 90756738..2dfe73fa 100644
--- a/libnm-core/nm-setting-gsm.h
+++ b/libnm-core/nm-setting-gsm.h
@@ -40,15 +40,18 @@ G_BEGIN_DECLS
 
 #define NM_SETTING_GSM_SETTING_NAME "gsm"
 
-#define NM_SETTING_GSM_NUMBER         "number"
-#define NM_SETTING_GSM_USERNAME       "username"
-#define NM_SETTING_GSM_PASSWORD       "password"
-#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_PIN            "pin"
-#define NM_SETTING_GSM_PIN_FLAGS      "pin-flags"
-#define NM_SETTING_GSM_HOME_ONLY      "home-only"
+#define NM_SETTING_GSM_NUMBER          "number"
+#define NM_SETTING_GSM_USERNAME        "username"
+#define NM_SETTING_GSM_PASSWORD        "password"
+#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_PIN             "pin"
+#define NM_SETTING_GSM_PIN_FLAGS       "pin-flags"
+#define NM_SETTING_GSM_HOME_ONLY       "home-only"
+#define NM_SETTING_GSM_DEVICE_ID       "device-id"
+#define NM_SETTING_GSM_SIM_ID          "sim-id"
+#define NM_SETTING_GSM_SIM_OPERATOR_ID "sim-operator-id"
 
 struct _NMSettingGsm {
 	NMSetting parent;
@@ -63,14 +66,21 @@ typedef struct {
 
 GType nm_setting_gsm_get_type (void);
 
-NMSetting *nm_setting_gsm_new                (void);
-const char *nm_setting_gsm_get_number        (NMSettingGsm *setting);
-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);
-const char *nm_setting_gsm_get_pin           (NMSettingGsm *setting);
-gboolean    nm_setting_gsm_get_home_only     (NMSettingGsm *setting);
+NMSetting *nm_setting_gsm_new                  (void);
+const char *nm_setting_gsm_get_number          (NMSettingGsm *setting);
+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);
+const char *nm_setting_gsm_get_pin             (NMSettingGsm *setting);
+gboolean    nm_setting_gsm_get_home_only       (NMSettingGsm *setting);
+
+NM_AVAILABLE_IN_1_2
+const char *nm_setting_gsm_get_device_id       (NMSettingGsm *setting);
+NM_AVAILABLE_IN_1_2
+const char *nm_setting_gsm_get_sim_id          (NMSettingGsm *setting);
+NM_AVAILABLE_IN_1_2
+const char *nm_setting_gsm_get_sim_operator_id (NMSettingGsm *setting);
 
 NMSettingSecretFlags nm_setting_gsm_get_pin_flags      (NMSettingGsm *setting);
 NMSettingSecretFlags nm_setting_gsm_get_password_flags (NMSettingGsm *setting);
diff --git a/libnm-core/nm-setting-infiniband.c b/libnm-core/nm-setting-infiniband.c
index b0afe04f..1cffdd79 100644
--- a/libnm-core/nm-setting-infiniband.c
+++ b/libnm-core/nm-setting-infiniband.c
@@ -22,7 +22,6 @@
 #include "config.h"
 
 #include <stdlib.h>
-#include <glib/gi18n-lib.h>
 
 #include "nm-setting-infiniband.h"
 #include "nm-utils.h"
diff --git a/libnm-core/nm-setting-ip-config.c b/libnm-core/nm-setting-ip-config.c
index 3a67ca32..7e719aae 100644
--- a/libnm-core/nm-setting-ip-config.c
+++ b/libnm-core/nm-setting-ip-config.c
@@ -24,13 +24,12 @@
 
 #include <string.h>
 #include <arpa/inet.h>
-#include <glib/gi18n-lib.h>
 
+#include "nm-default.h"
 #include "nm-setting-ip-config.h"
 #include "nm-setting-ip4-config.h"
 #include "nm-setting-ip6-config.h"
 #include "nm-utils.h"
-#include "nm-glib-compat.h"
 #include "nm-setting-private.h"
 #include "nm-utils-private.h"
 
@@ -46,6 +45,24 @@
  * related to IP addressing, routing, and Domain Name Service.
  **/
 
+const NMUtilsDNSOptionDesc _nm_utils_dns_option_descs[] = {
+	{ NM_SETTING_DNS_OPTION_DEBUG,                 FALSE,   FALSE },
+	{ NM_SETTING_DNS_OPTION_NDOTS,                 TRUE,    FALSE },
+	{ NM_SETTING_DNS_OPTION_TIMEOUT,               TRUE,    FALSE },
+	{ NM_SETTING_DNS_OPTION_ATTEMPTS,              TRUE,    FALSE },
+	{ NM_SETTING_DNS_OPTION_ROTATE,                FALSE,   FALSE },
+	{ NM_SETTING_DNS_OPTION_NO_CHECK_NAMES,        FALSE,   FALSE },
+	{ NM_SETTING_DNS_OPTION_INET6,                 FALSE,   TRUE },
+	{ NM_SETTING_DNS_OPTION_IP6_BYTESTRING,        FALSE,   TRUE },
+	{ NM_SETTING_DNS_OPTION_IP6_DOTINT,            FALSE,   TRUE },
+	{ NM_SETTING_DNS_OPTION_NO_IP6_DOTINT,         FALSE,   TRUE },
+	{ NM_SETTING_DNS_OPTION_EDNS0,                 FALSE,   FALSE },
+	{ NM_SETTING_DNS_OPTION_SINGLE_REQUEST,        FALSE,   FALSE },
+	{ NM_SETTING_DNS_OPTION_SINGLE_REQUEST_REOPEN, FALSE,   FALSE },
+	{ NM_SETTING_DNS_OPTION_NO_TLD_QUERY,          FALSE,   FALSE },
+	{ NULL,                                        FALSE,   FALSE }
+};
+
 static char *
 canonicalize_ip (int family, const char *ip, gboolean null_any)
 {
@@ -79,7 +96,7 @@ valid_ip (int family, const char *ip, GError **error)
 	}
 	if (!nm_utils_ipaddr_valid (family, ip)) {
 		g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_FAILED,
-		             family == AF_INET ? _("Invalid IPv4 address '%s'") : _("Invalid IPv6 address '%s"),
+		             family == AF_INET ? _("Invalid IPv4 address '%s'") : _("Invalid IPv6 address '%s'"),
 		             ip);
 		return FALSE;
 	} else
@@ -93,7 +110,7 @@ valid_prefix (int family, guint prefix, GError **error, gboolean allow_zero_pref
 	    || (family == AF_INET6 && prefix > 128)
 	    || (!allow_zero_prefix && prefix == 0)) {
 		g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_FAILED,
-		             family == AF_INET ? _("Invalid IPv4 address prefix '%u'") : _("Invalid IPv6 address prefix '%u"),
+		             family == AF_INET ? _("Invalid IPv4 address prefix '%u'") : _("Invalid IPv6 address prefix '%u'"),
 		             prefix);
 		return FALSE;
 	}
@@ -1065,6 +1082,7 @@ typedef struct {
 	char *method;
 	GPtrArray *dns;        /* array of IP address strings */
 	GPtrArray *dns_search; /* array of domain name strings */
+	GPtrArray *dns_options;/* array of DNS options */
 	GPtrArray *addresses;  /* array of NMIPAddress */
 	GPtrArray *routes;     /* array of NMIPRoute */
 	gint64 route_metric;
@@ -1082,6 +1100,7 @@ enum {
 	PROP_METHOD,
 	PROP_DNS,
 	PROP_DNS_SEARCH,
+	PROP_DNS_OPTIONS,
 	PROP_ADDRESSES,
 	PROP_GATEWAY,
 	PROP_ROUTES,
@@ -1131,21 +1150,21 @@ nm_setting_ip_config_get_num_dns (NMSettingIPConfig *setting)
 /**
  * nm_setting_ip_config_get_dns:
  * @setting: the #NMSettingIPConfig
- * @i: index number of the DNS server to return
+ * @idx: index number of the DNS server to return
  *
- * Returns: the IP address of the DNS server at index @i
+ * Returns: the IP address of the DNS server at index @idx
  **/
 const char *
-nm_setting_ip_config_get_dns (NMSettingIPConfig *setting, int i)
+nm_setting_ip_config_get_dns (NMSettingIPConfig *setting, int idx)
 {
 	NMSettingIPConfigPrivate *priv;
 
 	g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), NULL);
 
 	priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
-	g_return_val_if_fail (i < priv->dns->len, NULL);
+	g_return_val_if_fail (idx < priv->dns->len, NULL);
 
-	return priv->dns->pdata[i];
+	return priv->dns->pdata[idx];
 }
 
 /**
@@ -1187,21 +1206,21 @@ nm_setting_ip_config_add_dns (NMSettingIPConfig *setting, const char *dns)
 /**
  * nm_setting_ip_config_remove_dns:
  * @setting: the #NMSettingIPConfig
- * @i: index number of the DNS server to remove
+ * @idx: index number of the DNS server to remove
  *
- * Removes the DNS server at index @i.
+ * Removes the DNS server at index @idx.
  **/
 void
-nm_setting_ip_config_remove_dns (NMSettingIPConfig *setting, int i)
+nm_setting_ip_config_remove_dns (NMSettingIPConfig *setting, int idx)
 {
 	NMSettingIPConfigPrivate *priv;
 
 	g_return_if_fail (NM_IS_SETTING_IP_CONFIG (setting));
 
 	priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
-	g_return_if_fail (i < priv->dns->len);
+	g_return_if_fail (idx < priv->dns->len);
 
-	g_ptr_array_remove_index (priv->dns, i);
+	g_ptr_array_remove_index (priv->dns, idx);
 	g_object_notify (G_OBJECT (setting), NM_SETTING_IP_CONFIG_DNS);
 }
 
@@ -1275,21 +1294,21 @@ nm_setting_ip_config_get_num_dns_searches (NMSettingIPConfig *setting)
 /**
  * nm_setting_ip_config_get_dns_search:
  * @setting: the #NMSettingIPConfig
- * @i: index number of the DNS search domain to return
+ * @idx: index number of the DNS search domain to return
  *
- * Returns: the DNS search domain at index @i
+ * Returns: the DNS search domain at index @idx
  **/
 const char *
-nm_setting_ip_config_get_dns_search (NMSettingIPConfig *setting, int i)
+nm_setting_ip_config_get_dns_search (NMSettingIPConfig *setting, int idx)
 {
 	NMSettingIPConfigPrivate *priv;
 
 	g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), NULL);
 
 	priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
-	g_return_val_if_fail (i < priv->dns_search->len, NULL);
+	g_return_val_if_fail (idx < priv->dns_search->len, NULL);
 
-	return priv->dns_search->pdata[i];
+	return priv->dns_search->pdata[idx];
 }
 
 /**
@@ -1327,21 +1346,21 @@ nm_setting_ip_config_add_dns_search (NMSettingIPConfig *setting,
 /**
  * nm_setting_ip_config_remove_dns_search:
  * @setting: the #NMSettingIPConfig
- * @i: index number of the DNS search domain
+ * @idx: index number of the DNS search domain
  *
- * Removes the DNS search domain at index @i.
+ * Removes the DNS search domain at index @idx.
  **/
 void
-nm_setting_ip_config_remove_dns_search (NMSettingIPConfig *setting, int i)
+nm_setting_ip_config_remove_dns_search (NMSettingIPConfig *setting, int idx)
 {
 	NMSettingIPConfigPrivate *priv;
 
 	g_return_if_fail (NM_IS_SETTING_IP_CONFIG (setting));
 
 	priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
-	g_return_if_fail (i < priv->dns_search->len);
+	g_return_if_fail (idx < priv->dns_search->len);
 
-	g_ptr_array_remove_index (priv->dns_search, i);
+	g_ptr_array_remove_index (priv->dns_search, idx);
 	g_object_notify (G_OBJECT (setting), NM_SETTING_IP_CONFIG_DNS_SEARCH);
 }
 
@@ -1397,6 +1416,233 @@ nm_setting_ip_config_clear_dns_searches (NMSettingIPConfig *setting)
 }
 
 /**
+ * nm_setting_ip_config_get_num_dns_options:
+ * @setting: the #NMSettingIPConfig
+ *
+ * Returns: the number of configured DNS options
+ *
+ * Since: 1.2
+ **/
+guint
+nm_setting_ip_config_get_num_dns_options (NMSettingIPConfig *setting)
+{
+	NMSettingIPConfigPrivate *priv;
+
+	g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), 0);
+
+	priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
+
+	return priv->dns_options ? priv->dns_options->len : 0;
+}
+
+/**
+ * nm_setting_ip_config_has_dns_options:
+ * @setting: the #NMSettingIPConfig
+ *
+ * NMSettingIPConfig can have a list of dns-options. If the list
+ * is empty, there are two similar (but differentiated) states.
+ * Either the options are explicitly set to have no values,
+ * or the options are left undefined. The latter means to use
+ * a default configuration, while the former explicitly means "no-options".
+ *
+ * Returns: whether DNS options are initalized or left unset (the default).
+ **/
+gboolean
+nm_setting_ip_config_has_dns_options (NMSettingIPConfig *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), 0);
+
+	return !!NM_SETTING_IP_CONFIG_GET_PRIVATE (setting)->dns_options;
+}
+
+/**
+ * nm_setting_ip_config_get_dns_option:
+ * @setting: the #NMSettingIPConfig
+ * @idx: index number of the DNS option
+ *
+ * Returns: the DNS option at index @idx
+ *
+ * Since: 1.2
+ **/
+const char *
+nm_setting_ip_config_get_dns_option (NMSettingIPConfig *setting, guint idx)
+{
+	NMSettingIPConfigPrivate *priv;
+
+	g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), NULL);
+
+	priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
+	g_return_val_if_fail (priv->dns_options, NULL);
+	g_return_val_if_fail (idx < priv->dns_options->len, NULL);
+
+	return priv->dns_options->pdata[idx];
+}
+
+/**
+ * nm_setting_ip_config_next_valid_dns_option:
+ * @setting: the #NMSettingIPConfig
+ * @idx: index to start the search from
+ *
+ * Returns: the index, greater or equal than @idx, of the first valid
+ * DNS option, or -1 if no valid option is found
+ *
+ * Since: 1.2
+ **/
+gint
+nm_setting_ip_config_next_valid_dns_option (NMSettingIPConfig *setting, guint idx)
+{
+	NMSettingIPConfigPrivate *priv;
+
+	g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), -1);
+
+	priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
+
+	if (!priv->dns_options)
+		return -1;
+
+	for (; idx < priv->dns_options->len; idx++) {
+		if (_nm_utils_dns_option_validate (priv->dns_options->pdata[idx], NULL, NULL,
+		                                   NM_IS_SETTING_IP6_CONFIG (setting),
+		                                   _nm_utils_dns_option_descs))
+			return idx;
+	}
+
+	return -1;
+}
+
+/**
+ * nm_setting_ip_config_add_dns_option:
+ * @setting: the #NMSettingIPConfig
+ * @dns_option: the DNS option to add
+ *
+ * Adds a new DNS option to the setting.
+ *
+ * Returns: %TRUE if the DNS option was added; %FALSE otherwise
+ *
+ * Since: 1.2
+ **/
+gboolean
+nm_setting_ip_config_add_dns_option (NMSettingIPConfig *setting,
+                                     const char *dns_option)
+{
+	NMSettingIPConfigPrivate *priv;
+
+	g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), FALSE);
+	g_return_val_if_fail (dns_option != NULL, FALSE);
+	g_return_val_if_fail (dns_option[0] != '\0', FALSE);
+
+	if (!_nm_utils_dns_option_validate (dns_option, NULL, NULL, FALSE, NULL))
+		return FALSE;
+
+	priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
+	if (!priv->dns_options)
+		priv->dns_options = g_ptr_array_new_with_free_func (g_free);
+	else {
+		if (_nm_utils_dns_option_find_idx (priv->dns_options, dns_option) >= 0)
+			return FALSE;
+	}
+
+	g_ptr_array_add (priv->dns_options, g_strdup (dns_option));
+	g_object_notify (G_OBJECT (setting), NM_SETTING_IP_CONFIG_DNS_OPTIONS);
+	return TRUE;
+}
+
+/**
+ * nm_setting_ip_config_remove_dns_option:
+ * @setting: the #NMSettingIPConfig
+ * @idx: index number of the DNS option
+ *
+ * Removes the DNS option at index @idx.
+ *
+ * Since: 1.2
+ **/
+void
+nm_setting_ip_config_remove_dns_option (NMSettingIPConfig *setting, int idx)
+{
+	NMSettingIPConfigPrivate *priv;
+
+	g_return_if_fail (NM_IS_SETTING_IP_CONFIG (setting));
+
+	priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
+	g_return_if_fail (priv->dns_options);
+	g_return_if_fail (idx < priv->dns_options->len);
+
+	g_ptr_array_remove_index (priv->dns_options, idx);
+	g_object_notify (G_OBJECT (setting), NM_SETTING_IP_CONFIG_DNS_OPTIONS);
+}
+
+/**
+ * nm_setting_ip_config_remove_dns_option_by_value:
+ * @setting: the #NMSettingIPConfig
+ * @dns_option: the DNS option to remove
+ *
+ * Removes the DNS option @dns_option.
+ *
+ * Returns: %TRUE if the DNS option was found and removed; %FALSE if it was not.
+ *
+ * Since: 1.2
+ **/
+gboolean
+nm_setting_ip_config_remove_dns_option_by_value (NMSettingIPConfig *setting,
+                                                 const char *dns_option)
+{
+	NMSettingIPConfigPrivate *priv;
+	int i;
+
+	g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), FALSE);
+	g_return_val_if_fail (dns_option != NULL, FALSE);
+	g_return_val_if_fail (dns_option[0] != '\0', FALSE);
+
+	priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
+	if (!priv->dns_options)
+		return FALSE;
+
+	i = _nm_utils_dns_option_find_idx (priv->dns_options, dns_option);
+	if (i >= 0) {
+		g_ptr_array_remove_index (priv->dns_options, i);
+		g_object_notify (G_OBJECT (setting), NM_SETTING_IP_CONFIG_DNS_OPTIONS);
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+/**
+ * nm_setting_ip_config_clear_dns_options:
+ * @setting: the #NMSettingIPConfig
+ * @is_set: the dns-options can be either empty or unset (default).
+ *   Specify how to clear the options.
+ *
+ * Removes all configured DNS options.
+ *
+ * Since: 1.2
+ **/
+void
+nm_setting_ip_config_clear_dns_options (NMSettingIPConfig *setting, gboolean is_set)
+{
+	NMSettingIPConfigPrivate *priv;
+
+	g_return_if_fail (NM_IS_SETTING_IP_CONFIG (setting));
+
+	priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
+	if (!priv->dns_options) {
+		if (!is_set)
+			return;
+		priv->dns_options = g_ptr_array_new_with_free_func (g_free);
+	} else {
+		if (!is_set) {
+			g_ptr_array_unref (priv->dns_options);
+			priv->dns_options = NULL;
+		} else {
+			if (priv->dns_options->len == 0)
+				return;
+			g_ptr_array_set_size (priv->dns_options, 0);
+		}
+	}
+	g_object_notify (G_OBJECT (setting), NM_SETTING_IP_CONFIG_DNS_OPTIONS);
+}
+
+/**
  * nm_setting_ip_config_get_num_addresses:
  * @setting: the #NMSettingIPConfig
  *
@@ -1413,21 +1659,21 @@ nm_setting_ip_config_get_num_addresses (NMSettingIPConfig *setting)
 /**
  * nm_setting_ip_config_get_address:
  * @setting: the #NMSettingIPConfig
- * @i: index number of the address to return
+ * @idx: index number of the address to return
  *
- * Returns: (transfer none): the address at index @i
+ * Returns: (transfer none): the address at index @idx
  **/
 NMIPAddress *
-nm_setting_ip_config_get_address (NMSettingIPConfig *setting, int i)
+nm_setting_ip_config_get_address (NMSettingIPConfig *setting, int idx)
 {
 	NMSettingIPConfigPrivate *priv;
 
 	g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), NULL);
 
 	priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
-	g_return_val_if_fail (i < priv->addresses->len, NULL);
+	g_return_val_if_fail (idx < priv->addresses->len, NULL);
 
-	return priv->addresses->pdata[i];
+	return priv->addresses->pdata[idx];
 }
 
 /**
@@ -1467,21 +1713,21 @@ nm_setting_ip_config_add_address (NMSettingIPConfig *setting,
 /**
  * nm_setting_ip_config_remove_address:
  * @setting: the #NMSettingIPConfig
- * @i: index number of the address to remove
+ * @idx: index number of the address to remove
  *
- * Removes the address at index @i.
+ * Removes the address at index @idx.
  **/
 void
-nm_setting_ip_config_remove_address (NMSettingIPConfig *setting, int i)
+nm_setting_ip_config_remove_address (NMSettingIPConfig *setting, int idx)
 {
 	NMSettingIPConfigPrivate *priv;
 
 	g_return_if_fail (NM_IS_SETTING_IP_CONFIG (setting));
 
 	priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
-	g_return_if_fail (i < priv->addresses->len);
+	g_return_if_fail (idx < priv->addresses->len);
 
-	g_ptr_array_remove_index (priv->addresses, i);
+	g_ptr_array_remove_index (priv->addresses, idx);
 
 	g_object_notify (G_OBJECT (setting), NM_SETTING_IP_CONFIG_ADDRESSES);
 }
@@ -1565,21 +1811,21 @@ nm_setting_ip_config_get_num_routes (NMSettingIPConfig *setting)
 /**
  * nm_setting_ip_config_get_route:
  * @setting: the #NMSettingIPConfig
- * @i: index number of the route to return
+ * @idx: index number of the route to return
  *
- * Returns: (transfer none): the route at index @i
+ * Returns: (transfer none): the route at index @idx
  **/
 NMIPRoute *
-nm_setting_ip_config_get_route (NMSettingIPConfig *setting, int i)
+nm_setting_ip_config_get_route (NMSettingIPConfig *setting, int idx)
 {
 	NMSettingIPConfigPrivate *priv;
 
 	g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), NULL);
 
 	priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
-	g_return_val_if_fail (i < priv->routes->len, NULL);
+	g_return_val_if_fail (idx < priv->routes->len, NULL);
 
-	return priv->routes->pdata[i];
+	return priv->routes->pdata[idx];
 }
 
 /**
@@ -1617,21 +1863,21 @@ nm_setting_ip_config_add_route (NMSettingIPConfig *setting,
 /**
  * nm_setting_ip_config_remove_route:
  * @setting: the #NMSettingIPConfig
- * @i: index number of the route
+ * @idx: index number of the route
  *
- * Removes the route at index @i.
+ * Removes the route at index @idx.
  **/
 void
-nm_setting_ip_config_remove_route (NMSettingIPConfig *setting, int i)
+nm_setting_ip_config_remove_route (NMSettingIPConfig *setting, int idx)
 {
 	NMSettingIPConfigPrivate *priv;
 
 	g_return_if_fail (NM_IS_SETTING_IP_CONFIG (setting));
 
 	priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
-	g_return_if_fail (i < priv->routes->len);
+	g_return_if_fail (idx < priv->routes->len);
 
-	g_ptr_array_remove_index (priv->routes, i);
+	g_ptr_array_remove_index (priv->routes, idx);
 	g_object_notify (G_OBJECT (setting), NM_SETTING_IP_CONFIG_ROUTES);
 }
 
@@ -1962,6 +2208,7 @@ nm_setting_ip_config_init (NMSettingIPConfig *setting)
 
 	priv->dns = g_ptr_array_new_with_free_func (g_free);
 	priv->dns_search = g_ptr_array_new_with_free_func (g_free);
+	priv->dns_options = NULL;
 	priv->addresses = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip_address_unref);
 	priv->routes = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip_route_unref);
 }
@@ -1978,6 +2225,8 @@ finalize (GObject *object)
 
 	g_ptr_array_unref (priv->dns);
 	g_ptr_array_unref (priv->dns_search);
+	if (priv->dns_options)
+		g_ptr_array_unref (priv->dns_options);
 	g_ptr_array_unref (priv->addresses);
 	g_ptr_array_unref (priv->routes);
 
@@ -1991,6 +2240,8 @@ set_property (GObject *object, guint prop_id,
 	NMSettingIPConfig *setting = NM_SETTING_IP_CONFIG (object);
 	NMSettingIPConfigPrivate *priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
 	const char *gateway;
+	char **strv;
+	int i;
 
 	switch (prop_id) {
 	case PROP_METHOD:
@@ -2005,6 +2256,25 @@ set_property (GObject *object, guint prop_id,
 		g_ptr_array_unref (priv->dns_search);
 		priv->dns_search = _nm_utils_strv_to_ptrarray (g_value_get_boxed (value));
 		break;
+	case PROP_DNS_OPTIONS:
+		strv = g_value_get_boxed (value);
+		if (!strv) {
+			if (priv->dns_options) {
+				g_ptr_array_unref (priv->dns_options);
+				priv->dns_options = NULL;
+			}
+		} else {
+			if (priv->dns_options)
+				g_ptr_array_set_size (priv->dns_options, 0);
+			else
+				priv->dns_options = g_ptr_array_new_with_free_func (g_free);
+			for (i = 0; strv[i]; i++) {
+				if (   _nm_utils_dns_option_validate (strv[i], NULL, NULL, FALSE, NULL)
+				    && _nm_utils_dns_option_find_idx (priv->dns_options, strv[i]) < 0)
+					g_ptr_array_add (priv->dns_options, g_strdup (strv[i]));
+			}
+		}
+		break;
 	case PROP_ADDRESSES:
 		g_ptr_array_unref (priv->addresses);
 		priv->addresses = _nm_utils_copy_array (g_value_get_boxed (value),
@@ -2068,6 +2338,9 @@ get_property (GObject *object, guint prop_id,
 	case PROP_DNS_SEARCH:
 		g_value_take_boxed (value, _nm_utils_ptrarray_to_strv (priv->dns_search));
 		break;
+	case PROP_DNS_OPTIONS:
+		g_value_take_boxed (value, priv->dns_options ? _nm_utils_ptrarray_to_strv (priv->dns_options) : NULL);
+		break;
 	case PROP_ADDRESSES:
 		g_value_take_boxed (value, _nm_utils_copy_array (priv->addresses,
 		                                                 (NMUtilsCopyFunc) nm_ip_address_dup,
@@ -2188,6 +2461,24 @@ nm_setting_ip_config_class_init (NMSettingIPConfigClass *setting_class)
 		                     G_PARAM_STATIC_STRINGS));
 
 	/**
+	 * NMSettingIPConfig:dns-options:
+	 *
+	 * Array of DNS options.
+	 *
+	 * %NULL means that the options are unset and left at the default.
+	 * In this case NetworkManager will use default options. This is
+	 * distinct from an empty list of properties.
+	 *
+	 * Since: 1.2
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_DNS_OPTIONS,
+		 g_param_spec_boxed (NM_SETTING_IP_CONFIG_DNS_OPTIONS, "", "",
+		                     G_TYPE_STRV,
+		                     G_PARAM_READWRITE |
+		                     G_PARAM_STATIC_STRINGS));
+
+	/**
 	 * NMSettingIPConfig:addresses:
 	 *
 	 * Array of IP addresses.
@@ -2304,6 +2595,8 @@ nm_setting_ip_config_class_init (NMSettingIPConfigClass *setting_class)
 	 *
 	 * If the #NMSettingIPConfig:dhcp-send-hostname property is %TRUE, then the
 	 * specified name will be sent to the DHCP server when acquiring a lease.
+	 * This property and #NMSettingIP4Config:dhcp-fqdn are mutually exclusive and
+	 * cannot be set at the same time.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_DHCP_HOSTNAME,
diff --git a/libnm-core/nm-setting-ip-config.h b/libnm-core/nm-setting-ip-config.h
index 12763fa8..6e8c0202 100644
--- a/libnm-core/nm-setting-ip-config.h
+++ b/libnm-core/nm-setting-ip-config.h
@@ -133,6 +133,7 @@ void         nm_ip_route_set_attribute       (NMIPRoute   *route,
 #define NM_SETTING_IP_CONFIG_METHOD             "method"
 #define NM_SETTING_IP_CONFIG_DNS                "dns"
 #define NM_SETTING_IP_CONFIG_DNS_SEARCH         "dns-search"
+#define NM_SETTING_IP_CONFIG_DNS_OPTIONS        "dns-options"
 #define NM_SETTING_IP_CONFIG_ADDRESSES          "addresses"
 #define NM_SETTING_IP_CONFIG_GATEWAY            "gateway"
 #define NM_SETTING_IP_CONFIG_ROUTES             "routes"
@@ -144,6 +145,21 @@ void         nm_ip_route_set_attribute       (NMIPRoute   *route,
 #define NM_SETTING_IP_CONFIG_NEVER_DEFAULT      "never-default"
 #define NM_SETTING_IP_CONFIG_MAY_FAIL           "may-fail"
 
+#define NM_SETTING_DNS_OPTION_DEBUG                     "debug"
+#define NM_SETTING_DNS_OPTION_NDOTS                     "ndots"
+#define NM_SETTING_DNS_OPTION_TIMEOUT                   "timeout"
+#define NM_SETTING_DNS_OPTION_ATTEMPTS                  "attempts"
+#define NM_SETTING_DNS_OPTION_ROTATE                    "rotate"
+#define NM_SETTING_DNS_OPTION_NO_CHECK_NAMES            "no-check-names"
+#define NM_SETTING_DNS_OPTION_INET6                     "inet6"
+#define NM_SETTING_DNS_OPTION_IP6_BYTESTRING            "ip6-bytestring"
+#define NM_SETTING_DNS_OPTION_IP6_DOTINT                "ip6-dotint"
+#define NM_SETTING_DNS_OPTION_NO_IP6_DOTINT             "no-ip6-dotint"
+#define NM_SETTING_DNS_OPTION_EDNS0                     "edns0"
+#define NM_SETTING_DNS_OPTION_SINGLE_REQUEST            "single-request"
+#define NM_SETTING_DNS_OPTION_SINGLE_REQUEST_REOPEN     "single-request-reopen"
+#define NM_SETTING_DNS_OPTION_NO_TLD_QUERY              "no-tld-query"
+
 struct _NMSettingIPConfig {
 	NMSetting parent;
 };
@@ -161,33 +177,47 @@ const char   *nm_setting_ip_config_get_method                 (NMSettingIPConfig
 
 guint         nm_setting_ip_config_get_num_dns                (NMSettingIPConfig *setting);
 const char   *nm_setting_ip_config_get_dns                    (NMSettingIPConfig *setting,
-                                                               int                i);
+                                                               int                idx);
 gboolean      nm_setting_ip_config_add_dns                    (NMSettingIPConfig *setting,
                                                                const char        *dns);
 void          nm_setting_ip_config_remove_dns                 (NMSettingIPConfig *setting,
-                                                               int                i);
+                                                               int                idx);
 gboolean      nm_setting_ip_config_remove_dns_by_value        (NMSettingIPConfig *setting,
                                                                const char        *dns);
 void          nm_setting_ip_config_clear_dns                  (NMSettingIPConfig *setting);
 
 guint         nm_setting_ip_config_get_num_dns_searches       (NMSettingIPConfig *setting);
 const char   *nm_setting_ip_config_get_dns_search             (NMSettingIPConfig *setting,
-                                                               int                i);
+                                                               int                idx);
 gboolean      nm_setting_ip_config_add_dns_search             (NMSettingIPConfig *setting,
                                                                const char        *dns_search);
 void          nm_setting_ip_config_remove_dns_search          (NMSettingIPConfig *setting,
-                                                               int                i);
+                                                               int                idx);
 gboolean      nm_setting_ip_config_remove_dns_search_by_value (NMSettingIPConfig *setting,
                                                                const char        *dns_search);
 void          nm_setting_ip_config_clear_dns_searches         (NMSettingIPConfig *setting);
 
+guint         nm_setting_ip_config_get_num_dns_options        (NMSettingIPConfig *setting);
+gboolean      nm_setting_ip_config_has_dns_options            (NMSettingIPConfig *setting);
+const char   *nm_setting_ip_config_get_dns_option             (NMSettingIPConfig *setting,
+                                                               guint              idx);
+gint          nm_setting_ip_config_next_valid_dns_option      (NMSettingIPConfig *setting,
+                                                               guint              idx);
+gboolean      nm_setting_ip_config_add_dns_option             (NMSettingIPConfig *setting,
+                                                               const char        *dns_option);
+void          nm_setting_ip_config_remove_dns_option          (NMSettingIPConfig *setting,
+                                                               int                idx);
+gboolean      nm_setting_ip_config_remove_dns_option_by_value (NMSettingIPConfig *setting,
+                                                               const char        *dns_option);
+void          nm_setting_ip_config_clear_dns_options          (NMSettingIPConfig *setting, gboolean is_set);
+
 guint         nm_setting_ip_config_get_num_addresses          (NMSettingIPConfig *setting);
 NMIPAddress  *nm_setting_ip_config_get_address                (NMSettingIPConfig *setting,
-                                                               int                i);
+                                                               int                idx);
 gboolean      nm_setting_ip_config_add_address                (NMSettingIPConfig *setting,
                                                                NMIPAddress       *address);
 void          nm_setting_ip_config_remove_address             (NMSettingIPConfig *setting,
-                                                               int                i);
+                                                               int                idx);
 gboolean      nm_setting_ip_config_remove_address_by_value    (NMSettingIPConfig *setting,
                                                                NMIPAddress       *address);
 void          nm_setting_ip_config_clear_addresses            (NMSettingIPConfig *setting);
@@ -196,11 +226,11 @@ const char   *nm_setting_ip_config_get_gateway                (NMSettingIPConfig
 
 guint         nm_setting_ip_config_get_num_routes             (NMSettingIPConfig *setting);
 NMIPRoute    *nm_setting_ip_config_get_route                  (NMSettingIPConfig *setting,
-                                                               int                i);
+                                                               int                idx);
 gboolean      nm_setting_ip_config_add_route                  (NMSettingIPConfig *setting,
                                                                NMIPRoute         *route);
 void          nm_setting_ip_config_remove_route               (NMSettingIPConfig *setting,
-                                                               int                i);
+                                                               int                idx);
 gboolean      nm_setting_ip_config_remove_route_by_value      (NMSettingIPConfig *setting,
                                                                NMIPRoute         *route);
 void          nm_setting_ip_config_clear_routes               (NMSettingIPConfig *setting);
diff --git a/libnm-core/nm-setting-ip-tunnel.c b/libnm-core/nm-setting-ip-tunnel.c
new file mode 100644
index 00000000..cd63aa11
--- /dev/null
+++ b/libnm-core/nm-setting-ip-tunnel.c
@@ -0,0 +1,767 @@
+/* -*- 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 2015 Red Hat, Inc.
+ */
+
+#include "nm-setting-ip-tunnel.h"
+
+#include "config.h"
+
+#include "nm-setting-private.h"
+#include "nm-macros-internal.h"
+#include "nm-utils.h"
+
+/**
+ * SECTION:nm-setting-ip-tunnel
+ * @short_description: Describes connection properties for IP tunnel devices
+ **/
+
+G_DEFINE_TYPE_WITH_CODE (NMSettingIPTunnel, nm_setting_ip_tunnel, NM_TYPE_SETTING,
+                         _nm_register_setting (IP_TUNNEL, 1))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_IP_TUNNEL)
+
+#define NM_SETTING_IP_TUNNEL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_IP_TUNNEL, NMSettingIPTunnelPrivate))
+
+typedef struct {
+	char *parent;
+	NMIPTunnelMode mode;
+	char *local;
+	char *remote;
+	guint ttl;
+	guint tos;
+	gboolean path_mtu_discovery;
+	char *input_key;
+	char *output_key;
+	guint encapsulation_limit;
+	guint flow_label;
+	guint mtu;
+} NMSettingIPTunnelPrivate;
+
+enum {
+	PROP_0,
+	PROP_PARENT,
+	PROP_MODE,
+	PROP_LOCAL,
+	PROP_REMOTE,
+	PROP_TTL,
+	PROP_TOS,
+	PROP_PATH_MTU_DISCOVERY,
+	PROP_INPUT_KEY,
+	PROP_OUTPUT_KEY,
+	PROP_ENCAPSULATION_LIMIT,
+	PROP_FLOW_LABEL,
+	PROP_MTU,
+
+	LAST_PROP
+};
+
+/**
+ * nm_setting_ip_tunnel_get_parent:
+ * @setting: the #NMSettingIPTunnel
+ *
+ * Returns the #NMSettingIPTunnel:parent property of the setting
+ *
+ * Returns: the parent device
+ *
+ * Since: 1.2
+ **/
+const char *
+nm_setting_ip_tunnel_get_parent (NMSettingIPTunnel *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_IP_TUNNEL (setting), NULL);
+	return NM_SETTING_IP_TUNNEL_GET_PRIVATE (setting)->parent;
+}
+
+/**
+ * nm_setting_ip_tunnel_get_mode:
+ * @setting: the #NMSettingIPTunnel
+ *
+ * Returns the #NMSettingIPTunnel:mode property of the setting.
+ *
+ * Returns: the tunnel mode
+ *
+ * Since: 1.2
+ **/
+NMIPTunnelMode
+nm_setting_ip_tunnel_get_mode (NMSettingIPTunnel *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_IP_TUNNEL (setting), 0);
+
+	return NM_SETTING_IP_TUNNEL_GET_PRIVATE (setting)->mode;
+}
+
+/**
+ * nm_setting_ip_tunnel_get_local:
+ * @setting: the #NMSettingIPTunnel
+ *
+ * Returns the #NMSettingIPTunnel:local property of the setting.
+ *
+ * Returns: the local endpoint
+ *
+ * Since: 1.2
+ **/
+const char *
+nm_setting_ip_tunnel_get_local (NMSettingIPTunnel *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_IP_TUNNEL (setting), NULL);
+
+	return NM_SETTING_IP_TUNNEL_GET_PRIVATE (setting)->local;
+}
+
+/**
+ * nm_setting_ip_tunnel_get_remote:
+ * @setting: the #NMSettingIPTunnel
+ *
+ * Returns the #NMSettingIPTunnel:remote property of the setting.
+ *
+ * Returns: the remote endpoint
+ *
+ * Since: 1.2
+ **/
+const char *
+nm_setting_ip_tunnel_get_remote (NMSettingIPTunnel *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_IP_TUNNEL (setting), NULL);
+
+	return NM_SETTING_IP_TUNNEL_GET_PRIVATE (setting)->remote;
+}
+
+/**
+ * nm_setting_ip_tunnel_get_ttl:
+ * @setting: the #NMSettingIPTunnel
+ *
+ * Returns the #NMSettingIPTunnel:ttl property of the setting.
+ *
+ * Returns: the Time-to-live value
+ *
+ * Since: 1.2
+ **/
+
+guint
+nm_setting_ip_tunnel_get_ttl (NMSettingIPTunnel *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_IP_TUNNEL (setting), 0);
+
+	return NM_SETTING_IP_TUNNEL_GET_PRIVATE (setting)->ttl;
+}
+
+/**
+ * nm_setting_ip_tunnel_get_tos:
+ * @setting: the #NMSettingIPTunnel
+ *
+ * Returns the #NMSettingIPTunnel:tos property of the setting.
+ *
+ * Returns: the TOS value
+ *
+ * Since: 1.2
+ **/
+guint
+nm_setting_ip_tunnel_get_tos (NMSettingIPTunnel *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_IP_TUNNEL (setting), 0);
+
+	return NM_SETTING_IP_TUNNEL_GET_PRIVATE (setting)->tos;
+}
+
+/**
+ * nm_setting_ip_tunnel_get_path_mtu_discovery:
+ * @setting: the #NMSettingIPTunnel
+ *
+ * Returns the #NMSettingIPTunnel:path-mtu-discovery property of the setting.
+ *
+ * Returns: whether path MTU discovery is enabled
+ *
+ * Since: 1.2
+ **/
+gboolean
+nm_setting_ip_tunnel_get_path_mtu_discovery (NMSettingIPTunnel *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_IP_TUNNEL (setting), TRUE);
+
+	return NM_SETTING_IP_TUNNEL_GET_PRIVATE (setting)->path_mtu_discovery;
+}
+
+/**
+ * nm_setting_ip_tunnel_get_input_key:
+ * @setting: the #NMSettingIPTunnel
+ *
+ * Returns the #NMSettingIPTunnel:input-key property of the setting.
+ *
+ * Returns: the input key
+ *
+ * Since: 1.2
+ **/
+const char *
+nm_setting_ip_tunnel_get_input_key (NMSettingIPTunnel *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_IP_TUNNEL (setting), NULL);
+
+	return NM_SETTING_IP_TUNNEL_GET_PRIVATE (setting)->input_key;
+}
+
+/**
+ * nm_setting_ip_tunnel_get_output_key:
+ * @setting: the #NMSettingIPTunnel
+ *
+ * Returns the #NMSettingIPTunnel:output-key property of the setting.
+ *
+ * Returns: the output key
+ *
+ * Since: 1.2
+ **/
+const char *
+nm_setting_ip_tunnel_get_output_key (NMSettingIPTunnel *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_IP_TUNNEL (setting), NULL);
+
+	return NM_SETTING_IP_TUNNEL_GET_PRIVATE (setting)->output_key;
+}
+
+/**
+ * nm_setting_ip_tunnel_get_encapsulation_limit:
+ * @setting: the #NMSettingIPTunnel
+ *
+ * Returns the #NMSettingIPTunnel:encapsulation-limit property of the setting.
+ *
+ * Returns: the encapsulation limit value
+ *
+ * Since: 1.2
+ **/
+guint
+nm_setting_ip_tunnel_get_encapsulation_limit (NMSettingIPTunnel *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_IP_TUNNEL (setting), 0);
+
+	return NM_SETTING_IP_TUNNEL_GET_PRIVATE (setting)->encapsulation_limit;
+}
+
+/**
+ * nm_setting_ip_tunnel_get_flow_label:
+ * @setting: the #NMSettingIPTunnel
+ *
+ * Returns the #NMSettingIPTunnel:flow-label property of the setting.
+ *
+ * Returns: the flow label value
+ *
+ * Since: 1.2
+ **/
+guint
+nm_setting_ip_tunnel_get_flow_label (NMSettingIPTunnel *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_IP_TUNNEL (setting), 0);
+
+	return NM_SETTING_IP_TUNNEL_GET_PRIVATE (setting)->flow_label;
+}
+
+/**
+ * nm_setting_ip_tunnel_get_mtu:
+ * @setting: the #NMSettingIPTunnel
+ *
+ * Returns the #NMSettingIPTunnel:mtu property of the setting.
+ *
+ * Returns: the MTU
+ *
+ * Since: 1.2
+ **/
+guint
+nm_setting_ip_tunnel_get_mtu (NMSettingIPTunnel *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_IP_TUNNEL (setting), 0);
+
+	return NM_SETTING_IP_TUNNEL_GET_PRIVATE (setting)->mtu;
+}
+
+/*********************************************************************/
+
+static gboolean
+verify (NMSetting *setting, NMConnection *connection, GError **error)
+{
+	NMSettingIPTunnelPrivate *priv = NM_SETTING_IP_TUNNEL_GET_PRIVATE (setting);
+	int family;
+
+	switch (priv->mode) {
+	case NM_IP_TUNNEL_MODE_IPIP:
+	case NM_IP_TUNNEL_MODE_SIT:
+	case NM_IP_TUNNEL_MODE_ISATAP:
+	case NM_IP_TUNNEL_MODE_GRE:
+	case NM_IP_TUNNEL_MODE_VTI:
+		family = AF_INET;
+		break;
+	case NM_IP_TUNNEL_MODE_IP6IP6:
+	case NM_IP_TUNNEL_MODE_IPIP6:
+	case NM_IP_TUNNEL_MODE_IP6GRE:
+	case NM_IP_TUNNEL_MODE_VTI6:
+		family = AF_INET6;
+		break;
+	default:
+		family = AF_UNSPEC;
+	}
+
+	if (family == AF_UNSPEC) {
+		g_set_error (error,
+		             NM_CONNECTION_ERROR,
+		             NM_CONNECTION_ERROR_INVALID_PROPERTY,
+		             _("'%d' is not a valid tunnel mode"),
+		             (int) priv->mode);
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_IP_TUNNEL_SETTING_NAME, NM_SETTING_IP_TUNNEL_MODE);
+		return FALSE;
+	}
+
+	if (   priv->parent
+	    && !nm_utils_iface_valid_name (priv->parent)
+	    && !nm_utils_is_uuid (priv->parent)) {
+		g_set_error (error,
+		             NM_CONNECTION_ERROR,
+		             NM_CONNECTION_ERROR_INVALID_PROPERTY,
+		             _("'%s' is neither an UUID nor an interface name"),
+		             priv->parent);
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_IP_TUNNEL_SETTING_NAME,
+		                NM_SETTING_IP_TUNNEL_PARENT);
+		return FALSE;
+	}
+
+	if (priv->local && !nm_utils_ipaddr_valid (family, priv->local)) {
+		g_set_error (error,
+		             NM_CONNECTION_ERROR,
+		             NM_CONNECTION_ERROR_INVALID_PROPERTY,
+		             _("'%s' is not a valid IPv%c address"),
+		             priv->local,
+		             family == AF_INET ? '4' : '6');
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_IP_TUNNEL_SETTING_NAME, NM_SETTING_IP_TUNNEL_LOCAL);
+		return FALSE;
+	}
+
+	if (priv->remote && !nm_utils_ipaddr_valid (family, priv->remote)) {
+		g_set_error (error,
+		             NM_CONNECTION_ERROR,
+		             NM_CONNECTION_ERROR_INVALID_PROPERTY,
+		             _("'%s' is not a valid IPv%c address"),
+		             priv->remote,
+		             family == AF_INET ? '4' : '6');
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_IP_TUNNEL_SETTING_NAME, NM_SETTING_IP_TUNNEL_REMOTE);
+		return FALSE;
+	}
+
+	if (   (priv->input_key && priv->input_key[0])
+	    || (priv->output_key && priv->output_key[0])) {
+		if (   priv->mode != NM_IP_TUNNEL_MODE_GRE
+		    && priv->mode != NM_IP_TUNNEL_MODE_IP6GRE) {
+			g_set_error_literal (error,
+			                     NM_CONNECTION_ERROR,
+			                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
+			                     _("tunnel keys can only be specified for GRE tunnels"));
+			return FALSE;
+		}
+	}
+
+	if (priv->input_key && priv->input_key[0]) {
+		gint64 val;
+
+		val = _nm_utils_ascii_str_to_int64 (priv->input_key, 10, 0, G_MAXUINT32, -1);
+		if (val == -1) {
+			g_set_error (error,
+			             NM_CONNECTION_ERROR,
+			             NM_CONNECTION_ERROR_INVALID_PROPERTY,
+			             _("'%s' is not a valid tunnel key"),
+			             priv->input_key);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_IP_TUNNEL_SETTING_NAME,
+			                NM_SETTING_IP_TUNNEL_INPUT_KEY);
+		return FALSE;
+		}
+	}
+
+	if (priv->output_key && priv->output_key[0]) {
+		gint64 val;
+
+		val = _nm_utils_ascii_str_to_int64 (priv->output_key, 10, 0, G_MAXUINT32, -1);
+		if (val == -1) {
+			g_set_error (error,
+			             NM_CONNECTION_ERROR,
+			             NM_CONNECTION_ERROR_INVALID_PROPERTY,
+			             _("'%s' is not a valid tunnel key"),
+			             priv->output_key);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_IP_TUNNEL_SETTING_NAME,
+			                NM_SETTING_IP_TUNNEL_OUTPUT_KEY);
+		return FALSE;
+		}
+	}
+
+	if (!priv->path_mtu_discovery && priv->ttl != 0) {
+		g_set_error_literal (error,
+		                     NM_CONNECTION_ERROR,
+		                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
+		                     _("a fixed TTL is allowed only when path MTU discovery is enabled"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_IP_TUNNEL_SETTING_NAME,
+		                NM_SETTING_IP_TUNNEL_TTL);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+/**
+ * nm_setting_ip_tunnel_new:
+ *
+ * Creates a new #NMSettingIPTunnel object with default values.
+ *
+ * Returns: (transfer full): the new empty #NMSettingIPTunnel object
+ *
+ * Since: 1.2
+ **/
+NMSetting *
+nm_setting_ip_tunnel_new (void)
+{
+	return (NMSetting *) g_object_new (NM_TYPE_SETTING_IP_TUNNEL, NULL);
+}
+
+static void
+nm_setting_ip_tunnel_init (NMSettingIPTunnel *setting)
+{
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+              const GValue *value, GParamSpec *pspec)
+{
+	NMSettingIPTunnel *setting = NM_SETTING_IP_TUNNEL (object);
+	NMSettingIPTunnelPrivate *priv = NM_SETTING_IP_TUNNEL_GET_PRIVATE (setting);
+
+	switch (prop_id) {
+	case PROP_PARENT:
+		g_free (priv->parent);
+		priv->parent = g_value_dup_string (value);
+		break;
+	case PROP_MODE:
+		priv->mode = g_value_get_uint (value);
+		break;
+	case PROP_LOCAL:
+		g_free (priv->local);
+		priv->local = g_value_dup_string (value);
+		break;
+	case PROP_REMOTE:
+		g_free (priv->remote);
+		priv->remote = g_value_dup_string (value);
+		break;
+	case PROP_TTL:
+		priv->ttl = g_value_get_uint (value);
+		break;
+	case PROP_TOS:
+		priv->tos = g_value_get_uint (value);
+		break;
+	case PROP_PATH_MTU_DISCOVERY:
+		priv->path_mtu_discovery = g_value_get_boolean (value);
+		break;
+	case PROP_INPUT_KEY:
+		g_free (priv->input_key);
+		priv->input_key = g_value_dup_string (value);
+		break;
+	case PROP_OUTPUT_KEY:
+		g_free (priv->output_key);
+		priv->output_key = g_value_dup_string (value);
+		break;
+	case PROP_ENCAPSULATION_LIMIT:
+		priv->encapsulation_limit = g_value_get_uint (value);
+		break;
+	case PROP_FLOW_LABEL:
+		priv->flow_label = g_value_get_uint (value);
+		break;
+	case PROP_MTU:
+		priv->mtu = g_value_get_uint (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)
+{
+	NMSettingIPTunnel *setting = NM_SETTING_IP_TUNNEL (object);
+	NMSettingIPTunnelPrivate *priv = NM_SETTING_IP_TUNNEL_GET_PRIVATE (setting);
+
+	switch (prop_id) {
+	case PROP_PARENT:
+		g_value_set_string (value, priv->parent);
+		break;
+	case PROP_MODE:
+		g_value_set_uint (value, priv->mode);
+		break;
+	case PROP_LOCAL:
+		g_value_set_string (value, priv->local);
+		break;
+	case PROP_REMOTE:
+		g_value_set_string (value, priv->remote);
+		break;
+	case PROP_TTL:
+		g_value_set_uint (value, priv->ttl);
+		break;
+	case PROP_TOS:
+		g_value_set_uint (value, priv->tos);
+		break;
+	case PROP_PATH_MTU_DISCOVERY:
+		g_value_set_boolean (value, priv->path_mtu_discovery);
+		break;
+	case PROP_INPUT_KEY:
+		g_value_set_string (value, priv->input_key);
+		break;
+	case PROP_OUTPUT_KEY:
+		g_value_set_string (value, priv->output_key);
+		break;
+	case PROP_ENCAPSULATION_LIMIT:
+		g_value_set_uint (value, priv->encapsulation_limit);
+		break;
+	case PROP_FLOW_LABEL:
+		g_value_set_uint (value, priv->flow_label);
+		break;
+	case PROP_MTU:
+		g_value_set_uint (value, priv->mtu);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+finalize (GObject *object)
+{
+	NMSettingIPTunnel *setting = NM_SETTING_IP_TUNNEL (object);
+	NMSettingIPTunnelPrivate *priv = NM_SETTING_IP_TUNNEL_GET_PRIVATE (setting);
+
+	g_free (priv->local);
+	g_free (priv->remote);
+	g_free (priv->input_key);
+	g_free (priv->output_key);
+
+	G_OBJECT_CLASS (nm_setting_ip_tunnel_parent_class)->finalize (object);
+}
+
+static void
+nm_setting_ip_tunnel_class_init (NMSettingIPTunnelClass *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 (NMSettingIPTunnelPrivate));
+
+	/* virtual methods */
+	object_class->set_property = set_property;
+	object_class->get_property = get_property;
+	object_class->finalize     = finalize;
+	parent_class->verify       = verify;
+
+	/**
+	 * NMSettingIPTunnel:parent:
+	 *
+	 * If given, specifies the parent interface name or parent connection UUID
+	 * the new device will be bound to so that tunneled packets will only be
+	 * routed via that interface.
+	 *
+	 * Since: 1.2
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_PARENT,
+		 g_param_spec_string (NM_SETTING_IP_TUNNEL_PARENT, "", "",
+		                      NULL,
+		                      G_PARAM_READWRITE |
+		                      NM_SETTING_PARAM_INFERRABLE |
+		                      G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMSettingIPTunnel:mode:
+	 *
+	 * The tunneling mode, for example %NM_IP_TUNNEL_MODE_IPIP or
+	 * %NM_IP_TUNNEL_MODE_GRE.
+	 *
+	 * Since: 1.2
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_MODE,
+		 g_param_spec_uint (NM_SETTING_IP_TUNNEL_MODE, "", "",
+		                    0, G_MAXUINT, 0,
+		                    G_PARAM_READWRITE |
+		                    NM_SETTING_PARAM_INFERRABLE |
+		                    G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMSettingIPTunnel:local:
+	 *
+	 * The local endpoint of the tunnel; the value can be empty, otherwise it
+	 * must contain an IPv4 or IPv6 address.
+	 *
+	 * Since: 1.2
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_LOCAL,
+		 g_param_spec_string (NM_SETTING_IP_TUNNEL_LOCAL, "", "",
+		                      NULL,
+		                      G_PARAM_READWRITE |
+		                      NM_SETTING_PARAM_INFERRABLE |
+		                      G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMSettingIPTunnel:remote:
+	 *
+	 * The remote endpoint of the tunnel; the value must contain an IPv4 or IPv6
+	 * address.
+	 *
+	 * Since: 1.2
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_REMOTE,
+		 g_param_spec_string (NM_SETTING_IP_TUNNEL_REMOTE, "", "",
+		                      NULL,
+		                      G_PARAM_READWRITE |
+		                      NM_SETTING_PARAM_INFERRABLE |
+		                      G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMSettingIPTunnel:ttl
+	 *
+	 * The TTL to assign to tunneled packets. 0 is a special value meaning that
+	 * packets inherit the TTL value.
+	 *
+	 * Since: 1.2
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_TTL,
+		 g_param_spec_uint (NM_SETTING_IP_TUNNEL_TTL, "", "",
+		                    0, 255, 0,
+		                    G_PARAM_READWRITE |
+		                    G_PARAM_CONSTRUCT |
+		                    NM_SETTING_PARAM_INFERRABLE |
+		                    G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMSettingIPTunnel:tos
+	 *
+	 * The type of service (IPv4) or traffic class (IPv6) field to be set on
+	 * tunneled packets.
+	 *
+	 * Since: 1.2
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_TOS,
+		 g_param_spec_uint (NM_SETTING_IP_TUNNEL_TOS, "", "",
+		                    0, 255, 0,
+		                    G_PARAM_READWRITE |
+		                    G_PARAM_CONSTRUCT |
+		                    NM_SETTING_PARAM_INFERRABLE |
+		                    G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMSettingIPTunnel:path-mtu-discovery
+	 *
+	 * Whether to enable Path MTU Discovery on this tunnel.
+	 *
+	 * Since: 1.2
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_PATH_MTU_DISCOVERY,
+		 g_param_spec_boolean (NM_SETTING_IP_TUNNEL_PATH_MTU_DISCOVERY, "", "",
+		                       TRUE,
+		                       G_PARAM_READWRITE |
+		                       G_PARAM_CONSTRUCT |
+		                       NM_SETTING_PARAM_INFERRABLE |
+		                       G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMSettingIPTunnel:input-key:
+	 *
+	 * The key used for tunnel input packets; the property is valid only for
+	 * certain tunnel modes (GRE, IP6GRE). If empty, no key is used.
+	 *
+	 * Since: 1.2
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_INPUT_KEY,
+		 g_param_spec_string (NM_SETTING_IP_TUNNEL_INPUT_KEY, "", "",
+		                      NULL,
+		                      G_PARAM_READWRITE |
+		                      NM_SETTING_PARAM_INFERRABLE |
+		                      G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMSettingIPTunnel:output-key:
+	 *
+	 * The key used for tunnel output packets; the property is valid only for
+	 * certain tunnel modes (GRE, IP6GRE). If empty, no key is used.
+	 *
+	 * Since: 1.2
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_OUTPUT_KEY,
+		 g_param_spec_string (NM_SETTING_IP_TUNNEL_OUTPUT_KEY, "", "",
+		                      NULL,
+		                      G_PARAM_READWRITE |
+		                      NM_SETTING_PARAM_INFERRABLE |
+		                      G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMSettingIPTunnel:encapsulation-limit:
+	 *
+	 * How many additional levels of encapsulation are permitted to be prepended
+	 * to packets. This property applies only to IPv6 tunnels.
+	 *
+	 * Since: 1.2
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_ENCAPSULATION_LIMIT,
+		 g_param_spec_uint (NM_SETTING_IP_TUNNEL_ENCAPSULATION_LIMIT, "", "",
+		                    0, 255, 0,
+		                    G_PARAM_READWRITE |
+		                    G_PARAM_CONSTRUCT |
+		                    NM_SETTING_PARAM_INFERRABLE |
+		                    G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMSettingIPTunnel:flow-label:
+	 *
+	 * The flow label to assign to tunnel packets. This property applies only to
+	 * IPv6 tunnels.
+	 *
+	 * Since: 1.2
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_FLOW_LABEL,
+		 g_param_spec_uint (NM_SETTING_IP_TUNNEL_FLOW_LABEL, "", "",
+		                    0, (1 << 20) - 1, 0,
+		                    G_PARAM_READWRITE |
+		                    G_PARAM_CONSTRUCT |
+		                    NM_SETTING_PARAM_INFERRABLE |
+		                    G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMSettingIPTunel:mtu:
+	 *
+	 * If non-zero, only transmit packets of the specified size or smaller,
+	 * breaking larger packets up into multiple fragments.
+	 *
+	 * Since: 1.2
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_MTU,
+		 g_param_spec_uint (NM_SETTING_IP_TUNNEL_MTU, "", "",
+		                    0, G_MAXUINT, 0,
+		                    G_PARAM_READWRITE |
+		                    G_PARAM_CONSTRUCT |
+		                    NM_SETTING_PARAM_FUZZY_IGNORE |
+		                    G_PARAM_STATIC_STRINGS));
+}
diff --git a/libnm-core/nm-setting-ip-tunnel.h b/libnm-core/nm-setting-ip-tunnel.h
new file mode 100644
index 00000000..09814f35
--- /dev/null
+++ b/libnm-core/nm-setting-ip-tunnel.h
@@ -0,0 +1,98 @@
+/* -*- 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 2015 Red Hat, Inc.
+ */
+
+#ifndef __NM_SETTING_IP_TUNNEL_H__
+#define __NM_SETTING_IP_TUNNEL_H__
+
+#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION)
+#error "Only <NetworkManager.h> can be included directly."
+#endif
+
+#include <nm-setting.h>
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_SETTING_IP_TUNNEL            (nm_setting_ip_tunnel_get_type ())
+#define NM_SETTING_IP_TUNNEL(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_IP_TUNNEL, NMSettingIPTunnel))
+#define NM_SETTING_IP_TUNNEL_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_IP_TUNNEL, NMSettingIPTunnelClass))
+#define NM_IS_SETTING_IP_TUNNEL(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_IP_TUNNEL))
+#define NM_IS_SETTING_IP_TUNNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_IP_TUNNEL))
+#define NM_SETTING_IP_TUNNEL_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_IP_TUNNEL, NMSettingIPTunnelClass))
+
+#define NM_SETTING_IP_TUNNEL_SETTING_NAME        "ip-tunnel"
+
+#define NM_SETTING_IP_TUNNEL_PARENT              "parent"
+#define NM_SETTING_IP_TUNNEL_MODE                "mode"
+#define NM_SETTING_IP_TUNNEL_LOCAL               "local"
+#define NM_SETTING_IP_TUNNEL_REMOTE              "remote"
+#define NM_SETTING_IP_TUNNEL_TTL                 "ttl"
+#define NM_SETTING_IP_TUNNEL_TOS                 "tos"
+#define NM_SETTING_IP_TUNNEL_PATH_MTU_DISCOVERY  "path-mtu-discovery"
+#define NM_SETTING_IP_TUNNEL_INPUT_KEY           "input-key"
+#define NM_SETTING_IP_TUNNEL_OUTPUT_KEY          "output-key"
+#define NM_SETTING_IP_TUNNEL_ENCAPSULATION_LIMIT "encapsulation-limit"
+#define NM_SETTING_IP_TUNNEL_FLOW_LABEL          "flow-label"
+#define NM_SETTING_IP_TUNNEL_MTU                 "mtu"
+
+struct _NMSettingIPTunnel {
+	NMSetting parent;
+};
+
+typedef struct {
+	NMSettingClass parent;
+
+	/*< private >*/
+	gpointer padding[4];
+} NMSettingIPTunnelClass;
+
+NM_AVAILABLE_IN_1_2
+GType nm_setting_ip_tunnel_get_type (void);
+
+NM_AVAILABLE_IN_1_2
+NMSetting * nm_setting_ip_tunnel_new (void);
+
+NM_AVAILABLE_IN_1_2
+const char *nm_setting_ip_tunnel_get_parent (NMSettingIPTunnel *setting);
+NM_AVAILABLE_IN_1_2
+NMIPTunnelMode nm_setting_ip_tunnel_get_mode (NMSettingIPTunnel *setting);
+NM_AVAILABLE_IN_1_2
+const char *nm_setting_ip_tunnel_get_local (NMSettingIPTunnel *setting);
+NM_AVAILABLE_IN_1_2
+const char *nm_setting_ip_tunnel_get_remote (NMSettingIPTunnel *setting);
+NM_AVAILABLE_IN_1_2
+guint nm_setting_ip_tunnel_get_ttl (NMSettingIPTunnel *setting);
+NM_AVAILABLE_IN_1_2
+guint nm_setting_ip_tunnel_get_tos (NMSettingIPTunnel *setting);
+NM_AVAILABLE_IN_1_2
+gboolean nm_setting_ip_tunnel_get_path_mtu_discovery (NMSettingIPTunnel *setting);
+NM_AVAILABLE_IN_1_2
+const char *nm_setting_ip_tunnel_get_input_key (NMSettingIPTunnel *setting);
+NM_AVAILABLE_IN_1_2
+const char *nm_setting_ip_tunnel_get_output_key (NMSettingIPTunnel *setting);
+NM_AVAILABLE_IN_1_2
+guint nm_setting_ip_tunnel_get_encapsulation_limit (NMSettingIPTunnel *setting);
+NM_AVAILABLE_IN_1_2
+guint nm_setting_ip_tunnel_get_flow_label (NMSettingIPTunnel *setting);
+NM_AVAILABLE_IN_1_2
+guint nm_setting_ip_tunnel_get_mtu (NMSettingIPTunnel *setting);
+
+G_END_DECLS
+
+#endif /* __NM_SETTING_IP_TUNNEL_H__ */
diff --git a/libnm-core/nm-setting-ip4-config.c b/libnm-core/nm-setting-ip4-config.c
index 81cc1f88..7708b6c5 100644
--- a/libnm-core/nm-setting-ip4-config.c
+++ b/libnm-core/nm-setting-ip4-config.c
@@ -22,7 +22,6 @@
 #include "config.h"
 
 #include <string.h>
-#include <glib/gi18n-lib.h>
 
 #include "nm-setting-ip4-config.h"
 #include "nm-setting-private.h"
@@ -59,11 +58,15 @@ NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_IP4_CONFIG)
 
 typedef struct {
 	char *dhcp_client_id;
+	int dhcp_timeout;
+	char *dhcp_fqdn;
 } NMSettingIP4ConfigPrivate;
 
 enum {
 	PROP_0,
 	PROP_DHCP_CLIENT_ID,
+	PROP_DHCP_TIMEOUT,
+	PROP_DHCP_FQDN,
 
 	LAST_PROP
 };
@@ -99,6 +102,45 @@ nm_setting_ip4_config_get_dhcp_client_id (NMSettingIP4Config *setting)
 	return NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting)->dhcp_client_id;
 }
 
+/**
+ * nm_setting_ip4_config_get_dhcp_timeout:
+ * @setting: the #NMSettingIP4Config
+ *
+ * Returns the value contained in the #NMSettingIP4Config:dhcp-timeout
+ * property.
+ *
+ * Returns: the configured DHCP timeout in seconds. 0 = default for
+ * the particular kind of device.
+ *
+ * Since: 1.2
+ **/
+int
+nm_setting_ip4_config_get_dhcp_timeout (NMSettingIP4Config *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_IP4_CONFIG (setting), 0);
+
+	return NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting)->dhcp_timeout;
+}
+
+/**
+ * nm_setting_ip4_config_get_dhcp_fqdn:
+ * @setting: the #NMSettingIP4Config
+ *
+ * Returns the value contained in the #NMSettingIP4Config:dhcp-fqdn
+ * property.
+ *
+ * Returns: the configured FQDN to send to the DHCP server
+ *
+ * Since: 1.2
+ **/
+const char *
+nm_setting_ip4_config_get_dhcp_fqdn (NMSettingIP4Config *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_IP4_CONFIG (setting), NULL);
+
+	return NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting)->dhcp_fqdn;
+}
+
 static gboolean
 verify (NMSetting *setting, NMConnection *connection, GError **error)
 {
@@ -180,6 +222,31 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
 		return FALSE;
 	}
 
+	if (priv->dhcp_fqdn && !*priv->dhcp_fqdn) {
+		g_set_error_literal (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY,
+		                     _("property is empty"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_SETTING_IP4_CONFIG_DHCP_FQDN);
+		return FALSE;
+	}
+
+	if (priv->dhcp_fqdn && !strchr (priv->dhcp_fqdn, '.')) {
+		g_set_error (error,
+		             NM_CONNECTION_ERROR,
+		             NM_CONNECTION_ERROR_INVALID_PROPERTY,
+		             _("'%s' is not a valid FQDN"), priv->dhcp_fqdn);
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_SETTING_IP4_CONFIG_DHCP_FQDN);
+		return FALSE;
+	}
+
+	if (priv->dhcp_fqdn && nm_setting_ip_config_get_dhcp_hostname (s_ip)) {
+		g_set_error_literal (error,
+		                     NM_CONNECTION_ERROR,
+		                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
+		                     _("property cannot be set when dhcp-hostname is also set"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_SETTING_IP4_CONFIG_DHCP_FQDN);
+		return FALSE;
+	}
+
 	return TRUE;
 }
 
@@ -194,6 +261,7 @@ finalize (GObject *object)
 	NMSettingIP4ConfigPrivate *priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE (object);
 
 	g_free (priv->dhcp_client_id);
+	g_free (priv->dhcp_fqdn);
 
 	G_OBJECT_CLASS (nm_setting_ip4_config_parent_class)->finalize (object);
 }
@@ -209,6 +277,13 @@ set_property (GObject *object, guint prop_id,
 		g_free (priv->dhcp_client_id);
 		priv->dhcp_client_id = g_value_dup_string (value);
 		break;
+	case PROP_DHCP_TIMEOUT:
+		priv->dhcp_timeout = g_value_get_uint (value);
+		break;
+	case PROP_DHCP_FQDN:
+		g_free (priv->dhcp_fqdn);
+		priv->dhcp_fqdn = g_value_dup_string (value);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -225,6 +300,12 @@ get_property (GObject *object, guint prop_id,
 	case PROP_DHCP_CLIENT_ID:
 		g_value_set_string (value, nm_setting_ip4_config_get_dhcp_client_id (s_ip4));
 		break;
+	case PROP_DHCP_TIMEOUT:
+		g_value_set_uint (value, nm_setting_ip4_config_get_dhcp_timeout (s_ip4));
+		break;
+	case PROP_DHCP_FQDN:
+		g_value_set_string (value, nm_setting_ip4_config_get_dhcp_fqdn (s_ip4));
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -549,7 +630,8 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *ip4_class)
 	/* ---ifcfg-rh---
 	 * property: dhcp-hostname
 	 * variable: DHCP_HOSTNAME
-	 * description: Hostname to send to the DHCP server.
+	 * description: Hostname to send to the DHCP server. When both DHCP_HOSTNAME and
+	 *    DHCP_FQDN are specified only the latter is used.
 	 * ---end---
 	 */
 
@@ -600,6 +682,51 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *ip4_class)
 		                      G_PARAM_READWRITE |
 		                      G_PARAM_STATIC_STRINGS));
 
+	/**
+	 * NMSettingIP4Config:dhcp-timeout:
+	 *
+	 * A timeout for a DHCP transaction in seconds.
+	 **/
+	/* ---ifcfg-rh---
+	 * property: dhcp-timeout
+	 * variable: DHCP_TIMEOUT(+)
+	 * description: A timeout after which the DHCP transaction fails in case of no response.
+	 * example: DHCP_TIMEOUT=10
+	 * ---end---
+	 */
+	g_object_class_install_property
+		(object_class, PROP_DHCP_TIMEOUT,
+                 g_param_spec_uint (NM_SETTING_IP4_CONFIG_DHCP_TIMEOUT, "", "",
+                                    0, G_MAXUINT32, 0,
+                                    G_PARAM_READWRITE |
+                                    NM_SETTING_PARAM_FUZZY_IGNORE |
+                                    G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMSettingIP4Config:dhcp-fqdn:
+	 *
+	 * If the #NMSettingIPConfig:dhcp-send-hostname property is %TRUE, then the
+	 * specified FQDN will be sent to the DHCP server when acquiring a lease. This
+	 * property and #NMSettingIPConfig:dhcp-hostname are mutually exclusive and
+	 * cannot be set at the same time.
+	 *
+	 * Since: 1.2
+	 */
+	/* ---ifcfg-rh---
+	 * property: dhcp-fqdn
+	 * variable: DHCP_FQDN
+	 * description: FQDN to send to the DHCP server. When both DHCP_HOSTNAME and
+	 *    DHCP_FQDN are specified only the latter is used.
+	 * example: DHCP_FQDN=foo.bar.com
+	 * ---end---
+	 */
+	g_object_class_install_property
+		(object_class, PROP_DHCP_FQDN,
+		 g_param_spec_string (NM_SETTING_IP4_CONFIG_DHCP_FQDN, "", "",
+		                      NULL,
+		                      G_PARAM_READWRITE |
+		                      G_PARAM_STATIC_STRINGS));
+
 	/* IP4-specific property overrides */
 
 	/* ---dbus---
diff --git a/libnm-core/nm-setting-ip4-config.h b/libnm-core/nm-setting-ip4-config.h
index e944dfe3..a78df703 100644
--- a/libnm-core/nm-setting-ip4-config.h
+++ b/libnm-core/nm-setting-ip4-config.h
@@ -41,6 +41,8 @@ G_BEGIN_DECLS
 #define NM_SETTING_IP4_CONFIG_SETTING_NAME "ipv4"
 
 #define NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID     "dhcp-client-id"
+#define NM_SETTING_IP4_CONFIG_DHCP_TIMEOUT       "dhcp-timeout"
+#define NM_SETTING_IP4_CONFIG_DHCP_FQDN          "dhcp-fqdn"
 
 /**
  * NM_SETTING_IP4_CONFIG_METHOD_AUTO:
@@ -102,6 +104,10 @@ GType nm_setting_ip4_config_get_type (void);
 NMSetting *nm_setting_ip4_config_new (void);
 
 const char *nm_setting_ip4_config_get_dhcp_client_id     (NMSettingIP4Config *setting);
+NM_AVAILABLE_IN_1_2
+int nm_setting_ip4_config_get_dhcp_timeout               (NMSettingIP4Config *setting);
+NM_AVAILABLE_IN_1_2
+const char *nm_setting_ip4_config_get_dhcp_fqdn          (NMSettingIP4Config *setting);
 
 G_END_DECLS
 
diff --git a/libnm-core/nm-setting-ip6-config.c b/libnm-core/nm-setting-ip6-config.c
index 619e002c..bc516d6e 100644
--- a/libnm-core/nm-setting-ip6-config.c
+++ b/libnm-core/nm-setting-ip6-config.c
@@ -22,11 +22,11 @@
 #include "config.h"
 
 #include <string.h>
-#include <glib/gi18n-lib.h>
 
 #include "nm-setting-ip6-config.h"
 #include "nm-setting-private.h"
 #include "nm-core-enum-types.h"
+#include "nm-macros-internal.h"
 
 /**
  * SECTION:nm-setting-ip6-config
@@ -58,12 +58,14 @@ NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_IP6_CONFIG)
 
 typedef struct {
 	NMSettingIP6ConfigPrivacy ip6_privacy;
+	NMSettingIP6ConfigAddrGenMode addr_gen_mode;
 } NMSettingIP6ConfigPrivate;
 
 
 enum {
 	PROP_0,
 	PROP_IP6_PRIVACY,
+	PROP_ADDR_GEN_MODE,
 
 	LAST_PROP
 };
@@ -98,9 +100,30 @@ nm_setting_ip6_config_get_ip6_privacy (NMSettingIP6Config *setting)
 	return NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->ip6_privacy;
 }
 
+/**
+ * nm_setting_ip6_config_get_addr_gen_mode:
+ * @setting: the #NMSettingIP6Config
+ *
+ * Returns the value contained in the #NMSettingIP6Config:addr-gen-mode
+ * property.
+ *
+ * Returns: IPv6 Address Generation Mode.
+ *
+ * Since: 1.2
+ **/
+NMSettingIP6ConfigAddrGenMode
+nm_setting_ip6_config_get_addr_gen_mode (NMSettingIP6Config *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting),
+	                      NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY);
+
+	return NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->addr_gen_mode;
+}
+
 static gboolean
 verify (NMSetting *setting, NMConnection *connection, GError **error)
 {
+	NMSettingIP6ConfigPrivate *priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting);
 	NMSettingIPConfig *s_ip = NM_SETTING_IP_CONFIG (setting);
 	NMSettingVerifyResult ret;
 	const char *method;
@@ -167,6 +190,17 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
 		return FALSE;
 	}
 
+	if (!NM_IN_SET (priv->addr_gen_mode,
+	                NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64,
+	                NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY)) {
+		g_set_error_literal (error,
+		                     NM_CONNECTION_ERROR,
+		                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
+		                      _("property is invalid"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_SETTING_IP_CONFIG_METHOD);
+		return FALSE;
+	}
+
 	return TRUE;
 }
 
@@ -331,6 +365,9 @@ set_property (GObject *object, guint prop_id,
 	case PROP_IP6_PRIVACY:
 		priv->ip6_privacy = g_value_get_enum (value);
 		break;
+	case PROP_ADDR_GEN_MODE:
+		priv->addr_gen_mode = g_value_get_int (value);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -347,6 +384,9 @@ get_property (GObject *object, guint prop_id,
 	case PROP_IP6_PRIVACY:
 		g_value_set_enum (value, priv->ip6_privacy);
 		break;
+	case PROP_ADDR_GEN_MODE:
+		g_value_set_int (value, priv->addr_gen_mode);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -512,6 +552,10 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *ip6_class)
 	 *
 	 * If also global configuration is unspecified or set to "-1", fallback to read
 	 * "/proc/sys/net/ipv6/conf/default/use_tempaddr".
+	 *
+	 * Note that this setting is distinct from the Stable Privacy addresses
+	 * that can be enabled with the "addr-gen-mode" property's "stable-privacy"
+	 * setting as another way of avoiding host tracking with IPv6 addresses.
 	 **/
 	/* ---ifcfg-rh---
 	 * property: ip6-privacy
@@ -532,6 +576,53 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *ip6_class)
 		                    G_PARAM_CONSTRUCT |
 		                    G_PARAM_STATIC_STRINGS));
 
+	/**
+	 * NMSettingIP6Config:addr-gen-mode:
+	 *
+	 * Configure method for creating the address for use with RFC4862 IPv6
+	 * Stateless Address Autoconfiguration. The permitted values are: "eui64",
+	 * "stable-privacy" or unset.
+	 *
+	 * If the property is set to "eui64", the addresses will be generated
+	 * using the interface tokens derived from  hardware address. This makes
+	 * the host part of the address to stay constant, making it possible
+	 * to track host's presence when it changes networks. The address changes
+	 * when the interface hardware is replaced.
+	 *
+	 * The value of "stable-privacy" enables use of cryptographically
+	 * secure hash of a secret host-specific key along with the connection
+	 * identification and the network address as specified by RFC7217.
+	 * This makes it impossible to use the address track host's presence,
+	 * and makes the address stable when the network interface hardware is
+	 * replaced.
+	 *
+	 * Leaving this unset causes a default that could be subject to change
+	 * in future versions to be used.
+	 *
+	 * Note that this setting is distinct from the Privacy Extensions as
+	 * configured by "ip6-privacy" property and it does not affect the
+	 * temporary addresses configured with this option.
+	 *
+	 * Since: 1.2
+	 **/
+	/* ---ifcfg-rh---
+	 * property: addr-gen-mode
+	 * variable: IPV6_ADDR_GEN_MODE
+	 * values: IPV6_ADDR_GEN_MODE: eui64, stable-privacy
+	 * default: eui64
+	 * description: Configure IPv6 Stable Privacy addressing for SLAAC (RFC7217).
+	 * example: IPV6_ADDR_GEN_MODE=stable-privacy
+	 * ---end---
+	 */
+	g_object_class_install_property
+		(object_class, PROP_ADDR_GEN_MODE,
+		 g_param_spec_int (NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE, "", "",
+		                   G_MININT, G_MAXINT,
+		                   NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY,
+		                   G_PARAM_READWRITE |
+		                   G_PARAM_CONSTRUCT |
+		                   G_PARAM_STATIC_STRINGS));
+
 	/* IP6-specific property overrides */
 
 	/* ---dbus---
diff --git a/libnm-core/nm-setting-ip6-config.h b/libnm-core/nm-setting-ip6-config.h
index b791e937..f8923d19 100644
--- a/libnm-core/nm-setting-ip6-config.h
+++ b/libnm-core/nm-setting-ip6-config.h
@@ -41,6 +41,8 @@ G_BEGIN_DECLS
 
 #define NM_SETTING_IP6_CONFIG_IP6_PRIVACY "ip6-privacy"
 
+#define NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE "addr-gen-mode"
+
 /**
  * NM_SETTING_IP6_CONFIG_METHOD_IGNORE:
  *
@@ -114,6 +116,25 @@ typedef enum {
 	NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR = 2
 } NMSettingIP6ConfigPrivacy;
 
+/**
+ * NMSettingIP6ConfigAddrGenMode:
+ * @NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64: The Interface Identifier is derived
+ * from the interface hardware address.
+ * @NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY: The Interface Identifier
+ * is created by using a cryptographically secure hash of a secret host-specific
+ * key along with the connection identification and the network address as
+ * specified by RFC7217.
+ *
+ * #NMSettingIP6ConfigAddrGenMode controls how the the Interface Identifier for
+ * RFC4862 Stateless Address Autoconfiguration is created.
+ *
+ * Since: 1.2
+ */
+typedef enum {
+	NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64 = 0,
+	NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY = 1,
+} NMSettingIP6ConfigAddrGenMode;
+
 struct _NMSettingIP6Config {
 	NMSettingIPConfig parent;
 };
@@ -130,6 +151,8 @@ GType nm_setting_ip6_config_get_type (void);
 NMSetting *nm_setting_ip6_config_new (void);
 
 NMSettingIP6ConfigPrivacy nm_setting_ip6_config_get_ip6_privacy (NMSettingIP6Config *setting);
+NM_AVAILABLE_IN_1_2
+NMSettingIP6ConfigAddrGenMode nm_setting_ip6_config_get_addr_gen_mode (NMSettingIP6Config *setting);
 
 G_END_DECLS
 
diff --git a/libnm-core/nm-setting-macvlan.c b/libnm-core/nm-setting-macvlan.c
new file mode 100644
index 00000000..7bedf514
--- /dev/null
+++ b/libnm-core/nm-setting-macvlan.c
@@ -0,0 +1,350 @@
+/* -*- 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 2015 Red Hat, Inc.
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "nm-setting-macvlan.h"
+#include "nm-utils.h"
+#include "nm-setting-connection.h"
+#include "nm-setting-private.h"
+#include "nm-setting-wired.h"
+#include "nm-connection-private.h"
+
+/**
+ * SECTION:nm-setting-macvlan
+ * @short_description: Describes connection properties for macvlan interfaces
+ *
+ * The #NMSettingMacvlan object is a #NMSetting subclass that describes properties
+ * necessary for connection to macvlan interfaces.
+ **/
+
+G_DEFINE_TYPE_WITH_CODE (NMSettingMacvlan, nm_setting_macvlan, NM_TYPE_SETTING,
+                         _nm_register_setting (MACVLAN, 1))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_MACVLAN)
+
+#define NM_SETTING_MACVLAN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_MACVLAN, NMSettingMacvlanPrivate))
+
+typedef struct {
+	char *parent;
+	NMSettingMacvlanMode mode;
+	gboolean promiscuous;
+	gboolean tap;
+} NMSettingMacvlanPrivate;
+
+enum {
+	PROP_0,
+	PROP_PARENT,
+	PROP_MODE,
+	PROP_PROMISCUOUS,
+	PROP_TAP,
+	LAST_PROP
+};
+
+/**
+ * nm_setting_macvlan_new:
+ *
+ * Creates a new #NMSettingMacvlan object with default values.
+ *
+ * Returns: (transfer full): the new empty #NMSettingMacvlan object
+ *
+ * Since: 1.2
+ **/
+NMSetting *
+nm_setting_macvlan_new (void)
+{
+	return (NMSetting *) g_object_new (NM_TYPE_SETTING_MACVLAN, NULL);
+}
+
+/**
+ * nm_setting_macvlan_get_parent:
+ * @setting: the #NMSettingMacvlan
+ *
+ * Returns: the #NMSettingMacvlan:parent property of the setting
+ *
+ * Since: 1.2
+ **/
+const char *
+nm_setting_macvlan_get_parent (NMSettingMacvlan *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_MACVLAN (setting), NULL);
+	return NM_SETTING_MACVLAN_GET_PRIVATE (setting)->parent;
+}
+
+/**
+ * nm_setting_macvlan_get_mode:
+ * @setting: the #NMSettingMacvlan
+ *
+ * Returns: the #NMSettingMacvlan:mode property of the setting
+ *
+ * Since: 1.2
+ **/
+NMSettingMacvlanMode
+nm_setting_macvlan_get_mode (NMSettingMacvlan *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_MACVLAN (setting), NM_SETTING_MACVLAN_MODE_UNKNOWN);
+	return NM_SETTING_MACVLAN_GET_PRIVATE (setting)->mode;
+}
+
+/**
+ * nm_setting_macvlan_get_promiscuous:
+ * @setting: the #NMSettingMacvlan
+ *
+ * Returns: the #NMSettingMacvlan:promiscuous property of the setting
+ *
+ * Since: 1.2
+ **/
+gboolean
+nm_setting_macvlan_get_promiscuous (NMSettingMacvlan *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_MACVLAN (setting), FALSE);
+	return NM_SETTING_MACVLAN_GET_PRIVATE (setting)->promiscuous;
+}
+
+/**
+ * nm_setting_macvlan_get_tap:
+ * @setting: the #NMSettingMacvlan
+ *
+ * Returns: the #NMSettingMacvlan:tap property of the setting
+ *
+ * Since: 1.2
+ **/
+gboolean
+nm_setting_macvlan_get_tap (NMSettingMacvlan *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_MACVLAN (setting), FALSE);
+	return NM_SETTING_MACVLAN_GET_PRIVATE (setting)->tap;
+}
+
+/*********************************************************************/
+
+static void
+nm_setting_macvlan_init (NMSettingMacvlan *setting)
+{
+}
+
+static gboolean
+verify (NMSetting *setting, NMConnection *connection, GError **error)
+{
+	NMSettingMacvlanPrivate *priv = NM_SETTING_MACVLAN_GET_PRIVATE (setting);
+	NMSettingConnection *s_con;
+	NMSettingWired *s_wired;
+
+	if (connection) {
+		s_con = nm_connection_get_setting_connection (connection);
+		s_wired = nm_connection_get_setting_wired (connection);
+	} else {
+		s_con = NULL;
+		s_wired = NULL;
+	}
+
+	if (priv->parent) {
+		if (   !nm_utils_is_uuid (priv->parent)
+		    && !nm_utils_iface_valid_name (priv->parent)) {
+			g_set_error (error,
+			             NM_CONNECTION_ERROR,
+			             NM_CONNECTION_ERROR_INVALID_PROPERTY,
+			             _("'%s' is neither an UUID nor an interface name"),
+			             priv->parent);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_MACVLAN_SETTING_NAME, NM_SETTING_MACVLAN_PARENT);
+			return FALSE;
+		}
+	} else {
+		/* If parent is NULL, the parent must be specified via
+		 * NMSettingWired:mac-address.
+		 */
+		if (   connection
+		    && (!s_wired || !nm_setting_wired_get_mac_address (s_wired))) {
+			g_set_error (error,
+			             NM_CONNECTION_ERROR,
+			             NM_CONNECTION_ERROR_MISSING_PROPERTY,
+			             _("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_MACVLAN_SETTING_NAME, NM_SETTING_MACVLAN_PARENT);
+			return FALSE;
+		}
+	}
+
+	if (!priv->promiscuous && priv->mode != NM_SETTING_MACVLAN_MODE_PASSTHRU) {
+		g_set_error_literal (error,
+		                     NM_CONNECTION_ERROR,
+		                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
+		                     _("non promiscuous operation is allowed only in passthru mode'"));
+		g_prefix_error (error, "%s.%s: ",
+		                NM_SETTING_MACVLAN_SETTING_NAME,
+		                NM_SETTING_MACVLAN_PROMISCUOUS);
+		return FALSE;
+
+	}
+
+	return TRUE;
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+              const GValue *value, GParamSpec *pspec)
+{
+	NMSettingMacvlan *setting = NM_SETTING_MACVLAN (object);
+	NMSettingMacvlanPrivate *priv = NM_SETTING_MACVLAN_GET_PRIVATE (setting);
+
+	switch (prop_id) {
+	case PROP_PARENT:
+		g_free (priv->parent);
+		priv->parent = g_value_dup_string (value);
+		break;
+	case PROP_MODE:
+		priv->mode = g_value_get_uint (value);
+		break;
+	case PROP_PROMISCUOUS:
+		priv->promiscuous = g_value_get_boolean (value);
+		break;
+	case PROP_TAP:
+		priv->tap = g_value_get_boolean (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)
+{
+	NMSettingMacvlan *setting = NM_SETTING_MACVLAN (object);
+	NMSettingMacvlanPrivate *priv = NM_SETTING_MACVLAN_GET_PRIVATE (setting);
+
+	switch (prop_id) {
+	case PROP_PARENT:
+		g_value_set_string (value, priv->parent);
+		break;
+	case PROP_MODE:
+		g_value_set_uint (value, priv->mode);
+		break;
+	case PROP_PROMISCUOUS:
+		g_value_set_boolean (value, priv->promiscuous);
+		break;
+	case PROP_TAP:
+		g_value_set_boolean (value, priv->tap);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+finalize (GObject *object)
+{
+	NMSettingMacvlan *setting = NM_SETTING_MACVLAN (object);
+	NMSettingMacvlanPrivate *priv = NM_SETTING_MACVLAN_GET_PRIVATE (setting);
+
+	g_free (priv->parent);
+
+	G_OBJECT_CLASS (nm_setting_macvlan_parent_class)->finalize (object);
+}
+
+static void
+nm_setting_macvlan_class_init (NMSettingMacvlanClass *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 (NMSettingMacvlanPrivate));
+
+	/* virtual methods */
+	object_class->set_property = set_property;
+	object_class->get_property = get_property;
+	object_class->finalize     = finalize;
+	parent_class->verify       = verify;
+
+	/* Properties */
+
+	/**
+	 * NMSettingMacvlan:parent:
+	 *
+	 * If given, specifies the parent interface name or parent connection UUID
+	 * from which this MAC-VLAN interface should be created.  If this property is
+	 * not specified, the connection must contain an #NMSettingWired setting
+	 * with a #NMSettingWired:mac-address property.
+	 *
+	 * Since: 1.2
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_PARENT,
+		 g_param_spec_string (NM_SETTING_MACVLAN_PARENT, "", "",
+		                      NULL,
+		                      G_PARAM_READWRITE |
+		                      G_PARAM_CONSTRUCT |
+		                      NM_SETTING_PARAM_INFERRABLE |
+		                      G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMSettingMacvlan:mode:
+	 *
+	 * The macvlan mode, which specifies the communication mechanism between multiple
+	 * macvlans on the same lower device.
+	 *
+	 * Since: 1.2
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_MODE,
+		 g_param_spec_uint (NM_SETTING_MACVLAN_MODE, "", "",
+		                    0, G_MAXUINT, 0,
+		                    G_PARAM_READWRITE |
+		                    G_PARAM_CONSTRUCT |
+		                    NM_SETTING_PARAM_INFERRABLE |
+		                    G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMSettingMacvlan:promiscuous:
+	 *
+	 * Whether the interface should be put in promiscuous mode.
+	 *
+	 * Since: 1.2
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_PROMISCUOUS,
+		 g_param_spec_boolean (NM_SETTING_MACVLAN_PROMISCUOUS, "", "",
+		                       TRUE,
+		                       G_PARAM_READWRITE |
+		                       G_PARAM_CONSTRUCT |
+		                       NM_SETTING_PARAM_INFERRABLE |
+		                       G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMSettingMacvlan:tap:
+	 *
+	 * Whether the interface should be a MACVTAP.
+	 *
+	 * Since: 1.2
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_TAP,
+		 g_param_spec_boolean (NM_SETTING_MACVLAN_TAP, "", "",
+		                       FALSE,
+		                       G_PARAM_READWRITE |
+		                       G_PARAM_CONSTRUCT |
+		                       NM_SETTING_PARAM_INFERRABLE |
+		                       G_PARAM_STATIC_STRINGS));
+}
diff --git a/libnm-core/nm-setting-macvlan.h b/libnm-core/nm-setting-macvlan.h
new file mode 100644
index 00000000..3922cd93
--- /dev/null
+++ b/libnm-core/nm-setting-macvlan.h
@@ -0,0 +1,94 @@
+/* -*- 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 2015 Red Hat, Inc.
+ */
+
+#ifndef __NM_SETTING_MACVLAN_H__
+#define __NM_SETTING_MACVLAN_H__
+
+#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION)
+#error "Only <NetworkManager.h> can be included directly."
+#endif
+
+#include "nm-setting.h"
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_SETTING_MACVLAN            (nm_setting_macvlan_get_type ())
+#define NM_SETTING_MACVLAN(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_MACVLAN, NMSettingMacvlan))
+#define NM_SETTING_MACVLAN_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_MACVLANCONFIG, NMSettingMacvlanClass))
+#define NM_IS_SETTING_MACVLAN(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_MACVLAN))
+#define NM_IS_SETTING_MACVLAN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_MACVLAN))
+#define NM_SETTING_MACVLAN_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_MACVLAN, NMSettingMacvlanClass))
+
+#define NM_SETTING_MACVLAN_SETTING_NAME         "macvlan"
+
+#define NM_SETTING_MACVLAN_PARENT               "parent"
+#define NM_SETTING_MACVLAN_MODE                 "mode"
+#define NM_SETTING_MACVLAN_PROMISCUOUS          "promiscuous"
+#define NM_SETTING_MACVLAN_TAP                  "tap"
+
+struct _NMSettingMacvlan {
+	NMSetting parent;
+};
+
+typedef struct {
+	NMSettingClass parent;
+
+	/*< private >*/
+	gpointer padding[4];
+} NMSettingMacvlanClass;
+
+/**
+ * NMSettingMacvlanMode:
+ * @NM_SETTING_MACVLAN_MODE_UNKNOWN: unknown/unset mode
+ * @NM_SETTING_MACVLAN_MODE_VEPA: Virtual Ethernet Port Aggregator mode
+ * @NM_SETTING_MACVLAN_MODE_BRIDGE: bridge mode
+ * @NM_SETTING_MACVLAN_MODE_PRIVATE: private mode
+ * @NM_SETTING_MACVLAN_MODE_PASSTHRU: passthru mode
+ * @NM_SETTING_MACVLAN_MODE_SOURCE: source mode
+ **/
+typedef enum {
+	NM_SETTING_MACVLAN_MODE_UNKNOWN   = 0,
+	NM_SETTING_MACVLAN_MODE_VEPA      = 1,
+	NM_SETTING_MACVLAN_MODE_BRIDGE    = 2,
+	NM_SETTING_MACVLAN_MODE_PRIVATE   = 3,
+	NM_SETTING_MACVLAN_MODE_PASSTHRU  = 4,
+	NM_SETTING_MACVLAN_MODE_SOURCE    = 5,
+	_NM_SETTING_MACVLAN_MODE_NUM,     /*< skip >*/
+	NM_SETTING_MACVLAN_MODE_LAST      = _NM_SETTING_MACVLAN_MODE_NUM - 1, /*< skip >*/
+} NMSettingMacvlanMode;
+
+NM_AVAILABLE_IN_1_2
+GType nm_setting_macvlan_get_type (void);
+NM_AVAILABLE_IN_1_2
+NMSetting *nm_setting_macvlan_new (void);
+
+NM_AVAILABLE_IN_1_2
+const char          *nm_setting_macvlan_get_parent (NMSettingMacvlan *setting);
+NM_AVAILABLE_IN_1_2
+NMSettingMacvlanMode nm_setting_macvlan_get_mode (NMSettingMacvlan *setting);
+NM_AVAILABLE_IN_1_2
+gboolean             nm_setting_macvlan_get_promiscuous (NMSettingMacvlan *setting);
+NM_AVAILABLE_IN_1_2
+gboolean             nm_setting_macvlan_get_tap (NMSettingMacvlan *setting);
+
+G_END_DECLS
+
+#endif /* __NM_SETTING_MACVLAN_H__ */
diff --git a/libnm-core/nm-setting-olpc-mesh.c b/libnm-core/nm-setting-olpc-mesh.c
index a3a5d881..4b42c365 100644
--- a/libnm-core/nm-setting-olpc-mesh.c
+++ b/libnm-core/nm-setting-olpc-mesh.c
@@ -23,13 +23,20 @@
 #include "config.h"
 
 #include <string.h>
-#include <glib/gi18n-lib.h>
 
 #include "nm-setting-olpc-mesh.h"
 #include "nm-utils.h"
 #include "nm-utils-private.h"
 #include "nm-setting-private.h"
 
+/**
+ * SECTION:nm-setting-olpc-mesh
+ * @short_description: Describes connection properties for OLPC-Mesh devices
+ *
+ * The #NMSettingOlpcMesh object is a #NMSetting subclass that describes properties
+ * necessary for connection to OLPC-Mesh devices.
+ **/
+
 static void nm_setting_olpc_mesh_init (NMSettingOlpcMesh *setting);
 
 G_DEFINE_TYPE_WITH_CODE (NMSettingOlpcMesh, nm_setting_olpc_mesh, NM_TYPE_SETTING,
diff --git a/libnm-core/nm-setting-ppp.c b/libnm-core/nm-setting-ppp.c
index 01f798ea..2cc5a209 100644
--- a/libnm-core/nm-setting-ppp.c
+++ b/libnm-core/nm-setting-ppp.c
@@ -22,8 +22,6 @@
 
 #include "config.h"
 
-#include <glib/gi18n-lib.h>
-
 #include "nm-setting-ppp.h"
 #include "nm-setting-private.h"
 
diff --git a/libnm-core/nm-setting-pppoe.c b/libnm-core/nm-setting-pppoe.c
index ac6764d0..e2466eb3 100644
--- a/libnm-core/nm-setting-pppoe.c
+++ b/libnm-core/nm-setting-pppoe.c
@@ -23,7 +23,6 @@
 #include "config.h"
 
 #include <string.h>
-#include <glib/gi18n-lib.h>
 
 #include "nm-setting-pppoe.h"
 #include "nm-setting-ppp.h"
diff --git a/libnm-core/nm-setting-private.h b/libnm-core/nm-setting-private.h
index 955608fa..cb7ca52e 100644
--- a/libnm-core/nm-setting-private.h
+++ b/libnm-core/nm-setting-private.h
@@ -21,10 +21,10 @@
 #ifndef __NM_SETTING_PRIVATE_H__
 #define __NM_SETTING_PRIVATE_H__
 
+#include "nm-default.h"
 #include "nm-setting.h"
 #include "nm-connection.h"
 #include "nm-core-enum-types.h"
-#include "nm-glib-compat.h"
 
 #include "nm-core-internal.h"
 
@@ -89,10 +89,20 @@ gboolean _nm_setting_clear_secrets_with_flags (NMSetting *setting,
 /* This is a legacy property, which clients should not send to the daemon. */
 #define NM_SETTING_PARAM_LEGACY (1 << (5 + G_PARAM_USER_SHIFT))
 
+/* When a connection is active and gets modified, usually the change
+ * to the settings-connection does not propagate automatically to the
+ * applied-connection of the device. For certain properties like the
+ * firewall zone and the metered property, this is different.
+ *
+ * Such fields can be ignored during nm_connection_compare() with the
+ * NMSettingCompareFlag NM_SETTING_COMPARE_FLAG_IGNORE_REAPPLY_IMMEDIATELY.
+ */
+#define NM_SETTING_PARAM_REAPPLY_IMMEDIATELY (1 << (6 + 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); }
+{ nm_g_type_init (); g_type_ensure (x); }
 
 GVariant *_nm_setting_get_deprecated_virtual_interface_name (NMSetting *setting,
                                                              NMConnection *connection,
@@ -102,6 +112,11 @@ NMSettingVerifyResult _nm_setting_verify (NMSetting *setting,
                                           NMConnection *connection,
                                           GError **error);
 
+gboolean _nm_setting_verify_secret_string (const char *str,
+                                           const char *setting_name,
+                                           const char *property,
+                                           GError **error);
+
 gboolean _nm_setting_slave_type_is_valid (const char *slave_type, const char **out_port_type);
 
 GVariant   *_nm_setting_to_dbus       (NMSetting *setting,
@@ -155,6 +170,4 @@ gboolean _nm_setting_use_legacy_property (NMSetting *setting,
 
 GPtrArray  *_nm_setting_need_secrets (NMSetting *setting);
 
-NMSetting8021xCKScheme nm_setting_802_1x_check_cert_scheme (gconstpointer pdata, gsize length, GError **error);
-
 #endif  /* NM_SETTING_PRIVATE_H */
diff --git a/libnm-core/nm-setting-serial.c b/libnm-core/nm-setting-serial.c
index 3fd780c8..b8589cd2 100644
--- a/libnm-core/nm-setting-serial.c
+++ b/libnm-core/nm-setting-serial.c
@@ -24,8 +24,8 @@
 
 #include <string.h>
 
+#include "nm-default.h"
 #include "nm-setting-serial.h"
-#include "nm-glib-compat.h"
 #include "nm-setting-private.h"
 
 /**
diff --git a/libnm-core/nm-setting-team-port.c b/libnm-core/nm-setting-team-port.c
index 7fbf8620..78cb3cb7 100644
--- a/libnm-core/nm-setting-team-port.c
+++ b/libnm-core/nm-setting-team-port.c
@@ -23,7 +23,6 @@
 #include <string.h>
 #include <ctype.h>
 #include <stdlib.h>
-#include <glib/gi18n-lib.h>
 
 #include "nm-setting-team-port.h"
 #include "nm-utils.h"
diff --git a/libnm-core/nm-setting-team.c b/libnm-core/nm-setting-team.c
index 04b98243..2dfffaac 100644
--- a/libnm-core/nm-setting-team.c
+++ b/libnm-core/nm-setting-team.c
@@ -22,7 +22,6 @@
 
 #include <string.h>
 #include <stdlib.h>
-#include <glib/gi18n-lib.h>
 
 #include "nm-setting-team.h"
 #include "nm-utils.h"
diff --git a/libnm-core/nm-setting-tun.c b/libnm-core/nm-setting-tun.c
new file mode 100644
index 00000000..b3c11860
--- /dev/null
+++ b/libnm-core/nm-setting-tun.c
@@ -0,0 +1,409 @@
+/* -*- 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 2015 Red Hat, Inc.
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "nm-setting-tun.h"
+#include "nm-utils.h"
+#include "nm-setting-connection.h"
+#include "nm-setting-private.h"
+#include "nm-connection-private.h"
+
+/**
+ * SECTION:nm-setting-tun
+ * @short_description: Describes connection properties for TUN/TAP interfaces
+ *
+ * The #NMSettingTun object is a #NMSetting subclass that describes properties
+ * necessary for connection to TUN/TAP interfaces.
+ **/
+
+G_DEFINE_TYPE_WITH_CODE (NMSettingTun, nm_setting_tun, NM_TYPE_SETTING,
+                         _nm_register_setting (TUN, 1))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_TUN)
+
+#define NM_SETTING_TUN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_TUN, NMSettingTunPrivate))
+
+typedef struct {
+	NMSettingTunMode mode;
+	char *owner;
+	char *group;
+	gboolean pi;
+	gboolean vnet_hdr;
+	gboolean multi_queue;
+} NMSettingTunPrivate;
+
+enum {
+	PROP_0,
+	PROP_MODE,
+	PROP_OWNER,
+	PROP_GROUP,
+	PROP_PI,
+	PROP_VNET_HDR,
+	PROP_MULTI_QUEUE,
+	LAST_PROP
+};
+
+/**
+ * nm_setting_tun_new:
+ *
+ * Creates a new #NMSettingTun object with default values.
+ *
+ * Returns: (transfer full): the new empty #NMSettingTun object
+ *
+ * Since: 1.2
+ **/
+NMSetting *
+nm_setting_tun_new (void)
+{
+	return (NMSetting *) g_object_new (NM_TYPE_SETTING_TUN, NULL);
+}
+
+/**
+ * nm_setting_tun_get_mode:
+ * @setting: the #NMSettingTun
+ *
+ * Returns: the #NMSettingTun:mode property of the setting
+ *
+ * Since: 1.2
+ **/
+NMSettingTunMode
+nm_setting_tun_get_mode (NMSettingTun *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_TUN (setting), NM_SETTING_TUN_MODE_TUN);
+	return NM_SETTING_TUN_GET_PRIVATE (setting)->mode;
+}
+
+/**
+ * nm_setting_tun_get_owner:
+ * @setting: the #NMSettingTun
+ *
+ * Returns: the #NMSettingTun:owner property of the setting
+ *
+ * Since: 1.2
+ **/
+const char *
+nm_setting_tun_get_owner (NMSettingTun *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_TUN (setting), NULL);
+	return NM_SETTING_TUN_GET_PRIVATE (setting)->owner;
+}
+
+/**
+ * nm_setting_tun_get_group:
+ * @setting: the #NMSettingTun
+ *
+ * Returns: the #NMSettingTun:group property of the setting
+ *
+ * Since: 1.2
+ **/
+const char *
+nm_setting_tun_get_group (NMSettingTun *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_TUN (setting), NULL);
+	return NM_SETTING_TUN_GET_PRIVATE (setting)->group;
+}
+
+/**
+ * nm_setting_tun_get_pi:
+ * @setting: the #NMSettingTun
+ *
+ * Returns: the #NMSettingTun:pi property of the setting
+ *
+ * Since: 1.2
+ **/
+gboolean
+nm_setting_tun_get_pi (NMSettingTun *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_TUN (setting), FALSE);
+	return NM_SETTING_TUN_GET_PRIVATE (setting)->pi;
+}
+
+/**
+ * nm_setting_tun_get_vnet_hdr:
+ * @setting: the #NMSettingTun
+ *
+ * Returns: the #NMSettingTun:vnet_hdr property of the setting
+ *
+ * Since: 1.2
+ **/
+gboolean
+nm_setting_tun_get_vnet_hdr (NMSettingTun *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_TUN (setting), FALSE);
+	return NM_SETTING_TUN_GET_PRIVATE (setting)->vnet_hdr;
+}
+
+/**
+ * nm_setting_tun_get_multi_queue:
+ * @setting: the #NMSettingTun
+ *
+ * Returns: the #NMSettingTun:multi-queue property of the setting
+ *
+ * Since: 1.2
+ **/
+gboolean
+nm_setting_tun_get_multi_queue (NMSettingTun *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_TUN (setting), FALSE);
+	return NM_SETTING_TUN_GET_PRIVATE (setting)->multi_queue;
+}
+
+static void
+nm_setting_tun_init (NMSettingTun *setting)
+{
+}
+
+static gboolean
+verify (NMSetting *setting, NMConnection *connection, GError **error)
+{
+	NMSettingTunPrivate *priv = NM_SETTING_TUN_GET_PRIVATE (setting);
+
+	if (   priv->mode != NM_SETTING_TUN_MODE_TUN
+	    && priv->mode != NM_SETTING_TUN_MODE_TAP) {
+		g_set_error (error,
+		             NM_CONNECTION_ERROR,
+		             NM_CONNECTION_ERROR_INVALID_PROPERTY,
+		             _("'%u': invalid mode"), (unsigned int) priv->mode);
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_TUN_SETTING_NAME, NM_SETTING_TUN_MODE);
+		return FALSE;
+	}
+
+	if (priv->owner) {
+		if (_nm_utils_ascii_str_to_int64 (priv->owner, 10, 0, G_MAXINT32, -1) == -1) {
+			g_set_error (error,
+			             NM_CONNECTION_ERROR,
+			             NM_CONNECTION_ERROR_INVALID_PROPERTY,
+			             _("'%s': invalid user ID"), priv->owner);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_TUN_SETTING_NAME, NM_SETTING_TUN_OWNER);
+			return FALSE;
+		}
+	}
+
+	if (priv->group) {
+		if (_nm_utils_ascii_str_to_int64 (priv->group, 10, 0, G_MAXINT32, -1) == -1) {
+			g_set_error (error,
+			             NM_CONNECTION_ERROR,
+			             NM_CONNECTION_ERROR_INVALID_PROPERTY,
+			             _("'%s': invalid group ID"), priv->group);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_TUN_SETTING_NAME, NM_SETTING_TUN_GROUP);
+			return FALSE;
+		}
+	}
+
+	return TRUE;
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+              const GValue *value, GParamSpec *pspec)
+{
+	NMSettingTun *setting = NM_SETTING_TUN (object);
+	NMSettingTunPrivate *priv = NM_SETTING_TUN_GET_PRIVATE (setting);
+
+	switch (prop_id) {
+	case PROP_MODE:
+		priv->mode = g_value_get_uint (value);
+		break;
+	case PROP_OWNER:
+		g_free (priv->owner);
+		priv->owner = g_value_dup_string (value);
+		break;
+	case PROP_GROUP:
+		g_free (priv->group);
+		priv->group = g_value_dup_string (value);
+		break;
+	case PROP_PI:
+		priv->pi = g_value_get_boolean (value);
+		break;
+	case PROP_VNET_HDR:
+		priv->vnet_hdr = g_value_get_boolean (value);
+		break;
+	case PROP_MULTI_QUEUE:
+		priv->multi_queue = g_value_get_boolean (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)
+{
+	NMSettingTun *setting = NM_SETTING_TUN (object);
+	NMSettingTunPrivate *priv = NM_SETTING_TUN_GET_PRIVATE (setting);
+
+	switch (prop_id) {
+	case PROP_MODE:
+		g_value_set_uint (value, priv->mode);
+		break;
+	case PROP_OWNER:
+		g_value_set_string (value, priv->owner);
+		break;
+	case PROP_GROUP:
+		g_value_set_string (value, priv->group);
+		break;
+	case PROP_PI:
+		g_value_set_boolean (value, priv->pi);
+		break;
+	case PROP_VNET_HDR:
+		g_value_set_boolean (value, priv->vnet_hdr);
+		break;
+	case PROP_MULTI_QUEUE:
+		g_value_set_boolean (value, priv->multi_queue);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+finalize (GObject *object)
+{
+	NMSettingTun *setting = NM_SETTING_TUN (object);
+	NMSettingTunPrivate *priv = NM_SETTING_TUN_GET_PRIVATE (setting);
+
+	g_free (priv->owner);
+	g_free (priv->group);
+
+	G_OBJECT_CLASS (nm_setting_tun_parent_class)->finalize (object);
+}
+
+static void
+nm_setting_tun_class_init (NMSettingTunClass *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 (NMSettingTunPrivate));
+
+	/* virtual methods */
+	object_class->set_property = set_property;
+	object_class->get_property = get_property;
+	object_class->finalize     = finalize;
+	parent_class->verify       = verify;
+
+	/* Properties */
+	/**
+	 * NMSettingTun:mode:
+	 *
+	 * The operating mode of the virtual device. Allowed values are
+	 * %NM_SETTING_TUN_MODE_TUN to create a layer 3 device and
+	 * %NM_SETTING_TUN_MODE_TAP to create an Ethernet-like layer 2
+	 * one.
+	 *
+	 * Since: 1.2
+	 */
+	g_object_class_install_property
+		(object_class, PROP_MODE,
+		 g_param_spec_uint (NM_SETTING_TUN_MODE, "", "",
+		                    0, G_MAXUINT, NM_SETTING_TUN_MODE_TUN,
+		                    G_PARAM_READWRITE |
+		                    G_PARAM_CONSTRUCT |
+		                    NM_SETTING_PARAM_INFERRABLE |
+		                    G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMSettingTun:owner:
+	 *
+	 * The user ID which will own the device. If set to %NULL everyone
+	 * will be able to use the device.
+	 *
+	 * Since: 1.2
+	 */
+	g_object_class_install_property
+		(object_class, PROP_OWNER,
+		 g_param_spec_string (NM_SETTING_TUN_OWNER, "", "",
+		                      NULL,
+		                      G_PARAM_READWRITE |
+		                      NM_SETTING_PARAM_INFERRABLE |
+		                      G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMSettingTun:group:
+	 *
+	 * The group ID which will own the device. If set to %NULL everyone
+	 * will be able to use the device.
+	 *
+	 * Since: 1.2
+	 */
+	g_object_class_install_property
+		(object_class, PROP_GROUP,
+		 g_param_spec_string (NM_SETTING_TUN_GROUP, "", "",
+		                      NULL,
+		                      G_PARAM_READWRITE |
+		                      NM_SETTING_PARAM_INFERRABLE |
+		                      G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMSettingTun:pi:
+	 *
+	 * If %TRUE the interface will prepend a 4 byte header describing the
+	 * physical interface to the packets.
+	 *
+	 * Since: 1.2
+	 */
+	g_object_class_install_property
+		(object_class, PROP_PI,
+		 g_param_spec_boolean (NM_SETTING_TUN_PI, "", "",
+		                       FALSE,
+		                       G_PARAM_READWRITE |
+		                       NM_SETTING_PARAM_INFERRABLE |
+		                       G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMSettingTun:vnet-hdr:
+	 *
+	 * If %TRUE the IFF_VNET_HDR the tunnel packets will include a virtio
+	 * network header.
+	 *
+	 * Since: 1.2
+	 */
+	g_object_class_install_property
+		(object_class, PROP_VNET_HDR,
+		 g_param_spec_boolean (NM_SETTING_TUN_VNET_HDR, "", "",
+		                       FALSE,
+		                       G_PARAM_READWRITE |
+		                       NM_SETTING_PARAM_INFERRABLE |
+		                       G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMSettingTun:multi-queue:
+	 *
+	 * If the property is set to %TRUE, the interface will support
+	 * multiple file descriptors (queues) to parallelize packet
+	 * sending or receiving. Otherwise, the interface will only
+	 * support a single queue.
+	 *
+	 * Since: 1.2
+	 */
+	g_object_class_install_property
+		(object_class, PROP_MULTI_QUEUE,
+		 g_param_spec_boolean (NM_SETTING_TUN_MULTI_QUEUE, "", "",
+		                       FALSE,
+		                       G_PARAM_READWRITE |
+		                       NM_SETTING_PARAM_INFERRABLE |
+		                       G_PARAM_STATIC_STRINGS));
+}
diff --git a/libnm-core/nm-setting-tun.h b/libnm-core/nm-setting-tun.h
new file mode 100644
index 00000000..2b368a69
--- /dev/null
+++ b/libnm-core/nm-setting-tun.h
@@ -0,0 +1,94 @@
+/* -*- 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 2015 Red Hat, Inc.
+ */
+
+#ifndef __NM_SETTING_TUN_H__
+#define __NM_SETTING_TUN_H__
+
+#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION)
+#error "Only <NetworkManager.h> can be included directly."
+#endif
+
+#include "nm-setting.h"
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_SETTING_TUN            (nm_setting_tun_get_type ())
+#define NM_SETTING_TUN(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_TUN, NMSettingTun))
+#define NM_SETTING_TUN_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_TUNCONFIG, NMSettingTunClass))
+#define NM_IS_SETTING_TUN(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_TUN))
+#define NM_IS_SETTING_TUN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_TUN))
+#define NM_SETTING_TUN_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_TUN, NMSettingTunClass))
+
+#define NM_SETTING_TUN_SETTING_NAME         "tun"
+
+#define NM_SETTING_TUN_MODE                 "mode"
+#define NM_SETTING_TUN_OWNER                "owner"
+#define NM_SETTING_TUN_GROUP                "group"
+#define NM_SETTING_TUN_PI                   "pi"
+#define NM_SETTING_TUN_VNET_HDR             "vnet-hdr"
+#define NM_SETTING_TUN_MULTI_QUEUE          "multi-queue"
+
+/**
+ * NMSettingTunMode:
+ * @NM_SETTING_TUN_MODE_UNKNOWN: an unknown device type
+ * @NM_SETTING_TUN_MODE_TUN: a TUN device
+ * @NM_SETTING_TUN_MODE_TAP: a TAP device
+ *
+ * #NMSettingTunMode values indicate the device type (TUN/TAP)
+ */
+typedef enum {
+	NM_SETTING_TUN_MODE_UNKNOWN    = 0,
+	NM_SETTING_TUN_MODE_TUN        = 1,
+	NM_SETTING_TUN_MODE_TAP        = 2,
+} NMSettingTunMode;
+
+struct _NMSettingTun {
+	NMSetting parent;
+};
+
+typedef struct {
+	NMSettingClass parent;
+
+	/*< private >*/
+	gpointer padding[4];
+} NMSettingTunClass;
+
+NM_AVAILABLE_IN_1_2
+GType nm_setting_tun_get_type (void);
+NM_AVAILABLE_IN_1_2
+NMSetting *nm_setting_tun_new (void);
+
+NM_AVAILABLE_IN_1_2
+NMSettingTunMode nm_setting_tun_get_mode         (NMSettingTun *setting);
+NM_AVAILABLE_IN_1_2
+const char      *nm_setting_tun_get_owner        (NMSettingTun *setting);
+NM_AVAILABLE_IN_1_2
+const char      *nm_setting_tun_get_group        (NMSettingTun *setting);
+NM_AVAILABLE_IN_1_2
+gboolean         nm_setting_tun_get_pi           (NMSettingTun *setting);
+NM_AVAILABLE_IN_1_2
+gboolean         nm_setting_tun_get_vnet_hdr     (NMSettingTun *setting);
+NM_AVAILABLE_IN_1_2
+gboolean         nm_setting_tun_get_multi_queue  (NMSettingTun *setting);
+
+G_END_DECLS
+
+#endif /* __NM_SETTING_TUN_H__ */
diff --git a/libnm-core/nm-setting-vlan.c b/libnm-core/nm-setting-vlan.c
index 0547141c..8428a369 100644
--- a/libnm-core/nm-setting-vlan.c
+++ b/libnm-core/nm-setting-vlan.c
@@ -23,10 +23,12 @@
 
 #include <stdlib.h>
 #include <string.h>
-#include <glib/gi18n-lib.h>
 
 #include "nm-setting-vlan.h"
+#include "nm-default.h"
+#include "nm-macros-internal.h"
 #include "nm-utils.h"
+#include "nm-core-types-internal.h"
 #include "nm-setting-connection.h"
 #include "nm-setting-private.h"
 #include "nm-setting-wired.h"
@@ -67,11 +69,6 @@ enum {
 #define MAX_SKB_PRIO   G_MAXUINT32
 #define MAX_8021P_PRIO 7  /* Max 802.1p priority */
 
-typedef struct {
-	guint32 from;
-	guint32 to;
-} PriorityMap;
-
 /**
  * nm_setting_vlan_new:
  *
@@ -134,10 +131,10 @@ get_max_prio (NMVlanPriorityMap map, gboolean from)
 	g_assert_not_reached ();
 }
 
-static PriorityMap *
+static NMVlanQosMapping *
 priority_map_new_from_str (NMVlanPriorityMap map, const char *str)
 {
-	PriorityMap *p = NULL;
+	NMVlanQosMapping *p = NULL;
 	gchar **t = NULL;
 	guint32 len;
 	guint64 from, to;
@@ -151,7 +148,7 @@ priority_map_new_from_str (NMVlanPriorityMap map, const char *str)
 		to = g_ascii_strtoull (t[1], NULL, 10);
 
 		if ((from <= get_max_prio (map, TRUE)) && (to <= get_max_prio (map, FALSE))) {
-			p = g_malloc0 (sizeof (PriorityMap));
+			p = g_malloc0 (sizeof (NMVlanQosMapping));
 			p->from = from;
 			p->to = to;
 		}
@@ -165,7 +162,7 @@ priority_map_new_from_str (NMVlanPriorityMap map, const char *str)
 }
 
 static void
-priority_map_free (PriorityMap *map)
+priority_map_free (NMVlanQosMapping *map)
 {
 	g_return_if_fail (map != NULL);
 	g_free (map);
@@ -182,9 +179,44 @@ get_map (NMSettingVlan *self, NMVlanPriorityMap map)
 	return NULL;
 }
 
+static gint
+prio_map_compare (gconstpointer p_a, gconstpointer p_b)
+{
+	const NMVlanQosMapping *a = p_a;
+	const NMVlanQosMapping *b = p_b;
+
+	return a->from < b->from
+	       ? -1
+	       : (a->from > b->from
+	          ? 1
+	          : (a->to < b->to ? -1 : (a->to > b->to ? 1 : 0)));
+}
+
 static void
 set_map (NMSettingVlan *self, NMVlanPriorityMap map, GSList *list)
 {
+	/* Assert that the list is sorted */
+#if NM_MORE_ASSERTS >= 2
+	{
+		GSList *iter, *last;
+
+		last = list;
+		iter = list ? list->next : NULL;
+		while (iter) {
+			const NMVlanQosMapping *l = last->data;
+			const NMVlanQosMapping *m = iter->data;
+
+			nm_assert (prio_map_compare (last->data, iter->data) < 0);
+
+			/* Also reject duplicates (based on "from") */
+			nm_assert (l->from < m->from);
+
+			last = iter;
+			iter = iter->next;
+		}
+	}
+#endif
+
 	if (map == NM_VLAN_INGRESS_MAP) {
 		NM_SETTING_VLAN_GET_PRIVATE (self)->ingress_priority_map = list;
 		g_object_notify (G_OBJECT (self), NM_SETTING_VLAN_INGRESS_PRIORITY_MAP);
@@ -195,6 +227,22 @@ set_map (NMSettingVlan *self, NMVlanPriorityMap map, GSList *list)
 		g_assert_not_reached ();
 }
 
+static gboolean
+check_replace_duplicate_priority (GSList *list, guint32 from, guint32 to)
+{
+	GSList *iter;
+	NMVlanQosMapping *p;
+
+	for (iter = list; iter; iter = g_slist_next (iter)) {
+		p = iter->data;
+		if (p->from == from) {
+			p->to = to;
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
+
 /**
  * nm_setting_vlan_add_priority_str:
  * @setting: the #NMSettingVlan
@@ -213,8 +261,8 @@ nm_setting_vlan_add_priority_str (NMSettingVlan *setting,
                                   NMVlanPriorityMap map,
                                   const char *str)
 {
-	GSList *list = NULL, *iter = NULL;
-	PriorityMap *item = NULL;
+	GSList *list = NULL;
+	NMVlanQosMapping *item = NULL;
 
 	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);
@@ -227,21 +275,16 @@ nm_setting_vlan_add_priority_str (NMSettingVlan *setting,
 		g_return_val_if_reached (FALSE);
 
 	/* Duplicates get replaced */
-	for (iter = list; iter; iter = g_slist_next (iter)) {
-		PriorityMap *p = iter->data;
-
-		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;
-		}
+	if (check_replace_duplicate_priority (list, item->from, 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;
 	}
 
-	set_map (setting, map, g_slist_append (list, item));
+	set_map (setting, map, g_slist_insert_sorted (list, item, prio_map_compare));
 	return TRUE;
 }
 
@@ -286,7 +329,7 @@ nm_setting_vlan_get_priority (NMSettingVlan *setting,
                               guint32 *out_to)
 {
 	GSList *list = NULL;
-	PriorityMap *item = NULL;
+	NMVlanQosMapping *item = NULL;
 
 	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);
@@ -330,33 +373,111 @@ nm_setting_vlan_add_priority (NMSettingVlan *setting,
                               guint32 from,
                               guint32 to)
 {
-	GSList *list = NULL, *iter = NULL;
-	PriorityMap *item;
+	GSList *list = NULL;
+	NMVlanQosMapping *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;
-			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;
-		}
+	if (check_replace_duplicate_priority (list, from, 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;
 	}
 
-	item = g_malloc0 (sizeof (PriorityMap));
+	item = g_malloc0 (sizeof (NMVlanQosMapping));
 	item->from = from;
 	item->to = to;
-	set_map (setting, map, g_slist_append (list, item));
+	set_map (setting, map, g_slist_insert_sorted (list, item, prio_map_compare));
 
 	return TRUE;
 }
 
+gboolean
+_nm_setting_vlan_set_priorities (NMSettingVlan *setting,
+                                 NMVlanPriorityMap map,
+                                 const NMVlanQosMapping *qos_map,
+                                 guint n_qos_map)
+{
+	gboolean has_changes = FALSE;
+	GSList *map_prev, *map_new;
+	guint i;
+	gint64 from_last;
+
+	map_prev = get_map (setting, map);
+
+	if (n_qos_map != g_slist_length (map_prev))
+		has_changes = TRUE;
+	else {
+		const GSList *iter;
+
+		iter = map_prev;
+		for (i = 0; i < n_qos_map; i++, iter = iter->next) {
+			const NMVlanQosMapping *m = iter->data;
+
+			if (   m->from != qos_map[i].from
+			    || m->to != qos_map[i].to) {
+				has_changes = TRUE;
+				break;
+			}
+		}
+	}
+
+	if (!has_changes)
+		return FALSE;
+
+	map_new = NULL;
+	from_last = G_MAXINT64;
+	for (i = n_qos_map; i > 0;) {
+		const NMVlanQosMapping *m = &qos_map[--i];
+		NMVlanQosMapping *item;
+
+		/* We require the array to be presorted. */
+		if (m->from >= from_last)
+			g_return_val_if_reached (FALSE);
+		from_last = m->from;
+
+		item = g_malloc0 (sizeof (NMVlanQosMapping));
+		item->from = m->from;
+		item->to = m->to;
+		map_new = g_slist_prepend (map_new, item);
+	}
+
+	g_slist_free_full (map_prev, g_free);
+	set_map (setting, map, map_new);
+
+	return TRUE;
+}
+
+void
+_nm_setting_vlan_get_priorities (NMSettingVlan *setting,
+                                 NMVlanPriorityMap map,
+                                 NMVlanQosMapping **out_qos_map,
+                                 guint *out_n_qos_map)
+{
+	GSList *list;
+	NMVlanQosMapping *qos_map = NULL;
+	guint n_qos_map, i;
+
+	list = get_map (setting, map);
+
+	n_qos_map = g_slist_length (list);
+
+	if (n_qos_map > 0) {
+		qos_map = g_new (NMVlanQosMapping, n_qos_map);
+
+		for (i = 0; list; i++, list = list->next) {
+			nm_assert (i < n_qos_map);
+			qos_map[i] = *((const NMVlanQosMapping *) list->data);
+		}
+	}
+	*out_qos_map = qos_map;
+	*out_n_qos_map = n_qos_map;
+}
+
 /**
  * nm_setting_vlan_remove_priority:
  * @setting: the #NMSettingVlan
@@ -381,7 +502,7 @@ nm_setting_vlan_remove_priority (NMSettingVlan *setting,
 	g_return_if_fail (idx < g_slist_length (list));
 
 	item = g_slist_nth (list, idx);
-	priority_map_free ((PriorityMap *) (item->data));
+	priority_map_free ((NMVlanQosMapping *) (item->data));
 	set_map (setting, map, g_slist_delete_link (list, item));
 }
 
@@ -405,7 +526,7 @@ nm_setting_vlan_remove_priority_by_value (NMSettingVlan *setting,
                                           guint32 to)
 {
 	GSList *list = NULL, *iter = NULL;
-	PriorityMap *item;
+	NMVlanQosMapping *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);
@@ -414,7 +535,7 @@ nm_setting_vlan_remove_priority_by_value (NMSettingVlan *setting,
 	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));
+			priority_map_free ((NMVlanQosMapping *) (iter->data));
 			set_map (setting, map, g_slist_delete_link (list, iter));
 			return TRUE;
 		}
@@ -439,7 +560,7 @@ nm_setting_vlan_remove_priority_str_by_value (NMSettingVlan *setting,
                                               NMVlanPriorityMap map,
                                               const char *str)
 {
-	PriorityMap *item;
+	NMVlanQosMapping *item;
 	gboolean found;
 
 	g_return_val_if_fail (NM_IS_SETTING_VLAN (setting), FALSE);
@@ -545,9 +666,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
 		}
 	}
 
-	if (priv->flags & ~(NM_VLAN_FLAG_REORDER_HEADERS |
-	                    NM_VLAN_FLAG_GVRP |
-	                    NM_VLAN_FLAG_LOOSE_BINDING)) {
+	if (priv->flags & ~NM_VLAN_FLAGS_ALL) {
 		g_set_error_literal (error,
 		                     NM_CONNECTION_ERROR,
 		                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
@@ -559,6 +678,24 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
 	return TRUE;
 }
 
+static GVariant *
+_override_flags_get (NMSetting *setting, const char *property)
+{
+	return g_variant_new_uint32 (nm_setting_vlan_get_flags ((NMSettingVlan *) setting));
+}
+
+static void
+_override_flags_not_set (NMSetting *setting,
+                          GVariant *connection_dict,
+                          const char *property)
+{
+	/* we changed the default value for FLAGS. When an older client
+	 * doesn't serialize the property, we assume it is the old default. */
+	g_object_set (G_OBJECT (setting),
+	              NM_SETTING_VLAN_FLAGS, (NMVlanFlags) 0,
+	              NULL);
+}
+
 static GSList *
 priority_strv_to_maplist (NMVlanPriorityMap map, char **strv)
 {
@@ -566,13 +703,15 @@ priority_strv_to_maplist (NMVlanPriorityMap map, char **strv)
 	int i;
 
 	for (i = 0; strv && strv[i]; i++) {
-		PriorityMap *item;
+		NMVlanQosMapping *item;
 
 		item = priority_map_new_from_str (map, strv[i]);
-		if (item)
-			list = g_slist_prepend (list, item);
+		if (item) {
+			if (!check_replace_duplicate_priority (list, item->from, item->to))
+				list = g_slist_prepend (list, item);
+		}
 	}
-	return g_slist_reverse (list);
+	return g_slist_sort (list, prio_map_compare);
 }
 
 static void
@@ -618,7 +757,7 @@ priority_maplist_to_strv (GSList *list)
 	strv = g_ptr_array_new ();
 
 	for (iter = list; iter; iter = g_slist_next (iter)) {
-		PriorityMap *item = iter->data;
+		NMVlanQosMapping *item = iter->data;
 
 		g_ptr_array_add (strv, g_strdup_printf ("%d:%d", item->from, item->to));
 	}
@@ -736,12 +875,18 @@ nm_setting_vlan_class_init (NMSettingVlanClass *setting_class)
 	 * 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).
+	 * master device's operating state). %NM_VLAN_FLAG_MVRP (use of the MVRP
+	 * protocol).
+	 *
+	 * The default value of this property is NM_VLAN_FLAG_REORDER_HEADERS,
+	 * but it used to be 0. To preserve backward compatibility, the default-value
+	 * in the D-Bus API continues to be 0 and a missing property on D-Bus
+	 * is still considered as 0.
 	 **/
 	/* ---ifcfg-rh---
 	 * property: flags
-	 * variable: VLAN_FLAGS, REORDER_HDR
-	 * values: "GVRP", "LOOSE_BINDING" for VLAN_FLAGS; 0 or 1 for REORDER_HDR
+	 * variable: REORDER_HDR, GVRP, MVRP, VLAN_FLAGS
+	 * values: "yes or "no" for REORDER_HDR, GVRP and MVRP; "LOOSE_BINDING" for VLAN_FLAGS
 	 * description: VLAN flags.
 	 * ---end---
 	 */
@@ -754,6 +899,11 @@ nm_setting_vlan_class_init (NMSettingVlanClass *setting_class)
 		                     G_PARAM_CONSTRUCT |
 		                     NM_SETTING_PARAM_INFERRABLE |
 		                     G_PARAM_STATIC_STRINGS));
+	_nm_setting_class_override_property (parent_class, NM_SETTING_VLAN_FLAGS,
+	                                     NULL,
+	                                     _override_flags_get,
+	                                     NULL,
+	                                     _override_flags_not_set);
 
 	/**
 	 * NMSettingVlan:ingress-priority-map:
diff --git a/libnm-core/nm-setting-vlan.h b/libnm-core/nm-setting-vlan.h
index 30305d32..cf41ba17 100644
--- a/libnm-core/nm-setting-vlan.h
+++ b/libnm-core/nm-setting-vlan.h
@@ -79,6 +79,8 @@ typedef enum {
  * @NM_VLAN_FLAG_LOOSE_BINDING: indicates that this interface's operating
  *  state is tied to the underlying network interface but other details
  *  (like routing) are not.
+ * @NM_VLAN_FLAG_MVRP: indicates that this interface should use MVRP to register
+ *  itself with it's switch
  *
  * #NMVlanFlags values control the behavior of the VLAN interface.
  **/
@@ -86,10 +88,19 @@ typedef enum { /*< flags >*/
 	NM_VLAN_FLAG_REORDER_HEADERS = 0x1,
 	NM_VLAN_FLAG_GVRP            = 0x2,
 	NM_VLAN_FLAG_LOOSE_BINDING   = 0x4,
+	NM_VLAN_FLAG_MVRP            = 0x8,
 
 	/* NOTE: if adding flags update nm-setting-vlan.c::verify() */
+
+	/* NOTE: these flags must correspond to the value from the kernel
+	 * header files. */
 } NMVlanFlags;
 
+#define NM_VLAN_FLAGS_ALL  (NM_VLAN_FLAG_REORDER_HEADERS | \
+                            NM_VLAN_FLAG_GVRP | \
+                            NM_VLAN_FLAG_LOOSE_BINDING | \
+                            NM_VLAN_FLAG_MVRP)
+
 GType nm_setting_vlan_get_type (void);
 NMSetting *nm_setting_vlan_new (void);
 
diff --git a/libnm-core/nm-setting-vpn.c b/libnm-core/nm-setting-vpn.c
index e6fffa87..aae8ae13 100644
--- a/libnm-core/nm-setting-vpn.c
+++ b/libnm-core/nm-setting-vpn.c
@@ -24,7 +24,6 @@
 #include <string.h>
 #include <errno.h>
 #include <stdlib.h>
-#include <glib/gi18n-lib.h>
 
 #include "nm-setting-vpn.h"
 #include "nm-utils.h"
@@ -81,6 +80,9 @@ typedef struct {
 	 * freed with g_free().  Should contain secrets only.
 	 */
 	GHashTable *secrets;
+
+	/* Timeout for the VPN service to establish the connection */
+	guint32 timeout;
 } NMSettingVpnPrivate;
 
 enum {
@@ -90,6 +92,7 @@ enum {
 	PROP_PERSISTENT,
 	PROP_DATA,
 	PROP_SECRETS,
+	PROP_TIMEOUT,
 
 	LAST_PROP
 };
@@ -388,6 +391,22 @@ nm_setting_vpn_foreach_secret (NMSettingVpn *setting,
 	foreach_item_helper (NM_SETTING_VPN_GET_PRIVATE (setting)->secrets, func, user_data);
 }
 
+/**
+ * nm_setting_vpn_get_timeout:
+ * @setting: the #NMSettingVpn
+ *
+ * Returns: the #NMSettingVpn:timeout property of the setting
+ *
+ * Since: 1.2
+ **/
+guint32
+nm_setting_vpn_get_timeout (NMSettingVpn *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_VPN (setting), 0);
+
+	return NM_SETTING_VPN_GET_PRIVATE (setting)->timeout;
+}
+
 static gboolean
 verify (NMSetting *setting, NMConnection *connection, GError **error)
 {
@@ -754,6 +773,9 @@ set_property (GObject *object, guint prop_id,
 		g_hash_table_unref (priv->secrets);
 		priv->secrets = _nm_utils_copy_strdict (g_value_get_boxed (value));
 		break;
+	case PROP_TIMEOUT:
+		priv->timeout = g_value_get_uint (value);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -783,6 +805,9 @@ get_property (GObject *object, guint prop_id,
 	case PROP_SECRETS:
 		g_value_take_boxed (value, _nm_utils_copy_strdict (priv->secrets));
 		break;
+	case PROP_TIMEOUT:
+		g_value_set_uint (value, nm_setting_vpn_get_timeout (setting));
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -910,4 +935,22 @@ nm_setting_vpn_class_init (NMSettingVpnClass *setting_class)
 	                                      G_VARIANT_TYPE ("a{ss}"),
 	                                      _nm_utils_strdict_to_dbus,
 	                                      _nm_utils_strdict_from_dbus);
+
+	/**
+	 * NMSettingVpn:timeout:
+	 *
+	 * Timeout for the VPN service to establish the connection. Some services
+	 * may take quite a long time to connect.
+	 * Value of 0 means a default timeout, which is 60 seconds (unless overriden
+	 * by vpn.timeout in configuration file). Values greater than zero mean
+	 * timeout in seconds.
+	 *
+	 * Since: 1.2
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_TIMEOUT,
+		 g_param_spec_uint (NM_SETTING_VPN_TIMEOUT, "", "",
+		                    0, G_MAXUINT32, 0,
+		                    G_PARAM_READWRITE |
+		                    G_PARAM_STATIC_STRINGS));
 }
diff --git a/libnm-core/nm-setting-vpn.h b/libnm-core/nm-setting-vpn.h
index 487549af..31f3c7b8 100644
--- a/libnm-core/nm-setting-vpn.h
+++ b/libnm-core/nm-setting-vpn.h
@@ -45,6 +45,7 @@ G_BEGIN_DECLS
 #define NM_SETTING_VPN_PERSISTENT   "persistent"
 #define NM_SETTING_VPN_DATA         "data"
 #define NM_SETTING_VPN_SECRETS      "secrets"
+#define NM_SETTING_VPN_TIMEOUT      "timeout"
 
 struct _NMSettingVpn {
 	NMSetting parent;
@@ -96,6 +97,8 @@ gboolean          nm_setting_vpn_remove_secret     (NMSettingVpn *setting,
 void              nm_setting_vpn_foreach_secret    (NMSettingVpn *setting,
                                                     NMVpnIterFunc func,
                                                     gpointer user_data);
+NM_AVAILABLE_IN_1_2
+guint32           nm_setting_vpn_get_timeout       (NMSettingVpn *setting);
 
 G_END_DECLS
 
diff --git a/libnm-core/nm-setting-vxlan.c b/libnm-core/nm-setting-vxlan.c
new file mode 100644
index 00000000..814623b7
--- /dev/null
+++ b/libnm-core/nm-setting-vxlan.c
@@ -0,0 +1,843 @@
+/* -*- 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 2015 Red Hat, Inc.
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "nm-setting-vxlan.h"
+#include "nm-utils.h"
+#include "nm-setting-private.h"
+
+/**
+ * SECTION:nm-setting-vxlan
+ * @short_description: Describes connection properties for VXLAN interfaces
+ *
+ * The #NMSettingVxlan object is a #NMSetting subclass that describes properties
+ * necessary for connection to VXLAN interfaces.
+ **/
+
+G_DEFINE_TYPE_WITH_CODE (NMSettingVxlan, nm_setting_vxlan, NM_TYPE_SETTING,
+                         _nm_register_setting (VXLAN, 1))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_VXLAN)
+
+#define NM_SETTING_VXLAN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_VXLAN, NMSettingVxlanPrivate))
+
+typedef struct {
+	char *parent;
+	guint id;
+	char *local;
+	char *remote;
+	guint source_port_min;
+	guint source_port_max;
+	guint destination_port;
+	guint tos;
+	guint ttl;
+	guint ageing;
+	guint limit;
+	gboolean learning;
+	gboolean proxy;
+	gboolean rsc;
+	gboolean l2_miss;
+	gboolean l3_miss;
+} NMSettingVxlanPrivate;
+
+enum {
+	PROP_0,
+	PROP_PARENT,
+	PROP_ID,
+	PROP_LOCAL,
+	PROP_REMOTE,
+	PROP_SOURCE_PORT_MIN,
+	PROP_SOURCE_PORT_MAX,
+	PROP_DESTINATION_PORT,
+	PROP_TOS,
+	PROP_TTL,
+	PROP_AGEING,
+	PROP_LIMIT,
+	PROP_LEARNING,
+	PROP_PROXY,
+	PROP_RSC,
+	PROP_L2_MISS,
+	PROP_L3_MISS,
+
+	LAST_PROP
+};
+
+#define DST_PORT_DEFAULT   8472
+
+/**
+ * nm_setting_vxlan_new:
+ *
+ * Creates a new #NMSettingVxlan object with default values.
+ *
+ * Returns: (transfer full): the new empty #NMSettingVxlan object
+ *
+ * Since: 1.2
+ **/
+NMSetting *
+nm_setting_vxlan_new (void)
+{
+	return (NMSetting *) g_object_new (NM_TYPE_SETTING_VXLAN, NULL);
+}
+
+/**
+ * nm_setting_vxlan_get_parent:
+ * @setting: the #NMSettingVxlan
+ *
+ * Returns: the #NMSettingVxlan:parent property of the setting
+ *
+ * Since: 1.2
+ **/
+const char *
+nm_setting_vxlan_get_parent (NMSettingVxlan *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_VXLAN (setting), NULL);
+	return NM_SETTING_VXLAN_GET_PRIVATE (setting)->parent;
+}
+
+/**
+ * nm_setting_vxlan_get_id:
+ * @setting: the #NMSettingVxlan
+ *
+ * Returns: the #NMSettingVxlan:id property of the setting
+ *
+ * Since: 1.2
+ **/
+guint
+nm_setting_vxlan_get_id (NMSettingVxlan *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_VXLAN (setting), 0);
+	return NM_SETTING_VXLAN_GET_PRIVATE (setting)->id;
+}
+
+/**
+ * nm_setting_vxlan_get_local:
+ * @setting: the #NMSettingVxlan
+ *
+ * Returns: the #NMSettingVxlan:local property of the setting
+ *
+ * Since: 1.2
+ **/
+const char *
+nm_setting_vxlan_get_local (NMSettingVxlan *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_VXLAN (setting), NULL);
+	return NM_SETTING_VXLAN_GET_PRIVATE (setting)->local;
+}
+
+/**
+ * nm_setting_vxlan_get_remote:
+ * @setting: the #NMSettingVxlan
+ *
+ * Returns: the #NMSettingVxlan:remote property of the setting
+ *
+ * Since: 1.2
+ **/
+const char *
+nm_setting_vxlan_get_remote (NMSettingVxlan *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_VXLAN (setting), NULL);
+	return NM_SETTING_VXLAN_GET_PRIVATE (setting)->remote;
+}
+
+/**
+ * nm_setting_vxlan_get_source_port_min:
+ * @setting: the #NMSettingVxlan
+ *
+ * Returns: the #NMSettingVxlan:source-port-min property of the setting
+ *
+ * Since: 1.2
+ **/
+guint
+nm_setting_vxlan_get_source_port_min (NMSettingVxlan *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_VXLAN (setting), 0);
+	return NM_SETTING_VXLAN_GET_PRIVATE (setting)->source_port_min;
+}
+
+/**
+ * nm_setting_vxlan_get_source_port_max:
+ * @setting: the #NMSettingVxlan
+ *
+ * Returns: the #NMSettingVxlan:source-port-max property of the setting
+ *
+ * Since: 1.2
+ **/
+guint
+nm_setting_vxlan_get_source_port_max (NMSettingVxlan *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_VXLAN (setting), 0);
+	return NM_SETTING_VXLAN_GET_PRIVATE (setting)->source_port_max;
+}
+
+/**
+ * nm_setting_vxlan_get_destination_port:
+ * @setting: the #NMSettingVxlan
+ *
+ * Returns: the #NMSettingVxlan:destination-port property of the setting
+ *
+ * Since: 1.2
+ **/
+guint
+nm_setting_vxlan_get_destination_port (NMSettingVxlan *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_VXLAN (setting), DST_PORT_DEFAULT);
+	return NM_SETTING_VXLAN_GET_PRIVATE (setting)->destination_port;
+}
+
+/**
+ * nm_setting_vxlan_get_proxy:
+ * @setting: the #NMSettingVxlan
+ *
+ * Returns: the #NMSettingVxlan:proxy property of the setting
+ *
+ * Since: 1.2
+ **/
+gboolean
+nm_setting_vxlan_get_proxy (NMSettingVxlan *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_VXLAN (setting), FALSE);
+	return NM_SETTING_VXLAN_GET_PRIVATE (setting)->proxy;
+}
+
+/**
+ * nm_setting_vxlan_get_ageing:
+ * @setting: the #NMSettingVxlan
+ *
+ * Returns: the #NMSettingVxlan:ageing property of the setting
+ *
+ * Since: 1.2
+ **/
+guint
+nm_setting_vxlan_get_ageing (NMSettingVxlan *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_VXLAN (setting), 0);
+	return NM_SETTING_VXLAN_GET_PRIVATE (setting)->ageing;
+}
+
+/**
+ * nm_setting_vxlan_get_limit:
+ * @setting: the #NMSettingVxlan
+ *
+ * Returns: the #NMSettingVxlan:limit property of the setting
+ *
+ * Since: 1.2
+ **/
+guint
+nm_setting_vxlan_get_limit (NMSettingVxlan *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_VXLAN (setting), 0);
+	return NM_SETTING_VXLAN_GET_PRIVATE (setting)->limit;
+}
+
+/**
+ * nm_setting_vxlan_get_tos:
+ * @setting: the #NMSettingVxlan
+ *
+ * Returns: the #NMSettingVxlan:tos property of the setting
+ *
+ * Since: 1.2
+ **/
+guint
+nm_setting_vxlan_get_tos (NMSettingVxlan *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_VXLAN (setting), 0);
+	return NM_SETTING_VXLAN_GET_PRIVATE (setting)->tos;
+}
+
+/**
+ * nm_setting_vxlan_get_ttl:
+ * @setting: the #NMSettingVxlan
+ *
+ * Returns: the #NMSettingVxlan:ttl property of the setting
+ *
+ * Since: 1.2
+ **/
+guint
+nm_setting_vxlan_get_ttl (NMSettingVxlan *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_VXLAN (setting), 0);
+	return NM_SETTING_VXLAN_GET_PRIVATE (setting)->ttl;
+}
+
+/**
+ * nm_setting_vxlan_get_learning:
+ * @setting: the #NMSettingVxlan
+ *
+ * Returns: the #NMSettingVxlan:learning property of the setting
+ *
+ * Since: 1.2
+ **/
+gboolean
+nm_setting_vxlan_get_learning (NMSettingVxlan *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_VXLAN (setting), FALSE);
+	return NM_SETTING_VXLAN_GET_PRIVATE (setting)->learning;
+}
+
+/**
+ * nm_setting_vxlan_get_rsc:
+ * @setting: the #NMSettingVxlan
+ *
+ * Returns: the #NMSettingVxlan:rsc property of the setting
+ *
+ * Since: 1.2
+ **/
+gboolean
+nm_setting_vxlan_get_rsc (NMSettingVxlan *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_VXLAN (setting), FALSE);
+	return NM_SETTING_VXLAN_GET_PRIVATE (setting)->rsc;
+}
+
+/**
+ * nm_setting_vxlan_get_l2_miss:
+ * @setting: the #NMSettingVxlan
+ *
+ * Returns: the #NMSettingVxlan:l2_miss property of the setting
+ *
+ * Since: 1.2
+ **/
+gboolean
+nm_setting_vxlan_get_l2_miss (NMSettingVxlan *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_VXLAN (setting), FALSE);
+	return NM_SETTING_VXLAN_GET_PRIVATE (setting)->l2_miss;
+}
+
+/**
+ * nm_setting_vxlan_get_l3_miss:
+ * @setting: the #NMSettingVxlan
+ *
+ * Returns: the #NMSettingVxlan:l3_miss property of the setting
+ *
+ * Since: 1.2
+ **/
+gboolean
+nm_setting_vxlan_get_l3_miss (NMSettingVxlan *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_VXLAN (setting), FALSE);
+	return NM_SETTING_VXLAN_GET_PRIVATE (setting)->l3_miss;
+}
+
+/*********************************************************************/
+
+static void
+nm_setting_vxlan_init (NMSettingVxlan *setting)
+{
+}
+
+static gboolean
+verify (NMSetting *setting, NMConnection *connection, GError **error)
+{
+	NMSettingVxlanPrivate *priv = NM_SETTING_VXLAN_GET_PRIVATE (setting);
+	int family = AF_UNSPEC;
+
+	if (!priv->remote) {
+		g_set_error_literal (error,
+		                     NM_CONNECTION_ERROR,
+		                     NM_CONNECTION_ERROR_MISSING_PROPERTY,
+		                     _("property is missing"));
+		g_prefix_error (error, "%s.%s: ",
+		                NM_SETTING_VXLAN_SETTING_NAME,
+		                NM_SETTING_VXLAN_REMOTE);
+		return FALSE;
+	}
+
+	if (nm_utils_ipaddr_valid (AF_INET, priv->remote))
+		family = AF_INET;
+	else if (nm_utils_ipaddr_valid (AF_INET6, priv->remote))
+		family = AF_INET6;
+	else {
+		g_set_error (error,
+		             NM_CONNECTION_ERROR,
+		             NM_CONNECTION_ERROR_INVALID_PROPERTY,
+		             _("'%s' is not a valid IP address"),
+		             priv->remote);
+		g_prefix_error (error, "%s.%s: ",
+		                NM_SETTING_VXLAN_SETTING_NAME,
+		                NM_SETTING_VXLAN_REMOTE);
+		return FALSE;
+	}
+
+	if (priv->local) {
+		if (!nm_utils_ipaddr_valid (family, priv->local)) {
+			g_set_error (error,
+			             NM_CONNECTION_ERROR,
+			             NM_CONNECTION_ERROR_INVALID_PROPERTY,
+			             _("'%s' is not a valid IP%c address"),
+			             priv->local, family == AF_INET ? '4' : '6');
+			g_prefix_error (error, "%s.%s: ",
+			                NM_SETTING_VXLAN_SETTING_NAME,
+			                NM_SETTING_VXLAN_LOCAL);
+			return FALSE;
+		}
+	}
+
+	if (   priv->parent
+	    && !nm_utils_iface_valid_name (priv->parent)
+	    && !nm_utils_is_uuid (priv->parent)) {
+		g_set_error (error,
+		             NM_CONNECTION_ERROR,
+		             NM_CONNECTION_ERROR_INVALID_PROPERTY,
+		             _("'%s' is neither an UUID nor an interface name"),
+		             priv->parent);
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_VXLAN_SETTING_NAME,
+		                NM_SETTING_VXLAN_PARENT);
+		return FALSE;
+	}
+
+	if (   (priv->source_port_min || priv->source_port_max)
+	    && (priv->source_port_min > priv->source_port_max)) {
+		g_set_error (error,
+		             NM_CONNECTION_ERROR,
+		             NM_CONNECTION_ERROR_INVALID_PROPERTY,
+		             _("%d is greater than local port max %d"),
+		             priv->source_port_min,
+		             priv->source_port_max);
+		g_prefix_error (error, "%s.%s: ",
+		                NM_SETTING_VXLAN_SETTING_NAME,
+		                NM_SETTING_VXLAN_SOURCE_PORT_MIN);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+              const GValue *value, GParamSpec *pspec)
+{
+	NMSettingVxlan *setting = NM_SETTING_VXLAN (object);
+	NMSettingVxlanPrivate *priv = NM_SETTING_VXLAN_GET_PRIVATE (setting);
+
+	switch (prop_id) {
+	case PROP_PARENT:
+		g_free (priv->parent);
+		priv->parent = g_value_dup_string (value);
+		break;
+	case PROP_ID:
+		priv->id = g_value_get_uint (value);
+		break;
+	case PROP_LOCAL:
+		g_free (priv->local);
+		priv->local = g_value_dup_string (value);
+		break;
+	case PROP_REMOTE:
+		g_free (priv->remote);
+		priv->remote = g_value_dup_string (value);
+		break;
+	case PROP_SOURCE_PORT_MIN:
+		priv->source_port_min = g_value_get_uint (value);
+		break;
+	case PROP_SOURCE_PORT_MAX:
+		priv->source_port_max = g_value_get_uint (value);
+		break;
+	case PROP_DESTINATION_PORT:
+		priv->destination_port = g_value_get_uint (value);
+		break;
+	case PROP_TOS:
+		priv->tos = g_value_get_uint (value);
+		break;
+	case PROP_AGEING:
+		priv->ageing = g_value_get_uint (value);
+		break;
+	case PROP_LIMIT:
+		priv->limit = g_value_get_uint (value);
+		break;
+	case PROP_PROXY:
+		priv->proxy = g_value_get_boolean (value);
+		break;
+	case PROP_TTL:
+		priv->ttl = g_value_get_uint (value);
+		break;
+	case PROP_LEARNING:
+		priv->learning = g_value_get_boolean (value);
+		break;
+	case PROP_RSC:
+		priv->rsc = g_value_get_boolean (value);
+		break;
+	case PROP_L2_MISS:
+		priv->l2_miss = g_value_get_boolean (value);
+		break;
+	case PROP_L3_MISS:
+		priv->l3_miss = g_value_get_boolean (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)
+{
+	NMSettingVxlan *setting = NM_SETTING_VXLAN (object);
+	NMSettingVxlanPrivate *priv = NM_SETTING_VXLAN_GET_PRIVATE (setting);
+
+	switch (prop_id) {
+	case PROP_PARENT:
+		g_value_set_string (value, priv->parent);
+		break;
+	case PROP_ID:
+		g_value_set_uint (value, priv->id);
+		break;
+	case PROP_LOCAL:
+		g_value_set_string (value, priv->local);
+		break;
+	case PROP_REMOTE:
+		g_value_set_string (value, priv->remote);
+		break;
+	case PROP_SOURCE_PORT_MIN:
+		g_value_set_uint (value, priv->source_port_min);
+		break;
+	case PROP_SOURCE_PORT_MAX:
+		g_value_set_uint (value, priv->source_port_max);
+		break;
+	case PROP_DESTINATION_PORT:
+		g_value_set_uint (value, priv->destination_port);
+		break;
+	case PROP_TOS:
+		g_value_set_uint (value, priv->tos);
+		break;
+	case PROP_AGEING:
+		g_value_set_uint (value, priv->ageing);
+		break;
+	case PROP_LIMIT:
+		g_value_set_uint (value, priv->limit);
+		break;
+	case PROP_PROXY:
+		g_value_set_boolean (value, priv->proxy);
+		break;
+	case PROP_TTL:
+		g_value_set_uint (value, priv->ttl);
+		break;
+	case PROP_LEARNING:
+		g_value_set_boolean (value, priv->learning);
+		break;
+	case PROP_RSC:
+		g_value_set_boolean (value, priv->rsc);
+		break;
+	case PROP_L2_MISS:
+		g_value_set_boolean (value, priv->l2_miss);
+		break;
+	case PROP_L3_MISS:
+		g_value_set_boolean (value, priv->l3_miss);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+finalize (GObject *object)
+{
+	NMSettingVxlan *setting = NM_SETTING_VXLAN (object);
+	NMSettingVxlanPrivate *priv = NM_SETTING_VXLAN_GET_PRIVATE (setting);
+
+	g_free (priv->parent);
+	g_free (priv->local);
+	g_free (priv->remote);
+
+	G_OBJECT_CLASS (nm_setting_vxlan_parent_class)->finalize (object);
+}
+
+static void
+nm_setting_vxlan_class_init (NMSettingVxlanClass *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 (NMSettingVxlanPrivate));
+
+	/* virtual methods */
+	object_class->set_property = set_property;
+	object_class->get_property = get_property;
+	object_class->finalize     = finalize;
+	parent_class->verify       = verify;
+
+	/* Properties */
+
+	/**
+	 * NMSettingVxlan:parent:
+	 *
+	 * If given, specifies the parent interface name or parent connection UUID.
+	 *
+	 * Since: 1.2
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_PARENT,
+		 g_param_spec_string (NM_SETTING_VXLAN_PARENT, "", "",
+		                      NULL,
+		                      G_PARAM_READWRITE |
+		                      G_PARAM_CONSTRUCT |
+		                      NM_SETTING_PARAM_INFERRABLE |
+		                      G_PARAM_STATIC_STRINGS));
+	/**
+	 * NMSettingVxlan:id:
+	 *
+	 * Specifies the VXLAN Network Identifer (or VXLAN Segment Identifier) to
+	 * use.
+	 *
+	 * Since: 1.2
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_ID,
+		 g_param_spec_uint (NM_SETTING_VXLAN_ID, "", "",
+		                    0, (1 << 24) - 1, 0,
+		                    G_PARAM_READWRITE |
+		                    G_PARAM_CONSTRUCT |
+		                    NM_SETTING_PARAM_INFERRABLE |
+		                    G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMSettingVxlan:local:
+	 *
+	 * If given, specifies the source IP address to use in outgoing packets.
+	 *
+	 * Since: 1.2
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_LOCAL,
+		 g_param_spec_string (NM_SETTING_VXLAN_LOCAL, "", "",
+		                      NULL,
+		                      G_PARAM_READWRITE |
+		                      G_PARAM_CONSTRUCT |
+		                      NM_SETTING_PARAM_INFERRABLE |
+		                      G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMSettingVxlan:remote:
+	 *
+	 * Specifies the unicast destination IP address to use in outgoing packets
+	 * when the destination link layer address is not known in the VXLAN device
+	 * forwarding database, or the multicast IP address to join.
+	 *
+	 * Since: 1.2
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_REMOTE,
+		 g_param_spec_string (NM_SETTING_VXLAN_REMOTE, "", "",
+		                      NULL,
+		                      G_PARAM_READWRITE |
+		                      G_PARAM_CONSTRUCT |
+		                      NM_SETTING_PARAM_INFERRABLE |
+		                      G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMSettingVxlan:source-port-min:
+	 *
+	 * Specifies the minimum UDP source port to communicate to the remote VXLAN
+	 * tunnel endpoint.
+	 *
+	 * Since: 1.2
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_SOURCE_PORT_MIN,
+		 g_param_spec_uint (NM_SETTING_VXLAN_SOURCE_PORT_MIN, "", "",
+		                    0, G_MAXUINT16, 0,
+		                    G_PARAM_READWRITE |
+		                    G_PARAM_CONSTRUCT |
+		                    NM_SETTING_PARAM_INFERRABLE |
+		                    G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMSettingVxlan:source-port-max:
+	 *
+	 * Specifies the maximum UDP source port to communicate to the remote VXLAN
+	 * tunnel endpoint.
+	 *
+	 * Since: 1.2
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_SOURCE_PORT_MAX,
+		 g_param_spec_uint (NM_SETTING_VXLAN_SOURCE_PORT_MAX, "", "",
+		                    0, G_MAXUINT16, 0,
+		                    G_PARAM_READWRITE |
+		                    G_PARAM_CONSTRUCT |
+		                    NM_SETTING_PARAM_INFERRABLE |
+		                    G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMSettingVxlan:destination-port:
+	 *
+	 * Specifies the UDP destination port to communicate to the remote VXLAN
+	 * tunnel endpoint.
+	 *
+	 * Since: 1.2
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_DESTINATION_PORT,
+		 g_param_spec_uint (NM_SETTING_VXLAN_DESTINATION_PORT, "", "",
+		                    0, G_MAXUINT16, DST_PORT_DEFAULT,
+		                    G_PARAM_READWRITE |
+		                    G_PARAM_CONSTRUCT |
+		                    NM_SETTING_PARAM_INFERRABLE |
+		                    G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMSettingVxlan:ageing:
+	 *
+	 * Specifies the lifetime in seconds of FDB entries learnt by the kernel.
+	 *
+	 * Since: 1.2
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_AGEING,
+		 g_param_spec_uint (NM_SETTING_VXLAN_AGEING, "", "",
+		                    0, G_MAXINT32, 300,
+		                    G_PARAM_READWRITE |
+		                    G_PARAM_CONSTRUCT |
+		                    NM_SETTING_PARAM_INFERRABLE |
+		                    G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMSettingVxlan:limit:
+	 *
+	 * Specifies the maximum number of FDB entries. A value of zero means that
+	 * the kernel will store unlimited entries.
+	 *
+	 * Since: 1.2
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_AGEING,
+		 g_param_spec_uint (NM_SETTING_VXLAN_LIMIT, "", "",
+		                    0, G_MAXINT32, 0,
+		                    G_PARAM_READWRITE |
+		                    G_PARAM_CONSTRUCT |
+		                    NM_SETTING_PARAM_INFERRABLE |
+		                    G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMSettingVxlan:tos:
+	 *
+	 * Specifies the TOS value to use in outgoing packets.
+	 *
+	 * Since: 1.2
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_TOS,
+		 g_param_spec_uint (NM_SETTING_VXLAN_TOS, "", "",
+		                    0, 255, 0,
+		                    G_PARAM_READWRITE |
+		                    G_PARAM_CONSTRUCT |
+		                    NM_SETTING_PARAM_INFERRABLE |
+		                    G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMSettingVxlan:ttl:
+	 *
+	 * Specifies the time-to-live value to use in outgoing packets.
+	 *
+	 * Since: 1.2
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_TTL,
+		 g_param_spec_uint (NM_SETTING_VXLAN_TTL, "", "",
+		                    0, 255, 0,
+		                    G_PARAM_READWRITE |
+		                    G_PARAM_CONSTRUCT |
+		                    NM_SETTING_PARAM_INFERRABLE |
+		                    G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMSettingVxlan:proxy:
+	 *
+	 * Specifies whether ARP proxy is turned on.
+	 *
+	 * Since: 1.2
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_PROXY,
+		 g_param_spec_boolean (NM_SETTING_VXLAN_PROXY, "", "",
+		                       FALSE,
+		                       G_PARAM_READWRITE |
+		                       G_PARAM_CONSTRUCT |
+		                       NM_SETTING_PARAM_INFERRABLE |
+		                       G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMSettingVxlan:learning:
+	 *
+	 * Specifies whether unknown source link layer addresses and IP addresses
+	 * are entered into the VXLAN device forwarding database.
+	 *
+	 * Since: 1.2
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_LEARNING,
+		 g_param_spec_boolean (NM_SETTING_VXLAN_LEARNING, "", "",
+		                       TRUE,
+		                       G_PARAM_READWRITE |
+		                       G_PARAM_CONSTRUCT |
+		                       NM_SETTING_PARAM_INFERRABLE |
+		                       G_PARAM_STATIC_STRINGS));
+	/**
+	 * NMSettingVxlan:rsc:
+	 *
+	 * Specifies whether route short circuit is turned on.
+	 *
+	 * Since: 1.2
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_RSC,
+		 g_param_spec_boolean (NM_SETTING_VXLAN_RSC, "", "",
+		                       FALSE,
+		                       G_PARAM_READWRITE |
+		                       G_PARAM_CONSTRUCT |
+		                       NM_SETTING_PARAM_INFERRABLE |
+		                       G_PARAM_STATIC_STRINGS));
+	/**
+	 * NMSettingVxlan:l2-miss:
+	 *
+	 * Specifies whether netlink LL ADDR miss notifications are generated.
+	 *
+	 * Since: 1.2
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_L2_MISS,
+		 g_param_spec_boolean (NM_SETTING_VXLAN_L2_MISS, "", "",
+		                       FALSE,
+		                       G_PARAM_READWRITE |
+		                       G_PARAM_CONSTRUCT |
+		                       NM_SETTING_PARAM_INFERRABLE |
+		                       G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMSettingVxlan:l3-miss:
+	 *
+	 * Specifies whether netlink IP ADDR miss notifications are generated.
+	 *
+	 * Since: 1.2
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_L3_MISS,
+		 g_param_spec_boolean (NM_SETTING_VXLAN_L3_MISS, "", "",
+		                       FALSE,
+		                       G_PARAM_READWRITE |
+		                       G_PARAM_CONSTRUCT |
+		                       NM_SETTING_PARAM_INFERRABLE |
+		                       G_PARAM_STATIC_STRINGS));
+}
diff --git a/libnm-core/nm-setting-vxlan.h b/libnm-core/nm-setting-vxlan.h
new file mode 100644
index 00000000..c410338e
--- /dev/null
+++ b/libnm-core/nm-setting-vxlan.h
@@ -0,0 +1,109 @@
+/* -*- 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 2015 Red Hat, Inc.
+ */
+
+#ifndef __NM_SETTING_VXLAN_H__
+#define __NM_SETTING_VXLAN_H__
+
+#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION)
+#error "Only <NetworkManager.h> can be included directly."
+#endif
+
+#include "nm-setting.h"
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_SETTING_VXLAN            (nm_setting_vxlan_get_type ())
+#define NM_SETTING_VXLAN(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_VXLAN, NMSettingVxlan))
+#define NM_SETTING_VXLAN_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_VXLANCONFIG, NMSettingVxlanClass))
+#define NM_IS_SETTING_VXLAN(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_VXLAN))
+#define NM_IS_SETTING_VXLAN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_VXLAN))
+#define NM_SETTING_VXLAN_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_VXLAN, NMSettingVxlanClass))
+
+#define NM_SETTING_VXLAN_SETTING_NAME       "vxlan"
+
+#define NM_SETTING_VXLAN_PARENT             "parent"
+#define NM_SETTING_VXLAN_ID                 "id"
+#define NM_SETTING_VXLAN_LOCAL              "local"
+#define NM_SETTING_VXLAN_REMOTE             "remote"
+#define NM_SETTING_VXLAN_SOURCE_PORT_MIN    "source-port-min"
+#define NM_SETTING_VXLAN_SOURCE_PORT_MAX    "source-port-max"
+#define NM_SETTING_VXLAN_DESTINATION_PORT   "destination-port"
+#define NM_SETTING_VXLAN_TOS                "tos"
+#define NM_SETTING_VXLAN_TTL                "ttl"
+#define NM_SETTING_VXLAN_AGEING             "ageing"
+#define NM_SETTING_VXLAN_LIMIT              "limit"
+#define NM_SETTING_VXLAN_PROXY              "proxy"
+#define NM_SETTING_VXLAN_LEARNING           "learning"
+#define NM_SETTING_VXLAN_RSC                "rsc"
+#define NM_SETTING_VXLAN_L2_MISS            "l2-miss"
+#define NM_SETTING_VXLAN_L3_MISS            "l3-miss"
+
+struct _NMSettingVxlan {
+	NMSetting parent;
+};
+
+typedef struct {
+	NMSettingClass parent;
+
+	/*< private >*/
+	gpointer padding[4];
+} NMSettingVxlanClass;
+
+NM_AVAILABLE_IN_1_2
+GType       nm_setting_vxlan_get_type             (void);
+NM_AVAILABLE_IN_1_2
+NMSetting  *nm_setting_vxlan_new                  (void);
+NM_AVAILABLE_IN_1_2
+const char *nm_setting_vxlan_get_parent           (NMSettingVxlan *setting);
+NM_AVAILABLE_IN_1_2
+guint       nm_setting_vxlan_get_id               (NMSettingVxlan *setting);
+NM_AVAILABLE_IN_1_2
+const char *nm_setting_vxlan_get_local            (NMSettingVxlan *setting);
+NM_AVAILABLE_IN_1_2
+const char *nm_setting_vxlan_get_remote           (NMSettingVxlan *setting);
+NM_AVAILABLE_IN_1_2
+guint       nm_setting_vxlan_get_source_port_min  (NMSettingVxlan *setting);
+NM_AVAILABLE_IN_1_2
+guint       nm_setting_vxlan_get_source_port_max  (NMSettingVxlan *setting);
+NM_AVAILABLE_IN_1_2
+guint       nm_setting_vxlan_get_destination_port (NMSettingVxlan *setting);
+NM_AVAILABLE_IN_1_2
+guint       nm_setting_vxlan_get_tos              (NMSettingVxlan *setting);
+NM_AVAILABLE_IN_1_2
+guint       nm_setting_vxlan_get_ttl              (NMSettingVxlan *setting);
+NM_AVAILABLE_IN_1_2
+guint       nm_setting_vxlan_get_ageing           (NMSettingVxlan *setting);
+NM_AVAILABLE_IN_1_2
+guint       nm_setting_vxlan_get_limit            (NMSettingVxlan *setting);
+NM_AVAILABLE_IN_1_2
+gboolean    nm_setting_vxlan_get_proxy            (NMSettingVxlan *setting);
+NM_AVAILABLE_IN_1_2
+gboolean    nm_setting_vxlan_get_learning         (NMSettingVxlan *setting);
+NM_AVAILABLE_IN_1_2
+gboolean    nm_setting_vxlan_get_rsc              (NMSettingVxlan *setting);
+NM_AVAILABLE_IN_1_2
+gboolean    nm_setting_vxlan_get_l2_miss          (NMSettingVxlan *setting);
+NM_AVAILABLE_IN_1_2
+gboolean    nm_setting_vxlan_get_l3_miss          (NMSettingVxlan *setting);
+
+G_END_DECLS
+
+#endif /* __NM_SETTING_VXLAN_H__ */
diff --git a/libnm-core/nm-setting-wimax.c b/libnm-core/nm-setting-wimax.c
index 541c0bbf..95a09952 100644
--- a/libnm-core/nm-setting-wimax.c
+++ b/libnm-core/nm-setting-wimax.c
@@ -24,7 +24,6 @@
 
 #include <string.h>
 #include <net/ethernet.h>
-#include <glib/gi18n-lib.h>
 
 #include "nm-setting-wimax.h"
 #include "nm-setting-private.h"
@@ -37,6 +36,10 @@
  *
  * The #NMSettingWimax object is a #NMSetting subclass that describes properties
  * necessary for connection to 802.16e Mobile WiMAX networks.
+ *
+ * NetworkManager no longer supports WiMAX; while this API remains available for
+ * backward-compatibility reasons, it serves no real purpose, since WiMAX
+ * connections cannot be activated.
  **/
 
 G_DEFINE_TYPE_WITH_CODE (NMSettingWimax, nm_setting_wimax, NM_TYPE_SETTING,
@@ -64,6 +67,8 @@ enum {
  * Creates a new #NMSettingWimax object with default values.
  *
  * Returns: the new empty #NMSettingWimax object
+ *
+ * Deprecated: 1.2: WiMAX is no longer supported.
  **/
 NMSetting *
 nm_setting_wimax_new (void)
@@ -79,6 +84,8 @@ nm_setting_wimax_new (void)
  * specific WiMAX network this setting describes a connection to.
  *
  * Returns: the WiMAX NSP name
+ *
+ * Deprecated: 1.2: WiMAX is no longer supported.
  **/
 const char *
 nm_setting_wimax_get_network_name (NMSettingWimax *setting)
@@ -96,6 +103,8 @@ nm_setting_wimax_get_network_name (NMSettingWimax *setting)
  * to.
  *
  * Returns: the MAC address
+ *
+ * Deprecated: 1.2: WiMAX is no longer supported.
  **/
 const char *
 nm_setting_wimax_get_mac_address (NMSettingWimax *setting)
@@ -217,6 +226,8 @@ nm_setting_wimax_class_init (NMSettingWimaxClass *setting_class)
 	 *
 	 * Network Service Provider (NSP) name of the WiMAX network this connection
 	 * should use.
+	 *
+	 * Deprecated: 1.2: WiMAX is no longer supported.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_NETWORK_NAME,
@@ -231,6 +242,8 @@ nm_setting_wimax_class_init (NMSettingWimaxClass *setting_class)
 	 * 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).
+	 *
+	 * Deprecated: 1.2: WiMAX is no longer supported.
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_MAC_ADDRESS,
diff --git a/libnm-core/nm-setting-wimax.h b/libnm-core/nm-setting-wimax.h
index 0a585046..0a98fbb5 100644
--- a/libnm-core/nm-setting-wimax.h
+++ b/libnm-core/nm-setting-wimax.h
@@ -53,10 +53,14 @@ typedef struct {
 	gpointer padding[4];
 } NMSettingWimaxClass;
 
+NM_DEPRECATED_IN_1_2
 GType nm_setting_wimax_get_type (void);
 
+NM_DEPRECATED_IN_1_2
 NMSetting        *nm_setting_wimax_new              (void);
+NM_DEPRECATED_IN_1_2
 const char       *nm_setting_wimax_get_network_name (NMSettingWimax *setting);
+NM_DEPRECATED_IN_1_2
 const char       *nm_setting_wimax_get_mac_address  (NMSettingWimax *setting);
 
 G_END_DECLS
diff --git a/libnm-core/nm-setting-wired.c b/libnm-core/nm-setting-wired.c
index c38b1874..64b66971 100644
--- a/libnm-core/nm-setting-wired.c
+++ b/libnm-core/nm-setting-wired.c
@@ -24,7 +24,6 @@
 
 #include <string.h>
 #include <net/ethernet.h>
-#include <glib/gi18n-lib.h>
 
 #include "nm-setting-wired.h"
 #include "nm-utils.h"
@@ -567,7 +566,7 @@ nm_setting_wired_get_valid_s390_options (NMSettingWired *setting)
  *
  * Returns: the Wake-on-LAN options
  *
- * Since: 1.0.6
+ * Since: 1.2
  */
 NMSettingWiredWakeOnLan
 nm_setting_wired_get_wake_on_lan (NMSettingWired *setting)
@@ -576,6 +575,8 @@ nm_setting_wired_get_wake_on_lan (NMSettingWired *setting)
 
 	return NM_SETTING_WIRED_GET_PRIVATE (setting)->wol;
 }
+NM_BACKPORT_SYMBOL (libnm_1_0_6, NMSettingWiredWakeOnLan, nm_setting_wired_get_wake_on_lan,
+                    (NMSettingWired *setting), (setting));
 
 /**
  * nm_setting_wired_get_wake_on_lan_password:
@@ -586,7 +587,7 @@ nm_setting_wired_get_wake_on_lan (NMSettingWired *setting)
  *
  * Returns: the Wake-on-LAN setting password, or %NULL if there is no password.
  *
- * Since: 1.0.6
+ * Since: 1.2
  */
 const char *
 nm_setting_wired_get_wake_on_lan_password (NMSettingWired *setting)
@@ -595,6 +596,10 @@ nm_setting_wired_get_wake_on_lan_password (NMSettingWired *setting)
 
 	return NM_SETTING_WIRED_GET_PRIVATE (setting)->wol_password;
 }
+NM_BACKPORT_SYMBOL (libnm_1_0_6, const char *, nm_setting_wired_get_wake_on_lan_password,
+                    (NMSettingWired *setting), (setting));
+
+NM_BACKPORT_SYMBOL (libnm_1_0_6, GType, nm_setting_wired_wake_on_lan_get_type, (void), ());
 
 static gboolean
 verify (NMSetting *setting, NMConnection *connection, GError **error)
@@ -1195,7 +1200,7 @@ nm_setting_wired_class_init (NMSettingWiredClass *setting_class)
 	 * %NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE (to disable management of Wake-on-LAN in
 	 * NetworkManager).
 	 *
-	 * Since: 1.0.6
+	 * Since: 1.2
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_WAKE_ON_LAN,
@@ -1212,7 +1217,7 @@ nm_setting_wired_class_init (NMSettingWiredClass *setting_class)
 	 * Wake-on-LAN, represented as an Ethernet MAC address.  If %NULL,
 	 * no password will be required.
 	 *
-	 * Since: 1.0.6
+	 * Since: 1.2
 	 **/
 	g_object_class_install_property
 		(object_class, PROP_WAKE_ON_LAN_PASSWORD,
diff --git a/libnm-core/nm-setting-wired.h b/libnm-core/nm-setting-wired.h
index e1fd6f67..7eb53d30 100644
--- a/libnm-core/nm-setting-wired.h
+++ b/libnm-core/nm-setting-wired.h
@@ -60,7 +60,7 @@ G_BEGIN_DECLS
  * Options for #NMSettingWired:wake-on-lan. Note that not all options
  * are supported by all devices.
  *
- * Since: 1.0.6
+ * Since: 1.2
  */
 typedef enum { /*< flags >*/
 	NM_SETTING_WIRED_WAKE_ON_LAN_NONE      = 0, /*< skip >*/
@@ -145,9 +145,7 @@ gboolean          nm_setting_wired_remove_s390_option   (NMSettingWired *setting
                                                          const char *key);
 const char **     nm_setting_wired_get_valid_s390_options (NMSettingWired *setting);
 
-NM_AVAILABLE_IN_1_0_6
 NMSettingWiredWakeOnLan  nm_setting_wired_get_wake_on_lan          (NMSettingWired *setting);
-NM_AVAILABLE_IN_1_0_6
 const char *             nm_setting_wired_get_wake_on_lan_password (NMSettingWired *setting);
 
 G_END_DECLS
diff --git a/libnm-core/nm-setting-wireless-security.c b/libnm-core/nm-setting-wireless-security.c
index 6df5b461..7c5e3932 100644
--- a/libnm-core/nm-setting-wireless-security.c
+++ b/libnm-core/nm-setting-wireless-security.c
@@ -23,7 +23,6 @@
 #include "config.h"
 
 #include <string.h>
-#include <glib/gi18n-lib.h>
 
 #include "nm-setting-wireless-security.h"
 #include "nm-setting-8021x.h"
@@ -1018,6 +1017,63 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
 }
 
 static gboolean
+_verify_wep_key (const char *wep_key,
+                 NMWepKeyType wep_key_type,
+                 const char *property,
+                 GError **error)
+{
+	if (wep_key && !nm_utils_wep_key_valid (wep_key, wep_key_type)) {
+		g_set_error_literal (error,
+		                     NM_CONNECTION_ERROR,
+		                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
+		                     _("property is invalid"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, property);
+		return FALSE;
+	}
+	return TRUE;
+}
+
+static gboolean
+verify_secrets (NMSetting *setting, NMConnection *connection, GError **error)
+{
+	NMSettingWirelessSecurity *self = NM_SETTING_WIRELESS_SECURITY (setting);
+	NMSettingWirelessSecurityPrivate *priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (self);
+
+	/* LEAP */
+	if (   priv->auth_alg
+	    && !strcmp (priv->auth_alg, "leap")
+	    && !strcmp (priv->key_mgmt, "ieee8021x")) {
+		if (!_nm_setting_verify_secret_string (priv->leap_password,
+		                                       NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
+		                                       NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD,
+		                                       error))
+			return FALSE;
+	}
+
+	/* WEP */
+	if (!_verify_wep_key (priv->wep_key0, priv->wep_key_type, NM_SETTING_WIRELESS_SECURITY_WEP_KEY0, error))
+		return FALSE;
+	if (!_verify_wep_key (priv->wep_key1, priv->wep_key_type, NM_SETTING_WIRELESS_SECURITY_WEP_KEY1, error))
+		return FALSE;
+	if (!_verify_wep_key (priv->wep_key2, priv->wep_key_type, NM_SETTING_WIRELESS_SECURITY_WEP_KEY2, error))
+		return FALSE;
+	if (!_verify_wep_key (priv->wep_key3, priv->wep_key_type, NM_SETTING_WIRELESS_SECURITY_WEP_KEY3, error))
+		return FALSE;
+
+	/* WPA-PSK */
+	if (priv->psk && !nm_utils_wpa_psk_valid (priv->psk)) {
+		g_set_error_literal (error,
+		                     NM_CONNECTION_ERROR,
+		                     NM_CONNECTION_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;
+	}
+
+	return TRUE;
+}
+
+static gboolean
 get_secret_flags (NMSetting *setting,
                   const char *secret_name,
                   gboolean verify_secret,
@@ -1267,6 +1323,7 @@ nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *setting
 	object_class->finalize     = finalize;
 
 	parent_class->verify           = verify;
+	parent_class->verify_secrets   = verify_secrets;
 	parent_class->need_secrets     = need_secrets;
 	parent_class->get_secret_flags = get_secret_flags;
 	parent_class->set_secret_flags = set_secret_flags;
diff --git a/libnm-core/nm-setting-wireless.c b/libnm-core/nm-setting-wireless.c
index 34c97fe8..2a148293 100644
--- a/libnm-core/nm-setting-wireless.c
+++ b/libnm-core/nm-setting-wireless.c
@@ -24,7 +24,6 @@
 
 #include <string.h>
 #include <net/ethernet.h>
-#include <glib/gi18n-lib.h>
 
 #include "nm-setting-wireless.h"
 #include "nm-utils.h"
@@ -59,6 +58,8 @@ typedef struct {
 	guint32 mtu;
 	GSList *seen_bssids;
 	gboolean hidden;
+	guint32 powersave;
+	NMSettingMacRandomization mac_address_randomization;
 } NMSettingWirelessPrivate;
 
 enum {
@@ -76,6 +77,8 @@ enum {
 	PROP_MTU,
 	PROP_SEEN_BSSIDS,
 	PROP_HIDDEN,
+	PROP_POWERSAVE,
+	PROP_MAC_ADDRESS_RANDOMIZATION,
 
 	LAST_PROP
 };
@@ -601,6 +604,39 @@ nm_setting_wireless_get_hidden (NMSettingWireless *setting)
 }
 
 /**
+ * nm_setting_wireless_get_powersave:
+ * @setting: the #NMSettingWireless
+ *
+ * Returns: the #NMSettingWireless:powersave property of the setting
+ *
+ * Since: 1.2
+ **/
+guint32
+nm_setting_wireless_get_powersave (NMSettingWireless *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), 0);
+
+	return NM_SETTING_WIRELESS_GET_PRIVATE (setting)->powersave;
+}
+
+/**
+ * nm_setting_wireless_get_mac_address_randomization:
+ * @setting: the #NMSettingWireless
+ *
+ * Returns: the #NMSettingWireless:mac-address-randomization property of the
+ * setting
+ *
+ * Since: 1.2
+ **/
+NMSettingMacRandomization
+nm_setting_wireless_get_mac_address_randomization (NMSettingWireless *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), 0);
+
+	return NM_SETTING_WIRELESS_GET_PRIVATE (setting)->mac_address_randomization;
+}
+
+/**
  * nm_setting_wireless_add_seen_bssid:
  * @setting: the #NMSettingWireless
  * @bssid: the new BSSID to add to the list
@@ -915,6 +951,12 @@ set_property (GObject *object, guint prop_id,
 	case PROP_HIDDEN:
 		priv->hidden = g_value_get_boolean (value);
 		break;
+	case PROP_POWERSAVE:
+		priv->powersave = g_value_get_uint (value);
+		break;
+	case PROP_MAC_ADDRESS_RANDOMIZATION:
+		priv->mac_address_randomization = g_value_get_uint (value);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -968,6 +1010,12 @@ get_property (GObject *object, guint prop_id,
 	case PROP_HIDDEN:
 		g_value_set_boolean (value, nm_setting_wireless_get_hidden (setting));
 		break;
+	case PROP_POWERSAVE:
+		g_value_set_uint (value, nm_setting_wireless_get_powersave (setting));
+		break;
+	case PROP_MAC_ADDRESS_RANDOMIZATION:
+		g_value_set_uint (value, nm_setting_wireless_get_mac_address_randomization (setting));
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -1314,6 +1362,58 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *setting_class)
 		                       G_PARAM_READWRITE |
 		                       G_PARAM_STATIC_STRINGS));
 
+	/**
+	 * NMSettingWireless:powersave:
+	 *
+	 * If set to %FALSE, Wi-Fi power saving behavior is disabled.  If set to
+	 * %TRUE, Wi-Fi power saving behavior is enabled.  All other values are
+	 * reserved.  Note that even though only boolean values are allowed, the
+	 * property type is an unsigned integer to allow for future expansion.
+	 *
+	 * Since: 1.2
+	 **/
+	/* ---ifcfg-rh---
+	 * property: powersave
+	 * variable: POWERSAVE(+)
+	 * default: no
+	 * description: Enables or disables Wi-Fi power saving.
+	 * example: POWERSAVE=yes
+	 * ---end---
+	 */
+	g_object_class_install_property
+		(object_class, PROP_POWERSAVE,
+		 g_param_spec_uint (NM_SETTING_WIRELESS_POWERSAVE, "", "",
+		                    0, G_MAXUINT32, 0,
+		                    G_PARAM_READWRITE |
+		                    G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMSettingWireless:mac-address-randomization:
+	 *
+	 * One of %NM_SETTING_MAC_RANDOMIZATION_DEFAULT (never randomize unless
+	 * the user has set a global default to randomize and the supplicant
+	 * supports randomization),  %NM_SETTING_MAC_RANDOMIZATION_NEVER (never
+	 * randomize the MAC address), or %NM_SETTING_MAC_RANDOMIZATION_ALWAYS
+	 * (always randomize the MAC address).
+	 *
+	 * Since: 1.2
+	 **/
+	/* ---ifcfg-rh---
+	 * property: mac-address-randomization
+	 * variable: MAC_ADDRESS_RANDOMIZATION(+)
+	 * values: 0 (default), (1) never, (2) always
+	 * default: 1
+	 * description: Enables or disables Wi-Fi MAC address randomization.
+	 * example: MAC_ADDRESS_RANDOMIZATION=2
+	 * ---end---
+	 */
+	g_object_class_install_property
+		(object_class, PROP_MAC_ADDRESS_RANDOMIZATION,
+		 g_param_spec_uint (NM_SETTING_WIRELESS_MAC_ADDRESS_RANDOMIZATION, "", "",
+		                    0, G_MAXUINT32, NM_SETTING_MAC_RANDOMIZATION_DEFAULT,
+		                    G_PARAM_READWRITE |
+		                    G_PARAM_STATIC_STRINGS));
+
 	/* Compatibility for deprecated property */
 	/* ---ifcfg-rh---
 	 * property: security
diff --git a/libnm-core/nm-setting-wireless.h b/libnm-core/nm-setting-wireless.h
index ef27ded2..a4c0147f 100644
--- a/libnm-core/nm-setting-wireless.h
+++ b/libnm-core/nm-setting-wireless.h
@@ -54,6 +54,8 @@ G_BEGIN_DECLS
 #define NM_SETTING_WIRELESS_MTU         "mtu"
 #define NM_SETTING_WIRELESS_SEEN_BSSIDS "seen-bssids"
 #define NM_SETTING_WIRELESS_HIDDEN      "hidden"
+#define NM_SETTING_WIRELESS_POWERSAVE   "powersave"
+#define NM_SETTING_WIRELESS_MAC_ADDRESS_RANDOMIZATION   "mac-address-randomization"
 
 /**
  * NM_SETTING_WIRELESS_MODE_ADHOC:
@@ -117,6 +119,11 @@ void              nm_setting_wireless_clear_mac_blacklist_items   (NMSettingWire
 
 guint32           nm_setting_wireless_get_mtu                (NMSettingWireless *setting);
 gboolean          nm_setting_wireless_get_hidden             (NMSettingWireless *setting);
+NM_AVAILABLE_IN_1_2
+guint32           nm_setting_wireless_get_powersave          (NMSettingWireless *setting);
+
+NM_AVAILABLE_IN_1_2
+NMSettingMacRandomization nm_setting_wireless_get_mac_address_randomization (NMSettingWireless *setting);
 
 gboolean          nm_setting_wireless_add_seen_bssid         (NMSettingWireless *setting,
                                                               const char *bssid);
diff --git a/libnm-core/nm-setting.c b/libnm-core/nm-setting.c
index e1e81b5d..b08eea10 100644
--- a/libnm-core/nm-setting.c
+++ b/libnm-core/nm-setting.c
@@ -23,15 +23,15 @@
 #include "config.h"
 
 #include <string.h>
-#include <glib/gi18n-lib.h>
-#include <gio/gio.h>
 
+#include "nm-default.h"
 #include "nm-setting.h"
 #include "nm-setting-private.h"
 #include "nm-utils.h"
 #include "nm-core-internal.h"
 #include "nm-utils-private.h"
 #include "nm-property-compare.h"
+#include "nm-macros-internal.h"
 
 #include "nm-setting-connection.h"
 #include "nm-setting-bond.h"
@@ -95,9 +95,7 @@ static void
 _ensure_registered (void)
 {
 	if (G_UNLIKELY (registered_settings == NULL)) {
-#if !GLIB_CHECK_VERSION (2, 35, 0)
-		g_type_init ();
-#endif
+		nm_g_type_init ();
 		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);
 	}
@@ -1012,6 +1010,53 @@ _nm_setting_verify (NMSetting *setting, NMConnection *connection, GError **error
 	return NM_SETTING_VERIFY_SUCCESS;
 }
 
+/**
+ * nm_setting_verify_secrets:
+ * @setting: the #NMSetting to verify secrets in
+ * @connection: (allow-none): the #NMConnection that @setting came from, or
+ *   %NULL if @setting is being verified in isolation.
+ * @error: location to store error, or %NULL
+ *
+ * Verifies the secrets in the setting.
+ * The returned #GError contains information about which secret of the setting
+ * failed validation, and in what way that secret failed validation.
+ * The secret validation is done separately from main setting validation, because
+ * in some cases connection failure is not desired just for the secrets.
+ *
+ * Returns: %TRUE if the setting secrets are valid, %FALSE if they are not
+ *
+ * Since: 1.2
+ **/
+gboolean
+nm_setting_verify_secrets (NMSetting *setting, NMConnection *connection, GError **error)
+{
+	g_return_val_if_fail (NM_IS_SETTING (setting), NM_SETTING_VERIFY_ERROR);
+	g_return_val_if_fail (!connection || NM_IS_CONNECTION (connection), NM_SETTING_VERIFY_ERROR);
+	g_return_val_if_fail (!error || *error == NULL, NM_SETTING_VERIFY_ERROR);
+
+	if (NM_SETTING_GET_CLASS (setting)->verify_secrets)
+		return NM_SETTING_GET_CLASS (setting)->verify_secrets (setting, connection, error);
+
+	return NM_SETTING_VERIFY_SUCCESS;
+}
+
+gboolean
+_nm_setting_verify_secret_string (const char *str,
+                                  const char *setting_name,
+                                  const char *property,
+                                  GError **error)
+{
+	if (str && !*str) {
+		g_set_error_literal (error,
+		                     NM_CONNECTION_ERROR,
+		                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
+		                     _("property is empty"));
+		g_prefix_error (error, "%s.%s: ", setting_name, property);
+		return FALSE;
+	}
+	return TRUE;
+}
+
 static gboolean
 compare_property (NMSetting *setting,
                   NMSetting *other,
@@ -1101,15 +1146,20 @@ nm_setting_compare (NMSetting *a,
 		GParamSpec *prop_spec = property_specs[i];
 
 		/* Fuzzy compare ignores secrets and properties defined with the FUZZY_IGNORE flag */
-		if (   (flags & NM_SETTING_COMPARE_FLAG_FUZZY)
-		    && (prop_spec->flags & (NM_SETTING_PARAM_FUZZY_IGNORE | NM_SETTING_PARAM_SECRET)))
+		if (   NM_FLAGS_HAS (flags, NM_SETTING_COMPARE_FLAG_FUZZY)
+		    && !NM_FLAGS_ANY (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))
+		if (   NM_FLAGS_HAS (flags, NM_SETTING_COMPARE_FLAG_INFERRABLE)
+		    && !NM_FLAGS_HAS (prop_spec->flags, NM_SETTING_PARAM_INFERRABLE))
 			continue;
 
-		if (   (flags & NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS)
-		    && (prop_spec->flags & NM_SETTING_PARAM_SECRET))
+		if (   NM_FLAGS_HAS (flags, NM_SETTING_COMPARE_FLAG_IGNORE_REAPPLY_IMMEDIATELY)
+		    && NM_FLAGS_HAS (prop_spec->flags, NM_SETTING_PARAM_REAPPLY_IMMEDIATELY))
+			continue;
+
+		if (   NM_FLAGS_HAS (flags, NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS)
+		    && NM_FLAGS_HAS (prop_spec->flags, NM_SETTING_PARAM_SECRET))
 			continue;
 
 		same = NM_SETTING_GET_CLASS (a)->compare_property (a, b, prop_spec, flags);
@@ -1133,6 +1183,9 @@ should_compare_prop (NMSetting *setting,
 	if ((comp_flags & NM_SETTING_COMPARE_FLAG_INFERRABLE) && !(prop_flags & NM_SETTING_PARAM_INFERRABLE))
 		return FALSE;
 
+	if ((comp_flags & NM_SETTING_COMPARE_FLAG_IGNORE_REAPPLY_IMMEDIATELY) && !(prop_flags & NM_SETTING_PARAM_REAPPLY_IMMEDIATELY))
+		return FALSE;
+
 	if (prop_flags & NM_SETTING_PARAM_SECRET) {
 		NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE;
 
diff --git a/libnm-core/nm-setting.h b/libnm-core/nm-setting.h
index 3601fce3..3083ef60 100644
--- a/libnm-core/nm-setting.h
+++ b/libnm-core/nm-setting.h
@@ -127,11 +127,27 @@ typedef enum {
 	NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT = 0x00000040,
 	NM_SETTING_COMPARE_FLAG_IGNORE_TIMESTAMP = 0x00000080,
 
-	/* 0x80000000 is used for a private flag */
+	/* Higher flags like 0x80000000 and 0x40000000 are used internally as private flags */
 } NMSettingCompareFlags;
 
 
 /**
+ * NMSettingMacRandomization:
+ * @NM_SETTING_MAC_RANDOMIZATION_DEFAULT: the default value, which unless
+ * overridden by user-controlled defaults configuration, is "never".
+ * @NM_SETTING_MAC_RANDOMIZATION_NEVER: the device's MAC address is always used.
+ * @NM_SETTING_MAC_RANDOMIZATION_ALWAYS: a random MAC address is used.
+ *
+ * Controls if and how the MAC address of a device is randomzied.
+ **/
+typedef enum {
+	NM_SETTING_MAC_RANDOMIZATION_DEFAULT = 0,
+	NM_SETTING_MAC_RANDOMIZATION_NEVER,
+	NM_SETTING_MAC_RANDOMIZATION_ALWAYS,
+} NMSettingMacRandomization;
+
+
+/**
  * NMSetting:
  *
  * The NMSetting struct contains only private data.
@@ -164,6 +180,10 @@ typedef struct {
 	                                  NMConnection  *connection,
 	                                  GError       **error);
 
+	gboolean    (*verify_secrets)    (NMSetting     *setting,
+	                                  NMConnection  *connection,
+	                                  GError       **error);
+
 	GPtrArray  *(*need_secrets)      (NMSetting  *setting);
 
 	int         (*update_one_secret) (NMSetting  *setting,
@@ -195,7 +215,7 @@ typedef struct {
 	                                  NMSettingCompareFlags flags);
 
 	/*< private >*/
-	gpointer padding[8];
+	gpointer padding[7];
 } NMSettingClass;
 
 /**
@@ -226,6 +246,11 @@ gboolean    nm_setting_verify        (NMSetting     *setting,
                                       NMConnection  *connection,
                                       GError       **error);
 
+NM_AVAILABLE_IN_1_2
+gboolean    nm_setting_verify_secrets (NMSetting     *setting,
+                                       NMConnection  *connection,
+                                       GError       **error);
+
 gboolean    nm_setting_compare       (NMSetting *a,
                                       NMSetting *b,
                                       NMSettingCompareFlags flags);
diff --git a/libnm-core/nm-utils-private.h b/libnm-core/nm-utils-private.h
index ffdc6315..68aaaa1c 100644
--- a/libnm-core/nm-utils-private.h
+++ b/libnm-core/nm-utils-private.h
@@ -21,7 +21,12 @@
 #ifndef __NM_UTILS_PRIVATE_H__
 #define __NM_UTILS_PRIVATE_H__
 
+#ifdef __NETWORKMANAGER_TYPES_H__
+#error "nm-utils-private.h" must not be used outside of libnm-core/. Do you want "nm-core-internal.h"?
+#endif
+
 #include "nm-setting-private.h"
+#include "nm-setting-ip-config.h"
 
 gboolean    _nm_utils_string_slist_validate (GSList *list,
                                              const char **valid_values);
diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c
index 987cf731..930f528e 100644
--- a/libnm-core/nm-utils.c
+++ b/libnm-core/nm-utils.c
@@ -29,14 +29,13 @@
 #include <uuid/uuid.h>
 #include <libintl.h>
 #include <gmodule.h>
-#include <glib/gi18n-lib.h>
+#include <sys/stat.h>
 
+#include "nm-default.h"
 #include "nm-utils.h"
 #include "nm-utils-private.h"
-#include "nm-glib-compat.h"
 #include "nm-setting-private.h"
 #include "crypto.h"
-#include "gsystem-local-alloc.h"
 #include "nm-macros-internal.h"
 
 #include "nm-setting-bond.h"
@@ -240,7 +239,7 @@ _nm_utils_init (void)
 	bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
 	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
 
-	g_type_init ();
+	nm_g_type_init ();
 
 	_nm_dbus_errors_init ();
 }
@@ -845,6 +844,30 @@ _nm_utils_ptrarray_to_strv (GPtrArray *ptrarray)
 }
 
 /**
+ * _nm_utils_strv_equal:
+ * @strv1: a string array
+ * @strv2: a string array
+ *
+ * Compare NULL-terminated string arrays for equality.
+ *
+ * Returns: %TRUE if the arrays are equal, %FALSE otherwise.
+ **/
+gboolean
+_nm_utils_strv_equal (char **strv1, char **strv2)
+{
+	if (strv1 == strv2)
+		return TRUE;
+
+	if (!strv1 || !strv2)
+		return FALSE;
+
+	for ( ; *strv1 && *strv2 && !strcmp (*strv1, *strv2); strv1++, strv2++)
+		;
+
+	return !*strv1 && !*strv2;
+}
+
+/**
  * _nm_utils_strsplit_set:
  * @str: string to split
  * @delimiters: string of delimiter characters
@@ -1730,7 +1753,7 @@ nm_utils_ip6_addresses_from_variant (GVariant *value, char **out_gateway)
 					*out_gateway = g_strdup (nm_utils_inet6_ntop (gateway_bytes, NULL));
 			}
 		} else {
-			g_warning ("Ignoring invalid IP4 address: %s", error->message);
+			g_warning ("Ignoring invalid IP6 address: %s", error->message);
 			g_clear_error (&error);
 		}
 
@@ -2409,6 +2432,132 @@ nm_utils_file_is_pkcs12 (const char *filename)
 
 /**********************************************************************************************/
 
+gboolean
+_nm_utils_check_file (const char *filename,
+                      gint64 check_owner,
+                      NMUtilsCheckFilePredicate check_file,
+                      gpointer user_data,
+                      struct stat *out_st,
+                      GError **error)
+{
+	struct stat st_backup;
+
+	if (!out_st)
+		out_st = &st_backup;
+
+	if (stat (filename, out_st) != 0) {
+		int errsv = errno;
+
+		g_set_error (error,
+		             NM_VPN_PLUGIN_ERROR,
+		             NM_VPN_PLUGIN_ERROR_FAILED,
+		             _("failed stat file %s: %s"), filename, strerror (errsv));
+		return FALSE;
+	}
+
+	/* ignore non-files. */
+	if (!S_ISREG (out_st->st_mode)) {
+		g_set_error (error,
+		             NM_VPN_PLUGIN_ERROR,
+		             NM_VPN_PLUGIN_ERROR_FAILED,
+		             _("not a file (%s)"), filename);
+		return FALSE;
+	}
+
+	/* with check_owner enabled, check that the file belongs to the
+	 * owner or root. */
+	if (   check_owner >= 0
+	    && (out_st->st_uid != 0 && (gint64) out_st->st_uid != check_owner)) {
+		g_set_error (error,
+		             NM_VPN_PLUGIN_ERROR,
+		             NM_VPN_PLUGIN_ERROR_FAILED,
+		             _("invalid file owner %d for %s"), out_st->st_uid, filename);
+		return FALSE;
+	}
+
+	/* with check_owner enabled, check that the file cannot be modified
+	 * by other users (except root). */
+	if (   check_owner >= 0
+	    && NM_FLAGS_ANY (out_st->st_mode, S_IWGRP | S_IWOTH | S_ISUID)) {
+		g_set_error (error,
+		             NM_VPN_PLUGIN_ERROR,
+		             NM_VPN_PLUGIN_ERROR_FAILED,
+		             _("file permissions for %s"), filename);
+		return FALSE;
+	}
+
+	if (    check_file
+	    && !check_file (filename, out_st, user_data, error)) {
+		if (error && !*error) {
+			g_set_error (error,
+			             NM_VPN_PLUGIN_ERROR,
+			             NM_VPN_PLUGIN_ERROR_FAILED,
+			             _("reject %s"), filename);
+		}
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+
+gboolean
+_nm_utils_check_module_file (const char *name,
+                             int check_owner,
+                             NMUtilsCheckFilePredicate check_file,
+                             gpointer user_data,
+                             GError **error)
+{
+	if (!g_path_is_absolute (name)) {
+		g_set_error (error,
+		             NM_VPN_PLUGIN_ERROR,
+		             NM_VPN_PLUGIN_ERROR_FAILED,
+		             _("path is not absolute (%s)"), name);
+		return FALSE;
+	}
+
+	/* Set special error code if the file doesn't exist.
+	 * The VPN package might be split into separate packages,
+	 * so it could be correct that the plugin file is missing.
+	 *
+	 * Note that nm-applet checks for this error code to fail
+	 * gracefully. */
+	if (!g_file_test (name, G_FILE_TEST_EXISTS)) {
+		g_set_error (error,
+		             G_FILE_ERROR,
+		             G_FILE_ERROR_NOENT,
+		             _("Plugin file does not exist (%s)"), name);
+		return FALSE;
+	}
+
+	if (!g_file_test (name, G_FILE_TEST_IS_REGULAR)) {
+		g_set_error (error,
+		             NM_VPN_PLUGIN_ERROR,
+		             NM_VPN_PLUGIN_ERROR_FAILED,
+		             _("Plugin is not a valid file (%s)"), name);
+		return FALSE;
+	}
+
+	if (g_str_has_suffix (name, ".la")) {
+		/* g_module_open() treats files that end with .la special.
+		 * We don't want to parse the libtool archive. Just error out. */
+		g_set_error (error,
+		             NM_VPN_PLUGIN_ERROR,
+		             NM_VPN_PLUGIN_ERROR_FAILED,
+		             _("libtool archives are not supported (%s)"), name);
+		return FALSE;
+	}
+
+	return _nm_utils_check_file (name,
+	                             check_owner,
+	                             check_file,
+	                             user_data,
+	                             NULL,
+	                             error);
+}
+
+/**********************************************************************************************/
+
 /**
  * nm_utils_file_search_in_paths:
  * @progname: the helper program name, like "iptables"
@@ -2724,13 +2873,14 @@ _wifi_freqs (gboolean bg_band)
  *
  * Returns: zero-terminated array of frequencies numbers (in MHz)
  *
- * Since: 1.0.6
+ * Since: 1.2
  **/
 const guint *
 nm_utils_wifi_2ghz_freqs (void)
 {
 	return _wifi_freqs (TRUE);
 }
+NM_BACKPORT_SYMBOL (libnm_1_0_6, const guint *, nm_utils_wifi_2ghz_freqs, (void), ());
 
 /**
  * nm_utils_wifi_5ghz_freqs:
@@ -2739,13 +2889,14 @@ nm_utils_wifi_2ghz_freqs (void)
  *
  * Returns: zero-terminated array of frequencies numbers (in MHz)
  *
- * Since: 1.0.6
+ * Since: 1.2
  **/
 const guint *
 nm_utils_wifi_5ghz_freqs (void)
 {
 	return _wifi_freqs (FALSE);
 }
+NM_BACKPORT_SYMBOL (libnm_1_0_6, const guint *, nm_utils_wifi_5ghz_freqs, (void), ());
 
 /**
  * nm_utils_wifi_strength_bars:
@@ -3501,8 +3652,9 @@ static BondMode bond_mode_table[] = {
  * available modes.
  *
  * Returns: bonding mode string, or NULL on error
-*/
-
+ *
+ * Since: 1.2
+ */
 const char *
 nm_utils_bond_mode_int_to_string (int mode)
 {
@@ -3521,7 +3673,9 @@ nm_utils_bond_mode_int_to_string (int mode)
  * The @mode string can be either a descriptive name or a number (as string).
  *
  * Returns: numeric bond mode, or -1 on error
-*/
+ *
+ * Since: 1.2
+ */
 int
 nm_utils_bond_mode_string_to_int (const char *mode)
 {
@@ -3540,6 +3694,105 @@ nm_utils_bond_mode_string_to_int (const char *mode)
 
 /**********************************************************************************************/
 
+#define STRSTRDICTKEY_V1_SET  0x01
+#define STRSTRDICTKEY_V2_SET  0x02
+#define STRSTRDICTKEY_ALL_SET 0x03
+
+struct _NMUtilsStrStrDictKey {
+	char type;
+	char data[1];
+};
+
+guint
+_nm_utils_strstrdictkey_hash (gconstpointer a)
+{
+	const NMUtilsStrStrDictKey *k = a;
+	const signed char *p;
+	guint32 h = 5381;
+
+	if (k) {
+		if (((int) k->type) & ~STRSTRDICTKEY_ALL_SET)
+			g_return_val_if_reached (0);
+
+		h = (h << 5) + h + k->type;
+		if (k->type & STRSTRDICTKEY_ALL_SET) {
+			p = (void *) k->data;
+			for (; *p != '\0'; p++)
+				h = (h << 5) + h + *p;
+			if (k->type == STRSTRDICTKEY_ALL_SET) {
+				/* the key contains two strings. Continue... */
+				h = (h << 5) + h + '\0';
+				for (p++; *p != '\0'; p++)
+					h = (h << 5) + h + *p;
+			}
+		}
+	}
+
+	return h;
+}
+
+gboolean
+_nm_utils_strstrdictkey_equal  (gconstpointer a, gconstpointer b)
+{
+	const NMUtilsStrStrDictKey *k1 = a;
+	const NMUtilsStrStrDictKey *k2 = b;
+
+	if (k1 == k2)
+		return TRUE;
+	if (!k1 || !k2)
+		return FALSE;
+
+	if (k1->type != k2->type)
+		return FALSE;
+
+	if (k1->type & STRSTRDICTKEY_ALL_SET) {
+		if (strcmp (k1->data, k2->data) != 0)
+			return FALSE;
+
+		if (k1->type == STRSTRDICTKEY_ALL_SET) {
+			gsize l = strlen (k1->data) + 1;
+
+			return strcmp (&k1->data[l], &k2->data[l]) == 0;
+		}
+	}
+
+	return TRUE;
+}
+
+NMUtilsStrStrDictKey *
+_nm_utils_strstrdictkey_create (const char *v1, const char *v2)
+{
+	char type = 0;
+	gsize l1 = 0, l2 = 0;
+	NMUtilsStrStrDictKey *k;
+
+	if (!v1 && !v2)
+		return g_malloc0 (1);
+
+	/* we need to distinguish between ("",NULL) and (NULL,"").
+	 * Thus, in @type we encode which strings we have present
+	 * as not-NULL. */
+	if (v1) {
+		type |= STRSTRDICTKEY_V1_SET;
+		l1 = strlen (v1) + 1;
+	}
+	if (v2) {
+		type |= STRSTRDICTKEY_V2_SET;
+		l2 = strlen (v2) + 1;
+	}
+
+	k = g_malloc (G_STRUCT_OFFSET (NMUtilsStrStrDictKey, data) + l1 + l2);
+	k->type = type;
+	if (v1)
+		memcpy (&k->data[0], v1, l1);
+	if (v2)
+		memcpy (&k->data[l1], v2, l2);
+
+	return k;
+}
+
+/**********************************************************************************************/
+
 /* _nm_utils_ascii_str_to_int64:
  *
  * A wrapper for g_ascii_strtoll, that checks whether the whole string
@@ -3613,30 +3866,131 @@ _nm_utils_ascii_str_to_int64 (const char *str, guint base, gint64 min, gint64 ma
 	return v;
 }
 
+static gboolean
+validate_dns_option (const char *name, gboolean numeric, gboolean ipv6,
+                     const NMUtilsDNSOptionDesc *option_descs)
+{
+	const NMUtilsDNSOptionDesc *desc;
+
+	if (!option_descs)
+		return !!*name;
+
+	for (desc = option_descs; desc->name; desc++) {
+		if (!strcmp (name, desc->name) &&
+		    numeric == desc->numeric &&
+		    (!desc->ipv6_only || ipv6))
+			return TRUE;
+	}
+
+	return FALSE;
+}
+
 /**
- * _nm_dbus_error_has_name:
- * @error: (allow-none): a #GError, or %NULL
- * @dbus_error_name: a D-Bus error name
+ * _nm_utils_dns_option_validate:
+ * @option: option string
+ * @out_name: (out) (allow-none): the option name
+ * @out_value: (out) (allow-none): the option value
+ * @ipv6: whether the option refers to a IPv6 configuration
+ * @option_descs: (allow-none): an array of NMUtilsDNSOptionDesc which describes the
+ * valid options
+ *
+ * Parses a DNS option in the form "name" or "name:number" and, if
+ * @option_descs is not NULL, checks that the option conforms to one
+ * of the provided descriptors. If @option_descs is NULL @ipv6 is
+ * not considered.
+ *
+ * Returns: %TRUE when the parsing was successful and the option is valid,
+ * %FALSE otherwise
+ */
+gboolean
+_nm_utils_dns_option_validate (const char *option, char **out_name,
+                               long *out_value, gboolean ipv6,
+                               const NMUtilsDNSOptionDesc *option_descs)
+{
+	char **tokens, *ptr;
+	gboolean ret = FALSE;
+
+	g_return_val_if_fail (option != NULL, FALSE);
+
+	if (out_name)
+		*out_name = NULL;
+	if (out_value)
+		*out_value = -1;
+
+	if (!option[0])
+		return FALSE;
+
+	tokens = g_strsplit (option, ":", 2);
+
+	if (g_strv_length (tokens) == 1) {
+		ret = validate_dns_option (tokens[0], FALSE, ipv6, option_descs);
+		if (ret && out_name)
+			*out_name = g_strdup (tokens[0]);
+		goto out;
+	}
+
+	if (!tokens[1][0]) {
+		ret = FALSE;
+		goto out;
+	}
+
+	for (ptr = tokens[1]; *ptr; ptr++) {
+		if (!g_ascii_isdigit (*ptr)) {
+			ret = FALSE;
+			goto out;
+		}
+	}
+
+	ret = FALSE;
+	if (validate_dns_option (tokens[0], TRUE, ipv6, option_descs)) {
+		int value = _nm_utils_ascii_str_to_int64 (tokens[1], 10, 0, G_MAXINT32, -1);
+		if (value >= 0) {
+			if (out_name)
+				*out_name = g_strdup (tokens[0]);
+			if (out_value)
+				*out_value = value;
+			ret = TRUE;
+		}
+	}
+out:
+	g_strfreev (tokens);
+	return ret;
+}
+
+/**
+ * _nm_utils_dns_option_find_idx:
+ * @array: an array of strings
+ * @option: a dns option string
  *
- * Checks if @error is set and corresponds to the D-Bus error @dbus_error_name.
+ * Searches for an option in an array of strings. The match is
+ * performed only the option name; the option value is ignored.
  *
- * Returns: %TRUE or %FALSE
+ * Returns: the index of the option in the array or -1 if was not
+ * found.
  */
-gboolean
-_nm_dbus_error_has_name (GError     *error,
-                         const char *dbus_error_name)
+int _nm_utils_dns_option_find_idx (GPtrArray *array, const char *option)
 {
-	gboolean has_name = FALSE;
+	gboolean ret;
+	char *option_name, *tmp_name;
+	int i;
+
+	if (!_nm_utils_dns_option_validate (option, &option_name, NULL, FALSE, NULL))
+		return -1;
 
-	if (error && g_dbus_error_is_remote_error (error)) {
-		char *error_name;
+	for (i = 0; i < array->len; i++) {
+		if (_nm_utils_dns_option_validate (array->pdata[i], &tmp_name, NULL, FALSE, NULL)) {
+			ret = strcmp (tmp_name, option_name);
+			g_free (tmp_name);
+			if (!ret) {
+				g_free (option_name);
+				return i;
+			}
+		}
 
-		error_name = g_dbus_error_get_remote_error (error);
-		has_name = !g_strcmp0 (error_name, dbus_error_name);
-		g_free (error_name);
 	}
 
-	return has_name;
+	g_free (option_name);
+	return -1;
 }
 
 /**
@@ -3651,7 +4005,7 @@ _nm_dbus_error_has_name (GError     *error,
  *
  * Returns: a newly allocated string or %NULL
  *
- * Since: 1.0.6
+ * Since: 1.2
  */
 char *nm_utils_enum_to_str (GType type, int value)
 {
@@ -3689,13 +4043,15 @@ char *nm_utils_enum_to_str (GType type, int value)
 	g_type_class_unref (class);
 	return ret;
 }
+NM_BACKPORT_SYMBOL (libnm_1_0_6, char *, nm_utils_enum_to_str,
+                    (GType type, int value), (type, value));
 
 /**
  * nm_utils_enum_from_str:
  * @type: the %GType of the enum
  * @str: the input string
- * @out_value: (out) (allow-none) the output value
- * @err_token: (out) (allow-none) location to store the first unrecognized token
+ * @out_value: (out) (allow-none): the output value
+ * @err_token: (out) (allow-none): location to store the first unrecognized token
  *
  * Converts a string to the matching enum value.
  *
@@ -3706,7 +4062,7 @@ char *nm_utils_enum_to_str (GType type, int value)
  *
  * Returns: %TRUE if the conversion was successful, %FALSE otherwise
  *
- * Since: 1.0.6
+ * Since: 1.2
  */
 gboolean nm_utils_enum_from_str (GType type, const char *str,
                                  int *out_value, char **err_token)
@@ -3760,3 +4116,59 @@ gboolean nm_utils_enum_from_str (GType type, const char *str,
 	g_type_class_unref (class);
 	return ret;
 }
+NM_BACKPORT_SYMBOL (libnm_1_0_6, gboolean, nm_utils_enum_from_str,
+                    (GType type, const char *str, int *out_value, char **err_token),
+                    (type, str, out_value, err_token));
+
+/**
+ * nm_utils_enum_get_values:
+ * @type: the %GType of the enum
+ * @from: the first element to be returned
+ * @to: the last element to be returned
+ *
+ * Returns the list of possible values for a given enum.
+ *
+ * Returns: (transfer full): a NULL-terminated dynamically-allocated array of static strings
+ * or %NULL on error
+ *
+ * Since: 1.2
+ */
+const char **nm_utils_enum_get_values (GType type, gint from, gint to)
+{
+	GTypeClass *class;
+	GPtrArray *array;
+	gint i;
+
+	class = g_type_class_ref (type);
+	array = g_ptr_array_new ();
+
+	if (G_IS_ENUM_CLASS (class)) {
+		GEnumClass *enum_class = G_ENUM_CLASS (class);
+		GEnumValue *enum_value;
+
+		for (i = 0; i < enum_class->n_values; i++) {
+			enum_value = &enum_class->values[i];
+			if (enum_value->value >= from && enum_value->value <= to)
+				g_ptr_array_add (array, (gpointer) enum_value->value_nick);
+		}
+	} else if (G_IS_FLAGS_CLASS (class)) {
+		GFlagsClass *flags_class = G_FLAGS_CLASS (class);
+		GFlagsValue *flags_value;
+
+		for (i = 0; i < flags_class->n_values; i++) {
+			flags_value = &flags_class->values[i];
+			if (flags_value->value >= from && flags_value->value <= to)
+				g_ptr_array_add (array, (gpointer) flags_value->value_nick);
+		}
+	} else {
+		g_type_class_unref (class);
+		g_ptr_array_free (array, TRUE);
+		g_return_val_if_reached (NULL);
+	}
+
+	g_type_class_unref (class);
+	g_ptr_array_add (array, NULL);
+
+	return (const char **) g_ptr_array_free (array, FALSE);
+}
+
diff --git a/libnm-core/nm-utils.h b/libnm-core/nm-utils.h
index e97b823e..407c14e2 100644
--- a/libnm-core/nm-utils.h
+++ b/libnm-core/nm-utils.h
@@ -15,7 +15,7 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * Copyright 2005 - 2013 Red Hat, Inc.
+ * Copyright 2005 - 2014 Red Hat, Inc.
  */
 
 #ifndef __NM_UTILS_H__
@@ -127,6 +127,10 @@ gboolean nm_utils_file_is_pkcs12 (const char *filename);
 
 typedef gboolean (*NMUtilsFileSearchInPathsPredicate) (const char *filename, gpointer user_data);
 
+struct stat;
+
+typedef gboolean (*NMUtilsCheckFilePredicate) (const char *filename, const struct stat *stat, gpointer user_data, GError **error);
+
 const char *nm_utils_file_search_in_paths (const char *progname,
                                            const char *try_first,
                                            const char *const *paths,
@@ -139,9 +143,9 @@ guint32 nm_utils_wifi_freq_to_channel (guint32 freq);
 guint32 nm_utils_wifi_channel_to_freq (guint32 channel, const char *band);
 guint32 nm_utils_wifi_find_next_channel (guint32 channel, int direction, char *band);
 gboolean nm_utils_wifi_is_channel_valid (guint32 channel, const char *band);
-NM_AVAILABLE_IN_1_0_6
+NM_AVAILABLE_IN_1_2
 const guint *nm_utils_wifi_2ghz_freqs (void);
-NM_AVAILABLE_IN_1_0_6
+NM_AVAILABLE_IN_1_2
 const guint *nm_utils_wifi_5ghz_freqs (void);
 
 const char *nm_utils_wifi_strength_bars (guint8 strength);
@@ -188,12 +192,20 @@ gboolean nm_utils_ipaddr_valid (int family, const char *ip);
 
 gboolean nm_utils_check_virtual_device_compatibility (GType virtual_type, GType other_type);
 
-NM_AVAILABLE_IN_1_0_6
+NM_AVAILABLE_IN_1_2
+int nm_utils_bond_mode_string_to_int (const char *mode);
+NM_AVAILABLE_IN_1_2
+const char *nm_utils_bond_mode_int_to_string (int mode);
+
+NM_AVAILABLE_IN_1_2
 char *nm_utils_enum_to_str (GType type, int value);
 
-NM_AVAILABLE_IN_1_0_6
+NM_AVAILABLE_IN_1_2
 gboolean nm_utils_enum_from_str (GType type, const char *str, int *out_value, char **err_token);
 
+NM_AVAILABLE_IN_1_2
+const char **nm_utils_enum_get_values (GType type, gint from, gint to);
+
 G_END_DECLS
 
 #endif /* __NM_UTILS_H__ */
diff --git a/libnm-core/nm-version.h b/libnm-core/nm-version.h
index 730330ab..859a3a8c 100644
--- a/libnm-core/nm-version.h
+++ b/libnm-core/nm-version.h
@@ -76,16 +76,18 @@
 # define NM_AVAILABLE_IN_1_0
 #endif
 
-#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_0_4
-# define NM_AVAILABLE_IN_1_0_4          G_UNAVAILABLE(1,0.4)
+#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_1_2
+# define NM_DEPRECATED_IN_1_2           G_DEPRECATED
+# define NM_DEPRECATED_IN_1_2_FOR(f)    G_DEPRECATED_FOR(f)
 #else
-# define NM_AVAILABLE_IN_1_0_4
+# define NM_DEPRECATED_IN_1_2
+# define NM_DEPRECATED_IN_1_2_FOR(f)
 #endif
 
-#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_0_6
-# define NM_AVAILABLE_IN_1_0_6          G_UNAVAILABLE(1,0.6)
+#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_2
+# define NM_AVAILABLE_IN_1_2            G_UNAVAILABLE(1,2)
 #else
-# define NM_AVAILABLE_IN_1_0_6
+# define NM_AVAILABLE_IN_1_2
 #endif
 
 #endif  /* NM_VERSION_H */
diff --git a/libnm-core/nm-vpn-editor-plugin.c b/libnm-core/nm-vpn-editor-plugin.c
new file mode 100644
index 00000000..2d4fdf9c
--- /dev/null
+++ b/libnm-core/nm-vpn-editor-plugin.c
@@ -0,0 +1,287 @@
+/* -*- 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 2008 Novell, Inc.
+ * Copyright 2008 - 2010 Red Hat, Inc.
+ * Copyright 2015 Red Hat, Inc.
+ */
+
+#include "config.h"
+
+#include "nm-vpn-editor-plugin.h"
+
+#include <gio/gio.h>
+
+#include "nm-macros-internal.h"
+#include "gsystem-local-alloc.h"
+#include "nm-core-internal.h"
+
+static void nm_vpn_editor_plugin_default_init (NMVpnEditorPluginInterface *iface);
+
+G_DEFINE_INTERFACE (NMVpnEditorPlugin, nm_vpn_editor_plugin, G_TYPE_OBJECT)
+
+static void
+nm_vpn_editor_plugin_default_init (NMVpnEditorPluginInterface *iface)
+{
+	/* Properties */
+
+	/**
+	 * NMVpnEditorPlugin:name:
+	 *
+	 * Short display name of the VPN plugin.
+	 */
+	g_object_interface_install_property (iface,
+		 g_param_spec_string (NM_VPN_EDITOR_PLUGIN_NAME, "", "",
+		                      NULL,
+		                      G_PARAM_READABLE |
+		                      G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMVpnEditorPlugin:description:
+	 *
+	 * Longer description of the VPN plugin.
+	 */
+	g_object_interface_install_property (iface,
+		 g_param_spec_string (NM_VPN_EDITOR_PLUGIN_DESCRIPTION, "", "",
+		                      NULL,
+		                      G_PARAM_READABLE |
+		                      G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMVpnEditorPlugin:service:
+	 *
+	 * D-Bus service name of the plugin's VPN service.
+	 */
+	g_object_interface_install_property (iface,
+		 g_param_spec_string (NM_VPN_EDITOR_PLUGIN_SERVICE, "", "",
+		                      NULL,
+		                      G_PARAM_READABLE |
+		                      G_PARAM_STATIC_STRINGS));
+}
+
+/*********************************************************************/
+
+/**
+ * nm_vpn_editor_plugin_load_from_file:
+ * @plugin_filename: The path to the share library to load.
+ *  Apply some common heuristics to find the library, such as
+ *  appending "so" file ending.
+ *  If the path is not an absolute path or no matching module
+ *  can be found, lookup inside a directory defined at compile time.
+ *  Due to this, @check_file might be called for two different paths.
+ * @check_service: if not-null, check that the loaded plugin advertises
+ *  the given service.
+ * @check_owner: if non-negative, check whether the file is owned
+ *  by UID @check_owner or by root. In this case also check that
+ *  the file is not writable by anybody else.
+ * @check_file: (scope call): optional callback to validate the file prior to
+ *   loading the shared library.
+ * @user_data: user data for @check_file
+ * @error: on failure the error reason.
+ *
+ * Load the shared libary @plugin_filename and create a new
+ * #NMVpnEditorPlugin instace via the #NMVpnEditorPluginFactory
+ * function.
+ *
+ * Returns: (transfer full): a new plugin instance or %NULL on error.
+ *
+ * Since: 1.2
+ */
+NMVpnEditorPlugin *
+nm_vpn_editor_plugin_load_from_file  (const char *plugin_filename,
+                                      const char *check_service,
+                                      int check_owner,
+                                      NMUtilsCheckFilePredicate check_file,
+                                      gpointer user_data,
+                                      GError **error)
+{
+	GModule *module = NULL;
+	gs_free_error GError *local = NULL;
+	NMVpnEditorPluginFactory factory = NULL;
+	NMVpnEditorPlugin *editor_plugin = NULL;
+
+	g_return_val_if_fail (plugin_filename && *plugin_filename, NULL);
+
+	/* _nm_utils_check_module_file() fails with ENOENT if the plugin file
+	 * does not exist. That is relevant, because nm-applet checks for that. */
+	if (_nm_utils_check_module_file (plugin_filename,
+		                             check_owner,
+		                             check_file,
+		                             user_data,
+		                             &local))
+		module = g_module_open (plugin_filename, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
+
+	if (!module) {
+		if (local) {
+			g_propagate_error (error, local);
+			local = NULL;
+		} else {
+			g_set_error (error,
+			             NM_VPN_PLUGIN_ERROR,
+			             NM_VPN_PLUGIN_ERROR_FAILED,
+			             _("cannot load plugin %s"), plugin_filename);
+		}
+		return NULL;
+	}
+	g_clear_error (&local);
+
+	if (g_module_symbol (module, "nm_vpn_editor_plugin_factory", (gpointer) &factory)) {
+		gs_free_error GError *factory_error = NULL;
+		gboolean success = FALSE;
+
+		editor_plugin = factory (&factory_error);
+
+		g_assert (!editor_plugin || G_IS_OBJECT (editor_plugin));
+
+		if (editor_plugin) {
+			gs_free char *plug_name = NULL, *plug_service = NULL;
+
+			/* Validate plugin properties */
+
+			g_object_get (G_OBJECT (editor_plugin),
+			              NM_VPN_EDITOR_PLUGIN_NAME, &plug_name,
+			              NM_VPN_EDITOR_PLUGIN_SERVICE, &plug_service,
+			              NULL);
+
+			if (!plug_name || !*plug_name) {
+				g_set_error (error,
+				             NM_VPN_PLUGIN_ERROR,
+				             NM_VPN_PLUGIN_ERROR_FAILED,
+				             _("cannot load VPN plugin in '%s': missing plugin name"),
+				             g_module_name (module));
+			} else if (   check_service
+			           && g_strcmp0 (plug_service, check_service) != 0) {
+				g_set_error (error,
+				             NM_VPN_PLUGIN_ERROR,
+				             NM_VPN_PLUGIN_ERROR_FAILED,
+				             _("cannot load VPN plugin in '%s': invalid service name"),
+				             g_module_name (module));
+			} else {
+				/* Success! */
+				g_object_set_data_full (G_OBJECT (editor_plugin), "gmodule", module,
+				                        (GDestroyNotify) g_module_close);
+				success = TRUE;
+			}
+		} else {
+			if (factory_error) {
+				g_propagate_error (error, factory_error);
+				factory_error = NULL;
+			} else {
+				g_set_error (error,
+				             NM_VPN_PLUGIN_ERROR,
+				             NM_VPN_PLUGIN_ERROR_FAILED,
+				             _("unknown error initializing plugin %s"), plugin_filename);
+			}
+		}
+
+		if (!success) {
+			g_module_close (module);
+			editor_plugin = NULL;
+		}
+	} else {
+		g_set_error (error,
+		             NM_VPN_PLUGIN_ERROR,
+		             NM_VPN_PLUGIN_ERROR_FAILED,
+		             _("failed to load nm_vpn_editor_plugin_factory() from %s (%s)"),
+		             g_module_name (module), g_module_error ());
+		g_module_close (module);
+		editor_plugin = NULL;
+	}
+
+	return editor_plugin;
+}
+
+/*********************************************************************/
+
+/**
+ * nm_vpn_editor_plugin_get_editor:
+ *
+ * Returns: (transfer full):
+ */
+NMVpnEditor *
+nm_vpn_editor_plugin_get_editor (NMVpnEditorPlugin *plugin,
+                                 NMConnection *connection,
+                                 GError **error)
+{
+	g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), NULL);
+
+	return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->get_editor (plugin, connection, error);
+}
+
+NMVpnEditorPluginCapability
+nm_vpn_editor_plugin_get_capabilities (NMVpnEditorPlugin *plugin)
+{
+	g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), 0);
+
+	return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->get_capabilities (plugin);
+}
+
+/**
+ * nm_vpn_editor_plugin_import:
+ *
+ * Returns: (transfer full):
+ */
+NMConnection *
+nm_vpn_editor_plugin_import (NMVpnEditorPlugin *plugin,
+                             const char *path,
+                             GError **error)
+{
+	g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), NULL);
+
+	if (nm_vpn_editor_plugin_get_capabilities (plugin) & NM_VPN_EDITOR_PLUGIN_CAPABILITY_IMPORT) {
+		g_return_val_if_fail (NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->import_from_file != NULL, NULL);
+		return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->import_from_file (plugin, path, error);
+	}
+
+	g_set_error (error,
+	             NM_VPN_PLUGIN_ERROR,
+	             NM_VPN_PLUGIN_ERROR_FAILED,
+	             _("the plugin does not support import capability"));
+	return NULL;
+}
+
+gboolean
+nm_vpn_editor_plugin_export (NMVpnEditorPlugin *plugin,
+                             const char *path,
+                             NMConnection *connection,
+                             GError **error)
+{
+	g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), FALSE);
+
+	if (nm_vpn_editor_plugin_get_capabilities (plugin) & NM_VPN_EDITOR_PLUGIN_CAPABILITY_EXPORT) {
+		g_return_val_if_fail (NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->export_to_file != NULL, FALSE);
+		return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->export_to_file (plugin, path, connection, error);
+	}
+
+	g_set_error (error,
+	             NM_VPN_PLUGIN_ERROR,
+	             NM_VPN_PLUGIN_ERROR_FAILED,
+	             _("the plugin does not support export capability"));
+	return FALSE;
+}
+
+char *
+nm_vpn_editor_plugin_get_suggested_filename (NMVpnEditorPlugin *plugin,
+                                             NMConnection *connection)
+{
+	g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), NULL);
+
+	if (NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->get_suggested_filename)
+		return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->get_suggested_filename (plugin, connection);
+	return NULL;
+}
+
diff --git a/libnm-core/nm-vpn-editor-plugin.h b/libnm-core/nm-vpn-editor-plugin.h
new file mode 100644
index 00000000..16e9533d
--- /dev/null
+++ b/libnm-core/nm-vpn-editor-plugin.h
@@ -0,0 +1,152 @@
+/* -*- 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 2008 Novell, Inc.
+ * Copyright 2008 - 2015 Red Hat, Inc.
+ */
+
+#ifndef __NM_VPN_EDITOR_PLUGIN_H__
+#define __NM_VPN_EDITOR_PLUGIN_H__
+
+#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION)
+#error "Only <NetworkManager.h> can be included directly."
+#endif
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include "nm-connection.h"
+#include "nm-utils.h"
+
+G_BEGIN_DECLS
+
+typedef struct _NMVpnEditorPlugin NMVpnEditorPlugin;
+typedef struct _NMVpnEditor NMVpnEditor;
+
+/* Plugin's factory function that returns a GObject that implements
+ * NMVpnEditorPlugin.
+ */
+#ifndef __GI_SCANNER__
+typedef NMVpnEditorPlugin * (*NMVpnEditorPluginFactory) (GError **error);
+NMVpnEditorPlugin *nm_vpn_editor_plugin_factory (GError **error);
+#endif
+
+
+/**************************************************/
+/* Editor plugin interface                        */
+/**************************************************/
+
+#define NM_TYPE_VPN_EDITOR_PLUGIN               (nm_vpn_editor_plugin_get_type ())
+#define NM_VPN_EDITOR_PLUGIN(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_VPN_EDITOR_PLUGIN, NMVpnEditorPlugin))
+#define NM_IS_VPN_EDITOR_PLUGIN(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_VPN_EDITOR_PLUGIN))
+#define NM_VPN_EDITOR_PLUGIN_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), NM_TYPE_VPN_EDITOR_PLUGIN, NMVpnEditorPluginInterface))
+
+/**
+ * NMVpnEditorPluginCapability:
+ * @NM_VPN_EDITOR_PLUGIN_CAPABILITY_NONE: unknown or no capability
+ * @NM_VPN_EDITOR_PLUGIN_CAPABILITY_IMPORT: the plugin can import new connections
+ * @NM_VPN_EDITOR_PLUGIN_CAPABILITY_EXPORT: the plugin can export connections
+ * @NM_VPN_EDITOR_PLUGIN_CAPABILITY_IPV6: the plugin supports IPv6 addressing
+ *
+ * Flags that indicate certain capabilities of the plugin to editor programs.
+ **/
+typedef enum /*< flags >*/ {
+	NM_VPN_EDITOR_PLUGIN_CAPABILITY_NONE   = 0x00,
+	NM_VPN_EDITOR_PLUGIN_CAPABILITY_IMPORT = 0x01,
+	NM_VPN_EDITOR_PLUGIN_CAPABILITY_EXPORT = 0x02,
+	NM_VPN_EDITOR_PLUGIN_CAPABILITY_IPV6   = 0x04
+} NMVpnEditorPluginCapability;
+
+/* Short display name of the VPN plugin */
+#define NM_VPN_EDITOR_PLUGIN_NAME "name"
+
+/* Longer description of the VPN plugin */
+#define NM_VPN_EDITOR_PLUGIN_DESCRIPTION "description"
+
+/* D-Bus service name of the plugin's VPN service */
+#define NM_VPN_EDITOR_PLUGIN_SERVICE "service"
+
+/**
+ * NMVpnEditorPluginInterface:
+ * @g_iface: the parent interface
+ * @get_editor: returns an #NMVpnEditor, pre-filled with values from @connection
+ *   if non-%NULL.
+ * @get_capabilities: returns a bitmask of capabilities.
+ * @import_from_file: Try to import a connection from the specified path.  On
+ *   success, return a partial #NMConnection object.  On error, return %NULL and
+ *   set @error with additional information.  Note that @error can be %NULL, in
+ *   which case no additional error information should be provided.
+ * @export_to_file: Export the given connection to the specified path.  Return
+ *   %TRUE on success.  On error, return %FALSE and set @error with additional
+ *   error information.  Note that @error can be %NULL, in which case no
+ *   additional error information should be provided.
+ * @get_suggested_filename: For a given connection, return a suggested file
+ *   name.  Returned value will be %NULL or a suggested file name to be freed by
+ *   the caller.
+ *
+ * Interface for VPN editor plugins.
+ */
+typedef struct {
+	GTypeInterface g_iface;
+
+	NMVpnEditor * (*get_editor) (NMVpnEditorPlugin *plugin,
+	                             NMConnection *connection,
+	                             GError **error);
+
+	NMVpnEditorPluginCapability (*get_capabilities) (NMVpnEditorPlugin *plugin);
+
+	NMConnection * (*import_from_file) (NMVpnEditorPlugin *plugin,
+	                                    const char *path,
+	                                    GError **error);
+
+	gboolean (*export_to_file) (NMVpnEditorPlugin *plugin,
+	                            const char *path,
+	                            NMConnection *connection,
+	                            GError **error);
+
+	char * (*get_suggested_filename) (NMVpnEditorPlugin *plugin, NMConnection *connection);
+} NMVpnEditorPluginInterface;
+
+GType nm_vpn_editor_plugin_get_type (void);
+
+NMVpnEditor *nm_vpn_editor_plugin_get_editor (NMVpnEditorPlugin *plugin,
+                                              NMConnection *connection,
+                                              GError **error);
+
+NMVpnEditorPluginCapability nm_vpn_editor_plugin_get_capabilities (NMVpnEditorPlugin *plugin);
+
+NMConnection *nm_vpn_editor_plugin_import                 (NMVpnEditorPlugin *plugin,
+                                                           const char *path,
+                                                           GError **error);
+gboolean      nm_vpn_editor_plugin_export                 (NMVpnEditorPlugin *plugin,
+                                                           const char *path,
+                                                           NMConnection *connection,
+                                                           GError **error);
+char         *nm_vpn_editor_plugin_get_suggested_filename (NMVpnEditorPlugin *plugin,
+                                                           NMConnection *connection);
+
+NM_AVAILABLE_IN_1_2
+NMVpnEditorPlugin *nm_vpn_editor_plugin_load_from_file  (const char *plugin_filename,
+                                                         const char *check_service,
+                                                         int check_owner,
+                                                         NMUtilsCheckFilePredicate check_file,
+                                                         gpointer user_data,
+                                                         GError **error);
+
+G_END_DECLS
+
+#endif	/* __NM_VPN_EDITOR_PLUGIN_H__ */
diff --git a/libnm-core/nm-vpn-plugin-info.c b/libnm-core/nm-vpn-plugin-info.c
new file mode 100644
index 00000000..3a4796b9
--- /dev/null
+++ b/libnm-core/nm-vpn-plugin-info.c
@@ -0,0 +1,1030 @@
+/* -*- 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 2015 Red Hat, Inc.
+ */
+
+#include "config.h"
+
+#include "nm-vpn-plugin-info.h"
+
+#include <gio/gio.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/stat.h>
+
+#include "gsystem-local-alloc.h"
+#include "nm-errors.h"
+#include "nm-macros-internal.h"
+#include "nm-core-internal.h"
+
+#define DEFAULT_DIR_ETC     NMCONFDIR"/VPN"
+#define DEFAULT_DIR_LIB     NMLIBDIR"/VPN"
+
+enum {
+	PROP_0,
+	PROP_NAME,
+	PROP_FILENAME,
+	PROP_KEYFILE,
+
+	LAST_PROP,
+};
+
+typedef struct {
+	char *filename;
+	char *name;
+	char *service;
+	char **aliases;
+	GKeyFile *keyfile;
+
+	/* It is convenient for nm_vpn_plugin_info_lookup_property() to return a const char *,
+	 * contrary to what g_key_file_get_string() does. Hence we must cache the returned
+	 * value somewhere... let's put it in an internal hash table.
+	 * This contains a clone of all the strings in keyfile. */
+	GHashTable *keys;
+
+	gboolean editor_plugin_loaded;
+	NMVpnEditorPlugin *editor_plugin;
+} NMVpnPluginInfoPrivate;
+
+static void nm_vpn_plugin_info_initable_iface_init (GInitableIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (NMVpnPluginInfo, nm_vpn_plugin_info, G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, nm_vpn_plugin_info_initable_iface_init);
+                         )
+
+#define NM_VPN_PLUGIN_INFO_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_VPN_PLUGIN_INFO, NMVpnPluginInfoPrivate))
+
+/*********************************************************************/
+
+/**
+ * nm_vpn_plugin_info_validate_filename:
+ * @filename: the filename to check
+ *
+ * Regular name files have a certain pattern. That basically means
+ * they have the file extension "name". Check if @filename
+ * is valid according to that pattern.
+ *
+ * Since: 1.2
+ */
+gboolean
+nm_vpn_plugin_info_validate_filename (const char *filename)
+{
+	if (!filename || !g_str_has_suffix (filename, ".name"))
+		return FALSE;
+
+	/* originally, we didn't do further checks... but here we go. */
+	if (filename[0] == '.') {
+		/* this also rejects name ".name" alone. */
+		return FALSE;
+	}
+	return TRUE;
+}
+
+static gboolean
+nm_vpn_plugin_info_check_file_full (const char *filename,
+                                    gboolean check_absolute,
+                                    gboolean do_validate_filename,
+                                    gint64 check_owner,
+                                    NMUtilsCheckFilePredicate check_file,
+                                    gpointer user_data,
+                                    struct stat *out_st,
+                                    GError **error)
+{
+	if (!filename || !*filename) {
+		g_set_error (error,
+		             NM_VPN_PLUGIN_ERROR,
+		             NM_VPN_PLUGIN_ERROR_FAILED,
+		             _("missing filename"));
+		return FALSE;
+	}
+
+	if (check_absolute && !g_path_is_absolute (filename)) {
+		g_set_error (error,
+		             NM_VPN_PLUGIN_ERROR,
+		             NM_VPN_PLUGIN_ERROR_FAILED,
+		             _("filename must be an absolute path (%s)"), filename);
+		return FALSE;
+	}
+
+	if (   do_validate_filename
+	    && !nm_vpn_plugin_info_validate_filename (filename)) {
+		g_set_error (error,
+		             NM_VPN_PLUGIN_ERROR,
+		             NM_VPN_PLUGIN_ERROR_FAILED,
+		             _("filename has invalid format (%s)"), filename);
+		return FALSE;
+	}
+
+	return _nm_utils_check_file (filename,
+	                             check_owner,
+	                             check_file,
+	                             user_data,
+	                             out_st,
+	                             error);
+}
+
+/**
+ * _nm_vpn_plugin_info_check_file:
+ * @filename:
+ * @check_absolute: if %TRUE, only allow absolute path names.
+ * @do_validate_filename: if %TRUE, only accept the filename if
+ *   nm_vpn_plugin_info_validate_filename() succeeds.
+ * @check_owner: if non-negative, only accept the file if the
+ *   owner UID is equal to @check_owner or if the owner is 0.
+ *   In this case, also check that the file is not writable by
+ *   other users.
+ * @check_file: pass a callback to do your own validation.
+ * @user_data: user data for @check_file.
+ * @error: (allow-none): (out): the error reason if the check fails.
+ *
+ * Check whether the file exists and is a valid name file (in keyfile format).
+ * Additionally, also check for file permissions.
+ *
+ * Returns: %TRUE if a file @filename exists and has valid permissions.
+ *
+ * Since: 1.2
+ */
+gboolean
+_nm_vpn_plugin_info_check_file (const char *filename,
+                                gboolean check_absolute,
+                                gboolean do_validate_filename,
+                                gint64 check_owner,
+                                NMUtilsCheckFilePredicate check_file,
+                                gpointer user_data,
+                                GError **error)
+{
+	return nm_vpn_plugin_info_check_file_full (filename, check_absolute, do_validate_filename, check_owner, check_file, user_data, NULL, error);
+}
+
+typedef struct {
+	NMVpnPluginInfo *plugin_info;
+	struct stat stat;
+} LoadDirInfo;
+
+static int
+_sort_files (LoadDirInfo *a, LoadDirInfo *b)
+{
+	time_t ta, tb;
+
+	ta = MAX (a->stat.st_mtime, a->stat.st_ctime);
+	tb = MAX (b->stat.st_mtime, b->stat.st_ctime);
+	if (ta < tb)
+		return 1;
+	if (ta > tb)
+		return -1;
+	return g_strcmp0 (nm_vpn_plugin_info_get_filename (a->plugin_info),
+	                  nm_vpn_plugin_info_get_filename (b->plugin_info));
+}
+
+/**
+ * _nm_vpn_plugin_info_get_default_dir_etc:
+ *
+ * Returns: (transfer none): compile time constant of the default
+ *   VPN plugin directory.
+ */
+const char *
+_nm_vpn_plugin_info_get_default_dir_etc ()
+{
+	return DEFAULT_DIR_ETC;
+}
+
+/**
+ * _nm_vpn_plugin_info_get_default_dir_lib:
+ *
+ * Returns: (transfer none): compile time constant of the default
+ *   VPN plugin directory.
+ */
+const char *
+_nm_vpn_plugin_info_get_default_dir_lib ()
+{
+	return DEFAULT_DIR_LIB;
+}
+
+/**
+ * _nm_vpn_plugin_info_get_default_dir_user:
+ *
+ * Returns: The user can specify a different directory for VPN plugins
+ * by setting NM_VPN_PLUGIN_DIR environment variable. Return
+ * that directory.
+ */
+const char *
+_nm_vpn_plugin_info_get_default_dir_user ()
+{
+	return g_getenv ("NM_VPN_PLUGIN_DIR");
+}
+
+/**
+ * _nm_vpn_plugin_info_list_load_dir:
+ * @dirname: the name of the directory to load.
+ * @do_validate_filename: only consider filenames that have a certain
+ *   pattern (i.e. end with ".name").
+ * @check_owner: if set to a non-negative number, check that the file
+ *   owner is either the same uid or 0. In that case, also check
+ *   that the file is not writable by group or other.
+ * @check_file: (allow-none): callback to check whether the file is valid.
+ * @user_data: data for @check_file
+ *
+ * Iterate over the content of @dirname and load name files.
+ *
+ * Returns: (transfer full) (element-type NMVpnPluginInfo): list of loaded plugin infos.
+ */
+GSList *
+_nm_vpn_plugin_info_list_load_dir (const char *dirname,
+                                   gboolean do_validate_filename,
+                                   gint64 check_owner,
+                                   NMUtilsCheckFilePredicate check_file,
+                                   gpointer user_data)
+{
+	GDir *dir;
+	const char *fn;
+	GArray *array;
+	GSList *res = NULL;
+	guint i;
+
+	g_return_val_if_fail (dirname && dirname[0], NULL);
+
+	dir = g_dir_open (dirname, 0, NULL);
+	if (!dir)
+		return NULL;
+
+	array = g_array_new (FALSE, FALSE, sizeof (LoadDirInfo));
+
+	while ((fn = g_dir_read_name (dir))) {
+		gs_free char *filename = NULL;
+		LoadDirInfo info = { 0 };
+
+		filename = g_build_filename (dirname, fn, NULL);
+		if (nm_vpn_plugin_info_check_file_full (filename,
+		                                        FALSE,
+		                                        do_validate_filename,
+		                                        check_owner,
+		                                        check_file,
+		                                        user_data,
+		                                        &info.stat,
+		                                        NULL)) {
+			info.plugin_info = nm_vpn_plugin_info_new_from_file (filename, NULL);
+			if (info.plugin_info) {
+				g_array_append_val (array, info);
+				continue;
+			}
+		}
+	}
+	g_dir_close (dir);
+
+	/* sort the files so that we have a stable behavior. The directory might contain
+	 * duplicate VPNs, so while nm_vpn_plugin_info_list_load() would load them all, the
+	 * caller probably wants to reject duplicates. Having a stable order means we always
+	 * reject the same files in face of duplicates. */
+	g_array_sort (array, (GCompareFunc) _sort_files);
+
+	for (i = 0; i < array->len; i++)
+		res = g_slist_prepend (res, g_array_index (array, LoadDirInfo, i).plugin_info);
+
+	g_array_unref (array);
+
+	return g_slist_reverse (res);
+}
+
+/**
+ * nm_vpn_plugin_info_list_load:
+ *
+ * Returns: (element-type NMVpnPluginInfo) (transfer full): list of plugins
+ * loaded from the default directories rejecting duplicates.
+ *
+ * Since: 1.2
+ */
+GSList *
+nm_vpn_plugin_info_list_load ()
+{
+	int i;
+	gint64 uid;
+	GSList *list = NULL;
+	GSList *infos, *info;
+	const char *dir[] = {
+		/* We load plugins from NM_VPN_PLUGIN_DIR *and* DEFAULT_DIR*, with
+		 * preference to the former.
+		 *
+		 * load user directory with highest priority. */
+		_nm_vpn_plugin_info_get_default_dir_user (),
+
+		/* lib directory has higher priority then etc. The reason is that
+		 * etc is deprecated and used by old plugins. We expect newer plugins
+		 * to install their file in lib, where they have higher priority.
+		 *
+		 * Optimally, there are no duplicates anyway, so it doesn't really matter. */
+		_nm_vpn_plugin_info_get_default_dir_lib (),
+		_nm_vpn_plugin_info_get_default_dir_etc (),
+	};
+
+	uid = getuid ();
+
+	for (i = 0; i < G_N_ELEMENTS (dir); i++) {
+		if (   !dir[i]
+		    || _nm_utils_strv_find_first ((char **) dir, i, dir[i]) >= 0)
+			continue;
+
+		infos = _nm_vpn_plugin_info_list_load_dir (dir[i], TRUE, uid, NULL, NULL);
+
+		for (info = infos; info; info = info->next)
+			nm_vpn_plugin_info_list_add (&list, info->data, NULL);
+
+		g_slist_free_full (infos, g_object_unref);
+	}
+	return list;
+}
+
+/*********************************************************************/
+
+static gboolean
+_check_no_conflict (NMVpnPluginInfo *i1, NMVpnPluginInfo *i2, GError **error)
+{
+	NMVpnPluginInfoPrivate *priv1, *priv2;
+	uint i;
+	struct {
+		const char *group;
+		const char *key;
+	} check_list[] = {
+		{ NM_VPN_PLUGIN_INFO_KF_GROUP_CONNECTION, "service" },
+		{ NM_VPN_PLUGIN_INFO_KF_GROUP_LIBNM,      "plugin" },
+		{ NM_VPN_PLUGIN_INFO_KF_GROUP_GNOME,      "properties" },
+	};
+
+	priv1 = NM_VPN_PLUGIN_INFO_GET_PRIVATE (i1);
+	priv2 = NM_VPN_PLUGIN_INFO_GET_PRIVATE (i2);
+
+	for (i = 0; i < G_N_ELEMENTS (check_list); i++) {
+		gs_free NMUtilsStrStrDictKey *k = NULL;
+		const char *s1, *s2;
+
+		k = _nm_utils_strstrdictkey_create (check_list[i].group, check_list[i].key);
+		s1 = g_hash_table_lookup (priv1->keys, k);
+		if (!s1)
+			continue;
+		s2 = g_hash_table_lookup (priv2->keys, k);
+		if (!s2)
+			continue;
+
+		if (strcmp (s1, s2) == 0) {
+			g_set_error (error,
+			             NM_VPN_PLUGIN_ERROR,
+			             NM_VPN_PLUGIN_ERROR_FAILED,
+			             _("there exists a conflicting plugin (%s) that has the same %s.%s value"),
+			             priv2->name,
+			             check_list[i].group, check_list[i].key);
+			return FALSE;
+		}
+	}
+	return TRUE;
+}
+
+/**
+ * nm_vpn_plugin_info_list_add:
+ * @list: (element-type NMVpnPluginInfo): list of plugins
+ * @plugin_info: instance to add
+ * @error: failure reason
+ *
+ * Returns: %TRUE if the plugin was added to @list. This will fail
+ * to add duplicate plugins.
+ *
+ * Since: 1.2
+ */
+gboolean
+nm_vpn_plugin_info_list_add (GSList **list, NMVpnPluginInfo *plugin_info, GError **error)
+{
+	GSList *iter;
+	const char *name;
+
+	g_return_val_if_fail (list, FALSE);
+	g_return_val_if_fail (NM_IS_VPN_PLUGIN_INFO (plugin_info), FALSE);
+
+	name = nm_vpn_plugin_info_get_name (plugin_info);
+	for (iter = *list; iter; iter = iter->next) {
+		if (iter->data == plugin_info)
+			return TRUE;
+
+		if (strcmp (nm_vpn_plugin_info_get_name (iter->data), name) == 0) {
+			g_set_error (error,
+			             NM_VPN_PLUGIN_ERROR,
+			             NM_VPN_PLUGIN_ERROR_FAILED,
+			             _("there exists a conflicting plugin with the same name (%s)"),
+			             name);
+			return FALSE;
+		}
+
+		/* the plugin must have unique values for certain properties. E.g. two different
+		 * plugins cannot share the same service name. */
+		if (!_check_no_conflict (plugin_info, iter->data, error))
+			return FALSE;
+	}
+
+	*list = g_slist_append (*list, g_object_ref (plugin_info));
+	return TRUE;
+}
+
+/**
+ * nm_vpn_plugin_info_list_remove:
+ * @list: (element-type NMVpnPluginInfo): list of plugins
+ * @plugin_info: instance
+ *
+ * Remove @plugin_info from @list.
+ *
+ * Returns: %TRUE if @plugin_info was in @list and successfully removed.
+ *
+ * Since: 1.2
+ */
+gboolean
+nm_vpn_plugin_info_list_remove (GSList **list, NMVpnPluginInfo *plugin_info)
+{
+	g_return_val_if_fail (list, FALSE);
+	g_return_val_if_fail (NM_IS_VPN_PLUGIN_INFO (plugin_info), FALSE);
+
+	if (!g_slist_find (*list, plugin_info))
+		return FALSE;
+
+	*list = g_slist_remove (*list, plugin_info);
+	g_object_unref (plugin_info);
+	return TRUE;
+}
+
+/**
+ * nm_vpn_plugin_info_list_find_by_name:
+ * @list: (element-type NMVpnPluginInfo): list of plugins
+ * @name: name to search
+ *
+ * Returns: (transfer none): the first plugin with a matching @name (or %NULL).
+ *
+ * Since: 1.2
+ */
+NMVpnPluginInfo *
+nm_vpn_plugin_info_list_find_by_name (GSList *list, const char *name)
+{
+	GSList *iter;
+
+	if (!name)
+		g_return_val_if_reached (NULL);
+
+	for (iter = list; iter; iter = iter->next) {
+		if (strcmp (nm_vpn_plugin_info_get_name (iter->data), name) == 0)
+			return iter->data;
+	}
+	return NULL;
+}
+
+/**
+ * nm_vpn_plugin_info_list_find_by_filename:
+ * @list: (element-type NMVpnPluginInfo): list of plugins
+ * @filename: filename to search
+ *
+ * Returns: (transfer none): the first plugin with a matching @filename (or %NULL).
+ *
+ * Since: 1.2
+ */
+NMVpnPluginInfo *
+nm_vpn_plugin_info_list_find_by_filename (GSList *list, const char *filename)
+{
+	GSList *iter;
+
+	if (!filename)
+		g_return_val_if_reached (NULL);
+
+	for (iter = list; iter; iter = iter->next) {
+		if (g_strcmp0 (nm_vpn_plugin_info_get_filename (iter->data), filename) == 0)
+			return iter->data;
+	}
+	return NULL;
+}
+
+/**
+ * nm_vpn_plugin_info_list_find_by_service:
+ * @list: (element-type NMVpnPluginInfo): list of plugins
+ * @service: service to search
+ *
+ * Returns: (transfer none): the first plugin with a matching @service (or %NULL).
+ *
+ * Since: 1.2
+ */
+NMVpnPluginInfo *
+nm_vpn_plugin_info_list_find_by_service (GSList *list, const char *service)
+{
+	GSList *iter;
+
+	if (!service)
+		g_return_val_if_reached (NULL);
+
+	/* First, consider the primary service name. */
+	for (iter = list; iter; iter = iter->next) {
+		if (strcmp (NM_VPN_PLUGIN_INFO_GET_PRIVATE (iter->data)->service, service) == 0)
+			return iter->data;
+	}
+
+	/* Then look into the aliases. */
+	for (iter = list; iter; iter = iter->next) {
+		char **aliases = (NM_VPN_PLUGIN_INFO_GET_PRIVATE (iter->data))->aliases;
+
+		if (!aliases)
+			continue;
+		if (_nm_utils_strv_find_first (aliases, -1, service) >= 0)
+			return iter->data;
+	}
+	return NULL;
+}
+
+/*********************************************************************/
+
+/**
+ * nm_vpn_plugin_info_get_filename:
+ * @self: plugin info instance
+ *
+ * Returns: (transfer none): the filename. Can be %NULL.
+ *
+ * Since: 1.2
+ */
+const char *
+nm_vpn_plugin_info_get_filename (NMVpnPluginInfo *self)
+{
+	g_return_val_if_fail (NM_IS_VPN_PLUGIN_INFO (self), NULL);
+
+	return NM_VPN_PLUGIN_INFO_GET_PRIVATE (self)->filename;
+}
+
+/**
+ * nm_vpn_plugin_info_get_name:
+ * @self: plugin info instance
+ *
+ * Returns: (transfer none): the name. Cannot be %NULL.
+ *
+ * Since: 1.2
+ */
+const char *
+nm_vpn_plugin_info_get_name (NMVpnPluginInfo *self)
+{
+	g_return_val_if_fail (NM_IS_VPN_PLUGIN_INFO (self), NULL);
+
+	return NM_VPN_PLUGIN_INFO_GET_PRIVATE (self)->name;
+}
+
+/**
+ * nm_vpn_plugin_info_get_plugin:
+ * @self: plugin info instance
+ *
+ * Returns: (transfer none): the plugin. Can be %NULL.
+ *
+ * Since: 1.2
+ */
+const char *
+nm_vpn_plugin_info_get_plugin (NMVpnPluginInfo *self)
+{
+	g_return_val_if_fail (NM_IS_VPN_PLUGIN_INFO (self), NULL);
+
+	return g_hash_table_lookup (NM_VPN_PLUGIN_INFO_GET_PRIVATE (self)->keys,
+	                            _nm_utils_strstrdictkey_static (NM_VPN_PLUGIN_INFO_KF_GROUP_LIBNM, "plugin"));
+}
+
+/**
+ * nm_vpn_plugin_info_get_program:
+ * @self: plugin info instance
+ *
+ * Returns: (transfer none): the program. Can be %NULL.
+ *
+ * Since: 1.2
+ */
+const char *
+nm_vpn_plugin_info_get_program (NMVpnPluginInfo *self)
+{
+	g_return_val_if_fail (NM_IS_VPN_PLUGIN_INFO (self), NULL);
+
+	return g_hash_table_lookup (NM_VPN_PLUGIN_INFO_GET_PRIVATE (self)->keys,
+	                            _nm_utils_strstrdictkey_static (NM_VPN_PLUGIN_INFO_KF_GROUP_CONNECTION, "program"));
+}
+
+/**
+ * nm_vpn_plugin_info_supports_multiple:
+ * @self: plugin info instance
+ *
+ * Returns: %TRUE if the service supports multiple instances with different bus names, otherwise %FALSE
+ *
+ * Since: 1.2
+ */
+gboolean
+nm_vpn_plugin_info_supports_multiple (NMVpnPluginInfo *self)
+{
+	g_return_val_if_fail (NM_IS_VPN_PLUGIN_INFO (self), FALSE);
+
+	return g_key_file_get_boolean (NM_VPN_PLUGIN_INFO_GET_PRIVATE (self)->keyfile,
+	                               NM_VPN_PLUGIN_INFO_KF_GROUP_CONNECTION,
+	                               "supports-multiple-connections",
+	                               NULL);
+}
+
+
+/**
+ * nm_vpn_plugin_info_lookup_property:
+ * @self: plugin info instance
+ * @group: group name
+ * @key: name of the property
+ *
+ * Returns: (transfer none): #NMVpnPluginInfo is internally a #GKeyFile. Returns the matching
+ * property.
+ *
+ * Since: 1.2
+ */
+const char *
+nm_vpn_plugin_info_lookup_property (NMVpnPluginInfo *self, const char *group, const char *key)
+{
+	NMVpnPluginInfoPrivate *priv;
+	gs_free NMUtilsStrStrDictKey *k = NULL;
+
+	g_return_val_if_fail (NM_IS_VPN_PLUGIN_INFO (self), NULL);
+	g_return_val_if_fail (group, NULL);
+	g_return_val_if_fail (key, NULL);
+
+	priv = NM_VPN_PLUGIN_INFO_GET_PRIVATE (self);
+
+	k = _nm_utils_strstrdictkey_create (group, key);
+	return g_hash_table_lookup (priv->keys, k);
+}
+
+/*********************************************************************/
+
+/**
+ * nm_vpn_plugin_info_get_editor_plugin:
+ * @self: plugin info instance
+ *
+ * Returns: (transfer none): the cached #NMVpnEditorPlugin instance.
+ *
+ * Since: 1.2
+ */
+NMVpnEditorPlugin *
+nm_vpn_plugin_info_get_editor_plugin (NMVpnPluginInfo *self)
+{
+	g_return_val_if_fail (NM_IS_VPN_PLUGIN_INFO (self), NULL);
+
+	return NM_VPN_PLUGIN_INFO_GET_PRIVATE (self)->editor_plugin;
+}
+
+/**
+ * nm_vpn_plugin_info_set_editor_plugin:
+ * @self: plugin info instance
+ * @plugin: (allow-none): plugin instance
+ *
+ * Set the internal plugin instance. If %NULL, only clear the previous instance.
+ *
+ * Since: 1.2
+ */
+void
+nm_vpn_plugin_info_set_editor_plugin (NMVpnPluginInfo *self, NMVpnEditorPlugin *plugin)
+{
+	NMVpnPluginInfoPrivate *priv;
+	NMVpnEditorPlugin *old;
+
+	g_return_if_fail (NM_IS_VPN_PLUGIN_INFO (self));
+	g_return_if_fail (!plugin || G_IS_OBJECT (plugin));
+
+	priv = NM_VPN_PLUGIN_INFO_GET_PRIVATE (self);
+
+	if (!plugin) {
+		priv->editor_plugin_loaded = FALSE;
+		g_clear_object (&priv->editor_plugin);
+	} else {
+		old = priv->editor_plugin;
+		priv->editor_plugin = g_object_ref (plugin);
+		priv->editor_plugin_loaded = TRUE;
+		if (old)
+			g_object_unref (old);
+	}
+}
+
+/**
+ * nm_vpn_plugin_info_load_editor_plugin:
+ * @self: plugin info instance
+ * @error: error reason on failure
+ *
+ * Returns: (transfer none): loads the plugin and returns the newly created
+ *   instance. The plugin is owned by @self and can be later retrieved again
+ *   via nm_vpn_plugin_info_get_editor_plugin(). You can load the
+ *   plugin only once, unless you reset the state via
+ *   nm_vpn_plugin_info_set_editor_plugin().
+ *
+ * Since: 1.2
+ */
+NMVpnEditorPlugin *
+nm_vpn_plugin_info_load_editor_plugin (NMVpnPluginInfo *self, GError **error)
+{
+	NMVpnPluginInfoPrivate *priv;
+	const char *plugin_filename;
+
+	g_return_val_if_fail (NM_IS_VPN_PLUGIN_INFO (self), NULL);
+
+	priv = NM_VPN_PLUGIN_INFO_GET_PRIVATE (self);
+
+	if (priv->editor_plugin)
+		return priv->editor_plugin;
+
+	plugin_filename = nm_vpn_plugin_info_get_plugin (self);
+	if (!plugin_filename || !*plugin_filename) {
+		g_set_error (error,
+		             NM_VPN_PLUGIN_ERROR,
+		             NM_VPN_PLUGIN_ERROR_FAILED,
+		             _("missing \"plugin\" setting"));
+		return NULL;
+	}
+
+	/* We only try once to load the plugin. If we previously tried and it was
+	 * unsuccessful, error out immediately. */
+	if (priv->editor_plugin_loaded) {
+		g_set_error (error,
+		             NM_VPN_PLUGIN_ERROR,
+		             NM_VPN_PLUGIN_ERROR_FAILED,
+		             _("%s: don't retry loading plugin which already failed previously"), priv->name);
+		return NULL;
+	}
+
+	priv->editor_plugin_loaded = TRUE;
+	priv->editor_plugin = nm_vpn_editor_plugin_load_from_file (plugin_filename,
+	                                                           priv->service,
+	                                                           getuid (),
+	                                                           NULL,
+	                                                           NULL,
+	                                                           error);
+	return priv->editor_plugin;
+}
+
+/*********************************************************************/
+
+/**
+ * nm_vpn_plugin_info_new_from_file:
+ * @filename: filename to read.
+ * @error: on failure, the error reason.
+ *
+ * Read the plugin info from file @filename. Does not do
+ * any further verification on the file. You might want to check
+ * file permissions and ownership of the file.
+ *
+ * Returns: %NULL if there is any error or a newly created
+ * #NMVpnPluginInfo instance.
+ *
+ * Since: 1.2
+ */
+NMVpnPluginInfo *
+nm_vpn_plugin_info_new_from_file (const char *filename,
+                                  GError **error)
+{
+	g_return_val_if_fail (filename, NULL);
+
+	return NM_VPN_PLUGIN_INFO (g_initable_new (NM_TYPE_VPN_PLUGIN_INFO,
+	                                           NULL,
+	                                           error,
+	                                           NM_VPN_PLUGIN_INFO_FILENAME, filename,
+	                                           NULL));
+}
+
+/**
+ * nm_vpn_plugin_info_new_with_data:
+ * @filename: optional filename.
+ * @keyfile: inject data for the plugin info instance.
+ * @error: construction may fail if the keyfile lacks mandatory fields.
+ *   In this case, return the error reason.
+ *
+ * This constructor does not read any data from file but
+ * takes instead a @keyfile argument.
+ *
+ * Returns: new plugin info instance.
+ *
+ * Since: 1.2
+ */
+NMVpnPluginInfo *
+nm_vpn_plugin_info_new_with_data (const char *filename,
+                                  GKeyFile *keyfile,
+                                  GError **error)
+{
+	g_return_val_if_fail (keyfile, NULL);
+
+	return NM_VPN_PLUGIN_INFO (g_initable_new (NM_TYPE_VPN_PLUGIN_INFO,
+	                                           NULL,
+	                                           error,
+	                                           NM_VPN_PLUGIN_INFO_FILENAME, filename,
+	                                           NM_VPN_PLUGIN_INFO_KEYFILE, keyfile,
+	                                           NULL));
+}
+
+/*********************************************************************/
+
+static void
+nm_vpn_plugin_info_init (NMVpnPluginInfo *plugin)
+{
+}
+
+static gboolean
+init_sync (GInitable *initable, GCancellable *cancellable, GError **error)
+{
+	NMVpnPluginInfo *self = NM_VPN_PLUGIN_INFO (initable);
+	NMVpnPluginInfoPrivate *priv = NM_VPN_PLUGIN_INFO_GET_PRIVATE (self);
+	gs_strfreev char **groups = NULL;
+	guint i, j;
+
+	if (!priv->keyfile) {
+		if (!priv->filename) {
+			g_set_error_literal (error,
+			                     NM_VPN_PLUGIN_ERROR,
+			                     NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
+			                     _("missing filename to load VPN plugin info"));
+			return FALSE;
+		}
+		priv->keyfile = g_key_file_new ();
+		if (!g_key_file_load_from_file (priv->keyfile, priv->filename, G_KEY_FILE_NONE, error))
+			return FALSE;
+	}
+
+	/* we reqire at least a "name" */
+	priv->name = g_key_file_get_string (priv->keyfile, NM_VPN_PLUGIN_INFO_KF_GROUP_CONNECTION, "name", NULL);
+	if (!priv->name || !priv->name[0]) {
+		g_set_error_literal (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
+		                     _("missing name for VPN plugin info"));
+		return FALSE;
+	}
+
+	/* we also require "service", because that how we associate NMSettingVpn:service-type with the
+	 * NMVpnPluginInfo. */
+	priv->service = g_key_file_get_string (priv->keyfile, NM_VPN_PLUGIN_INFO_KF_GROUP_CONNECTION, "service", NULL);
+	if (!priv->service || !*priv->service) {
+		g_set_error_literal (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
+		                     _("missing service for VPN plugin info"));
+		return FALSE;
+	}
+
+	priv->aliases = g_key_file_get_string_list (priv->keyfile, NM_VPN_PLUGIN_INFO_KF_GROUP_CONNECTION, "aliases", NULL, NULL);
+
+	priv->keys = g_hash_table_new_full (_nm_utils_strstrdictkey_hash,
+	                                    _nm_utils_strstrdictkey_equal,
+	                                    g_free, g_free);
+	groups = g_key_file_get_groups (priv->keyfile, NULL);
+	for (i = 0; groups && groups[i]; i++) {
+		gs_strfreev char **keys = NULL;
+
+		keys = g_key_file_get_keys (priv->keyfile, groups[i], NULL, NULL);
+		for (j = 0; keys && keys[j]; j++) {
+			char *s;
+
+			/* Lookup the value via get_string(). We want that behavior.
+			 * You could still lookup the original values via g_key_file_get_value()
+			 * based on priv->keyfile. */
+			s = g_key_file_get_string (priv->keyfile, groups[i], keys[j], NULL);
+			if (s)
+				g_hash_table_insert (priv->keys, _nm_utils_strstrdictkey_create (groups[i], keys[j]), s);
+		}
+	}
+
+	return TRUE;
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+              const GValue *value, GParamSpec *pspec)
+{
+	NMVpnPluginInfoPrivate *priv = NM_VPN_PLUGIN_INFO_GET_PRIVATE (object);
+
+	switch (prop_id) {
+	case PROP_FILENAME:
+		priv->filename = g_value_dup_string (value);
+		break;
+	case PROP_KEYFILE:
+		priv->keyfile = g_value_dup_boxed (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)
+{
+	NMVpnPluginInfoPrivate *priv = NM_VPN_PLUGIN_INFO_GET_PRIVATE (object);
+
+	switch (prop_id) {
+	case PROP_NAME:
+		g_value_set_string (value, priv->name);
+		break;
+	case PROP_FILENAME:
+		g_value_set_string (value, priv->filename);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+dispose (GObject *object)
+{
+	NMVpnPluginInfo *self = NM_VPN_PLUGIN_INFO (object);
+	NMVpnPluginInfoPrivate *priv = NM_VPN_PLUGIN_INFO_GET_PRIVATE (self);
+
+	g_clear_object (&priv->editor_plugin);
+
+	G_OBJECT_CLASS (nm_vpn_plugin_info_parent_class)->dispose (object);
+}
+
+static void
+finalize (GObject *object)
+{
+	NMVpnPluginInfo *self = NM_VPN_PLUGIN_INFO (object);
+	NMVpnPluginInfoPrivate *priv = NM_VPN_PLUGIN_INFO_GET_PRIVATE (self);
+
+	g_free (priv->name);
+	g_free (priv->service);
+	g_strfreev (priv->aliases);
+	g_free (priv->filename);
+	g_key_file_unref (priv->keyfile);
+	g_hash_table_unref (priv->keys);
+
+	G_OBJECT_CLASS (nm_vpn_plugin_info_parent_class)->finalize (object);
+}
+
+static void
+nm_vpn_plugin_info_class_init (NMVpnPluginInfoClass *plugin_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (plugin_class);
+
+	g_type_class_add_private (object_class, sizeof (NMVpnPluginInfoPrivate));
+
+	/* virtual methods */
+	object_class->set_property = set_property;
+	object_class->get_property = get_property;
+	object_class->dispose      = dispose;
+	object_class->finalize     = finalize;
+
+	/* properties */
+
+	/**
+	 * NMVpnPluginInfo:name:
+	 *
+	 * The name of the VPN plugin.
+	 *
+	 * Since: 1.2
+	 */
+	g_object_class_install_property
+	    (object_class, PROP_NAME,
+	     g_param_spec_string (NM_VPN_PLUGIN_INFO_NAME, "", "",
+	                          NULL,
+	                          G_PARAM_READABLE |
+	                          G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMVpnPluginInfo:filename:
+	 *
+	 * The filename from which the info was loaded.
+	 * Can be %NULL if the instance was not loaded from
+	 * a file (i.e. the keyfile instance was passed to the
+	 * constructor).
+	 *
+	 * Since: 1.2
+	 */
+	g_object_class_install_property
+	    (object_class, PROP_FILENAME,
+	     g_param_spec_string (NM_VPN_PLUGIN_INFO_FILENAME, "", "",
+	                          NULL,
+	                          G_PARAM_READWRITE |
+	                          G_PARAM_CONSTRUCT_ONLY |
+	                          G_PARAM_STATIC_STRINGS));
+
+	/**
+	 * NMVpnPluginInfo:keyfile:
+	 *
+	 * Initalize the instance with a different keyfile instance.
+	 * When passing a keyfile instance, the constructor will not
+	 * try to read from filename.
+	 *
+	 * Since: 1.2
+	 */
+	g_object_class_install_property
+	    (object_class, PROP_KEYFILE,
+	     g_param_spec_boxed (NM_VPN_PLUGIN_INFO_KEYFILE, "", "",
+	                         G_TYPE_KEY_FILE,
+	                         G_PARAM_WRITABLE |
+	                         G_PARAM_CONSTRUCT_ONLY |
+	                         G_PARAM_STATIC_STRINGS));
+}
+
+static void
+nm_vpn_plugin_info_initable_iface_init (GInitableIface *iface)
+{
+	iface->init = init_sync;
+}
+
diff --git a/libnm-core/nm-vpn-plugin-info.h b/libnm-core/nm-vpn-plugin-info.h
new file mode 100644
index 00000000..667a4fe2
--- /dev/null
+++ b/libnm-core/nm-vpn-plugin-info.h
@@ -0,0 +1,114 @@
+/* -*- 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 2015 Red Hat, Inc.
+ */
+
+#ifndef __NM_VPN_PLUGIN_INFO_H__
+#define __NM_VPN_PLUGIN_INFO_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include "nm-utils.h"
+#include "nm-vpn-editor-plugin.h"
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_VPN_PLUGIN_INFO            (nm_vpn_plugin_info_get_type ())
+#define NM_VPN_PLUGIN_INFO(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_VPN_PLUGIN_INFO, NMVpnPluginInfo))
+#define NM_VPN_PLUGIN_INFO_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_VPN_PLUGIN_INFO, NMVpnPluginInfoClass))
+#define NM_IS_VPN_PLUGIN_INFO(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_VPN_PLUGIN_INFO))
+#define NM_IS_VPN_PLUGIN_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_VPN_PLUGIN_INFO))
+#define NM_VPN_PLUGIN_INFO_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_VPN_PLUGIN_INFO, NMVpnPluginInfoClass))
+
+#define NM_VPN_PLUGIN_INFO_NAME        "name"
+#define NM_VPN_PLUGIN_INFO_FILENAME    "filename"
+#define NM_VPN_PLUGIN_INFO_KEYFILE     "keyfile"
+
+#define NM_VPN_PLUGIN_INFO_KF_GROUP_CONNECTION   "VPN Connection"
+#define NM_VPN_PLUGIN_INFO_KF_GROUP_LIBNM        "libnm"
+#define NM_VPN_PLUGIN_INFO_KF_GROUP_GNOME        "GNOME"
+
+typedef struct {
+	NM_AVAILABLE_IN_1_2
+	GObject parent;
+} NMVpnPluginInfo;
+
+typedef struct {
+	NM_AVAILABLE_IN_1_2
+	GObjectClass parent;
+
+	/*< private >*/
+	NM_AVAILABLE_IN_1_2
+	gpointer padding[8];
+} NMVpnPluginInfoClass NM_AVAILABLE_IN_1_2;
+
+NM_AVAILABLE_IN_1_2
+GType  nm_vpn_plugin_info_get_type       (void);
+
+NM_AVAILABLE_IN_1_2
+NMVpnPluginInfo *nm_vpn_plugin_info_new_from_file (const char *filename,
+                                                   GError **error);
+
+NM_AVAILABLE_IN_1_2
+NMVpnPluginInfo *nm_vpn_plugin_info_new_with_data (const char *filename,
+                                                   GKeyFile *keyfile,
+                                                   GError **error);
+
+NM_AVAILABLE_IN_1_2
+const char *nm_vpn_plugin_info_get_name        (NMVpnPluginInfo *self);
+NM_AVAILABLE_IN_1_2
+const char *nm_vpn_plugin_info_get_filename    (NMVpnPluginInfo *self);
+NM_AVAILABLE_IN_1_2
+const char *nm_vpn_plugin_info_get_plugin      (NMVpnPluginInfo *self);
+NM_AVAILABLE_IN_1_2
+const char *nm_vpn_plugin_info_get_program     (NMVpnPluginInfo *self);
+NM_AVAILABLE_IN_1_2
+gboolean nm_vpn_plugin_info_supports_multiple  (NMVpnPluginInfo *self);
+NM_AVAILABLE_IN_1_2
+const char *nm_vpn_plugin_info_lookup_property (NMVpnPluginInfo *self, const char *group, const char *key);
+
+NM_AVAILABLE_IN_1_2
+gboolean nm_vpn_plugin_info_validate_filename (const char *filename);
+
+NM_AVAILABLE_IN_1_2
+GSList          *nm_vpn_plugin_info_list_load             (void);
+NM_AVAILABLE_IN_1_2
+gboolean         nm_vpn_plugin_info_list_add              (GSList **list, NMVpnPluginInfo *plugin_info, GError **error);
+NM_AVAILABLE_IN_1_2
+gboolean         nm_vpn_plugin_info_list_remove           (GSList **list, NMVpnPluginInfo *plugin_info);
+NM_AVAILABLE_IN_1_2
+NMVpnPluginInfo *nm_vpn_plugin_info_list_find_by_name     (GSList *list, const char *name);
+NM_AVAILABLE_IN_1_2
+NMVpnPluginInfo *nm_vpn_plugin_info_list_find_by_filename (GSList *list, const char *filename);
+NM_AVAILABLE_IN_1_2
+NMVpnPluginInfo *nm_vpn_plugin_info_list_find_by_service  (GSList *list, const char *service);
+
+
+NM_AVAILABLE_IN_1_2
+NMVpnEditorPlugin *nm_vpn_plugin_info_get_editor_plugin  (NMVpnPluginInfo *self);
+NM_AVAILABLE_IN_1_2
+void               nm_vpn_plugin_info_set_editor_plugin  (NMVpnPluginInfo *self,
+                                                          NMVpnEditorPlugin *plugin);
+NM_AVAILABLE_IN_1_2
+NMVpnEditorPlugin *nm_vpn_plugin_info_load_editor_plugin (NMVpnPluginInfo *self,
+                                                          GError **error);
+
+G_END_DECLS
+
+#endif /* __NM_VPN_PLUGIN_INFO_H__ */
diff --git a/libnm-core/tests/Makefile.am b/libnm-core/tests/Makefile.am
index bcccfda9..92c816fd 100644
--- a/libnm-core/tests/Makefile.am
+++ b/libnm-core/tests/Makefile.am
@@ -1,5 +1,3 @@
-if ENABLE_TESTS
-
 include $(GLIB_MAKEFILE)
 
 GLIB_GENERATED = nm-core-tests-enum-types.h nm-core-tests-enum-types.c
@@ -9,11 +7,13 @@ GLIB_MKENUMS_C_FLAGS = --identifier-prefix NM
 
 BUILT_SOURCES = $(GLIB_GENERATED)
 
+if ENABLE_TESTS
+
 certsdir = $(srcdir)/certs
 
 AM_CPPFLAGS = \
-	-I${top_srcdir}/include \
-	-I${top_builddir}/include \
+	-I${top_srcdir}/shared \
+	-I${top_builddir}/shared \
 	-I$(top_srcdir)/libnm-core \
 	-I$(top_builddir)/libnm-core \
 	-DNETWORKMANAGER_COMPILATION \
diff --git a/libnm-core/tests/Makefile.in b/libnm-core/tests/Makefile.in
index e46146a4..43892d75 100644
--- a/libnm-core/tests/Makefile.in
+++ b/libnm-core/tests/Makefile.in
@@ -460,7 +460,6 @@ BLUEZ5_LIBS = @BLUEZ5_LIBS@
 CC = @CC@
 CCDEPMODE = @CCDEPMODE@
 CFLAGS = @CFLAGS@
-CKDB_PATH = @CKDB_PATH@
 CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@
 CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@
 CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@
@@ -472,8 +471,6 @@ CXXDEPMODE = @CXXDEPMODE@
 CXXFLAGS = @CXXFLAGS@
 CYGPATH_W = @CYGPATH_W@
 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@
@@ -483,6 +480,7 @@ DHCPCD_PATH = @DHCPCD_PATH@
 DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@
 DLLTOOL = @DLLTOOL@
 DNSMASQ_PATH = @DNSMASQ_PATH@
+DNSSEC_TRIGGER_SCRIPT = @DNSSEC_TRIGGER_SCRIPT@
 DSYMUTIL = @DSYMUTIL@
 DUMPBIN = @DUMPBIN@
 ECHO_C = @ECHO_C@
@@ -537,16 +535,13 @@ INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@
 INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@
 INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@
 IPTABLES_PATH = @IPTABLES_PATH@
-IWMX_SDK_CFLAGS = @IWMX_SDK_CFLAGS@
-IWMX_SDK_LIBS = @IWMX_SDK_LIBS@
 KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@
 LCOV = @LCOV@
 LD = @LD@
 LDFLAGS = @LDFLAGS@
+LIBAUDIT_CFLAGS = @LIBAUDIT_CFLAGS@
+LIBAUDIT_LIBS = @LIBAUDIT_LIBS@
 LIBDL = @LIBDL@
-LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
-LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
-LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
 LIBICONV = @LIBICONV@
 LIBINTL = @LIBINTL@
 LIBM = @LIBM@
@@ -583,6 +578,8 @@ NEWT_LIBS = @NEWT_LIBS@
 NM = @NM@
 NMEDIT = @NMEDIT@
 NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@
+NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@
+NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@
 NM_MAJOR_VERSION = @NM_MAJOR_VERSION@
 NM_MICRO_VERSION = @NM_MICRO_VERSION@
 NM_MINOR_VERSION = @NM_MINOR_VERSION@
@@ -611,7 +608,6 @@ 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@
@@ -626,6 +622,8 @@ SYSTEMD_200_CFLAGS = @SYSTEMD_200_CFLAGS@
 SYSTEMD_200_LIBS = @SYSTEMD_200_LIBS@
 SYSTEMD_INHIBIT_CFLAGS = @SYSTEMD_INHIBIT_CFLAGS@
 SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@
+SYSTEMD_JOURNAL_CFLAGS = @SYSTEMD_JOURNAL_CFLAGS@
+SYSTEMD_JOURNAL_LIBS = @SYSTEMD_JOURNAL_LIBS@
 SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@
 SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@
 SYSTEM_CA_PATH = @SYSTEM_CA_PATH@
@@ -686,6 +684,7 @@ mkdir_p = @mkdir_p@
 nmbinary = @nmbinary@
 nmconfdir = @nmconfdir@
 nmdatadir = @nmdatadir@
+nmlibdir = @nmlibdir@
 nmrundir = @nmrundir@
 nmstatedir = @nmstatedir@
 oldincludedir = @oldincludedir@
@@ -693,6 +692,7 @@ pdfdir = @pdfdir@
 prefix = @prefix@
 program_transform_name = @program_transform_name@
 psdir = @psdir@
+runstatedir = @runstatedir@
 sbindir = @sbindir@
 sharedstatedir = @sharedstatedir@
 srcdir = @srcdir@
@@ -708,15 +708,15 @@ with_dhcpcd = @with_dhcpcd@
 with_netconfig = @with_netconfig@
 with_resolvconf = @with_resolvconf@
 with_valgrind = @with_valgrind@
-@ENABLE_TESTS_TRUE@GLIB_GENERATED = nm-core-tests-enum-types.h nm-core-tests-enum-types.c
-@ENABLE_TESTS_TRUE@nm_core_tests_enum_types_sources = test-general-enums.h
-@ENABLE_TESTS_TRUE@GLIB_MKENUMS_H_FLAGS = --identifier-prefix NM
-@ENABLE_TESTS_TRUE@GLIB_MKENUMS_C_FLAGS = --identifier-prefix NM
-@ENABLE_TESTS_TRUE@BUILT_SOURCES = $(GLIB_GENERATED)
+GLIB_GENERATED = nm-core-tests-enum-types.h nm-core-tests-enum-types.c
+nm_core_tests_enum_types_sources = test-general-enums.h
+GLIB_MKENUMS_H_FLAGS = --identifier-prefix NM
+GLIB_MKENUMS_C_FLAGS = --identifier-prefix NM
+BUILT_SOURCES = $(GLIB_GENERATED)
 @ENABLE_TESTS_TRUE@certsdir = $(srcdir)/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}/shared \
+@ENABLE_TESTS_TRUE@	-I${top_builddir}/shared \
 @ENABLE_TESTS_TRUE@	-I$(top_srcdir)/libnm-core \
 @ENABLE_TESTS_TRUE@	-I$(top_builddir)/libnm-core \
 @ENABLE_TESTS_TRUE@	-DNETWORKMANAGER_COMPILATION \
@@ -1306,8 +1306,7 @@ uninstall-am:
 
 .PRECIOUS: Makefile
 
-
-@ENABLE_TESTS_TRUE@include $(GLIB_MAKEFILE)
+include $(GLIB_MAKEFILE)
 
 @ENABLE_TESTS_TRUE@@VALGRIND_RULES@
 
diff --git a/libnm-core/tests/nm-core-tests-enum-types.c b/libnm-core/tests/nm-core-tests-enum-types.c
index 80271e52..e6eaa60b 100644
--- a/libnm-core/tests/nm-core-tests-enum-types.c
+++ b/libnm-core/tests/nm-core-tests-enum-types.c
@@ -3,6 +3,8 @@
 
 /* Generated by glib-mkenums. Do not edit */
 
+#include "config.h"
+
 #include "nm-core-tests-enum-types.h"
 
 #include "test-general-enums.h"
diff --git a/libnm-core/tests/test-compare.c b/libnm-core/tests/test-compare.c
index 12db9c23..914330fe 100644
--- a/libnm-core/tests/test-compare.c
+++ b/libnm-core/tests/test-compare.c
@@ -24,8 +24,7 @@
 #include <arpa/inet.h>
 #include <netinet/in.h>
 
-#include "nm-glib-compat.h"
-
+#include "nm-default.h"
 #include "nm-property-compare.h"
 
 #include "nm-test-utils.h"
diff --git a/libnm-core/tests/test-crypto.c b/libnm-core/tests/test-crypto.c
index e4ca8086..926cddb0 100644
--- a/libnm-core/tests/test-crypto.c
+++ b/libnm-core/tests/test-crypto.c
@@ -23,13 +23,12 @@
 
 #include "config.h"
 
-#include <glib.h>
 #include <unistd.h>
 #include <stdlib.h>
-#include <glib/gi18n.h>
 #include <stdio.h>
 #include <string.h>
 
+#include "nm-default.h"
 #include "crypto.h"
 #include "nm-utils.h"
 #include "nm-errors.h"
diff --git a/libnm-core/tests/test-general.c b/libnm-core/tests/test-general.c
index 53d8195c..e8eb0baf 100644
--- a/libnm-core/tests/test-general.c
+++ b/libnm-core/tests/test-general.c
@@ -7,7 +7,7 @@
  * 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
+ * but WITHOUT SC WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
@@ -23,14 +23,14 @@
 
 #include "config.h"
 
-#include <glib.h>
 #include <string.h>
 
 #include <nm-utils.h>
-#include "gsystem-local-alloc.h"
+#include "nm-default.h"
 
 #include "nm-setting-private.h"
 #include "nm-utils.h"
+#include "nm-utils-private.h"
 #include "nm-core-internal.h"
 #include "nm-core-tests-enum-types.h"
 
@@ -60,11 +60,19 @@
 #include "nm-setting-wireless.h"
 #include "nm-setting-wireless-security.h"
 #include "nm-simple-connection.h"
-#include "nm-glib-compat.h"
+#include "nm-keyfile-internal.h"
 
 #include "nm-test-utils.h"
 #include "test-general-enums.h"
 
+/* When passing a "bool" typed argument to a variadic function that
+ * expects a gboolean, the compiler will promote the integer type
+ * to have at least size (int). That way:
+ *   g_object_set (obj, PROP_BOOL, bool_val, NULL);
+ * will just work correctly. */
+G_STATIC_ASSERT (sizeof (gboolean) == sizeof (int));
+G_STATIC_ASSERT (sizeof (bool) <= sizeof (int));
+
 static void
 vpn_check_func (const char *key, const char *value, gpointer user_data)
 {
@@ -748,6 +756,35 @@ test_setting_gsm_without_number (void)
 	                                   NM_CONNECTION_ERROR_INVALID_PROPERTY);
 }
 
+static void
+test_setting_gsm_sim_operator_id (void)
+{
+	gs_unref_object NMSettingGsm *s_gsm = NULL;
+
+	s_gsm = (NMSettingGsm *) nm_setting_gsm_new ();
+	g_assert (s_gsm);
+
+	/* Valid */
+	g_object_set (s_gsm, NM_SETTING_GSM_SIM_OPERATOR_ID, "12345", NULL);
+	nmtst_assert_setting_verifies (NM_SETTING (s_gsm));
+
+	g_object_set (s_gsm, NM_SETTING_GSM_SIM_OPERATOR_ID, "123456", NULL);
+	nmtst_assert_setting_verifies (NM_SETTING (s_gsm));
+
+	/* Invalid */
+	g_object_set (s_gsm, NM_SETTING_GSM_SIM_OPERATOR_ID, "", NULL);
+	nmtst_assert_setting_verify_fails (NM_SETTING (s_gsm), NM_CONNECTION_ERROR,
+	                                   NM_CONNECTION_ERROR_INVALID_PROPERTY);
+
+	g_object_set (s_gsm, NM_SETTING_GSM_SIM_OPERATOR_ID, "     ", NULL);
+	nmtst_assert_setting_verify_fails (NM_SETTING (s_gsm), NM_CONNECTION_ERROR,
+	                                   NM_CONNECTION_ERROR_INVALID_PROPERTY);
+
+	g_object_set (s_gsm, NM_SETTING_GSM_SIM_OPERATOR_ID, "abcdef", NULL);
+	nmtst_assert_setting_verify_fails (NM_SETTING (s_gsm), NM_CONNECTION_ERROR,
+	                                   NM_CONNECTION_ERROR_INVALID_PROPERTY);
+}
+
 static NMSettingWirelessSecurity *
 make_test_wsec_setting (const char *detail)
 {
@@ -1972,6 +2009,7 @@ test_connection_diff_a_only (void)
 			{ NM_SETTING_CONNECTION_SECONDARIES,          NM_SETTING_DIFF_RESULT_IN_A },
 			{ NM_SETTING_CONNECTION_GATEWAY_PING_TIMEOUT, NM_SETTING_DIFF_RESULT_IN_A },
 			{ NM_SETTING_CONNECTION_METERED,              NM_SETTING_DIFF_RESULT_IN_A },
+			{ NM_SETTING_CONNECTION_LLDP,                 NM_SETTING_DIFF_RESULT_IN_A },
 			{ NULL, NM_SETTING_DIFF_RESULT_UNKNOWN }
 		} },
 		{ NM_SETTING_WIRED_SETTING_NAME, {
@@ -1994,6 +2032,7 @@ test_connection_diff_a_only (void)
 			{ NM_SETTING_IP_CONFIG_METHOD,             NM_SETTING_DIFF_RESULT_IN_A },
 			{ NM_SETTING_IP_CONFIG_DNS,                NM_SETTING_DIFF_RESULT_IN_A },
 			{ NM_SETTING_IP_CONFIG_DNS_SEARCH,         NM_SETTING_DIFF_RESULT_IN_A },
+			{ NM_SETTING_IP_CONFIG_DNS_OPTIONS,        NM_SETTING_DIFF_RESULT_IN_A },
 			{ NM_SETTING_IP_CONFIG_ADDRESSES,          NM_SETTING_DIFF_RESULT_IN_A },
 			{ NM_SETTING_IP_CONFIG_GATEWAY,            NM_SETTING_DIFF_RESULT_IN_A },
 			{ NM_SETTING_IP_CONFIG_ROUTES,             NM_SETTING_DIFF_RESULT_IN_A },
@@ -2001,8 +2040,10 @@ test_connection_diff_a_only (void)
 			{ NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES, NM_SETTING_DIFF_RESULT_IN_A },
 			{ NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS,    NM_SETTING_DIFF_RESULT_IN_A },
 			{ NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID,    NM_SETTING_DIFF_RESULT_IN_A },
+			{ NM_SETTING_IP4_CONFIG_DHCP_TIMEOUT,      NM_SETTING_DIFF_RESULT_IN_A },
 			{ NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME, NM_SETTING_DIFF_RESULT_IN_A },
 			{ NM_SETTING_IP_CONFIG_DHCP_HOSTNAME,      NM_SETTING_DIFF_RESULT_IN_A },
+			{ NM_SETTING_IP4_CONFIG_DHCP_FQDN,         NM_SETTING_DIFF_RESULT_IN_A },
 			{ NM_SETTING_IP_CONFIG_NEVER_DEFAULT,      NM_SETTING_DIFF_RESULT_IN_A },
 			{ NM_SETTING_IP_CONFIG_MAY_FAIL,           NM_SETTING_DIFF_RESULT_IN_A },
 			{ NULL, NM_SETTING_DIFF_RESULT_UNKNOWN },
@@ -2851,7 +2892,7 @@ test_setting_ip4_changed_signal (void)
 	ASSERT_CHANGED (nm_setting_ip_config_add_dns (s_ip4, "11.22.0.0"));
 	ASSERT_CHANGED (nm_setting_ip_config_remove_dns (s_ip4, 0));
 
-	g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*i < priv->dns->len*");
+	g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*idx < priv->dns->len*");
 	ASSERT_UNCHANGED (nm_setting_ip_config_remove_dns (s_ip4, 1));
 	g_test_assert_expected_messages ();
 
@@ -2861,7 +2902,7 @@ test_setting_ip4_changed_signal (void)
 	ASSERT_CHANGED (nm_setting_ip_config_add_dns_search (s_ip4, "foobar.com"));
 	ASSERT_CHANGED (nm_setting_ip_config_remove_dns_search (s_ip4, 0));
 
-	g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*i < priv->dns_search->len*");
+	g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*idx < priv->dns_search->len*");
 	ASSERT_UNCHANGED (nm_setting_ip_config_remove_dns_search (s_ip4, 1));
 	g_test_assert_expected_messages ();
 
@@ -2873,7 +2914,7 @@ test_setting_ip4_changed_signal (void)
 	ASSERT_CHANGED (nm_setting_ip_config_add_address (s_ip4, addr));
 	ASSERT_CHANGED (nm_setting_ip_config_remove_address (s_ip4, 0));
 
-	g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*i < priv->addresses->len*");
+	g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*idx < priv->addresses->len*");
 	ASSERT_UNCHANGED (nm_setting_ip_config_remove_address (s_ip4, 1));
 	g_test_assert_expected_messages ();
 
@@ -2886,13 +2927,20 @@ test_setting_ip4_changed_signal (void)
 	ASSERT_CHANGED (nm_setting_ip_config_add_route (s_ip4, route));
 	ASSERT_CHANGED (nm_setting_ip_config_remove_route (s_ip4, 0));
 
-	g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*i < priv->routes->len*");
+	g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*idx < priv->routes->len*");
 	ASSERT_UNCHANGED (nm_setting_ip_config_remove_route (s_ip4, 1));
 	g_test_assert_expected_messages ();
 
 	nm_setting_ip_config_add_route (s_ip4, route);
 	ASSERT_CHANGED (nm_setting_ip_config_clear_routes (s_ip4));
 
+	ASSERT_CHANGED (nm_setting_ip_config_add_dns_option (s_ip4, "debug"));
+	ASSERT_CHANGED (nm_setting_ip_config_remove_dns_option (s_ip4, 0));
+
+	g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*idx < priv->dns_options->len*");
+	ASSERT_UNCHANGED (nm_setting_ip_config_remove_dns_option (s_ip4, 1));
+	g_test_assert_expected_messages ();
+
 	nm_ip_address_unref (addr);
 	nm_ip_route_unref (route);
 	g_object_unref (connection);
@@ -2920,7 +2968,7 @@ test_setting_ip6_changed_signal (void)
 	ASSERT_CHANGED (nm_setting_ip_config_add_dns (s_ip6, "1:2:3::4:5:6"));
 	ASSERT_CHANGED (nm_setting_ip_config_remove_dns (s_ip6, 0));
 
-	g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*i < priv->dns->len*");
+	g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*idx < priv->dns->len*");
 	ASSERT_UNCHANGED (nm_setting_ip_config_remove_dns (s_ip6, 1));
 	g_test_assert_expected_messages ();
 
@@ -2930,7 +2978,7 @@ test_setting_ip6_changed_signal (void)
 	ASSERT_CHANGED (nm_setting_ip_config_add_dns_search (s_ip6, "foobar.com"));
 	ASSERT_CHANGED (nm_setting_ip_config_remove_dns_search (s_ip6, 0));
 
-	g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*i < priv->dns_search->len*");
+	g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*idx < priv->dns_search->len*");
 	ASSERT_UNCHANGED (nm_setting_ip_config_remove_dns_search (s_ip6, 1));
 	g_test_assert_expected_messages ();
 
@@ -2943,7 +2991,7 @@ test_setting_ip6_changed_signal (void)
 	ASSERT_CHANGED (nm_setting_ip_config_add_address (s_ip6, addr));
 	ASSERT_CHANGED (nm_setting_ip_config_remove_address (s_ip6, 0));
 
-	g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*i < priv->addresses->len*");
+	g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*idx < priv->addresses->len*");
 	ASSERT_UNCHANGED (nm_setting_ip_config_remove_address (s_ip6, 1));
 	g_test_assert_expected_messages ();
 
@@ -2956,7 +3004,7 @@ test_setting_ip6_changed_signal (void)
 	ASSERT_CHANGED (nm_setting_ip_config_add_route (s_ip6, route));
 	ASSERT_CHANGED (nm_setting_ip_config_remove_route (s_ip6, 0));
 
-	g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*i < priv->routes->len*");
+	g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*idx < priv->routes->len*");
 	ASSERT_UNCHANGED (nm_setting_ip_config_remove_route (s_ip6, 1));
 	g_test_assert_expected_messages ();
 
@@ -3964,6 +4012,51 @@ typedef struct {
 } HexItem;
 
 static void
+test_setting_compare_default_strv (void)
+{
+	gs_unref_object NMConnection *c1 = NULL, *c2 = NULL;
+	char **strv;
+	NMSettingIPConfig *s_ip2, *s_ip1;
+	gboolean compare;
+	GHashTable *out_settings = NULL;
+
+	c1 = nmtst_create_minimal_connection ("test_compare_default_strv", NULL,
+	                                      NM_SETTING_WIRED_SETTING_NAME, NULL);
+	nmtst_assert_connection_verifies_and_normalizable (c1);
+
+	c2 = nm_simple_connection_new_clone (c1);
+	nmtst_assert_connection_verifies_without_normalization (c2);
+
+	nmtst_assert_connection_equals (c1, FALSE, c2, FALSE);
+
+	s_ip1 = nm_connection_get_setting_ip4_config (c1);
+	s_ip2 = nm_connection_get_setting_ip4_config (c2);
+
+	nm_setting_ip_config_clear_dns_options (s_ip2, FALSE);
+	g_object_get (G_OBJECT (s_ip2), NM_SETTING_IP_CONFIG_DNS_OPTIONS, &strv, NULL);
+	g_assert (!strv);
+	nmtst_assert_connection_equals (c1, FALSE, c2, FALSE);
+
+	nm_setting_ip_config_clear_dns_options (s_ip2, TRUE);
+	g_object_get (G_OBJECT (s_ip2), NM_SETTING_IP_CONFIG_DNS_OPTIONS, &strv, NULL);
+	g_assert (strv && !strv[0]);
+	g_strfreev (strv);
+
+	compare = nm_setting_diff ((NMSetting *) s_ip1, (NMSetting *) s_ip2, NM_SETTING_COMPARE_FLAG_EXACT, FALSE, &out_settings);
+	g_assert (!compare);
+	g_assert (out_settings);
+	g_assert (g_hash_table_contains (out_settings, NM_SETTING_IP_CONFIG_DNS_OPTIONS));
+	g_hash_table_unref (out_settings);
+	out_settings = NULL;
+
+	compare = nm_connection_diff (c1, c2, NM_SETTING_COMPARE_FLAG_EXACT, &out_settings);
+	g_assert (!compare);
+	g_assert (out_settings);
+	g_hash_table_unref (out_settings);
+	out_settings = NULL;
+}
+
+static void
 test_hexstr2bin (void)
 {
 	static const HexItem items[] = {
@@ -4227,6 +4320,138 @@ test_nm_utils_ascii_str_to_int64 (void)
 
 /******************************************************************************/
 
+static void
+test_nm_utils_strstrdictkey (void)
+{
+#define _VALUES_STATIC(_v1, _v2) { .v1 = _v1, .v2 = _v2, .v_static = _nm_utils_strstrdictkey_static (_v1, _v2), }
+	const struct {
+		const char *v1;
+		const char *v2;
+		NMUtilsStrStrDictKey *v_static;
+	} *val1, *val2, values[] = {
+		{ NULL, NULL },
+		{ "", NULL },
+		{ NULL, "" },
+		{ "a", NULL },
+		{ NULL, "a" },
+		_VALUES_STATIC ("", ""),
+		_VALUES_STATIC ("a", ""),
+		_VALUES_STATIC ("", "a"),
+		_VALUES_STATIC ("a", "b"),
+	};
+	guint i, j;
+
+	for (i = 0; i < G_N_ELEMENTS (values); i++) {
+		gs_free NMUtilsStrStrDictKey *key1 = NULL;
+
+		val1 = &values[i];
+
+		key1 = _nm_utils_strstrdictkey_create (val1->v1, val1->v2);
+		if (val1->v_static) {
+			g_assert (_nm_utils_strstrdictkey_equal (key1, val1->v_static));
+			g_assert (_nm_utils_strstrdictkey_equal (val1->v_static, key1));
+			g_assert_cmpint (_nm_utils_strstrdictkey_hash (key1), ==, _nm_utils_strstrdictkey_hash (val1->v_static));
+		}
+
+		for (j = 0; j < G_N_ELEMENTS (values); j++) {
+			gs_free NMUtilsStrStrDictKey *key2 = NULL;
+
+			val2 = &values[j];
+			key2 = _nm_utils_strstrdictkey_create (val2->v1, val2->v2);
+			if (i != j) {
+				g_assert (!_nm_utils_strstrdictkey_equal (key1, key2));
+				g_assert (!_nm_utils_strstrdictkey_equal (key2, key1));
+			}
+		}
+	}
+}
+
+/******************************************************************************/
+
+static void
+test_nm_utils_dns_option_validate_do (char *option, gboolean ipv6, const NMUtilsDNSOptionDesc *descs,
+                                      gboolean exp_result, char *exp_name, gboolean exp_value)
+{
+	char *name;
+	long value = 0;
+	gboolean result;
+
+	result = _nm_utils_dns_option_validate (option, &name, &value, ipv6, descs);
+
+	g_assert (result == exp_result);
+	g_assert_cmpstr (name, ==, exp_name);
+	g_assert (value == exp_value);
+
+	g_free (name);
+}
+
+static const NMUtilsDNSOptionDesc opt_descs[] = {
+	/* name                   num      ipv6 */
+	{ "opt1",                 FALSE,   FALSE },
+	{ "opt2",                 TRUE,    FALSE },
+	{ "opt3",                 FALSE,   TRUE  },
+	{ "opt4",                 TRUE,    TRUE  },
+	{ NULL,                   FALSE,   FALSE }
+};
+
+static void
+test_nm_utils_dns_option_validate (void)
+{
+	/*                                    opt            ipv6    descs        result name       value */
+	test_nm_utils_dns_option_validate_do ("",            FALSE,  NULL,        FALSE, NULL,      -1);
+	test_nm_utils_dns_option_validate_do (":",           FALSE,  NULL,        FALSE, NULL,      -1);
+	test_nm_utils_dns_option_validate_do (":1",          FALSE,  NULL,        FALSE, NULL,      -1);
+	test_nm_utils_dns_option_validate_do (":val",        FALSE,  NULL,        FALSE, NULL,      -1);
+	test_nm_utils_dns_option_validate_do ("opt",         FALSE,  NULL,        TRUE,  "opt",     -1);
+	test_nm_utils_dns_option_validate_do ("opt:",        FALSE,  NULL,        FALSE, NULL,      -1);
+	test_nm_utils_dns_option_validate_do ("opt:12",      FALSE,  NULL,        TRUE,  "opt",     12);
+	test_nm_utils_dns_option_validate_do ("opt:12 ",     FALSE,  NULL,        FALSE, NULL,      -1);
+	test_nm_utils_dns_option_validate_do ("opt:val",     FALSE,  NULL,        FALSE, NULL,      -1);
+	test_nm_utils_dns_option_validate_do ("opt:2val",    FALSE,  NULL,        FALSE, NULL,      -1);
+	test_nm_utils_dns_option_validate_do ("opt:2:3",     FALSE,  NULL,        FALSE, NULL,      -1);
+	test_nm_utils_dns_option_validate_do ("opt-6",       FALSE,  NULL,        TRUE,  "opt-6",   -1);
+
+	test_nm_utils_dns_option_validate_do ("opt1",        FALSE,  opt_descs,   TRUE,  "opt1",    -1);
+	test_nm_utils_dns_option_validate_do ("opt1",        TRUE,   opt_descs,   TRUE,  "opt1",    -1);
+	test_nm_utils_dns_option_validate_do ("opt1:3",      FALSE,  opt_descs,   FALSE,  NULL,     -1);
+
+	test_nm_utils_dns_option_validate_do ("opt2",        FALSE,  opt_descs,   FALSE, NULL,      -1);
+	test_nm_utils_dns_option_validate_do ("opt2:5",      FALSE,  opt_descs,   TRUE,  "opt2",    5);
+
+	test_nm_utils_dns_option_validate_do ("opt3",        FALSE,  opt_descs,   FALSE, NULL,      -1);
+	test_nm_utils_dns_option_validate_do ("opt3",        TRUE,   opt_descs,   TRUE,  "opt3",    -1);
+
+	test_nm_utils_dns_option_validate_do ("opt4",        FALSE,  opt_descs,   FALSE, NULL,      -1);
+	test_nm_utils_dns_option_validate_do ("opt4",        TRUE,   opt_descs,   FALSE, NULL,      -1);
+	test_nm_utils_dns_option_validate_do ("opt4:40",     FALSE,  opt_descs,   FALSE, NULL,      -1);
+	test_nm_utils_dns_option_validate_do ("opt4:40",     TRUE,   opt_descs,   TRUE,  "opt4",    40);
+}
+
+static void
+test_nm_utils_dns_option_find_idx (void)
+{
+	GPtrArray *options;
+
+	options = g_ptr_array_new ();
+
+	g_ptr_array_add (options, "debug");
+	g_ptr_array_add (options, "timeout:5");
+	g_ptr_array_add (options, "edns0");
+
+	g_assert_cmpint (_nm_utils_dns_option_find_idx (options, "debug"),      ==, 0);
+	g_assert_cmpint (_nm_utils_dns_option_find_idx (options, "debug:1"),    ==, 0);
+	g_assert_cmpint (_nm_utils_dns_option_find_idx (options, "timeout"),    ==, 1);
+	g_assert_cmpint (_nm_utils_dns_option_find_idx (options, "timeout:5"),  ==, 1);
+	g_assert_cmpint (_nm_utils_dns_option_find_idx (options, "timeout:2"),  ==, 1);
+	g_assert_cmpint (_nm_utils_dns_option_find_idx (options, "edns0"),      ==, 2);
+	g_assert_cmpint (_nm_utils_dns_option_find_idx (options, "rotate"),     ==, -1);
+	g_assert_cmpint (_nm_utils_dns_option_find_idx (options, ""),           ==, -1);
+
+	g_ptr_array_free (options, TRUE);
+}
+
+/******************************************************************************/
+
 enum TEST_IS_POWER_OF_TWP_ENUM_SIGNED {
 	_DUMMY_1 = -1,
 };
@@ -4349,6 +4574,41 @@ test_g_ptr_array_insert (void)
 
 /******************************************************************************/
 
+static void
+test_g_hash_table_get_keys_as_array (void)
+{
+	GHashTable *table = g_hash_table_new (g_str_hash, g_str_equal);
+	guint length = 0;
+	char **keys;
+
+	g_hash_table_insert (table, "one",   "1");
+	g_hash_table_insert (table, "two",   "2");
+	g_hash_table_insert (table, "three", "3");
+
+	keys = (char **) _nm_g_hash_table_get_keys_as_array (table, &length);
+	g_assert (keys);
+	g_assert_cmpuint (length, ==, 3);
+
+	g_assert (   !strcmp (keys[0], "one")
+	          || !strcmp (keys[1], "one")
+	          || !strcmp (keys[2], "one"));
+
+	g_assert (   !strcmp (keys[0], "two")
+	          || !strcmp (keys[1], "two")
+	          || !strcmp (keys[2], "two"));
+
+	g_assert (   !strcmp (keys[0], "three")
+	          || !strcmp (keys[1], "three")
+	          || !strcmp (keys[2], "three"));
+
+	g_assert (!keys[3]);
+
+	g_free (keys);
+	g_hash_table_unref (table);
+}
+
+/******************************************************************************/
+
 static int
 _test_find_binary_search_cmp (gconstpointer a, gconstpointer b, gpointer dummy)
 {
@@ -4452,6 +4712,101 @@ test_nm_utils_ptrarray_find_binary_search (void)
 }
 
 /******************************************************************************/
+static void
+test_nm_utils_enum_from_str_do (GType type, const char *str,
+                                gboolean exp_result, int exp_flags,
+                                const char *exp_err_token)
+{
+	int flags = 1;
+	char *err_token = NULL;
+	gboolean result;
+
+	result = nm_utils_enum_from_str (type, str, &flags, &err_token);
+
+	g_assert (result == exp_result);
+	g_assert_cmpint (flags, ==, exp_flags);
+	g_assert_cmpstr (err_token, ==, exp_err_token);
+
+	g_free (err_token);
+}
+
+static void
+test_nm_utils_enum_to_str_do (GType type, int flags, const char *exp_str)
+{
+	char *str;
+
+	str = nm_utils_enum_to_str (type, flags);
+	g_assert_cmpstr (str, ==, exp_str);
+	g_free (str);
+}
+
+static void
+test_nm_utils_enum_get_values_do (GType type, int from, int to, const char *exp_str)
+{
+	const char **strv;
+	char *str;
+
+	strv = nm_utils_enum_get_values (type, from, to);
+	g_assert (strv);
+	str = g_strjoinv (",", (char **) strv);
+	g_assert_cmpstr (str, ==, exp_str);
+	g_free (str);
+	g_free (strv);
+}
+
+
+static void test_nm_utils_enum (void)
+{
+	GType bool_enum = nm_test_general_bool_enum_get_type();
+	GType meta_flags = nm_test_general_meta_flags_get_type();
+	GType color_flags = nm_test_general_color_flags_get_type();
+
+	test_nm_utils_enum_to_str_do (bool_enum, NM_TEST_GENERAL_BOOL_ENUM_YES, "yes");
+	test_nm_utils_enum_to_str_do (bool_enum, NM_TEST_GENERAL_BOOL_ENUM_UNKNOWN, "unknown");
+	test_nm_utils_enum_to_str_do (bool_enum, NM_TEST_GENERAL_BOOL_ENUM_INVALID, NULL);
+
+	test_nm_utils_enum_to_str_do (meta_flags, NM_TEST_GENERAL_META_FLAGS_NONE, "");
+	test_nm_utils_enum_to_str_do (meta_flags, NM_TEST_GENERAL_META_FLAGS_BAZ, "baz");
+	test_nm_utils_enum_to_str_do (meta_flags, NM_TEST_GENERAL_META_FLAGS_FOO |
+	                                          NM_TEST_GENERAL_META_FLAGS_BAR |
+	                                          NM_TEST_GENERAL_META_FLAGS_BAZ, "foo, bar, baz");
+
+	test_nm_utils_enum_to_str_do (color_flags, NM_TEST_GENERAL_COLOR_FLAGS_RED, "red");
+	test_nm_utils_enum_to_str_do (color_flags, NM_TEST_GENERAL_COLOR_FLAGS_WHITE, "");
+	test_nm_utils_enum_to_str_do (color_flags, NM_TEST_GENERAL_COLOR_FLAGS_RED |
+	                                           NM_TEST_GENERAL_COLOR_FLAGS_GREEN, "red, green");
+
+	test_nm_utils_enum_from_str_do (bool_enum, "", FALSE, 0, NULL);
+	test_nm_utils_enum_from_str_do (bool_enum, " ", FALSE, 0, NULL);
+	test_nm_utils_enum_from_str_do (bool_enum, "invalid", FALSE, 0, NULL);
+	test_nm_utils_enum_from_str_do (bool_enum, "yes", TRUE, NM_TEST_GENERAL_BOOL_ENUM_YES, NULL);
+	test_nm_utils_enum_from_str_do (bool_enum, "no", TRUE, NM_TEST_GENERAL_BOOL_ENUM_NO, NULL);
+	test_nm_utils_enum_from_str_do (bool_enum, "yes,no", FALSE, 0, NULL);
+
+	test_nm_utils_enum_from_str_do (meta_flags, "", TRUE, 0, NULL);
+	test_nm_utils_enum_from_str_do (meta_flags, " ", TRUE, 0, NULL);
+	test_nm_utils_enum_from_str_do (meta_flags, "foo", TRUE, NM_TEST_GENERAL_META_FLAGS_FOO, NULL);
+	test_nm_utils_enum_from_str_do (meta_flags, "foo,baz", TRUE, NM_TEST_GENERAL_META_FLAGS_FOO |
+	                                                             NM_TEST_GENERAL_META_FLAGS_BAZ, NULL);
+	test_nm_utils_enum_from_str_do (meta_flags, "foo, baz", TRUE, NM_TEST_GENERAL_META_FLAGS_FOO |
+	                                                              NM_TEST_GENERAL_META_FLAGS_BAZ, NULL);
+	test_nm_utils_enum_from_str_do (meta_flags, "foo,,bar", TRUE, NM_TEST_GENERAL_META_FLAGS_FOO |
+	                                                              NM_TEST_GENERAL_META_FLAGS_BAR, NULL);
+	test_nm_utils_enum_from_str_do (meta_flags, "foo,baz,quux,bar", FALSE, 0, "quux");
+
+	test_nm_utils_enum_from_str_do (color_flags, "green", TRUE, NM_TEST_GENERAL_COLOR_FLAGS_GREEN, NULL);
+	test_nm_utils_enum_from_str_do (color_flags, "blue,red", TRUE, NM_TEST_GENERAL_COLOR_FLAGS_BLUE |
+	                                                               NM_TEST_GENERAL_COLOR_FLAGS_RED, NULL);
+	test_nm_utils_enum_from_str_do (color_flags, "blue,white", FALSE, 0, "white");
+
+	test_nm_utils_enum_get_values_do (bool_enum, 0, G_MAXINT, "no,yes,maybe,unknown");
+	test_nm_utils_enum_get_values_do (bool_enum, NM_TEST_GENERAL_BOOL_ENUM_YES,
+	                                  NM_TEST_GENERAL_BOOL_ENUM_MAYBE, "yes,maybe");
+	test_nm_utils_enum_get_values_do (meta_flags, 0, G_MAXINT, "none,foo,bar,baz");
+	test_nm_utils_enum_get_values_do (color_flags, 0, G_MAXINT, "blue,red,green");
+}
+
+/******************************************************************************/
 
 static int
 _test_nm_in_set_get (int *call_counter, gboolean allow_called, int value)
@@ -4540,81 +4895,6 @@ test_nm_in_set (void)
 
 /******************************************************************************/
 
-static void
-test_nm_utils_enum_from_str_do (GType type, const char *str,
-                                gboolean exp_result, int exp_flags,
-                                const char *exp_err_token)
-{
-	int flags = 1;
-	char *err_token = NULL;
-	gboolean result;
-
-	result = nm_utils_enum_from_str (type, str, &flags, &err_token);
-
-	g_assert (result == exp_result);
-	g_assert_cmpint (flags, ==, exp_flags);
-	g_assert_cmpstr (err_token, ==, exp_err_token);
-
-	g_free (err_token);
-}
-
-static void
-test_nm_utils_enum_to_str_do (GType type, int flags, const char *exp_str)
-{
-	char *str;
-
-	str = nm_utils_enum_to_str (type, flags);
-	g_assert_cmpstr (str, ==, exp_str);
-	g_free (str);
-}
-
-static void test_nm_utils_enum (void)
-{
-	GType bool_enum = nm_test_general_bool_enum_get_type();
-	GType meta_flags = nm_test_general_meta_flags_get_type();
-	GType color_flags = nm_test_general_color_flags_get_type();
-
-	test_nm_utils_enum_to_str_do (bool_enum, NM_TEST_GENERAL_BOOL_ENUM_YES, "yes");
-	test_nm_utils_enum_to_str_do (bool_enum, NM_TEST_GENERAL_BOOL_ENUM_UNKNOWN, "unknown");
-	test_nm_utils_enum_to_str_do (bool_enum, NM_TEST_GENERAL_BOOL_ENUM_INVALID, NULL);
-
-	test_nm_utils_enum_to_str_do (meta_flags, NM_TEST_GENERAL_META_FLAGS_NONE, "");
-	test_nm_utils_enum_to_str_do (meta_flags, NM_TEST_GENERAL_META_FLAGS_BAZ, "baz");
-	test_nm_utils_enum_to_str_do (meta_flags, NM_TEST_GENERAL_META_FLAGS_FOO |
-	                                          NM_TEST_GENERAL_META_FLAGS_BAR |
-	                                          NM_TEST_GENERAL_META_FLAGS_BAZ, "foo, bar, baz");
-
-	test_nm_utils_enum_to_str_do (color_flags, NM_TEST_GENERAL_COLOR_FLAGS_RED, "red");
-	test_nm_utils_enum_to_str_do (color_flags, NM_TEST_GENERAL_COLOR_FLAGS_WHITE, "");
-	test_nm_utils_enum_to_str_do (color_flags, NM_TEST_GENERAL_COLOR_FLAGS_RED |
-	                                           NM_TEST_GENERAL_COLOR_FLAGS_GREEN, "red, green");
-
-	test_nm_utils_enum_from_str_do (bool_enum, "", FALSE, 0, NULL);
-	test_nm_utils_enum_from_str_do (bool_enum, " ", FALSE, 0, NULL);
-	test_nm_utils_enum_from_str_do (bool_enum, "invalid", FALSE, 0, NULL);
-	test_nm_utils_enum_from_str_do (bool_enum, "yes", TRUE, NM_TEST_GENERAL_BOOL_ENUM_YES, NULL);
-	test_nm_utils_enum_from_str_do (bool_enum, "no", TRUE, NM_TEST_GENERAL_BOOL_ENUM_NO, NULL);
-	test_nm_utils_enum_from_str_do (bool_enum, "yes,no", FALSE, 0, NULL);
-
-	test_nm_utils_enum_from_str_do (meta_flags, "", TRUE, 0, NULL);
-	test_nm_utils_enum_from_str_do (meta_flags, " ", TRUE, 0, NULL);
-	test_nm_utils_enum_from_str_do (meta_flags, "foo", TRUE, NM_TEST_GENERAL_META_FLAGS_FOO, NULL);
-	test_nm_utils_enum_from_str_do (meta_flags, "foo,baz", TRUE, NM_TEST_GENERAL_META_FLAGS_FOO |
-	                                                             NM_TEST_GENERAL_META_FLAGS_BAZ, NULL);
-	test_nm_utils_enum_from_str_do (meta_flags, "foo, baz", TRUE, NM_TEST_GENERAL_META_FLAGS_FOO |
-	                                                              NM_TEST_GENERAL_META_FLAGS_BAZ, NULL);
-	test_nm_utils_enum_from_str_do (meta_flags, "foo,,bar", TRUE, NM_TEST_GENERAL_META_FLAGS_FOO |
-	                                                              NM_TEST_GENERAL_META_FLAGS_BAR, NULL);
-	test_nm_utils_enum_from_str_do (meta_flags, "foo,baz,quux,bar", FALSE, 0, "quux");
-
-	test_nm_utils_enum_from_str_do (color_flags, "green", TRUE, NM_TEST_GENERAL_COLOR_FLAGS_GREEN, NULL);
-	test_nm_utils_enum_from_str_do (color_flags, "blue,red", TRUE, NM_TEST_GENERAL_COLOR_FLAGS_BLUE |
-	                                                               NM_TEST_GENERAL_COLOR_FLAGS_RED, NULL);
-	test_nm_utils_enum_from_str_do (color_flags, "blue,white", FALSE, 0, "white");
-}
-
-/******************************************************************************/
-
 NMTST_DEFINE ();
 
 int main (int argc, char **argv)
@@ -4632,6 +4912,7 @@ int main (int argc, char **argv)
 	g_test_add_func ("/core/general/test_setting_gsm_apn_bad_chars", test_setting_gsm_apn_bad_chars);
 	g_test_add_func ("/core/general/test_setting_gsm_apn_underscore", test_setting_gsm_apn_underscore);
 	g_test_add_func ("/core/general/test_setting_gsm_without_number", test_setting_gsm_without_number);
+	g_test_add_func ("/core/general/test_setting_gsm_sim_operator_id", test_setting_gsm_sim_operator_id);
 	g_test_add_func ("/core/general/test_setting_to_dbus_all", test_setting_to_dbus_all);
 	g_test_add_func ("/core/general/test_setting_to_dbus_no_secrets", test_setting_to_dbus_no_secrets);
 	g_test_add_func ("/core/general/test_setting_to_dbus_only_secrets", test_setting_to_dbus_only_secrets);
@@ -4710,6 +4991,7 @@ int main (int argc, char **argv)
 	g_test_add_func ("/core/general/test_setting_802_1x_changed_signal", test_setting_802_1x_changed_signal);
 	g_test_add_func ("/core/general/test_setting_ip4_gateway", test_setting_ip4_gateway);
 	g_test_add_func ("/core/general/test_setting_ip6_gateway", test_setting_ip6_gateway);
+	g_test_add_func ("/core/general/test_setting_compare_default_strv", test_setting_compare_default_strv);
 
 	g_test_add_func ("/core/general/hexstr2bin", test_hexstr2bin);
 	g_test_add_func ("/core/general/test_nm_utils_uuid_generate_from_string", test_nm_utils_uuid_generate_from_string);
@@ -4718,7 +5000,12 @@ int main (int argc, char **argv)
 	g_test_add_func ("/core/general/_nm_utils_ascii_str_to_int64", test_nm_utils_ascii_str_to_int64);
 	g_test_add_func ("/core/general/nm_utils_is_power_of_two", test_nm_utils_is_power_of_two);
 	g_test_add_func ("/core/general/_glib_compat_g_ptr_array_insert", test_g_ptr_array_insert);
+	g_test_add_func ("/core/general/_glib_compat_g_hash_table_get_keys_as_array", test_g_hash_table_get_keys_as_array);
 	g_test_add_func ("/core/general/_nm_utils_ptrarray_find_binary_search", test_nm_utils_ptrarray_find_binary_search);
+	g_test_add_func ("/core/general/_nm_utils_strstrdictkey", test_nm_utils_strstrdictkey);
+
+	g_test_add_func ("/core/general/_nm_utils_dns_option_validate", test_nm_utils_dns_option_validate);
+	g_test_add_func ("/core/general/_nm_utils_dns_option_find_idx", test_nm_utils_dns_option_find_idx);
 
 	g_test_add_func ("/core/general/test_nm_utils_enum", test_nm_utils_enum);
 
diff --git a/libnm-core/tests/test-secrets.c b/libnm-core/tests/test-secrets.c
index 178fddd5..4c0c7f5d 100644
--- a/libnm-core/tests/test-secrets.c
+++ b/libnm-core/tests/test-secrets.c
@@ -21,9 +21,9 @@
 
 #include "config.h"
 
-#include <glib.h>
 #include <string.h>
 
+#include "nm-default.h"
 #include "nm-setting-8021x.h"
 #include "nm-setting-cdma.h"
 #include "nm-setting-connection.h"
diff --git a/libnm-core/tests/test-setting-8021x.c b/libnm-core/tests/test-setting-8021x.c
index 16f6016e..49d7448e 100644
--- a/libnm-core/tests/test-setting-8021x.c
+++ b/libnm-core/tests/test-setting-8021x.c
@@ -21,11 +21,11 @@
 
 #include "config.h"
 
-#include <glib.h>
 #include <string.h>
 
 #include <nm-utils.h>
 
+#include "nm-default.h"
 #include "nm-setting-connection.h"
 #include "nm-setting-8021x.h"
 
diff --git a/libnm-core/tests/test-setting-dcb.c b/libnm-core/tests/test-setting-dcb.c
index f7554e81..f8b789c1 100644
--- a/libnm-core/tests/test-setting-dcb.c
+++ b/libnm-core/tests/test-setting-dcb.c
@@ -21,14 +21,14 @@
 
 #include "config.h"
 
-#include <glib.h>
 #include <string.h>
 #include <nm-utils.h>
-#include <nm-glib-compat.h>
+#include "nm-default.h"
 #include "nm-setting-dcb.h"
 #include "nm-connection.h"
 #include "nm-errors.h"
-#include "gsystem-local-alloc.h"
+
+#include "nm-test-utils.h"
 
 #define DCB_FLAGS_ALL (NM_SETTING_DCB_FLAG_ENABLE | \
                        NM_SETTING_DCB_FLAG_ADVERTISE | \
@@ -303,18 +303,12 @@ test_dcb_bandwidth_sums (void)
 
 #define TPATH "/libnm/settings/dcb/"
 
+NMTST_DEFINE ();
+
 int
 main (int argc, char **argv)
 {
-	g_test_init (&argc, &argv, NULL);
-
-#if !GLIB_CHECK_VERSION (2, 35, 0)
-	g_type_init ();
-#endif
-
-#if !GLIB_CHECK_VERSION(2,34,0)
-	g_log_set_always_fatal (G_LOG_LEVEL_CRITICAL);
-#endif
+	nmtst_init (&argc, &argv, TRUE);
 
 	g_test_add_func (TPATH "flags-valid", test_dcb_flags_valid);
 	g_test_add_func (TPATH "flags-invalid", test_dcb_flags_invalid);
diff --git a/libnm-core/tests/test-settings-defaults.c b/libnm-core/tests/test-settings-defaults.c
index 7d7715cb..21e16f3d 100644
--- a/libnm-core/tests/test-settings-defaults.c
+++ b/libnm-core/tests/test-settings-defaults.c
@@ -21,11 +21,11 @@
 
 #include "config.h"
 
-#include <glib.h>
 #include <string.h>
 
 #include <nm-utils.h>
 
+#include "nm-default.h"
 #include "nm-setting-8021x.h"
 #include "nm-setting-cdma.h"
 #include "nm-setting-connection.h"