summary refs log tree commit diff
path: root/libnm-glib
diff options
context:
space:
mode:
Diffstat (limited to 'libnm-glib')
-rw-r--r--libnm-glib/Makefile.am7
-rw-r--r--libnm-glib/Makefile.in38
-rw-r--r--libnm-glib/libnm-glib.ver11
-rw-r--r--libnm-glib/nm-access-point.c14
-rw-r--r--libnm-glib/nm-access-point.h1
-rw-r--r--libnm-glib/nm-active-connection.c14
-rw-r--r--libnm-glib/nm-client.c243
-rw-r--r--libnm-glib/nm-device-adsl.c245
-rw-r--r--libnm-glib/nm-device-adsl.h77
-rw-r--r--libnm-glib/nm-device-bond.c9
-rw-r--r--libnm-glib/nm-device-bt.c14
-rw-r--r--libnm-glib/nm-device-ethernet.c15
-rw-r--r--libnm-glib/nm-device-infiniband.c9
-rw-r--r--libnm-glib/nm-device-modem.c15
-rw-r--r--libnm-glib/nm-device-olpc-mesh.c14
-rw-r--r--libnm-glib/nm-device-vlan.c9
-rw-r--r--libnm-glib/nm-device-wifi.c14
-rw-r--r--libnm-glib/nm-device-wimax.c21
-rw-r--r--libnm-glib/nm-device.c177
-rw-r--r--libnm-glib/nm-device.h7
-rw-r--r--libnm-glib/nm-dhcp4-config.c2
-rw-r--r--libnm-glib/nm-dhcp6-config.c2
-rw-r--r--libnm-glib/nm-glib-enum-types.c41
-rw-r--r--libnm-glib/nm-glib-enum-types.h4
-rw-r--r--libnm-glib/nm-glib-marshal.c45
-rw-r--r--libnm-glib/nm-glib-marshal.h14
-rw-r--r--libnm-glib/nm-ip4-config.c2
-rw-r--r--libnm-glib/nm-ip6-config.c2
-rw-r--r--libnm-glib/nm-object-cache.c25
-rw-r--r--libnm-glib/nm-object-cache.h1
-rw-r--r--libnm-glib/nm-object.c112
-rw-r--r--libnm-glib/nm-object.h27
-rw-r--r--libnm-glib/nm-remote-connection.c11
-rw-r--r--libnm-glib/nm-remote-connection.h30
-rw-r--r--libnm-glib/nm-remote-settings.c138
-rw-r--r--libnm-glib/nm-secret-agent.c42
-rw-r--r--libnm-glib/nm-secret-agent.h7
-rw-r--r--libnm-glib/nm-vpn-connection.c2
-rw-r--r--libnm-glib/nm-vpn-plugin-ui-interface.h1
-rw-r--r--libnm-glib/nm-vpn-plugin-utils.c3
-rw-r--r--libnm-glib/nm-vpn-plugin.c400
-rw-r--r--libnm-glib/nm-vpn-plugin.h48
-rw-r--r--libnm-glib/nm-wimax-nsp.c14
-rw-r--r--libnm-glib/tests/Makefile.in11
44 files changed, 1526 insertions, 412 deletions
diff --git a/libnm-glib/Makefile.am b/libnm-glib/Makefile.am
index b2ea3b79..89ed3c5e 100644
--- a/libnm-glib/Makefile.am
+++ b/libnm-glib/Makefile.am
@@ -59,6 +59,7 @@ libnminclude_HEADERS = \
 	nm-device.h \
 	nm-device-ethernet.h \
 	nm-device-infiniband.h \
+	nm-device-adsl.h \
 	nm-device-wifi.h \
 	nm-device-bt.h \
 	nm-device-olpc-mesh.h \
@@ -92,6 +93,7 @@ libnm_glib_la_csources = \
 	nm-device.c \
 	nm-device-ethernet.c \
 	nm-device-infiniband.c \
+	nm-device-adsl.c \
 	nm-device-wifi.c \
 	nm-device-bt.c \
 	nm-device-olpc-mesh.c \
@@ -215,10 +217,11 @@ introspection_sources = $(libnminclude_HEADERS) $(libnm_glib_la_csources)
 NMClient-1.0.gir: libnm-glib.la
 NMClient_1_0_gir_INCLUDES = Gio-2.0 DBusGLib-1.0
 NMClient_1_0_gir_PACKAGES = gio-2.0 dbus-glib-1 gudev-1.0
+NMClient_1_0_gir_EXPORT_PACKAGES = libnm-glib libnm-glib-vpn
 NMClient_1_0_gir_CFLAGS = $(INCLUDES) -I$(top_srcdir)/libnm-glib -I$(top_srcdir)/libnm-util
-NMClient_1_0_gir_LIBS = libnm-glib.la
+NMClient_1_0_gir_LIBS = libnm-glib.la $(top_builddir)/libnm-util/libnm-util.la
 NMClient_1_0_gir_FILES = $(introspection_sources)
-NMClient_1_0_gir_SCANNERFLAGS = --warn-all --identifier-prefix=NM --symbol-prefix=nm_ --include-uninstalled=$(top_builddir)/libnm-util/NetworkManager-1.0.gir
+NMClient_1_0_gir_SCANNERFLAGS = --warn-all --identifier-prefix=NM --symbol-prefix=nm --include-uninstalled=$(top_builddir)/libnm-util/NetworkManager-1.0.gir
 INTROSPECTION_GIRS += NMClient-1.0.gir
 
 girdir = $(datadir)/gir-1.0
diff --git a/libnm-glib/Makefile.in b/libnm-glib/Makefile.in
index 5a013e87..b3535234 100644
--- a/libnm-glib/Makefile.in
+++ b/libnm-glib/Makefile.in
@@ -56,7 +56,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \
 	$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
 	$(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \
 	$(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \
-	$(top_srcdir)/configure.ac
+	$(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
 mkinstalldirs = $(install_sh) -d
@@ -108,6 +108,7 @@ am__objects_2 = libnm_glib_test_la-nm-object.lo \
 	libnm_glib_test_la-nm-device.lo \
 	libnm_glib_test_la-nm-device-ethernet.lo \
 	libnm_glib_test_la-nm-device-infiniband.lo \
+	libnm_glib_test_la-nm-device-adsl.lo \
 	libnm_glib_test_la-nm-device-wifi.lo \
 	libnm_glib_test_la-nm-device-bt.lo \
 	libnm_glib_test_la-nm-device-olpc-mesh.lo \
@@ -155,6 +156,7 @@ libnm_glib_la_DEPENDENCIES = $(top_builddir)/libnm-util/libnm-util.la \
 am__objects_4 = libnm_glib_la-nm-object.lo libnm_glib_la-nm-client.lo \
 	libnm_glib_la-nm-device.lo libnm_glib_la-nm-device-ethernet.lo \
 	libnm_glib_la-nm-device-infiniband.lo \
+	libnm_glib_la-nm-device-adsl.lo \
 	libnm_glib_la-nm-device-wifi.lo libnm_glib_la-nm-device-bt.lo \
 	libnm_glib_la-nm-device-olpc-mesh.lo \
 	libnm_glib_la-nm-device-bond.lo \
@@ -338,6 +340,10 @@ INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
 INTLTOOL_MERGE = @INTLTOOL_MERGE@
 INTLTOOL_PERL = @INTLTOOL_PERL@
 INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@
+INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@
+INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@
+INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@
 INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
 INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@
 INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@
@@ -433,6 +439,9 @@ UDEV_BASE_DIR = @UDEV_BASE_DIR@
 USE_NLS = @USE_NLS@
 UUID_CFLAGS = @UUID_CFLAGS@
 UUID_LIBS = @UUID_LIBS@
+VAPIGEN = @VAPIGEN@
+VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@
+VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@
 VERSION = @VERSION@
 XGETTEXT = @XGETTEXT@
 XGETTEXT_015 = @XGETTEXT_015@
@@ -471,6 +480,8 @@ htmldir = @htmldir@
 includedir = @includedir@
 infodir = @infodir@
 install_sh = @install_sh@
+intltool__v_merge_options_ = @intltool__v_merge_options_@
+intltool__v_merge_options_0 = @intltool__v_merge_options_0@
 libdir = @libdir@
 libexecdir = @libexecdir@
 localedir = @localedir@
@@ -543,6 +554,7 @@ libnminclude_HEADERS = \
 	nm-device.h \
 	nm-device-ethernet.h \
 	nm-device-infiniband.h \
+	nm-device-adsl.h \
 	nm-device-wifi.h \
 	nm-device-bt.h \
 	nm-device-olpc-mesh.h \
@@ -576,6 +588,7 @@ libnm_glib_la_csources = \
 	nm-device.c \
 	nm-device-ethernet.c \
 	nm-device-infiniband.c \
+	nm-device-adsl.c \
 	nm-device-wifi.c \
 	nm-device-bt.c \
 	nm-device-olpc-mesh.c \
@@ -674,10 +687,11 @@ INTROSPECTION_COMPILER_ARGS = --includedir=$(top_builddir)/libnm-util
 @HAVE_INTROSPECTION_TRUE@introspection_sources = $(libnminclude_HEADERS) $(libnm_glib_la_csources)
 @HAVE_INTROSPECTION_TRUE@NMClient_1_0_gir_INCLUDES = Gio-2.0 DBusGLib-1.0
 @HAVE_INTROSPECTION_TRUE@NMClient_1_0_gir_PACKAGES = gio-2.0 dbus-glib-1 gudev-1.0
+@HAVE_INTROSPECTION_TRUE@NMClient_1_0_gir_EXPORT_PACKAGES = libnm-glib libnm-glib-vpn
 @HAVE_INTROSPECTION_TRUE@NMClient_1_0_gir_CFLAGS = $(INCLUDES) -I$(top_srcdir)/libnm-glib -I$(top_srcdir)/libnm-util
-@HAVE_INTROSPECTION_TRUE@NMClient_1_0_gir_LIBS = libnm-glib.la
+@HAVE_INTROSPECTION_TRUE@NMClient_1_0_gir_LIBS = libnm-glib.la $(top_builddir)/libnm-util/libnm-util.la
 @HAVE_INTROSPECTION_TRUE@NMClient_1_0_gir_FILES = $(introspection_sources)
-@HAVE_INTROSPECTION_TRUE@NMClient_1_0_gir_SCANNERFLAGS = --warn-all --identifier-prefix=NM --symbol-prefix=nm_ --include-uninstalled=$(top_builddir)/libnm-util/NetworkManager-1.0.gir
+@HAVE_INTROSPECTION_TRUE@NMClient_1_0_gir_SCANNERFLAGS = --warn-all --identifier-prefix=NM --symbol-prefix=nm --include-uninstalled=$(top_builddir)/libnm-util/NetworkManager-1.0.gir
 @HAVE_INTROSPECTION_TRUE@girdir = $(datadir)/gir-1.0
 @HAVE_INTROSPECTION_TRUE@gir_DATA = $(INTROSPECTION_GIRS)
 @HAVE_INTROSPECTION_TRUE@typelibdir = $(libdir)/girepository-1.0
@@ -792,6 +806,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_la-nm-access-point.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_la-nm-active-connection.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_la-nm-client.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_la-nm-device-adsl.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_la-nm-device-bond.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_la-nm-device-bt.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_la-nm-device-ethernet.Plo@am__quote@
@@ -820,6 +835,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_test_la-nm-access-point.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_test_la-nm-active-connection.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_test_la-nm-client.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_test_la-nm-device-adsl.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_test_la-nm-device-bond.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_test_la-nm-device-bt.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_glib_test_la-nm-device-ethernet.Plo@am__quote@
@@ -924,6 +940,14 @@ libnm_glib_test_la-nm-device-infiniband.lo: nm-device-infiniband.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnm_glib_test_la_CFLAGS) $(CFLAGS) -c -o libnm_glib_test_la-nm-device-infiniband.lo `test -f 'nm-device-infiniband.c' || echo '$(srcdir)/'`nm-device-infiniband.c
 
+libnm_glib_test_la-nm-device-adsl.lo: nm-device-adsl.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) $(libnm_glib_test_la_CFLAGS) $(CFLAGS) -MT libnm_glib_test_la-nm-device-adsl.lo -MD -MP -MF $(DEPDIR)/libnm_glib_test_la-nm-device-adsl.Tpo -c -o libnm_glib_test_la-nm-device-adsl.lo `test -f 'nm-device-adsl.c' || echo '$(srcdir)/'`nm-device-adsl.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_glib_test_la-nm-device-adsl.Tpo $(DEPDIR)/libnm_glib_test_la-nm-device-adsl.Plo
+@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-device-adsl.c' object='libnm_glib_test_la-nm-device-adsl.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnm_glib_test_la_CFLAGS) $(CFLAGS) -c -o libnm_glib_test_la-nm-device-adsl.lo `test -f 'nm-device-adsl.c' || echo '$(srcdir)/'`nm-device-adsl.c
+
 libnm_glib_test_la-nm-device-wifi.lo: nm-device-wifi.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) $(libnm_glib_test_la_CFLAGS) $(CFLAGS) -MT libnm_glib_test_la-nm-device-wifi.lo -MD -MP -MF $(DEPDIR)/libnm_glib_test_la-nm-device-wifi.Tpo -c -o libnm_glib_test_la-nm-device-wifi.lo `test -f 'nm-device-wifi.c' || echo '$(srcdir)/'`nm-device-wifi.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_glib_test_la-nm-device-wifi.Tpo $(DEPDIR)/libnm_glib_test_la-nm-device-wifi.Plo
@@ -1172,6 +1196,14 @@ libnm_glib_la-nm-device-infiniband.lo: nm-device-infiniband.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnm_glib_la_CFLAGS) $(CFLAGS) -c -o libnm_glib_la-nm-device-infiniband.lo `test -f 'nm-device-infiniband.c' || echo '$(srcdir)/'`nm-device-infiniband.c
 
+libnm_glib_la-nm-device-adsl.lo: nm-device-adsl.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) $(libnm_glib_la_CFLAGS) $(CFLAGS) -MT libnm_glib_la-nm-device-adsl.lo -MD -MP -MF $(DEPDIR)/libnm_glib_la-nm-device-adsl.Tpo -c -o libnm_glib_la-nm-device-adsl.lo `test -f 'nm-device-adsl.c' || echo '$(srcdir)/'`nm-device-adsl.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_glib_la-nm-device-adsl.Tpo $(DEPDIR)/libnm_glib_la-nm-device-adsl.Plo
+@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-device-adsl.c' object='libnm_glib_la-nm-device-adsl.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnm_glib_la_CFLAGS) $(CFLAGS) -c -o libnm_glib_la-nm-device-adsl.lo `test -f 'nm-device-adsl.c' || echo '$(srcdir)/'`nm-device-adsl.c
+
 libnm_glib_la-nm-device-wifi.lo: nm-device-wifi.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) $(libnm_glib_la_CFLAGS) $(CFLAGS) -MT libnm_glib_la-nm-device-wifi.lo -MD -MP -MF $(DEPDIR)/libnm_glib_la-nm-device-wifi.Tpo -c -o libnm_glib_la-nm-device-wifi.lo `test -f 'nm-device-wifi.c' || echo '$(srcdir)/'`nm-device-wifi.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_glib_la-nm-device-wifi.Tpo $(DEPDIR)/libnm_glib_la-nm-device-wifi.Plo
diff --git a/libnm-glib/libnm-glib.ver b/libnm-glib/libnm-glib.ver
index 427e2484..4bcbfb0d 100644
--- a/libnm-glib/libnm-glib.ver
+++ b/libnm-glib/libnm-glib.ver
@@ -58,6 +58,11 @@ global:
 	nm_client_wwan_get_enabled;
 	nm_client_wwan_hardware_get_enabled;
 	nm_client_wwan_set_enabled;
+	nm_device_adsl_error_get_type;
+	nm_device_adsl_error_quark;
+	nm_device_adsl_get_carrier;
+	nm_device_adsl_get_type;
+	nm_device_adsl_new;
 	nm_device_bond_error_get_type;
 	nm_device_bond_error_quark;
 	nm_device_bond_get_carrier;
@@ -84,12 +89,15 @@ global:
 	nm_device_ethernet_new;
 	nm_device_filter_connections;
 	nm_device_get_active_connection;
+	nm_device_get_autoconnect;
 	nm_device_get_capabilities;
 	nm_device_get_device_type;
 	nm_device_get_dhcp4_config;
 	nm_device_get_dhcp6_config;
 	nm_device_get_driver;
+	nm_device_get_driver_version;
 	nm_device_get_firmware_missing;
+	nm_device_get_firmware_version;
 	nm_device_get_iface;
 	nm_device_get_ip4_config;
 	nm_device_get_ip6_config;
@@ -120,6 +128,7 @@ global:
 	nm_device_olpc_mesh_get_hw_address;
 	nm_device_olpc_mesh_get_type;
 	nm_device_olpc_mesh_new;
+	nm_device_set_autoconnect;
 	nm_device_vlan_error_get_type;
 	nm_device_vlan_error_quark;
 	nm_device_vlan_get_carrier;
@@ -177,6 +186,8 @@ global:
 	nm_ip6_config_new;
 	nm_ip6_route_object_array_get_type;
 	nm_object_array_get_type;
+	nm_object_error_get_type;
+	nm_object_error_quark;
 	nm_object_get_connection;
 	nm_object_get_path;
 	nm_object_get_type;
diff --git a/libnm-glib/nm-access-point.c b/libnm-glib/nm-access-point.c
index 53993b07..fef65575 100644
--- a/libnm-glib/nm-access-point.c
+++ b/libnm-glib/nm-access-point.c
@@ -25,6 +25,8 @@
 #include <string.h>
 #include <netinet/ether.h>
 
+#include "nm-glib-compat.h"
+
 #include <nm-connection.h>
 #include <nm-setting-connection.h>
 #include <nm-setting-wireless.h>
@@ -41,7 +43,6 @@ G_DEFINE_TYPE (NMAccessPoint, nm_access_point, NM_TYPE_OBJECT)
 #define NM_ACCESS_POINT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_ACCESS_POINT, NMAccessPointPrivate))
 
 typedef struct {
-	gboolean disposed;
 	DBusGProxy *proxy;
 
 	NM80211ApFlags flags;
@@ -431,14 +432,7 @@ dispose (GObject *object)
 {
 	NMAccessPointPrivate *priv = NM_ACCESS_POINT_GET_PRIVATE (object);
 
-	if (priv->disposed) {
-		G_OBJECT_CLASS (nm_access_point_parent_class)->dispose (object);
-		return;
-	}
-
-	priv->disposed = TRUE;
-
-	g_object_unref (priv->proxy);
+	g_clear_object (&priv->proxy);
 
 	G_OBJECT_CLASS (nm_access_point_parent_class)->dispose (object);
 }
@@ -464,6 +458,8 @@ get_property (GObject *object,
 {
 	NMAccessPoint *ap = NM_ACCESS_POINT (object);
 
+	_nm_object_ensure_inited (NM_OBJECT (object));
+
 	switch (prop_id) {
 	case PROP_FLAGS:
 		g_value_set_uint (value, nm_access_point_get_flags (ap));
diff --git a/libnm-glib/nm-access-point.h b/libnm-glib/nm-access-point.h
index 97bd9a25..ffbf63cc 100644
--- a/libnm-glib/nm-access-point.h
+++ b/libnm-glib/nm-access-point.h
@@ -27,6 +27,7 @@
 #include <glib.h>
 #include <glib-object.h>
 #include <NetworkManager.h>
+#include <nm-connection.h>
 #include "nm-object.h"
 
 G_BEGIN_DECLS
diff --git a/libnm-glib/nm-active-connection.c b/libnm-glib/nm-active-connection.c
index 59d8a6af..f170121b 100644
--- a/libnm-glib/nm-active-connection.c
+++ b/libnm-glib/nm-active-connection.c
@@ -49,7 +49,6 @@ G_DEFINE_TYPE_WITH_CODE (NMActiveConnection, nm_active_connection, NM_TYPE_OBJEC
 #define NM_ACTIVE_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_ACTIVE_CONNECTION, NMActiveConnectionPrivate))
 
 typedef struct {
-	gboolean disposed;
 	DBusGProxy *proxy;
 
 	char *connection;
@@ -357,18 +356,13 @@ dispose (GObject *object)
 {
 	NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (object);
 
-	if (priv->disposed) {
-		G_OBJECT_CLASS (nm_active_connection_parent_class)->dispose (object);
-		return;
-	}
-
-	priv->disposed = TRUE;
-
 	if (priv->devices) {
 		g_ptr_array_foreach (priv->devices, (GFunc) g_object_unref, NULL);
 		g_ptr_array_free (priv->devices, TRUE);
+		priv->devices = NULL;
 	}
-	g_object_unref (priv->proxy);
+
+	g_clear_object (&priv->proxy);
 
 	G_OBJECT_CLASS (nm_active_connection_parent_class)->dispose (object);
 }
@@ -394,6 +388,8 @@ get_property (GObject *object,
 {
 	NMActiveConnection *self = NM_ACTIVE_CONNECTION (object);
 
+	_nm_object_ensure_inited (NM_OBJECT (object));
+
 	switch (prop_id) {
 	case PROP_CONNECTION:
 		g_value_set_string (value, nm_active_connection_get_connection (self));
diff --git a/libnm-glib/nm-client.c b/libnm-glib/nm-client.c
index 937a1bf8..a21b8147 100644
--- a/libnm-glib/nm-client.c
+++ b/libnm-glib/nm-client.c
@@ -53,8 +53,6 @@ G_DEFINE_TYPE_WITH_CODE (NMClient, nm_client, NM_TYPE_OBJECT,
 #define NM_CLIENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_CLIENT, NMClientPrivate))
 
 typedef struct {
-	gboolean disposed;
-
 	DBusGProxy *client_proxy;
 	DBusGProxy *bus_proxy;
 	gboolean manager_running;
@@ -459,35 +457,56 @@ activate_info_complete (ActivateInfo *info,
 }
 
 static void
-recheck_pending_activations (NMClient *self)
+recheck_pending_activations (NMClient *self, const char *failed_path, GError *error)
 {
 	NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self);
 	GSList *iter;
 	const GPtrArray *active_connections;
+	gboolean found_in_active = FALSE;
+	gboolean found_in_pending = FALSE;
+	ActivateInfo *ainfo = NULL;
 	int i;
 
 	active_connections = nm_client_get_active_connections (self);
-	if (!active_connections)
-		return;
 
-	/* For each active connection, look for a pending activation that has
-	 * the active connection's object path, and call its callback.
+	/* For each pending activation, look for a active connection that has
+	 * the pending activation's object path, and call pending connection's
+	 * callback.
+	 * If the connection to activate doesn't make it to active_connections,
+	 * due to an error, we have to call the callback for failed_path.
 	 */
-	for (i = 0; i < active_connections->len; i++) {
-		NMActiveConnection *active = g_ptr_array_index (active_connections, i);
-		const char *active_path = nm_object_get_path (NM_OBJECT (active));
+	for (iter = priv->pending_activations; iter; iter = g_slist_next (iter)) {
+		ActivateInfo *info = iter->data;
+
+		if (!found_in_pending && failed_path && g_strcmp0 (failed_path, info->active_path) == 0) {
+			found_in_pending = TRUE;
+			ainfo = info;
+		}
 
-		for (iter = priv->pending_activations; iter; iter = g_slist_next (iter)) {
-			ActivateInfo *info = iter->data;
+		for (i = 0; active_connections && i < active_connections->len; i++) {
+			NMActiveConnection *active = g_ptr_array_index (active_connections, i);
+			const char *active_path = nm_object_get_path (NM_OBJECT (active));
+
+			if (!found_in_active && failed_path && g_strcmp0 (failed_path, active_path) == 0)
+				found_in_active = TRUE;
 
 			if (g_strcmp0 (info->active_path, active_path) == 0) {
-				/* Call the pending activation's callback and it all up*/
+				/* Call the pending activation's callback and it all up */
 				activate_info_complete (info, active, NULL);
 				activate_info_free (info);
 				break;
 			}
 		}
 	}
+
+	if (!found_in_active && found_in_pending) {
+		/* A newly activated connection failed due to some immediate error
+		 * and disappeared from active connection list.  Make sure the
+		 * callback gets called.
+		 */
+		activate_info_complete (ainfo, NULL, error);
+		activate_info_free (ainfo);
+	}
 }
 
 static void
@@ -508,7 +527,7 @@ activate_cb (DBusGProxy *proxy,
 		g_clear_error (&error);
 	} else {
 		info->active_path = path;
-		recheck_pending_activations (info->client);
+		recheck_pending_activations (info->client, NULL, NULL);
 	}
 }
 
@@ -587,7 +606,7 @@ add_activate_cb (DBusGProxy *proxy,
 	} else {
 		info->new_connection_path = connection_path;
 		info->active_path = active_path;
-		recheck_pending_activations (info->client);
+		recheck_pending_activations (info->client, NULL, NULL);
 	}
 }
 
@@ -653,7 +672,14 @@ nm_client_add_and_activate_connection (NMClient *client,
 static void
 active_connections_changed_cb (GObject *object, GParamSpec *pspec, gpointer user_data)
 {
-	recheck_pending_activations (NM_CLIENT (object));
+	recheck_pending_activations (NM_CLIENT (object), NULL, NULL);
+}
+
+static void
+object_creation_failed_cb (GObject *object, GError *error, char *failed_path)
+{
+	if (error)
+		recheck_pending_activations (NM_CLIENT (object), failed_path, error);
 }
 
 /**
@@ -692,7 +718,7 @@ nm_client_deactivate_connection (NMClient *client, NMActiveConnection *active)
  * Gets the active connections.
  *
  * Returns: (transfer none) (element-type NMClient.ActiveConnection): a #GPtrArray
-*  containing all the active #NMActiveConnection<!-- -->s.
+ *  containing all the active #NMActiveConnection<!-- -->s.
  * The returned array is owned by the client and should not be modified.
  **/
 const GPtrArray * 
@@ -1018,30 +1044,50 @@ nm_client_get_permission_result (NMClient *client, NMClientPermission permission
 /****************************************************************/
 
 static void
-free_object_array (GPtrArray **array)
+free_devices (NMClient *client, gboolean emit_signals)
 {
-	g_return_if_fail (array != NULL);
+	NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client);
+	GPtrArray *devices;
+	NMDevice *device;
+	int i;
+
+	if (!priv->devices)
+		return;
 
-	if (*array) {
-		g_ptr_array_foreach (*array, (GFunc) g_object_unref, NULL);
-		g_ptr_array_free (*array, TRUE);
-		*array = NULL;
+	devices = priv->devices;
+	priv->devices = NULL;
+	for (i = 0; i < devices->len; i++) {
+		device = devices->pdata[i];
+		if (emit_signals)
+			g_signal_emit (client, signals[DEVICE_REMOVED], 0, device);
+		g_object_unref (device);
 	}
+	g_ptr_array_free (devices, TRUE);
 }
 
 static void
-dispose_and_free_object_array (GPtrArray **array)
+free_active_connections (NMClient *client, gboolean emit_signals)
 {
-	g_return_if_fail (array != NULL);
+	NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client);
+	GPtrArray *active_connections;
+	NMActiveConnection *active_connection;
+	int i;
 
-	if (*array) {
-		/* The objects in the array may have circular refs with other
-		 * objects, which the caller will need to know to break by
-		 * calling this function rather than free_object_array().
-		 */
-		g_ptr_array_foreach (*array, (GFunc) g_object_run_dispose, NULL);
-		free_object_array (array);
+	if (!priv->active_connections)
+		return;
+
+	active_connections = priv->active_connections;
+	priv->active_connections = NULL;
+	for (i = 0; i < active_connections->len; i++) {
+		active_connection = active_connections->pdata[i];
+		/* Break circular refs */
+		g_object_run_dispose (G_OBJECT (active_connection));
+		g_object_unref (active_connection);
 	}
+	g_ptr_array_free (active_connections, TRUE);
+
+	if (emit_signals)
+		g_object_notify (G_OBJECT (client), NM_CLIENT_ACTIVE_CONNECTIONS);
 }
 
 static void
@@ -1088,8 +1134,8 @@ proxy_name_owner_changed (DBusGProxy *proxy,
 		_nm_object_queue_notify (NM_OBJECT (client), NM_CLIENT_MANAGER_RUNNING);
 		_nm_object_suppress_property_updates (NM_OBJECT (client), TRUE);
 		poke_wireless_devices_with_rf_status (client);
-		free_object_array (&priv->devices);
-		dispose_and_free_object_array (&priv->active_connections);
+		free_devices (client, TRUE);
+		free_active_connections (client, TRUE);
 		priv->wireless_enabled = FALSE;
 		priv->wireless_hw_enabled = FALSE;
 		priv->wwan_enabled = FALSE;
@@ -1098,6 +1144,11 @@ proxy_name_owner_changed (DBusGProxy *proxy,
 		priv->wimax_hw_enabled = FALSE;
 		g_free (priv->version);
 		priv->version = NULL;
+
+		/* Clear object cache to ensure bad refcounting by clients doesn't
+		 * keep objects in the cache.
+		 */
+		_nm_object_cache_clear (NM_OBJECT (client));
 	} else {
 		_nm_object_suppress_property_updates (NM_OBJECT (client), FALSE);
 		_nm_object_reload_properties_async (NM_OBJECT (client), updated_properties, client);
@@ -1241,6 +1292,104 @@ nm_client_new_finish (GAsyncResult *result, GError **error)
 		return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple));
 }
 
+/*
+ * Validate D-Bus object path.
+ * The function is copied and adjusted version of
+ * g_variant_serialiser_is_object_path() from glib.
+ * FIXME: The function can be replaced by g_variant_is_object_path()
+ * when we start using GLib >= 2.24
+ */
+static gboolean
+_nm_client_is_object_path (const char *string)
+{
+	gsize i;
+
+	if (!g_utf8_validate (string, -1, NULL))
+		return FALSE;
+
+	/* The path must begin with an ASCII '/' (integer 47) character */
+	if (string[0] != '/')
+		return FALSE;
+
+	for (i = 1; string[i]; i++) {
+		/* Each element must only contain the ASCII characters
+		 * "[A-Z][a-z][0-9]_"
+		 */
+		if (g_ascii_isalnum (string[i]) || string[i] == '_')
+			;
+		/* must consist of elements separated by slash characters. */
+		else if (string[i] == '/') {
+			/* No element may be the empty string. */
+			/* Multiple '/' characters cannot occur in sequence. */
+			if (string[i - 1] == '/')
+				return FALSE;
+		} else
+			return FALSE;
+	}
+
+	/* A trailing '/' character is not allowed unless the path is the
+	 * root path (a single '/' character).
+	 */
+	if (i > 1 && string[i - 1] == '/')
+		return FALSE;
+
+	return TRUE;
+}
+
+/*
+ * constructor() shouldn't be overriden in most cases, rather constructed()
+ * method is preferred and more useful.
+ * But, this serves as a workaround for bindings (use) calling the constructor()
+ * directly instead of nm_client_new() function, and neither providing
+ * construction properties. So, we fill "dbus-path" here if it was not specified
+ * (was set to default value (NULL)).
+ *
+ * It allows this python code:
+ * from gi.repository import NMClient
+ * nmclient = NMClient.Client()
+ * print nmclient.get_active_connections()
+ *
+ * instead of proper
+ * nmclient = NMClient.Client().new()
+ *
+ * Note:
+ * A nice overview of GObject construction is here:
+ * http://blogs.gnome.org/desrt/2012/02/26/a-gentle-introduction-to-gobject-construction
+ * It is much better explanation than the official docs
+ * http://developer.gnome.org/gobject/unstable/chapter-gobject.html#gobject-instantiation
+ */
+static GObject*
+constructor (GType type,
+             guint n_construct_params,
+             GObjectConstructParam *construct_params)
+{
+	GObject *object;
+	guint i;
+	const char *dbus_path;
+
+	for (i = 0; i < n_construct_params; i++) {
+		if (strcmp (construct_params[i].pspec->name, NM_OBJECT_DBUS_PATH) == 0) {
+			dbus_path = g_value_get_string (construct_params[i].value);
+			if (dbus_path == NULL) {
+				g_value_set_static_string (construct_params[i].value, NM_DBUS_PATH);
+			} else {
+				if (!_nm_client_is_object_path (dbus_path)) {
+					g_warning ("Passsed D-Bus object path '%s' is invalid; using default '%s' instead",
+					            dbus_path, NM_DBUS_PATH);
+					g_value_set_static_string (construct_params[i].value, NM_DBUS_PATH);
+				}
+			}
+			break;
+		}
+	}
+
+	object = G_OBJECT_CLASS (nm_client_parent_class)->constructor (type,
+	                                                               n_construct_params,
+	                                                               construct_params);
+
+	return object;
+}
+
 static void
 constructed (GObject *object)
 {
@@ -1287,6 +1436,9 @@ constructed (GObject *object)
 
 	g_signal_connect (object, "notify::" NM_CLIENT_ACTIVE_CONNECTIONS,
 	                  G_CALLBACK (active_connections_changed_cb), NULL);
+
+	g_signal_connect (object, "object-creation-failed",
+	                  G_CALLBACK (object_creation_failed_cb), NULL);
 }
 
 static gboolean
@@ -1417,26 +1569,26 @@ init_async (GAsyncInitable *initable, int io_priority,
 static void
 dispose (GObject *object)
 {
+	NMClient *client = NM_CLIENT (object);
 	NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (object);
 
-	if (priv->disposed) {
-		G_OBJECT_CLASS (nm_client_parent_class)->dispose (object);
-		return;
-	}
-
-	if (priv->perm_call)
+	if (priv->perm_call) {
 		dbus_g_proxy_cancel_call (priv->client_proxy, priv->perm_call);
+		priv->perm_call = NULL;
+	}
 
-	g_object_unref (priv->client_proxy);
-	g_object_unref (priv->bus_proxy);
+	g_clear_object (&priv->client_proxy);
+	g_clear_object (&priv->bus_proxy);
 
-	free_object_array (&priv->devices);
-	dispose_and_free_object_array (&priv->active_connections);
+	free_devices (client, FALSE);
+	free_active_connections (client, FALSE);
 
 	g_slist_foreach (priv->pending_activations, (GFunc) activate_info_free, NULL);
 	g_slist_free (priv->pending_activations);
+	priv->pending_activations = NULL;
 
 	g_hash_table_destroy (priv->permissions);
+	priv->permissions = NULL;
 
 	G_OBJECT_CLASS (nm_client_parent_class)->dispose (object);
 }
@@ -1502,6 +1654,8 @@ get_property (GObject *object,
 	NMClient *self = NM_CLIENT (object);
 	NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self);
 
+	_nm_object_ensure_inited (NM_OBJECT (object));
+
 	switch (prop_id) {
 	case PROP_VERSION:
 		g_value_set_string (value, nm_client_get_version (self));
@@ -1550,6 +1704,7 @@ nm_client_class_init (NMClientClass *client_class)
 	g_type_class_add_private (client_class, sizeof (NMClientPrivate));
 
 	/* virtual methods */
+	object_class->constructor = constructor;
 	object_class->constructed = constructed;
 	object_class->set_property = set_property;
 	object_class->get_property = get_property;
diff --git a/libnm-glib/nm-device-adsl.c b/libnm-glib/nm-device-adsl.c
new file mode 100644
index 00000000..67aad9e8
--- /dev/null
+++ b/libnm-glib/nm-device-adsl.c
@@ -0,0 +1,245 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * libnm_glib -- Access network status & information from glib applications
+ *
+ * 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.
+ *
+ * author: Pantelis Koukousoulas <pktoss@gmail.com>
+ * Copyright 2009 - 2011 Red Hat, Inc.
+ */
+
+#include "nm-device-adsl.h"
+#include "nm-device-private.h"
+#include "nm-object-private.h"
+
+#include "nm-setting-adsl.h"
+
+#include <string.h>
+
+G_DEFINE_TYPE (NMDeviceAdsl, nm_device_adsl, NM_TYPE_DEVICE)
+
+#define NM_DEVICE_ADSL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_ADSL, NMDeviceAdslPrivate))
+
+typedef struct {
+	DBusGProxy *proxy;
+
+	gboolean carrier;
+
+	gboolean disposed;
+} NMDeviceAdslPrivate;
+
+enum {
+	PROP_0,
+	PROP_CARRIER,
+	LAST_PROP
+};
+#define DBUS_PROP_CARRIER "Carrier"
+
+/**
+ * nm_device_adsl_error_quark:
+ *
+ * Registers an error quark for #NMDeviceAdsl if necessary.
+ *
+ * Returns: the error quark used for #NMDeviceAdsl errors.
+ **/
+GQuark
+nm_device_adsl_error_quark (void)
+{
+	static GQuark quark = 0;
+
+	if (G_UNLIKELY (quark == 0))
+		quark = g_quark_from_static_string ("nm-device-adsl-error-quark");
+	return quark;
+}
+
+/**
+ * nm_device_adsl_new:
+ * @connection: the #DBusGConnection
+ * @path: the DBus object path of the device
+ *
+ * Creates a new #NMDeviceAdsl.
+ *
+ * Returns: a new device
+ **/
+GObject *
+nm_device_adsl_new (DBusGConnection *connection, const char *path)
+{
+	GObject *device;
+
+	g_return_val_if_fail (connection != NULL, NULL);
+	g_return_val_if_fail (path != NULL, NULL);
+
+	device = g_object_new (NM_TYPE_DEVICE_ADSL,
+	                       NM_OBJECT_DBUS_CONNECTION, connection,
+	                       NM_OBJECT_DBUS_PATH, path,
+	                       NULL);
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return device;
+}
+
+/**
+ * nm_device_adsl_get_carrier:
+ * @device: a #NMDeviceAdsl
+ *
+ * Whether the device has carrier.
+ *
+ * Returns: %TRUE if the device has carrier
+ **/
+gboolean
+nm_device_adsl_get_carrier (NMDeviceAdsl *device)
+{
+	g_return_val_if_fail (NM_IS_DEVICE_ADSL (device), FALSE);
+
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return NM_DEVICE_ADSL_GET_PRIVATE (device)->carrier;
+}
+
+static gboolean
+connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
+{
+	NMSettingConnection *s_con;
+	NMSettingAdsl *s_adsl;
+	const char *ctype;
+
+	s_con = nm_connection_get_setting_connection (connection);
+	g_assert (s_con);
+
+	ctype = nm_setting_connection_get_connection_type (s_con);
+	if (strcmp (ctype, NM_SETTING_ADSL_SETTING_NAME) != 0) {
+		g_set_error (error, NM_DEVICE_ADSL_ERROR, NM_DEVICE_ADSL_ERROR_NOT_ADSL_CONNECTION,
+		             "The connection was not an ADSL connection.");
+		return FALSE;
+	}
+
+	s_adsl = nm_connection_get_setting_adsl (connection);
+	if (!s_adsl) {
+		g_set_error (error, NM_DEVICE_ADSL_ERROR, NM_DEVICE_ADSL_ERROR_INVALID_ADSL_CONNECTION,
+		             "The connection was not a valid ADSL connection.");
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+/******************************************************************/
+
+static void
+nm_device_adsl_init (NMDeviceAdsl *device)
+{
+	_nm_device_set_device_type (NM_DEVICE (device), NM_DEVICE_TYPE_ADSL);
+}
+
+static void
+register_properties (NMDeviceAdsl *device)
+{
+	NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (device);
+	const NMPropertiesInfo property_info[] = {
+		{ NM_DEVICE_ADSL_CARRIER,              &priv->carrier },
+		{ NULL },
+	};
+
+	_nm_object_register_properties (NM_OBJECT (device),
+	                                priv->proxy,
+	                                property_info);
+}
+
+static void
+constructed (GObject *object)
+{
+	NMDeviceAdslPrivate *priv;
+
+	G_OBJECT_CLASS (nm_device_adsl_parent_class)->constructed (object);
+
+	priv = NM_DEVICE_ADSL_GET_PRIVATE (object);
+
+	priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (NM_OBJECT (object)),
+	                                         NM_DBUS_SERVICE,
+	                                         nm_object_get_path (NM_OBJECT (object)),
+	                                         NM_DBUS_INTERFACE_DEVICE_ADSL);
+
+	register_properties (NM_DEVICE_ADSL (object));
+}
+
+static void
+dispose (GObject *object)
+{
+	NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (object);
+
+	if (priv->disposed) {
+		G_OBJECT_CLASS (nm_device_adsl_parent_class)->dispose (object);
+		return;
+	}
+
+	priv->disposed = TRUE;
+
+	g_object_unref (priv->proxy);
+
+	G_OBJECT_CLASS (nm_device_adsl_parent_class)->dispose (object);
+}
+
+static void
+finalize (GObject *object)
+{
+	G_OBJECT_CLASS (nm_device_adsl_parent_class)->finalize (object);
+}
+
+static void
+get_property (GObject *object,
+              guint prop_id,
+              GValue *value,
+              GParamSpec *pspec)
+{
+	NMDeviceAdsl *device = NM_DEVICE_ADSL (object);
+
+	switch (prop_id) {
+	case PROP_CARRIER:
+		g_value_set_boolean (value, nm_device_adsl_get_carrier (device));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+nm_device_adsl_class_init (NMDeviceAdslClass *adsl_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (adsl_class);
+	NMDeviceClass *device_class = NM_DEVICE_CLASS (adsl_class);
+
+	g_type_class_add_private (object_class, sizeof (NMDeviceAdslPrivate));
+
+	/* virtual methods */
+	object_class->constructed = constructed;
+	object_class->dispose = dispose;
+	object_class->finalize = finalize;
+	object_class->get_property = get_property;
+	device_class->connection_compatible = connection_compatible;
+
+	/* properties */
+	/**
+	 * NMDeviceAdsl:carrier:
+	 *
+	 * Whether the device has carrier.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_CARRIER,
+		 g_param_spec_boolean (NM_DEVICE_ADSL_CARRIER,
+		                       "Carrier",
+		                       "Carrier",
+		                       FALSE,
+		                       G_PARAM_READABLE));
+}
diff --git a/libnm-glib/nm-device-adsl.h b/libnm-glib/nm-device-adsl.h
new file mode 100644
index 00000000..9d83e267
--- /dev/null
+++ b/libnm-glib/nm-device-adsl.h
@@ -0,0 +1,77 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * libnm_glib -- Access network status & information from glib applications
+ *
+ * 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 (C) 2011 Pantelis Koukousoulas <pktoss@gmail.com>
+ */
+
+#ifndef NM_DEVICE_ADSL_H
+#define NM_DEVICE_ADSL_H
+
+#include "nm-device.h"
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_DEVICE_ADSL            (nm_device_adsl_get_type ())
+#define NM_DEVICE_ADSL(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_ADSL, NMDeviceAdsl))
+#define NM_DEVICE_ADSL_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_ADSL, NMDeviceAdslClass))
+#define NM_IS_DEVICE_ADSL(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_ADSL))
+#define NM_IS_DEVICE_ADSL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_DEVICE_ADSL))
+#define NM_DEVICE_ADSL_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_ADSL, NMDeviceAdslClass))
+
+/**
+ * NMDeviceAdslError:
+ * @NM_DEVICE_ADSL_ERROR_UNKNOWN: unknown or unclassified error
+ * @NM_DEVICE_ADSL_ERROR_NOT_ADSL_CONNECTION: the connection was not of ADSL type
+ * @NM_DEVICE_ADSL_ERROR_INVALID_ADSL_CONNECTION: the ADSL connection was invalid
+ */
+typedef enum {
+	NM_DEVICE_ADSL_ERROR_UNKNOWN = 0,             /*< nick=UnknownError >*/
+	NM_DEVICE_ADSL_ERROR_NOT_ADSL_CONNECTION,     /*< nick=NotAdslConnection >*/
+	NM_DEVICE_ADSL_ERROR_INVALID_ADSL_CONNECTION, /*< nick=InvalidAdslConnection >*/
+} NMDeviceAdslError;
+
+#define NM_DEVICE_ADSL_ERROR nm_device_adsl_error_quark ()
+GQuark nm_device_adsl_error_quark (void);
+
+#define NM_DEVICE_ADSL_CARRIER "carrier"
+
+typedef struct {
+	NMDevice parent;
+} NMDeviceAdsl;
+
+typedef struct {
+	NMDeviceClass parent;
+
+	/* Padding for future expansion */
+	void (*_reserved1) (void);
+	void (*_reserved2) (void);
+	void (*_reserved3) (void);
+	void (*_reserved4) (void);
+	void (*_reserved5) (void);
+	void (*_reserved6) (void);
+} NMDeviceAdslClass;
+
+GType nm_device_adsl_get_type (void);
+
+GObject *nm_device_adsl_new (DBusGConnection *connection, const char *path);
+gboolean nm_device_adsl_get_carrier (NMDeviceAdsl *device);
+
+G_END_DECLS
+
+#endif /* NM_DEVICE_ADSL_H */
diff --git a/libnm-glib/nm-device-bond.c b/libnm-glib/nm-device-bond.c
index 034b7b3c..d5e33e50 100644
--- a/libnm-glib/nm-device-bond.c
+++ b/libnm-glib/nm-device-bond.c
@@ -24,6 +24,8 @@
 #include <string.h>
 #include <netinet/ether.h>
 
+#include "nm-glib-compat.h"
+
 #include <nm-setting-connection.h>
 #include <nm-setting-bond.h>
 #include <nm-utils.h>
@@ -215,10 +217,7 @@ dispose (GObject *object)
 {
 	NMDeviceBondPrivate *priv = NM_DEVICE_BOND_GET_PRIVATE (object);
 
-	if (priv->proxy) {
-		g_object_unref (priv->proxy);
-		priv->proxy = NULL;
-	}
+	g_clear_object (&priv->proxy);
 
 	G_OBJECT_CLASS (nm_device_bond_parent_class)->dispose (object);
 }
@@ -241,6 +240,8 @@ get_property (GObject *object,
 {
 	NMDeviceBond *device = NM_DEVICE_BOND (object);
 
+	_nm_object_ensure_inited (NM_OBJECT (object));
+
 	switch (prop_id) {
 	case PROP_HW_ADDRESS:
 		g_value_set_string (value, nm_device_bond_get_hw_address (device));
diff --git a/libnm-glib/nm-device-bt.c b/libnm-glib/nm-device-bt.c
index 8e0ff200..ccfa83ca 100644
--- a/libnm-glib/nm-device-bt.c
+++ b/libnm-glib/nm-device-bt.c
@@ -25,6 +25,8 @@
 #include <string.h>
 #include <netinet/ether.h>
 
+#include "nm-glib-compat.h"
+
 #include <nm-setting-connection.h>
 #include <nm-setting-bluetooth.h>
 
@@ -42,8 +44,6 @@ typedef struct {
 	char *hw_address;
 	char *name;
 	guint32 bt_capabilities;
-
-	gboolean disposed;
 } NMDeviceBtPrivate;
 
 enum {
@@ -273,13 +273,7 @@ dispose (GObject *object)
 {
 	NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (object);
 
-	if (priv->disposed) {
-		G_OBJECT_CLASS (nm_device_bt_parent_class)->dispose (object);
-		return;
-	}
-	priv->disposed = TRUE;
-
-	g_object_unref (priv->proxy);
+	g_clear_object (&priv->proxy);
 
 	G_OBJECT_CLASS (nm_device_bt_parent_class)->dispose (object);
 }
@@ -303,6 +297,8 @@ get_property (GObject *object,
 {
 	NMDeviceBt *device = NM_DEVICE_BT (object);
 
+	_nm_object_ensure_inited (NM_OBJECT (object));
+
 	switch (prop_id) {
 	case PROP_HW_ADDRESS:
 		g_value_set_string (value, nm_device_bt_get_hw_address (device));
diff --git a/libnm-glib/nm-device-ethernet.c b/libnm-glib/nm-device-ethernet.c
index 62aedbbf..e9d1b4ad 100644
--- a/libnm-glib/nm-device-ethernet.c
+++ b/libnm-glib/nm-device-ethernet.c
@@ -25,6 +25,8 @@
 #include <string.h>
 #include <netinet/ether.h>
 
+#include "nm-glib-compat.h"
+
 #include <nm-setting-connection.h>
 #include <nm-setting-wired.h>
 #include <nm-setting-pppoe.h>
@@ -44,8 +46,6 @@ typedef struct {
 	char *perm_hw_address;
 	guint32 speed;
 	gboolean carrier;
-
-	gboolean disposed;
 } NMDeviceEthernetPrivate;
 
 enum {
@@ -280,14 +280,7 @@ dispose (GObject *object)
 {
 	NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (object);
 
-	if (priv->disposed) {
-		G_OBJECT_CLASS (nm_device_ethernet_parent_class)->dispose (object);
-		return;
-	}
-
-	priv->disposed = TRUE;
-
-	g_object_unref (priv->proxy);
+	g_clear_object (&priv->proxy);
 
 	G_OBJECT_CLASS (nm_device_ethernet_parent_class)->dispose (object);
 }
@@ -311,6 +304,8 @@ get_property (GObject *object,
 {
 	NMDeviceEthernet *device = NM_DEVICE_ETHERNET (object);
 
+	_nm_object_ensure_inited (NM_OBJECT (object));
+
 	switch (prop_id) {
 	case PROP_HW_ADDRESS:
 		g_value_set_string (value, nm_device_ethernet_get_hw_address (device));
diff --git a/libnm-glib/nm-device-infiniband.c b/libnm-glib/nm-device-infiniband.c
index ec5f4a8b..d611993b 100644
--- a/libnm-glib/nm-device-infiniband.c
+++ b/libnm-glib/nm-device-infiniband.c
@@ -25,6 +25,8 @@
 #include <linux/if_infiniband.h>
 #include <netinet/ether.h>
 
+#include "nm-glib-compat.h"
+
 #include <nm-setting-connection.h>
 #include <nm-setting-infiniband.h>
 #include <nm-utils.h>
@@ -224,10 +226,7 @@ dispose (GObject *object)
 {
 	NMDeviceInfinibandPrivate *priv = NM_DEVICE_INFINIBAND_GET_PRIVATE (object);
 
-	if (priv->proxy) {
-		g_object_unref (priv->proxy);
-		priv->proxy = NULL;
-	}
+	g_clear_object (&priv->proxy);
 
 	G_OBJECT_CLASS (nm_device_infiniband_parent_class)->dispose (object);
 }
@@ -250,6 +249,8 @@ get_property (GObject *object,
 {
 	NMDeviceInfiniband *device = NM_DEVICE_INFINIBAND (object);
 
+	_nm_object_ensure_inited (NM_OBJECT (object));
+
 	switch (prop_id) {
 	case PROP_HW_ADDRESS:
 		g_value_set_string (value, nm_device_infiniband_get_hw_address (device));
diff --git a/libnm-glib/nm-device-modem.c b/libnm-glib/nm-device-modem.c
index f1d1389b..f7a9230e 100644
--- a/libnm-glib/nm-device-modem.c
+++ b/libnm-glib/nm-device-modem.c
@@ -24,6 +24,8 @@
 #include <config.h>
 #include <string.h>
 
+#include "nm-glib-compat.h"
+
 #include <nm-setting-connection.h>
 #include <nm-setting-gsm.h>
 #include <nm-setting-cdma.h>
@@ -44,8 +46,6 @@ typedef struct {
 
 	NMDeviceModemCapabilities caps;
 	NMDeviceModemCapabilities current_caps;
-
-	gboolean disposed;
 } NMDeviceModemPrivate;
 
 enum {
@@ -205,6 +205,8 @@ get_property (GObject *object,
 {
 	NMDeviceModem *self = NM_DEVICE_MODEM (object);
 
+	_nm_object_ensure_inited (NM_OBJECT (object));
+
 	switch (prop_id) {
 	case PROP_MODEM_CAPS:
 		g_value_set_uint (value, nm_device_modem_get_modem_capabilities (self));
@@ -223,14 +225,7 @@ dispose (GObject *object)
 {
 	NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (object);
 
-	if (priv->disposed) {
-		G_OBJECT_CLASS (nm_device_modem_parent_class)->dispose (object);
-		return;
-	}
-
-	priv->disposed = TRUE;
-
-	g_object_unref (priv->proxy);
+	g_clear_object (&priv->proxy);
 
 	G_OBJECT_CLASS (nm_device_modem_parent_class)->dispose (object);
 }
diff --git a/libnm-glib/nm-device-olpc-mesh.c b/libnm-glib/nm-device-olpc-mesh.c
index ed48ecb6..7ca36890 100644
--- a/libnm-glib/nm-device-olpc-mesh.c
+++ b/libnm-glib/nm-device-olpc-mesh.c
@@ -24,6 +24,8 @@
 #include <config.h>
 #include <string.h>
 
+#include "nm-glib-compat.h"
+
 #include <nm-setting-connection.h>
 #include <nm-setting-olpc-mesh.h>
 
@@ -227,14 +229,8 @@ dispose (GObject *object)
 {
 	NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (object);
 
-	if (priv->companion) {
-		g_object_unref (priv->companion);
-		priv->companion = NULL;
-	}
-	if (priv->proxy) {
-		g_object_unref (priv->proxy);
-		priv->proxy = NULL;
-	}
+	g_clear_object (&priv->companion);
+	g_clear_object (&priv->proxy);
 
 	G_OBJECT_CLASS (nm_device_olpc_mesh_parent_class)->dispose (object);
 }
@@ -257,6 +253,8 @@ get_property (GObject *object,
 {
 	NMDeviceOlpcMesh *device = NM_DEVICE_OLPC_MESH (object);
 
+	_nm_object_ensure_inited (NM_OBJECT (object));
+
 	switch (prop_id) {
 	case PROP_HW_ADDRESS:
 		g_value_set_string (value, nm_device_olpc_mesh_get_hw_address (device));
diff --git a/libnm-glib/nm-device-vlan.c b/libnm-glib/nm-device-vlan.c
index 08b1142d..13ca3ac3 100644
--- a/libnm-glib/nm-device-vlan.c
+++ b/libnm-glib/nm-device-vlan.c
@@ -24,6 +24,8 @@
 #include <string.h>
 #include <netinet/ether.h>
 
+#include "nm-glib-compat.h"
+
 #include <nm-setting-connection.h>
 #include <nm-setting-vlan.h>
 #include <nm-utils.h>
@@ -238,10 +240,7 @@ dispose (GObject *object)
 {
 	NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (object);
 
-	if (priv->proxy) {
-		g_object_unref (priv->proxy);
-		priv->proxy = NULL;
-	}
+	g_clear_object (&priv->proxy);
 
 	G_OBJECT_CLASS (nm_device_vlan_parent_class)->dispose (object);
 }
@@ -264,6 +263,8 @@ get_property (GObject *object,
 {
 	NMDeviceVlan *device = NM_DEVICE_VLAN (object);
 
+	_nm_object_ensure_inited (NM_OBJECT (object));
+
 	switch (prop_id) {
 	case PROP_HW_ADDRESS:
 		g_value_set_string (value, nm_device_vlan_get_hw_address (device));
diff --git a/libnm-glib/nm-device-wifi.c b/libnm-glib/nm-device-wifi.c
index 6975898f..0058fd10 100644
--- a/libnm-glib/nm-device-wifi.c
+++ b/libnm-glib/nm-device-wifi.c
@@ -25,6 +25,8 @@
 #include <string.h>
 #include <netinet/ether.h>
 
+#include "nm-glib-compat.h"
+
 #include <nm-setting-connection.h>
 #include <nm-setting-wireless.h>
 #include <nm-setting-wireless-security.h>
@@ -43,7 +45,6 @@ G_DEFINE_TYPE (NMDeviceWifi, nm_device_wifi, NM_TYPE_DEVICE)
 void _nm_device_wifi_set_wireless_enabled (NMDeviceWifi *device, gboolean enabled);
 
 typedef struct {
-	gboolean disposed;
 	DBusGProxy *proxy;
 
 	char *hw_address;
@@ -501,6 +502,8 @@ get_property (GObject *object,
 {
 	NMDeviceWifi *self = NM_DEVICE_WIFI (object);
 
+	_nm_object_ensure_inited (NM_OBJECT (object));
+
 	switch (prop_id) {
 	case PROP_HW_ADDRESS:
 		g_value_set_string (value, nm_device_wifi_get_hw_address (self));
@@ -606,15 +609,8 @@ dispose (GObject *object)
 {
 	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (object);
 
-	if (priv->disposed) {
-		G_OBJECT_CLASS (nm_device_wifi_parent_class)->dispose (object);
-		return;
-	}
-
-	priv->disposed = TRUE;
-
 	clean_up_aps (NM_DEVICE_WIFI (object), FALSE);
-	g_object_unref (priv->proxy);
+	g_clear_object (&priv->proxy);
 
 	G_OBJECT_CLASS (nm_device_wifi_parent_class)->dispose (object);
 }
diff --git a/libnm-glib/nm-device-wimax.c b/libnm-glib/nm-device-wimax.c
index 48a518d7..62e3f772 100644
--- a/libnm-glib/nm-device-wimax.c
+++ b/libnm-glib/nm-device-wimax.c
@@ -25,6 +25,8 @@
 #include <string.h>
 #include <netinet/ether.h>
 
+#include "nm-glib-compat.h"
+
 #include <nm-setting-connection.h>
 #include <nm-setting-wimax.h>
 
@@ -42,7 +44,6 @@ G_DEFINE_TYPE (NMDeviceWimax, nm_device_wimax, NM_TYPE_DEVICE)
 void _nm_device_wimax_set_wireless_enabled (NMDeviceWimax *wimax, gboolean enabled);
 
 typedef struct {
-	gboolean disposed;
 	DBusGProxy *proxy;
 
 	char *hw_address;
@@ -444,6 +445,8 @@ get_property (GObject *object,
 {
 	NMDeviceWimax *self = NM_DEVICE_WIMAX (object);
 
+	_nm_object_ensure_inited (NM_OBJECT (object));
+
 	switch (prop_id) {
 	case PROP_HW_ADDRESS:
 		g_value_set_string (value, nm_device_wimax_get_hw_address (self));
@@ -591,18 +594,18 @@ dispose (GObject *object)
 {
 	NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (object);
 
-	if (priv->disposed) {
-		G_OBJECT_CLASS (nm_device_wimax_parent_class)->dispose (object);
-		return;
+	if (priv->hw_address) {
+		g_free (priv->hw_address);
+		priv->hw_address = NULL;
 	}
 
-	priv->disposed = TRUE;
-
-	g_free (priv->hw_address);
-	g_free (priv->bsid);
+	if (priv->bsid) {
+		g_free (priv->bsid);
+		priv->bsid = NULL;
+	}
 
 	clean_up_nsps (NM_DEVICE_WIMAX (object), FALSE);
-	g_object_unref (priv->proxy);
+	g_clear_object (&priv->proxy);
 
 	G_OBJECT_CLASS (nm_device_wimax_parent_class)->dispose (object);
 }
diff --git a/libnm-glib/nm-device.c b/libnm-glib/nm-device.c
index 96a037d5..36a36ebf 100644
--- a/libnm-glib/nm-device.c
+++ b/libnm-glib/nm-device.c
@@ -27,6 +27,7 @@
 
 #include "NetworkManager.h"
 #include "nm-device-ethernet.h"
+#include "nm-device-adsl.h"
 #include "nm-device-wifi.h"
 #include "nm-device-modem.h"
 #include "nm-device-bt.h"
@@ -60,7 +61,6 @@ G_DEFINE_TYPE_WITH_CODE (NMDevice, nm_device, NM_TYPE_OBJECT,
 #define NM_DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE, NMDevicePrivate))
 
 typedef struct {
-	gboolean disposed;
 	DBusGProxy *proxy;
 
 	char *iface;
@@ -68,9 +68,12 @@ typedef struct {
 	NMDeviceType device_type;
 	char *udi;
 	char *driver;
+	char *driver_version;
+	char *firmware_version;
 	NMDeviceCapabilities capabilities;
 	gboolean managed;
 	gboolean firmware_missing;
+	gboolean autoconnect;
 	NMIP4Config *ip4_config;
 	NMDHCP4Config *dhcp4_config;
 	NMIP6Config *ip6_config;
@@ -90,8 +93,11 @@ enum {
 	PROP_INTERFACE,
 	PROP_UDI,
 	PROP_DRIVER,
+	PROP_DRIVER_VERSION,
+	PROP_FIRMWARE_VERSION,
 	PROP_CAPABILITIES,
 	PROP_MANAGED,
+	PROP_AUTOCONNECT,
 	PROP_FIRMWARE_MISSING,
 	PROP_IP4_CONFIG,
 	PROP_DHCP4_CONFIG,
@@ -152,8 +158,11 @@ register_properties (NMDevice *device)
 		{ NM_DEVICE_INTERFACE,         &priv->iface },
 		{ NM_DEVICE_IP_INTERFACE,      &priv->ip_iface },
 		{ NM_DEVICE_DRIVER,            &priv->driver },
+		{ NM_DEVICE_DRIVER_VERSION,    &priv->driver_version },
+		{ NM_DEVICE_FIRMWARE_VERSION,  &priv->firmware_version },
 		{ NM_DEVICE_CAPABILITIES,      &priv->capabilities },
 		{ NM_DEVICE_MANAGED,           &priv->managed },
+		{ NM_DEVICE_AUTOCONNECT,       &priv->autoconnect },
 		{ NM_DEVICE_FIRMWARE_MISSING,  &priv->firmware_missing },
 		{ NM_DEVICE_IP4_CONFIG,        &priv->ip4_config, NULL, NM_TYPE_IP4_CONFIG },
 		{ NM_DEVICE_DHCP4_CONFIG,      &priv->dhcp4_config, NULL, NM_TYPE_DHCP4_CONFIG },
@@ -208,6 +217,8 @@ _nm_device_gtype_from_dtype (NMDeviceType dtype)
 		return NM_TYPE_DEVICE_MODEM;
 	case NM_DEVICE_TYPE_BT:
 		return NM_TYPE_DEVICE_BT;
+	case NM_DEVICE_TYPE_ADSL:
+		return NM_TYPE_DEVICE_ADSL;
 	case NM_DEVICE_TYPE_OLPC_MESH:
 		return NM_TYPE_DEVICE_OLPC_MESH;
 	case NM_DEVICE_TYPE_WIMAX:
@@ -265,26 +276,13 @@ dispose (GObject *object)
 {
 	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (object);
 
-	if (priv->disposed) {
-		G_OBJECT_CLASS (nm_device_parent_class)->dispose (object);
-		return;
-	}
-
-	priv->disposed = TRUE;
-
-	g_object_unref (priv->proxy);
-	if (priv->ip4_config)
-		g_object_unref (priv->ip4_config);
-	if (priv->dhcp4_config)
-		g_object_unref (priv->dhcp4_config);
-	if (priv->ip6_config)
-		g_object_unref (priv->ip6_config);
-	if (priv->dhcp6_config)
-		g_object_unref (priv->dhcp6_config);
-	if (priv->client)
-		g_object_unref (priv->client);
-	if (priv->active_connection)
-		g_object_unref (priv->active_connection);
+	g_clear_object (&priv->proxy);
+	g_clear_object (&priv->ip4_config);
+	g_clear_object (&priv->dhcp4_config);
+	g_clear_object (&priv->ip6_config);
+	g_clear_object (&priv->dhcp6_config);
+	g_clear_object (&priv->client);
+	g_clear_object (&priv->active_connection);
 
 	G_OBJECT_CLASS (nm_device_parent_class)->dispose (object);
 }
@@ -298,6 +296,8 @@ finalize (GObject *object)
 	g_free (priv->ip_iface);
 	g_free (priv->udi);
 	g_free (priv->driver);
+	g_free (priv->driver_version);
+	g_free (priv->firmware_version);
 	g_free (priv->product);
 	g_free (priv->vendor);
 
@@ -313,6 +313,8 @@ get_property (GObject *object,
 	NMDevice *device = NM_DEVICE (object);
 	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
 
+	_nm_object_ensure_inited (NM_OBJECT (object));
+
 	switch (prop_id) {
 	case PROP_DEVICE_TYPE:
 		g_value_set_uint (value, nm_device_get_device_type (device));
@@ -329,12 +331,21 @@ get_property (GObject *object,
 	case PROP_DRIVER:
 		g_value_set_string (value, nm_device_get_driver (device));
 		break;
+	case PROP_DRIVER_VERSION:
+		g_value_set_string (value, nm_device_get_driver_version (device));
+		break;
+	case PROP_FIRMWARE_VERSION:
+		g_value_set_string (value, nm_device_get_firmware_version (device));
+		break;
 	case PROP_CAPABILITIES:
 		g_value_set_uint (value, nm_device_get_capabilities (device));
 		break;
 	case PROP_MANAGED:
 		g_value_set_boolean (value, nm_device_get_managed (device));
 		break;
+	case PROP_AUTOCONNECT:
+		g_value_set_boolean (value, nm_device_get_autoconnect (device));
+		break;
 	case PROP_FIRMWARE_MISSING:
 		g_value_set_boolean (value, nm_device_get_firmware_missing (device));
 		break;
@@ -384,12 +395,18 @@ set_property (GObject *object,
 {
 	NMDevice *self = NM_DEVICE (object);
 	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
+	gboolean b;
 
 	switch (prop_id) {
 	case PROP_DEVICE_TYPE:
 		/* Construct only */
 		priv->device_type = g_value_get_uint (value);
 		break;
+	case PROP_AUTOCONNECT:
+		b = g_value_get_boolean (value);
+		if (priv->autoconnect != b)
+			nm_device_set_autoconnect (NM_DEVICE (object), b);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -483,6 +500,32 @@ nm_device_class_init (NMDeviceClass *device_class)
 						  G_PARAM_READABLE));
 
 	/**
+	 * NMDevice:driver-version:
+	 *
+	 * The version of the device driver.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_DRIVER_VERSION,
+		 g_param_spec_string (NM_DEVICE_DRIVER_VERSION,
+		                      "Driver Version",
+		                      "Driver Version",
+		                      NULL,
+		                      G_PARAM_READABLE));
+
+	/**
+	 * NMDevice:firmware-version:
+	 *
+	 * The firmware version of the device.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_FIRMWARE_VERSION,
+		 g_param_spec_string (NM_DEVICE_FIRMWARE_VERSION,
+		                      "Firmware Version",
+		                      "Firmware Version",
+		                      NULL,
+		                      G_PARAM_READABLE));
+
+	/**
 	 * NMDevice:capabilities:
 	 *
 	 * The capabilities of the device.
@@ -509,6 +552,19 @@ nm_device_class_init (NMDeviceClass *device_class)
 						  G_PARAM_READABLE));
 
 	/**
+	 * NMDevice:autoconnect:
+	 *
+	 * Whether the device can auto-activate a connection.
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_AUTOCONNECT,
+		 g_param_spec_boolean (NM_DEVICE_AUTOCONNECT,
+		                       "Autoconnect",
+		                       "Autoconnect",
+		                       TRUE,
+		                       G_PARAM_READWRITE));
+
+	/**
 	 * NMDevice:firmware-missing:
 	 *
 	 * When %TRUE indicates the device is likely missing firmware required
@@ -893,6 +949,42 @@ nm_device_get_driver (NMDevice *device)
 }
 
 /**
+ * nm_device_get_driver_version:
+ * @device: a #NMDevice
+ *
+ * Gets the driver version of the #NMDevice.
+ *
+ * Returns: the version of the device driver. This is the internal string used by the
+ * device, and must not be modified.
+ **/
+const char *
+nm_device_get_driver_version (NMDevice *device)
+{
+	g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
+
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return NM_DEVICE_GET_PRIVATE (device)->driver_version;
+}
+
+/**
+ * nm_device_get_firmware_version:
+ * @device: a #NMDevice
+ *
+ * Gets the firmware version of the #NMDevice.
+ *
+ * Returns: the firmware version of the device. This is the internal string used by the
+ * device, and must not be modified.
+ **/
+const char *
+nm_device_get_firmware_version (NMDevice *device)
+{
+	g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
+
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return NM_DEVICE_GET_PRIVATE (device)->firmware_version;
+}
+
+/**
  * nm_device_get_capabilities:
  * @device: a #NMDevice
  *
@@ -927,6 +1019,49 @@ nm_device_get_managed (NMDevice *device)
 }
 
 /**
+ * nm_device_get_autoconnect:
+ * @device: a #NMDevice
+ *
+ * Whether the #NMDevice can be autoconnected.
+ *
+ * Returns: %TRUE if the device is allowed to be autoconnected
+ **/
+gboolean
+nm_device_get_autoconnect (NMDevice *device)
+{
+	g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);
+
+	_nm_object_ensure_inited (NM_OBJECT (device));
+	return NM_DEVICE_GET_PRIVATE (device)->autoconnect;
+}
+
+/**
+ * nm_device_set_autoconnect:
+ * @device: a #NMDevice
+ * @autoconnect: %TRUE to enable autoconnecting
+ *
+ * Enables or disables automatic activation of the #NMDevice.
+ **/
+void
+nm_device_set_autoconnect (NMDevice *device, gboolean autoconnect)
+{
+	GValue value = {0,};
+
+	g_return_if_fail (NM_IS_DEVICE (device));
+
+	g_value_init (&value, G_TYPE_BOOLEAN);
+	g_value_set_boolean (&value, autoconnect);
+
+
+	NM_DEVICE_GET_PRIVATE (device)->autoconnect = autoconnect;
+
+	_nm_object_set_property (NM_OBJECT (device),
+	                         NM_DBUS_INTERFACE_DEVICE,
+	                         "Autoconnect",
+	                         &value);
+}
+
+/**
  * nm_device_get_firmware_missing:
  * @device: a #NMDevice
  *
diff --git a/libnm-glib/nm-device.h b/libnm-glib/nm-device.h
index 50301dc9..9260a33c 100644
--- a/libnm-glib/nm-device.h
+++ b/libnm-glib/nm-device.h
@@ -50,8 +50,11 @@ G_BEGIN_DECLS
 #define NM_DEVICE_INTERFACE "interface"
 #define NM_DEVICE_IP_INTERFACE "ip-interface"
 #define NM_DEVICE_DRIVER "driver"
+#define NM_DEVICE_DRIVER_VERSION "driver-version"
+#define NM_DEVICE_FIRMWARE_VERSION "firmware-version"
 #define NM_DEVICE_CAPABILITIES "capabilities"
 #define NM_DEVICE_MANAGED "managed"
+#define NM_DEVICE_AUTOCONNECT "autoconnect"
 #define NM_DEVICE_FIRMWARE_MISSING "firmware-missing"
 #define NM_DEVICE_IP4_CONFIG "ip4-config"
 #define NM_DEVICE_DHCP4_CONFIG "dhcp4-config"
@@ -98,8 +101,12 @@ const char *         nm_device_get_ip_iface         (NMDevice *device);
 NMDeviceType         nm_device_get_device_type      (NMDevice *device);
 const char *         nm_device_get_udi              (NMDevice *device);
 const char *         nm_device_get_driver           (NMDevice *device);
+const char *         nm_device_get_driver_version   (NMDevice *device);
+const char *         nm_device_get_firmware_version (NMDevice *device);
 NMDeviceCapabilities nm_device_get_capabilities     (NMDevice *device);
 gboolean             nm_device_get_managed          (NMDevice *device);
+gboolean             nm_device_get_autoconnect      (NMDevice *device);
+void                 nm_device_set_autoconnect      (NMDevice *device, gboolean autoconnect);
 gboolean             nm_device_get_firmware_missing (NMDevice *device);
 NMIP4Config *        nm_device_get_ip4_config       (NMDevice *device);
 NMDHCP4Config *      nm_device_get_dhcp4_config     (NMDevice *device);
diff --git a/libnm-glib/nm-dhcp4-config.c b/libnm-glib/nm-dhcp4-config.c
index 2074e6d1..89ccf25e 100644
--- a/libnm-glib/nm-dhcp4-config.c
+++ b/libnm-glib/nm-dhcp4-config.c
@@ -132,6 +132,8 @@ get_property (GObject *object,
 {
 	NMDHCP4Config *self = NM_DHCP4_CONFIG (object);
 
+	_nm_object_ensure_inited (NM_OBJECT (object));
+
 	switch (prop_id) {
 	case PROP_OPTIONS:
 		g_value_set_boxed (value, nm_dhcp4_config_get_options (self));
diff --git a/libnm-glib/nm-dhcp6-config.c b/libnm-glib/nm-dhcp6-config.c
index 3764cbf0..88b3b103 100644
--- a/libnm-glib/nm-dhcp6-config.c
+++ b/libnm-glib/nm-dhcp6-config.c
@@ -132,6 +132,8 @@ get_property (GObject *object,
 {
 	NMDHCP6Config *self = NM_DHCP6_CONFIG (object);
 
+	_nm_object_ensure_inited (NM_OBJECT (object));
+
 	switch (prop_id) {
 	case PROP_OPTIONS:
 		g_value_set_boxed (value, nm_dhcp6_config_get_options (self));
diff --git a/libnm-glib/nm-glib-enum-types.c b/libnm-glib/nm-glib-enum-types.c
index 9fc4de96..6af605cf 100644
--- a/libnm-glib/nm-glib-enum-types.c
+++ b/libnm-glib/nm-glib-enum-types.c
@@ -10,6 +10,7 @@
 #include "nm-device.h" 
 #include "nm-device-ethernet.h" 
 #include "nm-device-infiniband.h" 
+#include "nm-device-adsl.h" 
 #include "nm-device-wifi.h" 
 #include "nm-device-bt.h" 
 #include "nm-device-olpc-mesh.h" 
@@ -31,6 +32,25 @@
 #include "nm-wimax-nsp.h"
 
 GType
+nm_object_error_get_type (void)
+{
+  static volatile gsize g_define_type_id__volatile = 0;
+
+  if (g_once_init_enter (&g_define_type_id__volatile))
+    {
+      static const GEnumValue values[] = {
+        { NM_OBJECT_ERROR_UNKNOWN, "NM_OBJECT_ERROR_UNKNOWN", "unknown" },
+        { NM_OBJECT_ERROR_OBJECT_CREATION_FAILURE, "NM_OBJECT_ERROR_OBJECT_CREATION_FAILURE", "object-creation-failure" },
+        { 0, NULL, NULL }
+      };
+      GType g_define_type_id =
+        g_enum_register_static (g_intern_static_string ("NMObjectError"), values);
+      g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+    }
+
+  return g_define_type_id__volatile;
+}
+GType
 nm_client_permission_get_type (void)
 {
   static volatile gsize g_define_type_id__volatile = 0;
@@ -126,6 +146,26 @@ nm_device_infiniband_error_get_type (void)
   return g_define_type_id__volatile;
 }
 GType
+nm_device_adsl_error_get_type (void)
+{
+  static volatile gsize g_define_type_id__volatile = 0;
+
+  if (g_once_init_enter (&g_define_type_id__volatile))
+    {
+      static const GEnumValue values[] = {
+        { NM_DEVICE_ADSL_ERROR_UNKNOWN, "NM_DEVICE_ADSL_ERROR_UNKNOWN", "UnknownError" },
+        { NM_DEVICE_ADSL_ERROR_NOT_ADSL_CONNECTION, "NM_DEVICE_ADSL_ERROR_NOT_ADSL_CONNECTION", "NotAdslConnection" },
+        { NM_DEVICE_ADSL_ERROR_INVALID_ADSL_CONNECTION, "NM_DEVICE_ADSL_ERROR_INVALID_ADSL_CONNECTION", "InvalidAdslConnection" },
+        { 0, NULL, NULL }
+      };
+      GType g_define_type_id =
+        g_enum_register_static (g_intern_static_string ("NMDeviceAdslError"), values);
+      g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+    }
+
+  return g_define_type_id__volatile;
+}
+GType
 nm_device_wifi_error_get_type (void)
 {
   static volatile gsize g_define_type_id__volatile = 0;
@@ -310,6 +350,7 @@ nm_secret_agent_get_secrets_flags_get_type (void)
         { NM_SECRET_AGENT_GET_SECRETS_FLAG_NONE, "NM_SECRET_AGENT_GET_SECRETS_FLAG_NONE", "none" },
         { NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION, "NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION", "allow-interaction" },
         { NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW, "NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW", "request-new" },
+        { NM_SECRET_AGENT_GET_SECRETS_FLAG_USER_REQUESTED, "NM_SECRET_AGENT_GET_SECRETS_FLAG_USER_REQUESTED", "user-requested" },
         { 0, NULL, NULL }
       };
       GType g_define_type_id =
diff --git a/libnm-glib/nm-glib-enum-types.h b/libnm-glib/nm-glib-enum-types.h
index 9aa5fa90..6493ab19 100644
--- a/libnm-glib/nm-glib-enum-types.h
+++ b/libnm-glib/nm-glib-enum-types.h
@@ -9,6 +9,8 @@
 #include <glib-object.h>
 
 G_BEGIN_DECLS
+GType nm_object_error_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_OBJECT_ERROR (nm_object_error_get_type ())
 GType nm_client_permission_get_type (void) G_GNUC_CONST;
 #define NM_TYPE_CLIENT_PERMISSION (nm_client_permission_get_type ())
 GType nm_client_permission_result_get_type (void) G_GNUC_CONST;
@@ -17,6 +19,8 @@ GType nm_device_ethernet_error_get_type (void) G_GNUC_CONST;
 #define NM_TYPE_DEVICE_ETHERNET_ERROR (nm_device_ethernet_error_get_type ())
 GType nm_device_infiniband_error_get_type (void) G_GNUC_CONST;
 #define NM_TYPE_DEVICE_INFINIBAND_ERROR (nm_device_infiniband_error_get_type ())
+GType nm_device_adsl_error_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_DEVICE_ADSL_ERROR (nm_device_adsl_error_get_type ())
 GType nm_device_wifi_error_get_type (void) G_GNUC_CONST;
 #define NM_TYPE_DEVICE_WIFI_ERROR (nm_device_wifi_error_get_type ())
 GType nm_device_bt_error_get_type (void) G_GNUC_CONST;
diff --git a/libnm-glib/nm-glib-marshal.c b/libnm-glib/nm-glib-marshal.c
index a6ca0113..4f4e4c86 100644
--- a/libnm-glib/nm-glib-marshal.c
+++ b/libnm-glib/nm-glib-marshal.c
@@ -5,7 +5,7 @@
 
 #ifdef G_ENABLE_DEBUG
 #define g_marshal_value_peek_boolean(v)  g_value_get_boolean (v)
-#define g_marshal_value_peek_char(v)     g_value_get_char (v)
+#define g_marshal_value_peek_char(v)     g_value_get_schar (v)
 #define g_marshal_value_peek_uchar(v)    g_value_get_uchar (v)
 #define g_marshal_value_peek_int(v)      g_value_get_int (v)
 #define g_marshal_value_peek_uint(v)     g_value_get_uint (v)
@@ -50,7 +50,44 @@
 #endif /* !G_ENABLE_DEBUG */
 
 
-/* VOID:STRING,STRING,STRING (nm-glib-marshal.list:1) */
+/* VOID:POINTER,POINTER (nm-glib-marshal.list:1) */
+void
+_nm_glib_marshal_VOID__POINTER_POINTER (GClosure     *closure,
+                                        GValue       *return_value G_GNUC_UNUSED,
+                                        guint         n_param_values,
+                                        const GValue *param_values,
+                                        gpointer      invocation_hint G_GNUC_UNUSED,
+                                        gpointer      marshal_data)
+{
+  typedef void (*GMarshalFunc_VOID__POINTER_POINTER) (gpointer     data1,
+                                                      gpointer     arg_1,
+                                                      gpointer     arg_2,
+                                                      gpointer     data2);
+  register GMarshalFunc_VOID__POINTER_POINTER callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+
+  g_return_if_fail (n_param_values == 3);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_VOID__POINTER_POINTER) (marshal_data ? marshal_data : cc->callback);
+
+  callback (data1,
+            g_marshal_value_peek_pointer (param_values + 1),
+            g_marshal_value_peek_pointer (param_values + 2),
+            data2);
+}
+
+/* VOID:STRING,STRING,STRING (nm-glib-marshal.list:2) */
 void
 _nm_glib_marshal_VOID__STRING_STRING_STRING (GClosure     *closure,
                                              GValue       *return_value G_GNUC_UNUSED,
@@ -89,7 +126,7 @@ _nm_glib_marshal_VOID__STRING_STRING_STRING (GClosure     *closure,
             data2);
 }
 
-/* VOID:UINT,UINT (nm-glib-marshal.list:2) */
+/* VOID:UINT,UINT (nm-glib-marshal.list:3) */
 void
 _nm_glib_marshal_VOID__UINT_UINT (GClosure     *closure,
                                   GValue       *return_value G_GNUC_UNUSED,
@@ -126,7 +163,7 @@ _nm_glib_marshal_VOID__UINT_UINT (GClosure     *closure,
             data2);
 }
 
-/* VOID:UINT,UINT,UINT (nm-glib-marshal.list:3) */
+/* VOID:UINT,UINT,UINT (nm-glib-marshal.list:4) */
 void
 _nm_glib_marshal_VOID__UINT_UINT_UINT (GClosure     *closure,
                                        GValue       *return_value G_GNUC_UNUSED,
diff --git a/libnm-glib/nm-glib-marshal.h b/libnm-glib/nm-glib-marshal.h
index 53d8c06b..01a96a87 100644
--- a/libnm-glib/nm-glib-marshal.h
+++ b/libnm-glib/nm-glib-marshal.h
@@ -6,7 +6,15 @@
 
 G_BEGIN_DECLS
 
-/* VOID:STRING,STRING,STRING (nm-glib-marshal.list:1) */
+/* VOID:POINTER,POINTER (nm-glib-marshal.list:1) */
+extern void _nm_glib_marshal_VOID__POINTER_POINTER (GClosure     *closure,
+                                                    GValue       *return_value,
+                                                    guint         n_param_values,
+                                                    const GValue *param_values,
+                                                    gpointer      invocation_hint,
+                                                    gpointer      marshal_data);
+
+/* VOID:STRING,STRING,STRING (nm-glib-marshal.list:2) */
 extern void _nm_glib_marshal_VOID__STRING_STRING_STRING (GClosure     *closure,
                                                          GValue       *return_value,
                                                          guint         n_param_values,
@@ -14,7 +22,7 @@ extern void _nm_glib_marshal_VOID__STRING_STRING_STRING (GClosure     *closure,
                                                          gpointer      invocation_hint,
                                                          gpointer      marshal_data);
 
-/* VOID:UINT,UINT (nm-glib-marshal.list:2) */
+/* VOID:UINT,UINT (nm-glib-marshal.list:3) */
 extern void _nm_glib_marshal_VOID__UINT_UINT (GClosure     *closure,
                                               GValue       *return_value,
                                               guint         n_param_values,
@@ -22,7 +30,7 @@ extern void _nm_glib_marshal_VOID__UINT_UINT (GClosure     *closure,
                                               gpointer      invocation_hint,
                                               gpointer      marshal_data);
 
-/* VOID:UINT,UINT,UINT (nm-glib-marshal.list:3) */
+/* VOID:UINT,UINT,UINT (nm-glib-marshal.list:4) */
 extern void _nm_glib_marshal_VOID__UINT_UINT_UINT (GClosure     *closure,
                                                    GValue       *return_value,
                                                    guint         n_param_values,
diff --git a/libnm-glib/nm-ip4-config.c b/libnm-glib/nm-ip4-config.c
index 56678545..862e7a01 100644
--- a/libnm-glib/nm-ip4-config.c
+++ b/libnm-glib/nm-ip4-config.c
@@ -187,6 +187,8 @@ get_property (GObject *object,
 	NMIP4Config *self = NM_IP4_CONFIG (object);
 	NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self);
 
+	_nm_object_ensure_inited (NM_OBJECT (object));
+
 	switch (prop_id) {
 	case PROP_ADDRESSES:
 		nm_utils_ip4_addresses_to_gvalue (priv->addresses, value);
diff --git a/libnm-glib/nm-ip6-config.c b/libnm-glib/nm-ip6-config.c
index c9a26279..988dcd30 100644
--- a/libnm-glib/nm-ip6-config.c
+++ b/libnm-glib/nm-ip6-config.c
@@ -268,6 +268,8 @@ get_property (GObject *object,
 	NMIP6Config *self = NM_IP6_CONFIG (object);
 	NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self);
 
+	_nm_object_ensure_inited (NM_OBJECT (object));
+
 	switch (prop_id) {
 	case PROP_ADDRESSES:
 		nm_utils_ip6_addresses_to_gvalue (priv->addresses, value);
diff --git a/libnm-glib/nm-object-cache.c b/libnm-glib/nm-object-cache.c
index 741f1291..2748b1df 100644
--- a/libnm-glib/nm-object-cache.c
+++ b/libnm-glib/nm-object-cache.c
@@ -64,3 +64,28 @@ _nm_object_cache_get (const char *path)
 	return object ? g_object_ref (object) : NULL;
 }
 
+void
+_nm_object_cache_clear (NMObject *except)
+{
+	GHashTableIter iter;
+	NMObject *obj;
+	const char *path;
+	char *foo;
+
+	_init_cache ();
+	g_hash_table_iter_init (&iter, cache);
+	while (g_hash_table_iter_next (&iter, (gpointer) &path, (gpointer) &obj)) {
+		if (obj != except) {
+			/* Remove the callback so that if the object isn't yet released
+			 * by a client, when it does finally get unrefed, it won't trigger
+			 * the cache removal for a new object with the same path as the
+			 * one being released.
+			 */
+			foo = g_object_steal_data (G_OBJECT (obj), "nm-object-cache-tag");
+			g_free (foo);
+
+			g_hash_table_iter_remove (&iter);
+		}
+	}
+}
+
diff --git a/libnm-glib/nm-object-cache.h b/libnm-glib/nm-object-cache.h
index 8386591c..84752134 100644
--- a/libnm-glib/nm-object-cache.h
+++ b/libnm-glib/nm-object-cache.h
@@ -32,6 +32,7 @@ G_BEGIN_DECLS
 /* Returns referenced object from the cache */
 NMObject *_nm_object_cache_get (const char *path);
 void _nm_object_cache_add (NMObject *object);
+void _nm_object_cache_clear (NMObject *except);
 
 G_END_DECLS
 
diff --git a/libnm-glib/nm-object.c b/libnm-glib/nm-object.c
index fc9d7f86..756bfa7a 100644
--- a/libnm-glib/nm-object.c
+++ b/libnm-glib/nm-object.c
@@ -18,7 +18,7 @@
  * Boston, MA 02110-1301 USA.
  *
  * Copyright (C) 2007 - 2008 Novell, Inc.
- * Copyright (C) 2007 - 2011 Red Hat, Inc.
+ * Copyright (C) 2007 - 2012 Red Hat, Inc.
  */
 
 #include <string.h>
@@ -31,6 +31,7 @@
 #include "nm-dbus-glib-types.h"
 #include "nm-glib-compat.h"
 #include "nm-types.h"
+#include "nm-glib-marshal.h"
 
 #define DEBUG 0
 
@@ -78,7 +79,7 @@ typedef struct {
 
 	GSList *notify_props;
 	guint32 notify_id;
-	gboolean inited, disposed;
+	gboolean inited;
 
 	GSList *reload_results;
 	guint reload_remaining;
@@ -93,6 +94,31 @@ enum {
 	LAST_PROP
 };
 
+enum {
+	OBJECT_CREATION_FAILED,
+
+	LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+/**
+ * nm_object_error_quark:
+ *
+ * Registers an error quark for #NMObject if necessary.
+ *
+ * Returns: the error quark used for #NMObject errors.
+ **/
+GQuark
+nm_object_error_quark (void)
+{
+	static GQuark quark;
+
+	if (G_UNLIKELY (!quark))
+		quark = g_quark_from_static_string ("nm-object-error-quark");
+	return quark;
+}
+
 static void
 nm_object_init (NMObject *object)
 {
@@ -194,13 +220,6 @@ dispose (GObject *object)
 {
 	NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
 
-	if (priv->disposed) {
-		G_OBJECT_CLASS (nm_object_parent_class)->dispose (object);
-		return;
-	}
-
-	priv->disposed = TRUE;
-
 	if (priv->notify_id) {
 		g_source_remove (priv->notify_id);
 		priv->notify_id = 0;
@@ -208,12 +227,18 @@ dispose (GObject *object)
 
 	g_slist_foreach (priv->notify_props, (GFunc) g_free, NULL);
 	g_slist_free (priv->notify_props);
+	priv->notify_props = NULL;
 
 	g_slist_foreach (priv->property_interfaces, (GFunc) g_free, NULL);
 	g_slist_free (priv->property_interfaces);
+	priv->property_interfaces = NULL;
+
+	g_clear_object (&priv->properties_proxy);
 
-	g_object_unref (priv->properties_proxy);
-	dbus_g_connection_unref (priv->connection);
+	if (priv->connection) {
+		dbus_g_connection_unref (priv->connection);
+		priv->connection = NULL;
+	}
 
 	G_OBJECT_CLASS (nm_object_parent_class)->dispose (object);
 }
@@ -324,6 +349,29 @@ nm_object_class_init (NMObjectClass *nm_object_class)
 							  "DBus Object Path",
 							  NULL,
 							  G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+	/* signals */
+
+	/**
+	 * NMObject::object-creation-failed:
+	 * @master_object: the object that received the signal
+	 * @error: the error that occured while creating object
+	 * @failed_path: object path of the failed object
+	 *
+	 * Indicates that an error occured while creating an #NMObject object
+	 * during property handling of @master_object.
+	 *
+	 * Note: Be aware that the signal is private for libnm-glib's internal
+	 *       use.
+	 **/
+	signals[OBJECT_CREATION_FAILED] =
+		g_signal_new ("object-creation-failed",
+		              G_OBJECT_CLASS_TYPE (object_class),
+		              G_SIGNAL_RUN_FIRST,
+		              G_STRUCT_OFFSET (NMObjectClass, object_creation_failed),
+		              NULL, NULL,
+		              _nm_glib_marshal_VOID__POINTER_POINTER,
+		              G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_POINTER);
 }
 
 static void
@@ -464,7 +512,7 @@ _nm_object_create (GType type, DBusGConnection *connection, const char *path)
 	return object;
 }
 
-typedef void (*NMObjectCreateCallbackFunc) (GObject *, gpointer);
+typedef void (*NMObjectCreateCallbackFunc) (GObject *, const char *, gpointer);
 typedef struct {
 	DBusGConnection *connection;
 	char *path;
@@ -475,7 +523,7 @@ typedef struct {
 static void
 create_async_complete (GObject *object, NMObjectTypeAsyncData *async_data)
 {
-	async_data->callback (object, async_data->user_data);
+	async_data->callback (object, async_data->path, async_data->user_data);
 
 	g_free (async_data->path);
 	g_slice_free (NMObjectTypeAsyncData, async_data);
@@ -644,12 +692,23 @@ object_property_complete (ObjectCreatedData *odata)
 }
 
 static void
-object_created (GObject *obj, gpointer user_data)
+object_created (GObject *obj, const char *path, gpointer user_data)
 {
 	ObjectCreatedData *odata = user_data;
 
 	/* We assume that on error, the creator_func printed something */
 
+	if (obj == NULL && g_strcmp0 (path, "/") != 0 ) {
+		GError *error;
+		error = g_error_new (NM_OBJECT_ERROR,
+		                     NM_OBJECT_ERROR_OBJECT_CREATION_FAILURE,
+		                     "Creating object for path '%s' failed in libnm-glib.",
+		                     path);
+		/* Emit a signal about the error. */
+		g_signal_emit (odata->self, signals[OBJECT_CREATION_FAILED], 0, error, path);
+		g_error_free (error);
+	}
+
 	odata->objects[--odata->remaining] = obj;
 	if (!odata->remaining)
 		object_property_complete (odata);
@@ -676,18 +735,19 @@ handle_object_property (NMObject *self, const char *property_name, GValue *value
 		priv->reload_remaining++;
 
 	path = g_value_get_boxed (value);
+
 	if (!strcmp (path, "/")) {
-		object_created (NULL, odata);
+		object_created (NULL, path, odata);
 		return TRUE;
 	}
 
 	obj = G_OBJECT (_nm_object_cache_get (path));
 	if (obj) {
-		object_created (obj, odata);
+		object_created (obj, path, odata);
 		return TRUE;
 	} else if (synchronously) {
 		obj = _nm_object_create (pi->object_type, priv->connection, path);
-		object_created (obj, odata);
+		object_created (obj, path, odata);
 		return obj != NULL;
 	} else {
 		_nm_object_create_async (pi->object_type, priv->connection, path,
@@ -736,10 +796,10 @@ handle_object_array_property (NMObject *self, const char *property_name, GValue
 
 		obj = G_OBJECT (_nm_object_cache_get (path));
 		if (obj) {
-			object_created (obj, odata);
+			object_created (obj, path, odata);
 		} else if (synchronously) {
 			obj = _nm_object_create (pi->object_type, priv->connection, path);
-			object_created (obj, odata);
+			object_created (obj, path, odata);
 		} else {
 			_nm_object_create_async (pi->object_type, priv->connection, path,
 			                         object_created, odata);
@@ -844,8 +904,14 @@ process_properties_changed (NMObject *self, GHashTable *properties, gboolean syn
 		return;
 
 	g_hash_table_iter_init (&iter, properties);
-	while (g_hash_table_iter_next (&iter, &name, &value))
-		handle_property_changed (self, name, value, synchronously);
+	while (g_hash_table_iter_next (&iter, &name, &value)) {
+		if (value)
+			handle_property_changed (self, name, value, synchronously);
+		else {
+			g_warning ("%s:%d %s(): object %s property '%s' value is unexpectedly NULL",
+			           __FILE__, __LINE__, __func__, G_OBJECT_TYPE_NAME (self), (const char *) name);
+		}
+	}
 }
 
 static void
@@ -1086,7 +1152,7 @@ _nm_object_set_property (NMObject *object,
 }
 
 static void
-pseudo_property_object_created (GObject *obj, gpointer user_data)
+pseudo_property_object_created (GObject *obj, const char *path, gpointer user_data)
 {
 	PseudoPropertyInfo *ppi = user_data;
 
@@ -1112,7 +1178,7 @@ pseudo_property_added (DBusGProxy *proxy, const char *path, gpointer user_data)
 
 	obj = _nm_object_cache_get (path);
 	if (obj)
-		pseudo_property_object_created (G_OBJECT (obj), ppi);
+		pseudo_property_object_created (G_OBJECT (obj), path, ppi);
 	else {
 		_nm_object_create_async (ppi->pi.object_type, priv->connection, path,
 		                         pseudo_property_object_created, ppi);
diff --git a/libnm-glib/nm-object.h b/libnm-glib/nm-object.h
index 3f7b36cf..267c7148 100644
--- a/libnm-glib/nm-object.h
+++ b/libnm-glib/nm-object.h
@@ -18,7 +18,7 @@
  * Boston, MA 02110-1301 USA.
  *
  * Copyright (C) 2007 - 2008 Novell, Inc.
- * Copyright (C) 2007 - 2008 Red Hat, Inc.
+ * Copyright (C) 2007 - 2012 Red Hat, Inc.
  */
 
 #ifndef NM_OBJECT_H
@@ -37,6 +37,22 @@ G_BEGIN_DECLS
 #define NM_IS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_OBJECT))
 #define NM_OBJECT_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_OBJECT, NMObjectClass))
 
+/**
+ * NMObjectError:
+ * @NM_OBJECT_ERROR_UNKNOWN: unknown or unclassified error
+ * @NM_OBJECT_ERROR_OBJECT_CREATION_FAILURE: an error ocured while creating an #NMObject
+ *
+ * Describes errors that may result from operations involving a #NMObject.
+ *
+ **/
+typedef enum {
+	NM_OBJECT_ERROR_UNKNOWN = 0,
+	NM_OBJECT_ERROR_OBJECT_CREATION_FAILURE,
+} NMObjectError;
+
+#define NM_OBJECT_ERROR nm_object_error_quark ()
+GQuark nm_object_error_quark (void);
+
 #define NM_OBJECT_DBUS_CONNECTION "dbus-connection"
 #define NM_OBJECT_DBUS_PATH "dbus-path"
 
@@ -47,6 +63,15 @@ typedef struct {
 typedef struct {
 	GObjectClass parent;
 
+	/* Signals */
+	/* The "object-creation-failed" signal is PRIVATE for libnm-glib and
+	 * is not meant for any external usage.  It indicates that an error
+	 * occured during creation of an object.
+	 */
+	void (*object_creation_failed) (NMObject *master_object,
+	                                GError *error,
+	                                char *failed_path);
+
 	/* Padding for future expansion */
 	void (*_reserved1) (void);
 	void (*_reserved2) (void);
diff --git a/libnm-glib/nm-remote-connection.c b/libnm-glib/nm-remote-connection.c
index c5e38643..e8b99dff 100644
--- a/libnm-glib/nm-remote-connection.c
+++ b/libnm-glib/nm-remote-connection.c
@@ -72,7 +72,6 @@ typedef struct {
 	GSList *calls;
 
 	gboolean visible;
-	gboolean disposed;
 } NMRemoteConnectionPrivate;
 
 #define NM_REMOTE_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_REMOTE_CONNECTION, NMRemoteConnectionPrivate))
@@ -477,14 +476,14 @@ dispose (GObject *object)
 	NMRemoteConnection *self = NM_REMOTE_CONNECTION (object);
 	NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (object);
 
-	if (!priv->disposed) {
-		priv->disposed = TRUE;
+	while (g_slist_length (priv->calls))
+		remote_call_complete (self, priv->calls->data);
 
-		while (g_slist_length (priv->calls))
-			remote_call_complete (self, priv->calls->data);
+	g_clear_object (&priv->proxy);
 
-		g_object_unref (priv->proxy);
+	if (priv->bus) {
 		dbus_g_connection_unref (priv->bus);
+		priv->bus = NULL;
 	}
 
 	G_OBJECT_CLASS (nm_remote_connection_parent_class)->dispose (object);
diff --git a/libnm-glib/nm-remote-connection.h b/libnm-glib/nm-remote-connection.h
index 809927ea..577e9a1b 100644
--- a/libnm-glib/nm-remote-connection.h
+++ b/libnm-glib/nm-remote-connection.h
@@ -63,14 +63,44 @@ typedef struct {
 	void (*_reserved6) (void);
 } NMRemoteConnectionClass;
 
+/**
+ * NMRemoteConnectionCommitFunc:
+ * @connection: the connection for which updates are to be committed
+ * @error: on failure, a descriptive error
+ * @user_data: user data passed to nm_remote_connection_commit_changes()
+ *
+ * Called when NetworkManager has committed outstanding changes to a connection
+ * to backing storage as a result of nm_remote_connection_commit_changes().
+ */
 typedef void (*NMRemoteConnectionCommitFunc) (NMRemoteConnection *connection,
                                               GError *error,
                                               gpointer user_data);
 
+/**
+ * NMRemoteConnectionDeleteFunc:
+ * @connection: the connection to be deleted
+ * @error: on failure, a descriptive error
+ * @user_data: user data passed to nm_remote_connection_delete()
+ *
+ * Called when NetworkManager has deleted a connection as a result of
+ * nm_remote_connection_delete().
+ */
 typedef void (*NMRemoteConnectionDeleteFunc) (NMRemoteConnection *connection,
                                               GError *error,
                                               gpointer user_data);
 
+/**
+ * NMRemoteConnectionGetSecretsFunc:
+ * @connection: the connection for which secrets were requested
+ * @secrets: (element-type utf8 GLib.HashTable): on success, a hash table of
+ *  hash tables, with each inner hash mapping a setting property to a #GValue
+ *  containing that property's value
+ * @error: on failure, a descriptive error
+ * @user_data: user data passed to nm_remote_connection_get_secrets()
+ *
+ * Called when NetworkManager returns secrets in response to a request for
+ * secrets via nm_remote_connection_get_secrets().
+ */
 typedef void (*NMRemoteConnectionGetSecretsFunc) (NMRemoteConnection *connection,
                                                   GHashTable *secrets,
                                                   GError *error,
diff --git a/libnm-glib/nm-remote-settings.c b/libnm-glib/nm-remote-settings.c
index 8f213f9e..19d865c0 100644
--- a/libnm-glib/nm-remote-settings.c
+++ b/libnm-glib/nm-remote-settings.c
@@ -61,8 +61,6 @@ typedef struct {
 	DBusGProxy *dbus_proxy;
 
 	guint fetch_id;
-
-	gboolean disposed;
 } NMRemoteSettingsPrivate;
 
 enum {
@@ -109,7 +107,7 @@ static void
 _nm_remote_settings_ensure_inited (NMRemoteSettings *self)
 {
 	NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
-	GError *error;
+	GError *error = NULL;
 
 	if (!priv->inited) {
 		if (!g_initable_init (G_INITABLE (self), NULL, &error)) {
@@ -258,6 +256,43 @@ connection_removed_cb (NMRemoteConnection *remote, gpointer user_data)
 	g_hash_table_remove (priv->pending, path);
 }
 
+static void connection_visible_cb (NMRemoteConnection *remote,
+                                   gboolean visible,
+                                   gpointer user_data);
+
+/* Takes a reference to the connection when adding to 'to' */
+static void
+move_connection (NMRemoteSettings *self,
+                 NMRemoteConnection *remote,
+                 GHashTable *from,
+                 GHashTable *to)
+{
+	const char *path = nm_connection_get_path (NM_CONNECTION (remote));
+
+	g_hash_table_insert (to, g_strdup (path), g_object_ref (remote));
+	if (from)
+		g_hash_table_remove (from, path);
+
+	/* Setup connection signals since removing from 'from' clears them, but
+	 * also the first time the connection is added to a hash if 'from' is NULL.
+	 */
+	if (!g_signal_handler_find (remote, G_SIGNAL_MATCH_FUNC,
+	                            0, 0, NULL, connection_removed_cb, NULL)) {
+		g_signal_connect (remote,
+		                  NM_REMOTE_CONNECTION_REMOVED,
+		                  G_CALLBACK (connection_removed_cb),
+		                  self);
+	}
+
+	if (!g_signal_handler_find (remote, G_SIGNAL_MATCH_FUNC,
+	                            0, 0, NULL, connection_visible_cb, NULL)) {
+		g_signal_connect (remote,
+		                  "visible",
+		                  G_CALLBACK (connection_visible_cb),
+		                  self);
+	}
+}
+
 static void
 connection_visible_cb (NMRemoteConnection *remote,
                        gboolean visible,
@@ -278,16 +313,14 @@ connection_visible_cb (NMRemoteConnection *remote,
 		/* Connection visible to this user again */
 		if (g_hash_table_lookup (priv->pending, path)) {
 			/* Move connection from pending to visible hash; emit for clients */
-			g_hash_table_insert (priv->connections, g_strdup (path), g_object_ref (remote));
-			g_hash_table_remove (priv->pending, path);
+			move_connection (self, remote, priv->pending, priv->connections);
 			g_signal_emit (self, signals[NEW_CONNECTION], 0, remote);
 		}
 	} else {
 		/* Connection now invisible to this user */
 		if (g_hash_table_lookup (priv->connections, path)) {
 			/* Move connection to pending hash and wait for it to become visible again */
-			g_hash_table_insert (priv->pending, g_strdup (path), g_object_ref (remote));
-			g_hash_table_remove (priv->connections, path);
+			move_connection (self, remote, priv->connections, priv->pending);
 
 			/* Signal to clients that the connection is gone; but we have to
 			 * block our connection removed handler so we don't destroy
@@ -308,17 +341,14 @@ connection_inited (GObject *source, GAsyncResult *result, gpointer user_data)
 	NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
 	AddConnectionInfo *addinfo;
 	const char *path;
-	GError *error = NULL;
-	gboolean remove_from_pending = TRUE;
+	GError *error = NULL, *local;
 
 	path = nm_connection_get_path (NM_CONNECTION (remote));
 	addinfo = add_connection_info_find (self, remote);
 
 	if (g_async_initable_init_finish (G_ASYNC_INITABLE (remote), result, &error)) {
-		/* ref it when adding to ->connections, since removing it from ->pending
-		 * will unref it.
-		 */
-		g_hash_table_insert (priv->connections, g_strdup (path), g_object_ref (remote));
+		/* Connection is initialized and visible; expose it to clients */
+		move_connection (self, remote, priv->pending, priv->connections);
 
 		/* If there's a pending AddConnection request, complete that here before
 		 * signaling new-connection.
@@ -331,23 +361,23 @@ connection_inited (GObject *source, GAsyncResult *result, gpointer user_data)
 		 */
 		g_signal_emit (self, signals[NEW_CONNECTION], 0, remote);
 	} else {
-		if (dbus_g_error_has_name (error, "org.freedesktop.NetworkManager.Settings.PermissionDenied")) {
-			/* Connection doesn't exist, or isn't visible to this user */
-			remove_from_pending = FALSE;
-		}
-		g_error_free (error);
-
 		if (addinfo) {
-			error = g_error_new_literal (NM_REMOTE_SETTINGS_ERROR,
+			local = g_error_new_literal (NM_REMOTE_SETTINGS_ERROR,
 			                             NM_REMOTE_SETTINGS_ERROR_CONNECTION_UNAVAILABLE,
 			                             "Connection not visible or not available");
-			add_connection_info_complete (self, addinfo, error);
-			g_error_free (error);
+			add_connection_info_complete (self, addinfo, local);
+			g_error_free (local);
 		}
-	}
 
-	if (remove_from_pending)
-		g_hash_table_remove (priv->pending, path);
+		/* PermissionDenied means the connection isn't visible to this user, so
+		 * keep it in priv->pending to be notified later of visibility changes.
+		 * Otherwise forget it.
+		 */
+		if (!dbus_g_error_has_name (error, "org.freedesktop.NetworkManager.Settings.PermissionDenied"))
+			g_hash_table_remove (priv->pending, path);
+
+		g_error_free (error);
+	}
 
 	/* Let listeners know that all connections have been found */
 	priv->init_left--;
@@ -373,14 +403,6 @@ new_connection_cb (DBusGProxy *proxy, const char *path, gpointer user_data)
 	/* Create a new connection object for it */
 	connection = nm_remote_connection_new (priv->bus, path);
 	if (connection) {
-		g_signal_connect (connection, NM_REMOTE_CONNECTION_REMOVED,
-		                  G_CALLBACK (connection_removed_cb),
-		                  self);
-
-		g_signal_connect (connection, "visible",
-		                  G_CALLBACK (connection_visible_cb),
-		                  self);
-
 		g_async_initable_init_async (G_ASYNC_INITABLE (connection),
 		                             G_PRIORITY_DEFAULT, NULL,
 		                             connection_inited, self);
@@ -389,7 +411,8 @@ new_connection_cb (DBusGProxy *proxy, const char *path, gpointer user_data)
 		 * it's settings asynchronously over D-Bus.  The connection isn't
 		 * really valid until it has all its settings, so hide it until it does.
 		 */
-		g_hash_table_insert (priv->pending, g_strdup (path), connection);
+		move_connection (self, connection, NULL, priv->pending);
+		g_object_unref (connection); /* move_connection() takes a ref */
 	}
 	return connection;
 }
@@ -796,14 +819,25 @@ nm_remote_settings_new_finish (GAsyncResult *result, GError **error)
 		return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple));
 }
 
+static void
+forget_connection (gpointer user_data)
+{
+	NMRemoteConnection *remote = NM_REMOTE_CONNECTION (user_data);
+
+	g_signal_handlers_disconnect_matched (remote, G_SIGNAL_MATCH_FUNC,
+	                                      0, 0, NULL, connection_removed_cb, NULL);
+	g_signal_handlers_disconnect_matched (remote, G_SIGNAL_MATCH_FUNC,
+	                                      0, 0, NULL, connection_visible_cb, NULL);
+	g_object_unref (remote);
+}
 
 static void
 nm_remote_settings_init (NMRemoteSettings *self)
 {
 	NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
 
-	priv->connections = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
-	priv->pending = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
+	priv->connections = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, forget_connection);
+	priv->pending = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, forget_connection);
 }
 
 static void
@@ -1007,29 +1041,35 @@ dispose (GObject *object)
 	NMRemoteSettings *self = NM_REMOTE_SETTINGS (object);
 	NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
 
-	if (priv->disposed)
-		return;
-
-	priv->disposed = TRUE;
-
-	if (priv->fetch_id)
+	if (priv->fetch_id) {
 		g_source_remove (priv->fetch_id);
+		priv->fetch_id = 0;
+	}
 
 	while (g_slist_length (priv->add_list))
 		add_connection_info_dispose (self, (AddConnectionInfo *) priv->add_list->data);
 
-	if (priv->connections)
+	if (priv->connections) {
 		g_hash_table_destroy (priv->connections);
+		priv->connections = NULL;
+	}
 
-	if (priv->pending)
+	if (priv->pending) {
 		g_hash_table_destroy (priv->pending);
+		priv->pending = NULL;
+	}
 
 	g_free (priv->hostname);
+	priv->hostname = NULL;
 
-	g_object_unref (priv->dbus_proxy);
-	g_object_unref (priv->proxy);
-	g_object_unref (priv->props_proxy);
-	dbus_g_connection_unref (priv->bus);
+	g_clear_object (&priv->dbus_proxy);
+	g_clear_object (&priv->proxy);
+	g_clear_object (&priv->props_proxy);
+
+	if (priv->bus) {
+		dbus_g_connection_unref (priv->bus);
+		priv->bus = NULL;
+	}
 
 	G_OBJECT_CLASS (nm_remote_settings_parent_class)->dispose (object);
 }
@@ -1061,6 +1101,8 @@ get_property (GObject *object, guint prop_id,
 {
 	NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (object);
 
+	_nm_remote_settings_ensure_inited (NM_REMOTE_SETTINGS (object));
+
 	switch (prop_id) {
 	case PROP_BUS:
 		g_value_set_boxed (value, priv->bus);
diff --git a/libnm-glib/nm-secret-agent.c b/libnm-glib/nm-secret-agent.c
index 19f55c0e..ae048d80 100644
--- a/libnm-glib/nm-secret-agent.c
+++ b/libnm-glib/nm-secret-agent.c
@@ -21,9 +21,12 @@
 #include <config.h>
 #include <ctype.h>
 #include <string.h>
-#include <NetworkManager.h>
 #include <dbus/dbus-glib-lowlevel.h>
 
+#include "nm-glib-compat.h"
+
+#include <NetworkManager.h>
+
 #include "nm-secret-agent.h"
 #include "nm-glib-enum-types.h"
 #include "nm-glib-marshal.h"
@@ -79,8 +82,6 @@ typedef struct {
 	gboolean auto_register;
 	gboolean suppress_auto;
 	gboolean auto_register_id;
-
-	gboolean disposed;
 } NMSecretAgentPrivate;
 
 enum {
@@ -878,29 +879,28 @@ dispose (GObject *object)
 	NMSecretAgent *self = NM_SECRET_AGENT (object);
 	NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (self);
 
-	if (!priv->disposed) {
-		priv->disposed = TRUE;
+	if (priv->registered)
+		nm_secret_agent_unregister (self);
 
-		if (priv->registered)
-			nm_secret_agent_unregister (self);
-
-		if (priv->auto_register_id)
-			g_source_remove (priv->auto_register_id);
-
-		g_free (priv->identifier);
-		g_free (priv->nm_owner);
+	if (priv->auto_register_id) {
+		g_source_remove (priv->auto_register_id);
+		priv->auto_register_id = 0;
+	}
 
-		while (priv->pending_gets)
-			get_secrets_info_finalize (self, priv->pending_gets->data);
+	g_free (priv->identifier);
+	priv->identifier = NULL;
+	g_free (priv->nm_owner);
+	priv->nm_owner = NULL;
 
-		if (priv->dbus_proxy)
-			g_object_unref (priv->dbus_proxy);
+	while (priv->pending_gets)
+		get_secrets_info_finalize (self, priv->pending_gets->data);
 
-		if (priv->manager_proxy)
-			g_object_unref (priv->manager_proxy);
+	g_clear_object (&priv->dbus_proxy);
+	g_clear_object (&priv->manager_proxy);
 
-		if (priv->bus)
-			dbus_g_connection_unref (priv->bus);
+	if (priv->bus) {
+		dbus_g_connection_unref (priv->bus);
+		priv->bus = NULL;
 	}
 
 	G_OBJECT_CLASS (nm_secret_agent_parent_class)->dispose (object);
diff --git a/libnm-glib/nm-secret-agent.h b/libnm-glib/nm-secret-agent.h
index c367f916..f96a39c1 100644
--- a/libnm-glib/nm-secret-agent.h
+++ b/libnm-glib/nm-secret-agent.h
@@ -50,13 +50,18 @@ typedef enum {
  * secrets from the user.  This flag signals that NetworkManager thinks any
  * existing secrets are invalid or wrong.  This flag implies that interaction
  * is allowed.
+ * @NM_SECRET_AGENT_GET_SECRETS_FLAG_USER_REQUESTED: set if the request was
+ * initiated by user-requested action via the D-Bus interface, as opposed to
+ * automatically initiated by NetworkManager in response to (for example) scan
+ * results or carrier changes.
  *
  * #NMSecretAgentGetSecretsFlags values modify the behavior of a GetSecrets request.
  */
 typedef enum {
 	NM_SECRET_AGENT_GET_SECRETS_FLAG_NONE = 0x0,
 	NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION = 0x1,
-	NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW = 0x2
+	NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW = 0x2,
+	NM_SECRET_AGENT_GET_SECRETS_FLAG_USER_REQUESTED = 0x4
 } NMSecretAgentGetSecretsFlags;
 
 #define NM_TYPE_SECRET_AGENT            (nm_secret_agent_get_type ())
diff --git a/libnm-glib/nm-vpn-connection.c b/libnm-glib/nm-vpn-connection.c
index 53934216..1fe59e5e 100644
--- a/libnm-glib/nm-vpn-connection.c
+++ b/libnm-glib/nm-vpn-connection.c
@@ -211,6 +211,8 @@ get_property (GObject *object,
 {
 	NMVPNConnection *self = NM_VPN_CONNECTION (object);
 
+	_nm_object_ensure_inited (NM_OBJECT (object));
+
 	switch (prop_id) {
 	case PROP_VPN_STATE:
 		g_value_set_uint (value, nm_vpn_connection_get_vpn_state (self));
diff --git a/libnm-glib/nm-vpn-plugin-ui-interface.h b/libnm-glib/nm-vpn-plugin-ui-interface.h
index 93c5659b..80a5b82e 100644
--- a/libnm-glib/nm-vpn-plugin-ui-interface.h
+++ b/libnm-glib/nm-vpn-plugin-ui-interface.h
@@ -52,6 +52,7 @@ NMVpnPluginUiInterface *nm_vpn_plugin_ui_factory (GError **error);
 #define NM_VPN_PLUGIN_UI_CAPABILITY_NONE     0x00
 #define NM_VPN_PLUGIN_UI_CAPABILITY_IMPORT   0x01
 #define NM_VPN_PLUGIN_UI_CAPABILITY_EXPORT   0x02
+#define NM_VPN_PLUGIN_UI_CAPABILITY_IPV6     0x04
 
 /* Short display name of the VPN plugin */
 #define NM_VPN_PLUGIN_UI_INTERFACE_NAME "name"
diff --git a/libnm-glib/nm-vpn-plugin-utils.c b/libnm-glib/nm-vpn-plugin-utils.c
index 8234a919..b9838df9 100644
--- a/libnm-glib/nm-vpn-plugin-utils.c
+++ b/libnm-glib/nm-vpn-plugin-utils.c
@@ -24,7 +24,9 @@
 #include <string.h>
 
 #include "nm-vpn-plugin-utils.h"
+#include "nm-vpn-plugin.h"
 #include "nm-setting-private.h"
+#include "nm-dbus-glib-types.h"
 
 #define DATA_KEY_TAG "DATA_KEY="
 #define DATA_VAL_TAG "DATA_VAL="
@@ -185,4 +187,3 @@ nm_vpn_plugin_utils_get_secret_flags (GHashTable *data,
 	g_free (flag_name);
 	return success;
 }
-
diff --git a/libnm-glib/nm-vpn-plugin.c b/libnm-glib/nm-vpn-plugin.c
index 23685384..dd4d7b3a 100644
--- a/libnm-glib/nm-vpn-plugin.c
+++ b/libnm-glib/nm-vpn-plugin.c
@@ -30,24 +30,32 @@
 #include "nm-dbus-glib-types.h"
 
 static gboolean impl_vpn_plugin_connect    (NMVPNPlugin *plugin,
-								    GHashTable *connection,
-								    GError **err);
+                                            GHashTable *connection,
+                                            GError **err);
 
 static gboolean impl_vpn_plugin_need_secrets (NMVPNPlugin *plugin,
-								    GHashTable *connection,
-								    char **service_name,
-								    GError **err);
+                                              GHashTable *connection,
+                                              char **service_name,
+                                              GError **err);
 
 static gboolean impl_vpn_plugin_disconnect (NMVPNPlugin *plugin,
-								    GError **err);
+                                            GError **err);
+
+static gboolean impl_vpn_plugin_set_config (NMVPNPlugin *plugin,
+                                            GHashTable *config,
+                                            GError **err);
 
 static gboolean impl_vpn_plugin_set_ip4_config (NMVPNPlugin *plugin,
-									   GHashTable *config,
-									   GError **err);
+                                                GHashTable *config,
+                                                GError **err);
+
+static gboolean impl_vpn_plugin_set_ip6_config (NMVPNPlugin *plugin,
+                                                GHashTable *config,
+                                                GError **err);
 
 static gboolean impl_vpn_plugin_set_failure (NMVPNPlugin *plugin,
-									char *reason,
-									GError **err);
+                                             char *reason,
+                                             GError **err);
 
 #include "nm-vpn-plugin-glue.h"
 
@@ -63,20 +71,26 @@ typedef struct {
 	DBusGConnection *connection;
 	char *dbus_service_name;
 
-	/* GObject-y stuff */
-	gboolean disposed;
-
 	/* Temporary stuff */
 	guint connect_timer;
 	guint quit_timer;
 	guint fail_stop_id;
+
+	gboolean got_config;
+	gboolean has_ip4, got_ip4;
+	gboolean has_ip6, got_ip6;
+
+	/* Config stuff copied from config to ip4config */
+	GValue banner, tundev, gateway, mtu;
 } NMVPNPluginPrivate;
 
 #define NM_VPN_PLUGIN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_VPN_PLUGIN, NMVPNPluginPrivate))
 
 enum {
 	STATE_CHANGED,
+	CONFIG,
 	IP4_CONFIG,
+	IP6_CONFIG,
 	LOGIN_BANNER,
 	FAILURE,
 	QUIT,
@@ -111,7 +125,7 @@ nm_vpn_plugin_error_quark (void)
 
 static void
 nm_vpn_plugin_set_connection (NMVPNPlugin *plugin,
-						DBusGConnection *connection)
+                              DBusGConnection *connection)
 {
 	NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin);
 
@@ -146,7 +160,7 @@ nm_vpn_plugin_get_state (NMVPNPlugin *plugin)
 
 void
 nm_vpn_plugin_set_state (NMVPNPlugin *plugin,
-					NMVPNServiceState state)
+                         NMVPNServiceState state)
 {
 	NMVPNPluginPrivate *priv;
 
@@ -161,7 +175,7 @@ nm_vpn_plugin_set_state (NMVPNPlugin *plugin,
 
 void
 nm_vpn_plugin_set_login_banner (NMVPNPlugin *plugin,
-						  const char *banner)
+                                const char *banner)
 {
 	g_return_if_fail (NM_IS_VPN_PLUGIN (plugin));
 	g_return_if_fail (banner != NULL);
@@ -171,7 +185,7 @@ nm_vpn_plugin_set_login_banner (NMVPNPlugin *plugin,
 
 void
 nm_vpn_plugin_failure (NMVPNPlugin *plugin,
-				   NMVPNPluginFailure reason)
+                       NMVPNPluginFailure reason)
 {
 	g_return_if_fail (NM_IS_VPN_PLUGIN (plugin));
 
@@ -190,17 +204,17 @@ nm_vpn_plugin_disconnect (NMVPNPlugin *plugin, GError **err)
 	switch (state) {
 	case NM_VPN_SERVICE_STATE_STOPPING:
 		g_set_error (err,
-				   NM_VPN_PLUGIN_ERROR,
-				   NM_VPN_PLUGIN_ERROR_STOPPING_IN_PROGRESS,
-				   "%s",
-				   "Could not process the request because the VPN connection is already being stopped.");
+		             NM_VPN_PLUGIN_ERROR,
+		             NM_VPN_PLUGIN_ERROR_STOPPING_IN_PROGRESS,
+		             "%s",
+		             "Could not process the request because the VPN connection is already being stopped.");
 		break;
 	case NM_VPN_SERVICE_STATE_STOPPED:
 		g_set_error (err,
-				   NM_VPN_PLUGIN_ERROR,
-				   NM_VPN_PLUGIN_ERROR_ALREADY_STOPPED,
-				   "%s",
-				   "Could not process the request because no VPN connection was active.");
+		             NM_VPN_PLUGIN_ERROR,
+		             NM_VPN_PLUGIN_ERROR_ALREADY_STOPPED,
+		             "%s",
+		             "Could not process the request because no VPN connection was active.");
 		break;
 	case NM_VPN_SERVICE_STATE_STARTING:
 	case NM_VPN_SERVICE_STATE_STARTED:
@@ -264,8 +278,8 @@ fail_stop (gpointer data)
 
 static gboolean
 nm_vpn_plugin_connect (NMVPNPlugin *plugin,
-				   NMConnection *connection,
-				   GError **err)
+                       NMConnection *connection,
+                       GError **err)
 {
 	NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin);
 	gboolean ret = FALSE;
@@ -277,24 +291,24 @@ nm_vpn_plugin_connect (NMVPNPlugin *plugin,
 	switch (state) {
 	case NM_VPN_SERVICE_STATE_STARTING:
 		g_set_error (err,
-				   NM_VPN_PLUGIN_ERROR,
-				   NM_VPN_PLUGIN_ERROR_STARTING_IN_PROGRESS,
-				   "%s",
-				   "Could not process the request because the VPN connection is already being started.");
+		             NM_VPN_PLUGIN_ERROR,
+		             NM_VPN_PLUGIN_ERROR_STARTING_IN_PROGRESS,
+		             "%s",
+		             "Could not process the request because the VPN connection is already being started.");
 		break;
 	case NM_VPN_SERVICE_STATE_STARTED:
 		g_set_error (err,
-				   NM_VPN_PLUGIN_ERROR,
-				   NM_VPN_PLUGIN_ERROR_ALREADY_STARTED,
-				   "%s",
-				   "Could not process the request because a VPN connection was already active.");
+		             NM_VPN_PLUGIN_ERROR,
+		             NM_VPN_PLUGIN_ERROR_ALREADY_STARTED,
+		             "%s",
+		             "Could not process the request because a VPN connection was already active.");
 		break;
 	case NM_VPN_SERVICE_STATE_STOPPING:
 		g_set_error (err,
-				   NM_VPN_PLUGIN_ERROR,
-				   NM_VPN_PLUGIN_ERROR_STOPPING_IN_PROGRESS,
-				   "%s",
-				   "Could not process the request because the VPN connection is being stopped.");
+		             NM_VPN_PLUGIN_ERROR,
+		             NM_VPN_PLUGIN_ERROR_STOPPING_IN_PROGRESS,
+		             "%s",
+		             "Could not process the request because the VPN connection is being stopped.");
 		break;
 	case NM_VPN_SERVICE_STATE_STOPPED:
 	case NM_VPN_SERVICE_STATE_INIT:
@@ -319,22 +333,124 @@ nm_vpn_plugin_connect (NMVPNPlugin *plugin,
 }
 
 void
+nm_vpn_plugin_set_config (NMVPNPlugin *plugin,
+                          GHashTable *config)
+{
+	NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin);
+	GValue *val;
+
+	g_return_if_fail (NM_IS_VPN_PLUGIN (plugin));
+	g_return_if_fail (config != NULL);
+
+	priv->got_config = TRUE;
+
+	val = g_hash_table_lookup (config, NM_VPN_PLUGIN_CONFIG_HAS_IP4);
+	if (val && g_value_get_boolean (val))
+		priv->has_ip4 = TRUE;
+	val = g_hash_table_lookup (config, NM_VPN_PLUGIN_CONFIG_HAS_IP6);
+	if (val && g_value_get_boolean (val))
+		priv->has_ip6 = TRUE;
+
+	g_warn_if_fail (priv->has_ip4 || priv->has_ip6);
+
+	/* Record the items that need to also be inserted into the
+	 * ip4config, for compatibility with older daemons.
+	 */
+	val = g_hash_table_lookup (config, NM_VPN_PLUGIN_CONFIG_BANNER);
+	if (val) {
+		g_value_init (&priv->banner, G_VALUE_TYPE (val));
+		g_value_copy (val, &priv->banner);
+	}
+	val = g_hash_table_lookup (config, NM_VPN_PLUGIN_CONFIG_TUNDEV);
+	if (val) {
+		g_value_init (&priv->tundev, G_VALUE_TYPE (val));
+		g_value_copy (val, &priv->tundev);
+	}
+	val = g_hash_table_lookup (config, NM_VPN_PLUGIN_CONFIG_EXT_GATEWAY);
+	if (val) {
+		g_value_init (&priv->gateway, G_VALUE_TYPE (val));
+		g_value_copy (val, &priv->gateway);
+	}
+	val = g_hash_table_lookup (config, NM_VPN_PLUGIN_CONFIG_MTU);
+	if (val) {
+		g_value_init (&priv->mtu, G_VALUE_TYPE (val));
+		g_value_copy (val, &priv->mtu);
+	}
+
+	g_signal_emit (plugin, signals[CONFIG], 0, config);
+}
+
+void
 nm_vpn_plugin_set_ip4_config (NMVPNPlugin *plugin,
-						GHashTable *ip4_config)
+                              GHashTable *ip4_config)
 {
+	NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin);
+	GHashTable *combined_config;
+	GHashTableIter iter;
+	gpointer key, value;
+
 	g_return_if_fail (NM_IS_VPN_PLUGIN (plugin));
 	g_return_if_fail (ip4_config != NULL);
 
-	g_signal_emit (plugin, signals[IP4_CONFIG], 0, ip4_config);
+	priv->got_ip4 = TRUE;
+
+	/* Old plugins won't send the "config" signal and thus can't send
+	 * NM_VPN_PLUGIN_CONFIG_HAS_IP4 either.  But since they don't support IPv6,
+	 * we can safely assume that, if we don't receive a "config" signal but do
+	 * receive an "ip4-config" signal, the old plugin supports IPv4.
+	 */
+	if (!priv->got_config)
+		priv->has_ip4 = TRUE;
+
+	/* Older NetworkManager daemons expect all config info to be in
+	 * the ip4 config, so they won't even notice the "config" signal
+	 * being emitted. So just copy all of that data into the ip4
+	 * config too.
+	 */
+	combined_config = g_hash_table_new (g_str_hash, g_str_equal);
+	g_hash_table_iter_init (&iter, ip4_config);
+	while (g_hash_table_iter_next (&iter, &key, &value))
+		g_hash_table_insert (combined_config, key, value);
+
+	if (G_VALUE_TYPE (&priv->banner) != G_TYPE_INVALID)
+		g_hash_table_insert (combined_config, NM_VPN_PLUGIN_IP4_CONFIG_BANNER, &priv->banner);
+	if (G_VALUE_TYPE (&priv->tundev) != G_TYPE_INVALID)
+		g_hash_table_insert (combined_config, NM_VPN_PLUGIN_IP4_CONFIG_TUNDEV, &priv->tundev);
+	if (G_VALUE_TYPE (&priv->gateway) != G_TYPE_INVALID)
+		g_hash_table_insert (combined_config, NM_VPN_PLUGIN_IP4_CONFIG_EXT_GATEWAY, &priv->gateway);
+	if (G_VALUE_TYPE (&priv->mtu) != G_TYPE_INVALID)
+		g_hash_table_insert (combined_config, NM_VPN_PLUGIN_IP4_CONFIG_MTU, &priv->mtu);
+
+	g_signal_emit (plugin, signals[IP4_CONFIG], 0, combined_config);
+	g_hash_table_destroy (combined_config);
+
+	if (   priv->has_ip4 == priv->got_ip4
+	    && priv->has_ip6 == priv->got_ip6)
+		nm_vpn_plugin_set_state (plugin, NM_VPN_SERVICE_STATE_STARTED);
+}
 
-	nm_vpn_plugin_set_state (plugin, NM_VPN_SERVICE_STATE_STARTED);
+void
+nm_vpn_plugin_set_ip6_config (NMVPNPlugin *plugin,
+                              GHashTable *ip6_config)
+{
+	NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin);
+
+	g_return_if_fail (NM_IS_VPN_PLUGIN (plugin));
+	g_return_if_fail (ip6_config != NULL);
+
+	priv->got_ip6 = TRUE;
+	g_signal_emit (plugin, signals[IP6_CONFIG], 0, ip6_config);
+
+	if (   priv->has_ip4 == priv->got_ip4
+	    && priv->has_ip6 == priv->got_ip6)
+		nm_vpn_plugin_set_state (plugin, NM_VPN_SERVICE_STATE_STARTED);
 }
 
 
 static gboolean
 impl_vpn_plugin_connect (NMVPNPlugin *plugin,
-					GHashTable *properties,
-					GError **error)
+                         GHashTable *properties,
+                         GError **error)
 {
 	NMConnection *connection;
 	gboolean success = FALSE;
@@ -410,15 +526,25 @@ out:
 
 static gboolean
 impl_vpn_plugin_disconnect (NMVPNPlugin *plugin,
-					   GError **err)
+                            GError **err)
 {
 	return nm_vpn_plugin_disconnect (plugin, err);
 }
 
 static gboolean
+impl_vpn_plugin_set_config (NMVPNPlugin *plugin,
+                            GHashTable *config,
+                            GError **err)
+{
+	nm_vpn_plugin_set_config (plugin, config);
+
+	return TRUE;
+}
+
+static gboolean
 impl_vpn_plugin_set_ip4_config (NMVPNPlugin *plugin,
-						  GHashTable *config,
-						  GError **err)
+                                GHashTable *config,
+                                GError **err)
 {
 	nm_vpn_plugin_set_ip4_config (plugin, config);
 
@@ -426,9 +552,19 @@ impl_vpn_plugin_set_ip4_config (NMVPNPlugin *plugin,
 }
 
 static gboolean
+impl_vpn_plugin_set_ip6_config (NMVPNPlugin *plugin,
+                                GHashTable *config,
+                                GError **err)
+{
+	nm_vpn_plugin_set_ip6_config (plugin, config);
+
+	return TRUE;
+}
+
+static gboolean
 impl_vpn_plugin_set_failure (NMVPNPlugin *plugin,
-					    char *reason,
-					    GError **err)
+                             char *reason,
+                             GError **err)
 {
 	nm_vpn_plugin_failure (plugin, NM_VPN_PLUGIN_FAILURE_BAD_IP_CONFIG);
 
@@ -461,7 +597,7 @@ setup_unix_signal_handler (void)
 
 static void
 one_plugin_destroyed (gpointer data,
-				  GObject *object)
+                      GObject *object)
 {
 	active_plugins = g_slist_remove (active_plugins, object);
 }
@@ -477,8 +613,8 @@ nm_vpn_plugin_init (NMVPNPlugin *plugin)
 
 static GObject *
 constructor (GType type,
-		   guint n_construct_params,
-		   GObjectConstructParam *construct_params)
+             guint n_construct_params,
+             GObjectConstructParam *construct_params)
 {
 	GObject *object;
 	NMVPNPlugin *plugin;
@@ -503,16 +639,16 @@ constructor (GType type,
 		goto err;
 
 	proxy = dbus_g_proxy_new_for_name (connection,
-								"org.freedesktop.DBus",
-								"/org/freedesktop/DBus",
-								"org.freedesktop.DBus");
+	                                   "org.freedesktop.DBus",
+	                                   "/org/freedesktop/DBus",
+	                                   "org.freedesktop.DBus");
 
 	if (!dbus_g_proxy_call (proxy, "RequestName", &err,
-					    G_TYPE_STRING, priv->dbus_service_name,
-					    G_TYPE_UINT, 0,
-					    G_TYPE_INVALID,
-					    G_TYPE_UINT, &request_name_result,
-					    G_TYPE_INVALID)) {
+	                        G_TYPE_STRING, priv->dbus_service_name,
+	                        G_TYPE_UINT, 0,
+	                        G_TYPE_INVALID,
+	                        G_TYPE_UINT, &request_name_result,
+	                        G_TYPE_INVALID)) {
 		g_object_unref (proxy);
 		goto err;
 	}
@@ -520,8 +656,8 @@ constructor (GType type,
 	g_object_unref (proxy);
 
 	dbus_g_connection_register_g_object (connection,
-								  NM_VPN_DBUS_PLUGIN_PATH,
-								  object);
+	                                     NM_VPN_DBUS_PLUGIN_PATH,
+	                                     object);
 
 	plugin = NM_VPN_PLUGIN (object);
 
@@ -544,7 +680,7 @@ constructor (GType type,
 
 static void
 set_property (GObject *object, guint prop_id,
-		    const GValue *value, GParamSpec *pspec)
+              const GValue *value, GParamSpec *pspec)
 {
 	NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (object);
 
@@ -555,7 +691,7 @@ set_property (GObject *object, guint prop_id,
 		break;
 	case PROP_STATE:
 		nm_vpn_plugin_set_state (NM_VPN_PLUGIN (object),
-							(NMVPNServiceState) g_value_get_uint (value));
+		                         (NMVPNServiceState) g_value_get_uint (value));
 		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -590,15 +726,10 @@ dispose (GObject *object)
 	NMVPNServiceState state;
 	GError *err = NULL;
 
-	if (priv->disposed) {
-		G_OBJECT_CLASS (nm_vpn_plugin_parent_class)->dispose (object);
-		return;
-	}
-
-	priv->disposed = TRUE;
-
-	if (priv->fail_stop_id)
+	if (priv->fail_stop_id) {
 		g_source_remove (priv->fail_stop_id);
+		priv->fail_stop_id = 0;
+	}
 
 	state = nm_vpn_plugin_get_state (plugin);
 
@@ -623,6 +754,15 @@ finalize (GObject *object)
 	nm_vpn_plugin_set_connection (plugin, NULL);
 	g_free (priv->dbus_service_name);
 
+	if (G_IS_VALUE (&priv->banner))
+		g_value_unset (&priv->banner);
+	if (G_IS_VALUE (&priv->tundev))
+		g_value_unset (&priv->tundev);
+	if (G_IS_VALUE (&priv->gateway))
+		g_value_unset (&priv->gateway);
+	if (G_IS_VALUE (&priv->mtu))
+		g_value_unset (&priv->mtu);
+
 	G_OBJECT_CLASS (nm_vpn_plugin_parent_class)->finalize (object);
 }
 
@@ -692,7 +832,7 @@ nm_vpn_plugin_class_init (NMVPNPluginClass *plugin_class)
 	g_type_class_add_private (object_class, sizeof (NMVPNPluginPrivate));
 
 	dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (plugin_class),
-							   &dbus_glib_nm_vpn_plugin_object_info);
+	                                 &dbus_glib_nm_vpn_plugin_object_info);
 
 	/* virtual methods */
 	object_class->constructor  = constructor;
@@ -707,75 +847,95 @@ nm_vpn_plugin_class_init (NMVPNPluginClass *plugin_class)
 	g_object_class_install_property
 		(object_class, PROP_DBUS_SERVICE_NAME,
 		 g_param_spec_string (NM_VPN_PLUGIN_DBUS_SERVICE_NAME,
-						  "DBus service name",
-						  "DBus service name",
-						  NULL,
-						  G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+		                      "DBus service name",
+		                      "DBus service name",
+		                      NULL,
+		                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 
 	g_object_class_install_property
 		(object_class, PROP_STATE,
 		 g_param_spec_uint (NM_VPN_PLUGIN_STATE,
-						"State",
-						"Current VPN service state",
-						NM_VPN_SERVICE_STATE_UNKNOWN,
-						NM_VPN_SERVICE_STATE_STOPPED,
-						NM_VPN_SERVICE_STATE_INIT,
-						G_PARAM_READWRITE));
+		                    "State",
+		                    "Current VPN service state",
+		                    NM_VPN_SERVICE_STATE_UNKNOWN,
+		                    NM_VPN_SERVICE_STATE_STOPPED,
+		                    NM_VPN_SERVICE_STATE_INIT,
+		                    G_PARAM_READWRITE));
 
 	/* signals */
 	signals[STATE_CHANGED] =
 		g_signal_new ("state-changed",
-				    G_OBJECT_CLASS_TYPE (object_class),
-				    G_SIGNAL_RUN_FIRST,
-				    G_STRUCT_OFFSET (NMVPNPluginClass, state_changed),
-				    NULL, NULL,
-				    g_cclosure_marshal_VOID__UINT,
-				    G_TYPE_NONE, 1,
-				    G_TYPE_UINT);
+		              G_OBJECT_CLASS_TYPE (object_class),
+		              G_SIGNAL_RUN_FIRST,
+		              G_STRUCT_OFFSET (NMVPNPluginClass, state_changed),
+		              NULL, NULL,
+		              g_cclosure_marshal_VOID__UINT,
+		              G_TYPE_NONE, 1,
+		              G_TYPE_UINT);
+
+	signals[CONFIG] =
+		g_signal_new ("config",
+		              G_OBJECT_CLASS_TYPE (object_class),
+		              G_SIGNAL_RUN_FIRST,
+		              G_STRUCT_OFFSET (NMVPNPluginClass, config),
+		              NULL, NULL,
+		              g_cclosure_marshal_VOID__BOXED,
+		              G_TYPE_NONE, 1,
+		              DBUS_TYPE_G_MAP_OF_VARIANT);
 
 	signals[IP4_CONFIG] =
 		g_signal_new ("ip4-config",
-				    G_OBJECT_CLASS_TYPE (object_class),
-				    G_SIGNAL_RUN_FIRST,
-				    G_STRUCT_OFFSET (NMVPNPluginClass, ip4_config),
-				    NULL, NULL,
-				    g_cclosure_marshal_VOID__BOXED,
-				    G_TYPE_NONE, 1,
-				    DBUS_TYPE_G_MAP_OF_VARIANT);
+		              G_OBJECT_CLASS_TYPE (object_class),
+		              G_SIGNAL_RUN_FIRST,
+		              G_STRUCT_OFFSET (NMVPNPluginClass, ip4_config),
+		              NULL, NULL,
+		              g_cclosure_marshal_VOID__BOXED,
+		              G_TYPE_NONE, 1,
+		              DBUS_TYPE_G_MAP_OF_VARIANT);
+
+	signals[IP6_CONFIG] =
+		g_signal_new ("ip6-config",
+		              G_OBJECT_CLASS_TYPE (object_class),
+		              G_SIGNAL_RUN_FIRST,
+		              G_STRUCT_OFFSET (NMVPNPluginClass, ip6_config),
+		              NULL, NULL,
+		              g_cclosure_marshal_VOID__BOXED,
+		              G_TYPE_NONE, 1,
+		              DBUS_TYPE_G_MAP_OF_VARIANT);
 
 	signals[LOGIN_BANNER] =
 		g_signal_new ("login-banner",
-				    G_OBJECT_CLASS_TYPE (object_class),
-				    G_SIGNAL_RUN_FIRST,
-				    G_STRUCT_OFFSET (NMVPNPluginClass, login_banner),
-				    NULL, NULL,
-				    g_cclosure_marshal_VOID__STRING,
-				    G_TYPE_NONE, 1,
-				    G_TYPE_STRING);
+		              G_OBJECT_CLASS_TYPE (object_class),
+		              G_SIGNAL_RUN_FIRST,
+		              G_STRUCT_OFFSET (NMVPNPluginClass, login_banner),
+		              NULL, NULL,
+		              g_cclosure_marshal_VOID__STRING,
+		              G_TYPE_NONE, 1,
+		              G_TYPE_STRING);
 
 	signals[FAILURE] =
 		g_signal_new ("failure",
-				    G_OBJECT_CLASS_TYPE (object_class),
-				    G_SIGNAL_RUN_FIRST,
-				    G_STRUCT_OFFSET (NMVPNPluginClass, failure),
-				    NULL, NULL,
-				    g_cclosure_marshal_VOID__UINT,
-				    G_TYPE_NONE, 1,
-				    G_TYPE_UINT);
+		              G_OBJECT_CLASS_TYPE (object_class),
+		              G_SIGNAL_RUN_FIRST,
+		              G_STRUCT_OFFSET (NMVPNPluginClass, failure),
+		              NULL, NULL,
+		              g_cclosure_marshal_VOID__UINT,
+		              G_TYPE_NONE, 1,
+		              G_TYPE_UINT);
 
 	signals[QUIT] =
 		g_signal_new ("quit",
-				    G_OBJECT_CLASS_TYPE (object_class),
-				    G_SIGNAL_RUN_FIRST,
-				    G_STRUCT_OFFSET (NMVPNPluginClass, quit),
-				    NULL, NULL,
-				    g_cclosure_marshal_VOID__VOID,
-				    G_TYPE_NONE, 0,
-				    G_TYPE_NONE);
+		              G_OBJECT_CLASS_TYPE (object_class),
+		              G_SIGNAL_RUN_FIRST,
+		              G_STRUCT_OFFSET (NMVPNPluginClass, quit),
+		              NULL, NULL,
+		              g_cclosure_marshal_VOID__VOID,
+		              G_TYPE_NONE, 0,
+		              G_TYPE_NONE);
 
 	dbus_g_error_domain_register (NM_VPN_PLUGIN_ERROR,
-							NULL,
-							NM_TYPE_VPN_PLUGIN_ERROR);
+	                              NULL,
+	                              NM_TYPE_VPN_PLUGIN_ERROR);
 
 	setup_unix_signal_handler ();
 }
diff --git a/libnm-glib/nm-vpn-plugin.h b/libnm-glib/nm-vpn-plugin.h
index 15cbf686..cdd55c15 100644
--- a/libnm-glib/nm-vpn-plugin.h
+++ b/libnm-glib/nm-vpn-plugin.h
@@ -64,40 +64,44 @@ typedef struct {
 	GObjectClass parent;
 
 	/* virtual methods */
-	gboolean (*connect)    (NMVPNPlugin   *plugin,
-					    NMConnection  *connection,
-					    GError       **err);
+	gboolean (*connect)      (NMVPNPlugin   *plugin,
+	                          NMConnection  *connection,
+	                          GError       **err);
 
 	gboolean (*need_secrets) (NMVPNPlugin *plugin,
-	                              NMConnection *connection,
-	                              char **setting_name,
-	                              GError **error);
+	                          NMConnection *connection,
+	                          char **setting_name,
+	                          GError **error);
 
-	gboolean (*disconnect) (NMVPNPlugin   *plugin,
-					    GError       **err);
+	gboolean (*disconnect)   (NMVPNPlugin   *plugin,
+	                          GError       **err);
 
 	/* Signals */
 	void (*state_changed)  (NMVPNPlugin *plugin,
-					    NMVPNServiceState state);
+	                        NMVPNServiceState state);
 
 	void (*ip4_config)     (NMVPNPlugin *plugin,
-					    GHashTable  *ip4_config);
+	                        GHashTable  *ip4_config);
 
 	void (*login_banner)   (NMVPNPlugin *plugin,
-					    const char *banner);
+	                        const char *banner);
 
 	void (*failure)        (NMVPNPlugin *plugin,
-					    NMVPNPluginFailure reason);
+	                        NMVPNPluginFailure reason);
 
 	void (*quit)           (NMVPNPlugin *plugin);
 
+	void (*config)         (NMVPNPlugin *plugin,
+	                        GHashTable  *config);
+
+	void (*ip6_config)     (NMVPNPlugin *plugin,
+	                        GHashTable  *config);
+
 	/* Padding for future expansion */
 	void (*_reserved1) (void);
 	void (*_reserved2) (void);
 	void (*_reserved3) (void);
 	void (*_reserved4) (void);
-	void (*_reserved5) (void);
-	void (*_reserved6) (void);
 } NMVPNPluginClass;
 
 GType  nm_vpn_plugin_get_type       (void);
@@ -107,19 +111,25 @@ GType  nm_vpn_plugin_error_get_type (void);
 DBusGConnection   *nm_vpn_plugin_get_connection (NMVPNPlugin *plugin);
 NMVPNServiceState  nm_vpn_plugin_get_state      (NMVPNPlugin *plugin);
 void               nm_vpn_plugin_set_state      (NMVPNPlugin *plugin,
-									    NMVPNServiceState state);
+                                                 NMVPNServiceState state);
 
 void               nm_vpn_plugin_set_login_banner (NMVPNPlugin *plugin,
-										 const char *banner);
+                                                   const char *banner);
 
 void               nm_vpn_plugin_failure        (NMVPNPlugin *plugin,
-									    NMVPNPluginFailure reason);
+                                                 NMVPNPluginFailure reason);
+
+void               nm_vpn_plugin_set_config     (NMVPNPlugin *plugin,
+                                                 GHashTable *config);
 
 void               nm_vpn_plugin_set_ip4_config (NMVPNPlugin *plugin,
-									    GHashTable *ip4_config);
+                                                 GHashTable *ip4_config);
+
+void               nm_vpn_plugin_set_ip6_config (NMVPNPlugin *plugin,
+                                                 GHashTable *ip6_config);
 
 gboolean           nm_vpn_plugin_disconnect     (NMVPNPlugin *plugin,
-									    GError **err);
+                                                 GError **err);
 
 G_END_DECLS
 
diff --git a/libnm-glib/nm-wimax-nsp.c b/libnm-glib/nm-wimax-nsp.c
index c3b222df..ce1048be 100644
--- a/libnm-glib/nm-wimax-nsp.c
+++ b/libnm-glib/nm-wimax-nsp.c
@@ -23,6 +23,8 @@
 #include <config.h>
 #include <string.h>
 
+#include "nm-glib-compat.h"
+
 #include <nm-connection.h>
 #include <nm-setting-connection.h>
 #include <nm-setting-wimax.h>
@@ -37,7 +39,6 @@ G_DEFINE_TYPE (NMWimaxNsp, nm_wimax_nsp, NM_TYPE_OBJECT)
 #define NM_WIMAX_NSP_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_WIMAX_NSP, NMWimaxNspPrivate))
 
 typedef struct {
-	gboolean disposed;
 	DBusGProxy *proxy;
 
 	char *name;
@@ -217,14 +218,7 @@ dispose (GObject *object)
 {
 	NMWimaxNspPrivate *priv = NM_WIMAX_NSP_GET_PRIVATE (object);
 
-	if (priv->disposed) {
-		G_OBJECT_CLASS (nm_wimax_nsp_parent_class)->dispose (object);
-		return;
-	}
-
-	priv->disposed = TRUE;
-
-	g_object_unref (priv->proxy);
+	g_clear_object (&priv->proxy);
 
 	G_OBJECT_CLASS (nm_wimax_nsp_parent_class)->dispose (object);
 }
@@ -247,6 +241,8 @@ get_property (GObject *object,
 {
 	NMWimaxNsp *nsp = NM_WIMAX_NSP (object);
 
+	_nm_object_ensure_inited (NM_OBJECT (object));
+
 	switch (prop_id) {
 	case PROP_NAME:
 		g_value_set_string (value, nm_wimax_nsp_get_name (nsp));
diff --git a/libnm-glib/tests/Makefile.in b/libnm-glib/tests/Makefile.in
index ad4d1c44..a9840c03 100644
--- a/libnm-glib/tests/Makefile.in
+++ b/libnm-glib/tests/Makefile.in
@@ -48,7 +48,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \
 	$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
 	$(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \
 	$(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \
-	$(top_srcdir)/configure.ac
+	$(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
 mkinstalldirs = $(install_sh) -d
@@ -170,6 +170,10 @@ INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
 INTLTOOL_MERGE = @INTLTOOL_MERGE@
 INTLTOOL_PERL = @INTLTOOL_PERL@
 INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@
+INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@
+INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@
+INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@
 INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
 INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@
 INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@
@@ -265,6 +269,9 @@ UDEV_BASE_DIR = @UDEV_BASE_DIR@
 USE_NLS = @USE_NLS@
 UUID_CFLAGS = @UUID_CFLAGS@
 UUID_LIBS = @UUID_LIBS@
+VAPIGEN = @VAPIGEN@
+VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@
+VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@
 VERSION = @VERSION@
 XGETTEXT = @XGETTEXT@
 XGETTEXT_015 = @XGETTEXT_015@
@@ -303,6 +310,8 @@ htmldir = @htmldir@
 includedir = @includedir@
 infodir = @infodir@
 install_sh = @install_sh@
+intltool__v_merge_options_ = @intltool__v_merge_options_@
+intltool__v_merge_options_0 = @intltool__v_merge_options_0@
 libdir = @libdir@
 libexecdir = @libexecdir@
 localedir = @localedir@